static csync_vio_file_stat_t *owncloud_readdir(csync_vio_method_handle_t *dhandle) { struct listdir_context *fetchCtx = dhandle; csync_vio_file_stat_t *lfs = NULL; if( fetchCtx == NULL) { /* DEBUG_WEBDAV("An empty dir or at end); */ return NULL; } if( fetchCtx->currResource ) { /* FIXME: Who frees the allocated mem for lfs, allocated in the helper func? */ lfs = resourceToFileStat( fetchCtx->currResource ); /* set pointer to next element */ fetchCtx->currResource = fetchCtx->currResource->next; /* fill the static stat buf as input for the stat function */ _fs.name = lfs->name; _fs.mtime = lfs->mtime; _fs.fields = lfs->fields; _fs.type = lfs->type; _fs.size = lfs->size; } // DEBUG_WEBDAV("LFS fields: %s: %d, lfs->name, lfs->type ); return lfs; }
static csync_vio_file_stat_t *owncloud_readdir(csync_vio_method_handle_t *dhandle) { struct listdir_context *fetchCtx = dhandle; if( fetchCtx == NULL) { /* DEBUG_WEBDAV("An empty dir or at end"); */ return NULL; } while( fetchCtx->currResource ) { resource* currResource = fetchCtx->currResource; char *escaped_path = NULL; /* set pointer to next element */ fetchCtx->currResource = fetchCtx->currResource->next; /* It seems strange: first uri->path is unescaped to escape it in the next step again. * The reason is that uri->path is not completely escaped (ie. it seems only to have * spaces escaped), while the fetchCtx->target is fully escaped. * See http://bugs.owncloud.org/thebuggenie/owncloud/issues/oc-613 */ escaped_path = ne_path_escape( currResource->uri ); if (ne_path_compare(fetchCtx->target, escaped_path) != 0) { csync_vio_file_stat_t* lfs = resourceToFileStat(currResource); fill_stat_cache(lfs); SAFE_FREE( escaped_path ); return lfs; } /* This is the target URI */ SAFE_FREE( escaped_path ); } return NULL; }
/* * file functions */ static int owncloud_stat(const char *uri, csync_vio_file_stat_t *buf) { /* get props: * modtime * creattime * size */ int rc = 0; csync_vio_file_stat_t *lfs = NULL; struct listdir_context *fetchCtx = NULL; char *curi = NULL; char *decodedUri = NULL; char strbuf[PATH_MAX +1]; int len = 0; DEBUG_WEBDAV("owncloud_stat %s called", uri ); buf->name = c_basename(uri); if (buf->name == NULL) { csync_vio_file_stat_destroy(buf); errno = ENOMEM; return -1; } /* check if the data in the static 'cache' fs is for the same file. * The cache is filled by readdir which is often called directly before * stat. If the cache matches, a http call is saved. */ if( _fs.name && strcmp( buf->name, _fs.name ) == 0 ) { buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE; buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; 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 = _fs.fields; buf->type = _fs.type; buf->mtime = _fs.mtime; buf->size = _fs.size; buf->mode = _stat_perms( _fs.type ); } else { /* fetch data via a propfind call. */ fetchCtx = c_malloc( sizeof( struct listdir_context )); if( ! fetchCtx ) { errno = ENOMEM; return -1; } curi = _cleanPath( uri ); DEBUG_WEBDAV("I have no stat cache, call propfind for %s.", curi ); fetchCtx->list = NULL; fetchCtx->target = curi; fetchCtx->include_target = 1; fetchCtx->currResource = NULL; rc = fetch_resource_list( curi, NE_DEPTH_ONE, fetchCtx ); if( rc != NE_OK ) { if( errno != ENOENT ) { set_errno_from_session(); } DEBUG_WEBDAV("stat fails with errno %d", errno ); return -1; } if( fetchCtx ) { struct resource *res = fetchCtx->list; while( res ) { /* remove trailing slashes */ len = strlen(res->uri); while( len > 0 && res->uri[len-1] == '/' ) --len; memset( strbuf, 0, PATH_MAX+1); strncpy( strbuf, res->uri, len < PATH_MAX ? len : PATH_MAX ); decodedUri = ne_path_unescape( curi ); /* allocates memory */ if( c_streq(strbuf, decodedUri )) { SAFE_FREE( decodedUri ); break; } res = res->next; SAFE_FREE( decodedUri ); } DEBUG_WEBDAV("Working on file %s", res ? res->name : "NULL"); lfs = resourceToFileStat( res ); if( lfs ) { buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE; buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; 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 = lfs->fields; buf->type = lfs->type; buf->mtime = lfs->mtime; buf->size = lfs->size; buf->mode = _stat_perms( lfs->type ); csync_vio_file_stat_destroy( lfs ); } SAFE_FREE( fetchCtx ); } } DEBUG_WEBDAV("STAT result: %s, type=%d", buf->name ? buf->name:"NULL", buf->type ); return 0; }
/* * file functions */ int owncloud_stat(const char *uri, csync_vio_file_stat_t *buf) { /* get props: * modtime * creattime * size */ csync_vio_file_stat_t *lfs = NULL; struct listdir_context *fetchCtx = NULL; char *decodedUri = NULL; int len = 0; errno = 0; DEBUG_WEBDAV("owncloud_stat %s called", uri ); buf->name = c_basename(uri); if (buf->name == NULL) { errno = ENOMEM; return -1; } if( _stat_cache.name && strcmp( buf->name, _stat_cache.name ) == 0 ) { buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE; buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; 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->etag = NULL; if( _stat_cache.etag ) { buf->etag = c_strdup( _stat_cache.etag ); buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG; } 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); /* fetch data via a propfind call. */ /* fetchCtx = fetch_resource_list( uri, NE_DEPTH_ONE); */ fetchCtx = fetch_resource_list_attempts( uri, NE_DEPTH_ONE); DEBUG_WEBDAV("=> Errno after fetch resource list for %s: %d", uri, errno); if (!fetchCtx) { return -1; } if( fetchCtx ) { struct resource *res = fetchCtx->list; while( res ) { /* remove trailing slashes */ len = strlen(res->uri); while( len > 0 && res->uri[len-1] == '/' ) --len; decodedUri = ne_path_unescape( fetchCtx->target ); /* allocates memory */ /* Only do the comparaison of the part of the string without the trailing slashes, and make sure decodedUri is not too large */ if( strncmp(res->uri, decodedUri, len ) == 0 && decodedUri[len] == '\0') { SAFE_FREE( decodedUri ); break; } res = res->next; SAFE_FREE( decodedUri ); } if( res ) { DEBUG_WEBDAV("Working on file %s", res->name ); } else { DEBUG_WEBDAV("ERROR: Result struct not valid!"); } lfs = resourceToFileStat( res ); if( lfs ) { buf->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE; buf->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; 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 |= CSYNC_VIO_FILE_STAT_FIELDS_ETAG; buf->fields = lfs->fields; buf->type = lfs->type; buf->mtime = lfs->mtime; buf->size = lfs->size; buf->mode = _stat_perms( lfs->type ); buf->etag = NULL; if( lfs->etag ) { buf->etag = c_strdup( lfs->etag ); } 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 ); } free_fetchCtx( fetchCtx ); } DEBUG_WEBDAV("STAT result from propfind: %s, mtime: %llu", buf->name ? buf->name:"NULL", (unsigned long long) buf->mtime ); return 0; }