Add fileId data support to csync.

That stores a life time lasting unique Id for every file which
is maintained by the server. It is used on the client to detect
server side moves.
This commit is contained in:
Klaas Freitag 2013-10-25 13:12:59 +02:00
parent 5a26221a6b
commit 4440acdb1d
7 changed files with 57 additions and 12 deletions

View File

@ -42,6 +42,7 @@ static void free_fetchCtx( struct listdir_context *ctx )
SAFE_FREE(res->uri);
SAFE_FREE(res->name);
SAFE_FREE(res->md5);
memset( res->file_id, 0, FILE_ID_BUF_SIZE+1 );
newres = res->next;
SAFE_FREE(res);
@ -80,6 +81,7 @@ static void clean_caches() {
SAFE_FREE(_stat_cache.name);
SAFE_FREE(_stat_cache.md5 );
memset( _stat_cache.file_id, 0, FILE_ID_BUF_SIZE+1 );
SAFE_FREE(_id_cache.uri);
SAFE_FREE(_id_cache.id);
@ -627,6 +629,7 @@ static void results(void *userdata,
const char *clength, *modtime = NULL;
const char *resourcetype = NULL;
const char *md5sum = NULL;
const char *file_id = NULL;
const ne_status *status = NULL;
char *path = ne_path_unescape( uri->path );
@ -650,6 +653,7 @@ static void results(void *userdata,
clength = ne_propset_value( set, &ls_props[1] );
resourcetype = ne_propset_value( set, &ls_props[2] );
md5sum = ne_propset_value( set, &ls_props[3] );
file_id = ne_propset_value( set, &ls_props[4] );
newres->type = resr_normal;
if( clength == NULL && resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) {
@ -677,6 +681,8 @@ static void results(void *userdata,
}
}
csync_vio_set_file_id(newres->file_id, file_id);
/* prepend the new resource to the result list */
newres->next = fetchCtx->list;
fetchCtx->list = newres;
@ -821,6 +827,8 @@ static void fill_stat_cache( csync_vio_file_stat_t *lfs ) {
_stat_cache.fields = lfs->fields;
_stat_cache.type = lfs->type;
_stat_cache.size = lfs->size;
csync_vio_file_stat_set_file_id(&_stat_cache, lfs->file_id);
if( lfs->md5 ) {
_stat_cache.md5 = c_strdup(lfs->md5);
}
@ -858,17 +866,17 @@ static int owncloud_stat(const char *uri, csync_vio_file_stat_t *buf) {
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_SIZE;
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME;
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_PERMISSIONS;
buf->fields = _stat_cache.fields;
buf->type = _stat_cache.type;
buf->mtime = _stat_cache.mtime;
buf->size = _stat_cache.size;
buf->mode = _stat_perms( _stat_cache.type );
buf->md5 = NULL;
buf->fields = _stat_cache.fields;
buf->type = _stat_cache.type;
buf->mtime = _stat_cache.mtime;
buf->size = _stat_cache.size;
buf->mode = _stat_perms( _stat_cache.type );
buf->md5 = NULL;
if( _stat_cache.md5 ) {
buf->md5 = c_strdup( _stat_cache.md5 );
buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MD5;
}
csync_vio_file_stat_set_file_id( buf, _stat_cache.file_id );
return 0;
}
DEBUG_WEBDAV("owncloud_stat => Could not find in stat cache %s", uri);
@ -922,6 +930,7 @@ static int owncloud_stat(const char *uri, csync_vio_file_stat_t *buf) {
if( lfs->md5 ) {
buf->md5 = c_strdup( lfs->md5 );
}
csync_vio_file_stat_set_file_id( buf, lfs->file_id );
/* fill the static stat buf as input for the stat function */
csync_vio_file_stat_destroy( lfs );
@ -1058,7 +1067,7 @@ static const char* owncloud_get_etag( const char *path )
/* ... and do a stat call. */
fs = csync_vio_file_stat_new();
if(fs == NULL) {
DEBUG_WEBDAV( "owncloud_file_id: memory fault.");
DEBUG_WEBDAV( "owncloud_get_etag: memory fault.");
errno = ENOMEM;
return NULL;
}
@ -1761,8 +1770,6 @@ static int owncloud_commit() {
return 0;
}
static int owncloud_utimes(const char *uri, const struct timeval *times) {
ne_proppatch_operation ops[2];

View File

@ -84,6 +84,7 @@ typedef struct resource {
int64_t size;
time_t modtime;
char* md5;
char file_id[FILE_ID_BUF_SIZE+1];
struct resource *next;
} resource;
@ -177,6 +178,7 @@ static const ne_propname ls_props[] = {
{ "DAV:", "getcontentlength" },
{ "DAV:", "resourcetype" },
{ "DAV:", "getetag"},
{ "http://owncloud.org/ns", "id"},
{ NULL, NULL }
};

View File

@ -36,6 +36,8 @@ static struct resource* resource_dup(struct resource* o) {
r->modtime = o->modtime;
r->md5 = c_strdup(o->md5);
r->next = o->next;
csync_vio_set_file_id(r->file_id, o->file_id);
return r;
}
static void resource_free(struct resource* o) {
@ -126,7 +128,7 @@ static void propfind_results_recursive(void *userdata,
const ne_prop_result_set *set)
{
struct resource *newres = 0;
const char *clength, *modtime = NULL;
const char *clength, *modtime, *file_id = NULL;
const char *resourcetype = NULL;
const char *md5sum = NULL;
const ne_status *status = NULL;
@ -153,6 +155,7 @@ static void propfind_results_recursive(void *userdata,
clength = ne_propset_value( set, &ls_props[1] );
resourcetype = ne_propset_value( set, &ls_props[2] );
md5sum = ne_propset_value( set, &ls_props[3] );
file_id = ne_propset_value( set, &ls_props[4] );
newres->type = resr_normal;
if( resourcetype && strncmp( resourcetype, "<DAV:collection>", 16 ) == 0) {
@ -184,6 +187,7 @@ static void propfind_results_recursive(void *userdata,
}
}
csync_vio_set_file_id(newres->file_id, file_id);
/*
DEBUG_WEBDAV("propfind_results_recursive %s [%s] %s", newres->uri, newres->type == resr_collection ? "collection" : "file", newres->md5);
*/

View File

@ -312,6 +312,8 @@ csync_vio_file_stat_t *resourceToFileStat( struct resource *res )
lfs->md5 = c_strdup(res->md5);
}
lfs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MD5;
csync_vio_file_stat_set_file_id(lfs, res->file_id);
return lfs;
}

View File

@ -41,6 +41,7 @@
#include "c_private.h"
#include "csync.h"
#include "csync_misc.h"
#include "vio/csync_vio_file_stat.h"
#ifdef WITH_ICONV
#include <iconv.h>
@ -195,6 +196,7 @@ struct csync_file_stat_s {
char *destpath; /* for renames */
const char *md5;
char file_id[FILE_ID_BUF_SIZE+1]; /* the ownCloud file id is fixed width of 21 byte. */
const char *error_string;
enum csync_instructions_e instruction; /* u32 */

View File

@ -29,6 +29,7 @@ csync_vio_file_stat_t *csync_vio_file_stat_new(void) {
return NULL;
}
file_stat->md5 = NULL;
memset(file_stat->file_id, 0, FILE_ID_BUF_SIZE+1);
return file_stat;
}
@ -51,3 +52,21 @@ void csync_vio_file_stat_destroy(csync_vio_file_stat_t *file_stat) {
SAFE_FREE(file_stat);
}
void csync_vio_file_stat_set_file_id( csync_vio_file_stat_t *dst, const char* src ) {
csync_vio_set_file_id( dst->file_id, src );
if( c_streq( dst->file_id, INVALID_FILE_ID )) {
return;
}
dst->fields |= CSYNC_VIO_FILE_STAT_FIELDS_FILE_ID;
}
void csync_vio_set_file_id( char* dst, const char *src ) {
if( src && dst ) {
if( strlen(src) > FILE_ID_BUF_SIZE ) {
strcpy(dst, INVALID_FILE_ID);
} else {
strcpy(dst, src);
}
}
}

View File

@ -26,12 +26,15 @@
* that would cause circular inclusion
*/
#include "c_private.h"
#include "csync.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdint.h>
#define FILE_ID_BUF_SIZE 21
#define INVALID_FILE_ID "-invalid_fileid-"
typedef struct csync_vio_file_stat_s csync_vio_file_stat_t;
enum csync_vio_file_flags_e {
@ -71,6 +74,7 @@ enum csync_vio_file_stat_fields_e {
CSYNC_VIO_FILE_STAT_FIELDS_UID = 1 << 15,
CSYNC_VIO_FILE_STAT_FIELDS_GID = 1 << 16,
CSYNC_VIO_FILE_STAT_FIELDS_MD5 = 1 << 17,
CSYNC_VIO_FILE_STAT_FIELDS_FILE_ID = 1 << 18
};
@ -83,6 +87,7 @@ struct csync_vio_file_stat_s {
void *acl;
char *name;
char *md5;
char file_id[FILE_ID_BUF_SIZE+1];
uid_t uid;
gid_t gid;
@ -115,4 +120,8 @@ csync_vio_file_stat_t *csync_vio_file_stat_new(void);
void csync_vio_file_stat_destroy(csync_vio_file_stat_t *fstat);
void csync_vio_file_stat_set_file_id( csync_vio_file_stat_t* dst, const char* src );
void csync_vio_set_file_id(char* dst, const char *src );
#endif /* _CSYNC_VIO_METHOD_H */