/* * directory functions */ static csync_vio_method_handle_t *owncloud_opendir(const char *uri) { int rc; struct listdir_context *fetchCtx = NULL; struct resource *reslist = NULL; char *curi = _cleanPath( uri ); DEBUG_WEBDAV("opendir method called on %s", uri ); dav_connect( uri ); fetchCtx = c_malloc( sizeof( struct listdir_context )); fetchCtx->list = reslist; fetchCtx->target = curi; fetchCtx->include_target = 0; fetchCtx->currResource = NULL; rc = fetch_resource_list( curi, NE_DEPTH_ONE, fetchCtx ); if( rc != NE_OK ) { set_errno_from_session(); return NULL; } else { fetchCtx->currResource = fetchCtx->list; DEBUG_WEBDAV("opendir returning handle %p", (void*) fetchCtx ); return fetchCtx; } /* no freeing of curi because its part of the fetchCtx and gets freed later */ }
static void fetch_a_context(void **state) { struct listdir_context *fetchCtx = NULL; char *curi = _cleanPath(_credentials.oc_server); int rc = 0; unsigned int i; (void) state; fetchCtx = c_malloc( sizeof( struct listdir_context )); fetchCtx->target = curi; fetchCtx->include_target = 1; rc = fetch_resource_list( curi, NE_DEPTH_ONE, fetchCtx ); assert_int_equal( rc, 0 ); printf("Results: %d\n", fetchCtx->result_count); fetchCtx->currResource = fetchCtx->list; for( i = 0; i < fetchCtx->result_count; i++ ) { assert_true( fetchCtx->currResource != NULL ); assert_true( fetchCtx->currResource->uri != NULL ); assert_true( fetchCtx->currResource->name != NULL ); printf( " %s -> %s\n", fetchCtx->currResource->uri, fetchCtx->currResource->name ); fetchCtx->currResource = fetchCtx->currResource->next; } }
static struct listdir_context *fetch_resource_list_attempts(const char *uri, int depth) { int i; struct listdir_context *fetchCtx = NULL; for(i = 0; i < 10; ++i) { fetchCtx = fetch_resource_list(uri, depth); if(fetchCtx) break; /* only loop in case the content is not XML formatted. Otherwise for every * non successful stat (for non existing directories) its tried 10 times. */ if( errno != ERRNO_WRONG_CONTENT ) break; DEBUG_WEBDAV("=> Errno after fetch resource list for %s: %d", uri, errno); DEBUG_WEBDAV(" New attempt %i", i); } return fetchCtx; }
/* * 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; }
static char *remote_completion(const char *text, int state) { static struct resource *reslist, *current; static int len; static time_t last_fetch; static char *last_path; char *name; if (state == 0) { /* Check to see if we should refresh the dumb cache. * or, initialize the local cache of remote filenames * The remote resource list persists until a completion * in a new context is requested or the cache expires. */ /* TODO get cache expire time from config, currently from cadaver.h * TODO cache and fetch on deep/absolute paths: (path: /a/b/, text: c/d) */ if (last_fetch < (time(NULL) - COMPLETION_CACHE_EXPIRE) || !last_path || strcmp(session.uri.path, last_path) != 0) { if (last_path != NULL) { free(last_path); } if (reslist != NULL) { free_resource_list(reslist); } /* Hide the connection status */ ne_set_notifier(session.sess, NULL, NULL); if (fetch_resource_list(session.sess, session.uri.path, 1, 0, &reslist) != NE_OK) { reslist = NULL; } /* Restore the session connection printing */ ne_set_notifier(session.sess, notifier, NULL); last_path = ne_strdup(session.uri.path); } current = reslist; len = strlen(text); time(&last_fetch); } while (current) { /* Massage the absolute URI to a URI relative to our path */ /* Copy & paste & search & replace from ls.c */ if (ne_path_has_trailing_slash(current->uri)) { current->uri[strlen(current->uri)-1] = '\0'; } name = strrchr(current->uri, '/'); if (name != NULL && strlen(name+1) > 0) { name++; } else { name = current->uri; } name = ne_path_unescape(name); if (strncmp(text, name, len) == 0) { current = current->next; /* FIXME: readline docs say readline will free() this when * it's finished with, although 'memprof' shows that it * leaks. */ return name; } current = current->next; } return NULL; }