int stat_cache_delete_parent(stat_cache_t *cache, const char *path) { char *p; log_print(LOG_DEBUG, "stat_cache_delete_parent: %s", path); if ((p = ne_path_parent(path))) { int l = strlen(p); if (strcmp(p, "/") && l) { if (p[l-1] == '/') p[l-1] = 0; } stat_cache_delete(cache, p); stat_cache_updated_children(cache, p, time(NULL) - CACHE_TIMEOUT - 1); free(p); } else { stat_cache_delete(cache, path); stat_cache_updated_children(cache, path, time(NULL) - CACHE_TIMEOUT - 1); } return 0; }
void ne_lock_using_parent(ne_request *req, const char *path) { NE_DEBUG_WINSCP_CONTEXT(ne_get_session(req)); struct lh_req_cookie *lrc = ne_get_request_private(req, HOOK_ID); ne_uri u = {0}; struct lock_list *item; char *parent; if (lrc == NULL) return; parent = ne_path_parent(path); if (parent == NULL) return; ne_fill_server_uri(ne_get_session(req), &u); for (item = lrc->store->locks; item != NULL; item = item->next) { /* Only care about locks which are on this server. */ u.path = item->lock->uri.path; if (ne_uri_cmp(&u, &item->lock->uri)) continue; /* This lock is needed if it is an infinite depth lock which * covers the parent, or a lock on the parent itself. */ if ((item->lock->depth == NE_DEPTH_INFINITE && ne_path_childof(item->lock->uri.path, parent)) || ne_path_compare(item->lock->uri.path, parent) == 0) { NE_DEBUG(NE_DBG_LOCKS, "Locked parent, %s on %s\n", item->lock->token, item->lock->uri.path); submit_lock(lrc, item->lock); } } u.path = parent; /* handy: makes u.path valid and ne_free(parent). */ ne_uri_free(&u); }
static void propfind_results_recursive(void *userdata, const ne_uri *uri, const ne_prop_result_set *set) { struct resource *newres = 0; const char *clength, *modtime, *file_id = NULL; const char *resourcetype = NULL; const char *md5sum = NULL; const ne_status *status = NULL; char *path = ne_path_unescape( uri->path ); char *parentPath; char *propfindRootUri = (char*) userdata; propfind_recursive_element_t *element = NULL; propfind_recursive_element_t *pElement = NULL; int depth = 0; (void) status; (void) propfindRootUri; if (!propfind_recursive_cache) { c_rbtree_create(&propfind_recursive_cache, _key_cmp, _data_cmp); } /* Fill the resource structure with the data about the file */ newres = c_malloc(sizeof(struct resource)); ZERO_STRUCTP(newres); newres->uri = path; /* no need to strdup because ne_path_unescape already allocates */ newres->name = c_basename( path ); modtime = ne_propset_value( set, &ls_props[0] ); 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) { newres->type = resr_collection; propfind_recursive_cache_folder_count++; } else { /* DEBUG_WEBDAV("propfind_results_recursive %s [%d]", newres->uri, newres->type); */ propfind_recursive_cache_file_count++; } if (modtime) { newres->modtime = oc_httpdate_parse(modtime); } /* DEBUG_WEBDAV("Parsing Modtime: %s -> %llu", modtime, (unsigned long long) newres->modtime ); */ newres->size = 0; if (clength) { newres->size = atoll(clength); /* DEBUG_WEBDAV("Parsed File size for %s from %s: %lld", newres->name, clength, (long long)newres->size ); */ } if( md5sum ) { newres->md5 = csync_normalize_etag(md5sum); } 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); */ /* Create new item in rb tree */ if (newres->type == resr_collection) { DEBUG_WEBDAV("propfind_results_recursive %s is a folder", newres->uri); /* Check if in rb tree */ element = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache,uri->path)); /* If not, create a new item and insert it */ if (!element) { element = c_malloc(sizeof(propfind_recursive_element_t)); element->self = resource_dup(newres); element->children = NULL; element->parent = NULL; c_rbtree_insert(propfind_recursive_cache, element); /* DEBUG_WEBDAV("results_recursive Added collection %s", newres->uri); */ } } /* Check for parent in tree. If exists: Insert it into the children elements there */ parentPath = ne_path_parent(uri->path); if (parentPath) { propfind_recursive_element_t *parentElement = NULL; parentElement = c_rbtree_node_data(c_rbtree_find(propfind_recursive_cache,parentPath)); free(parentPath); if (parentElement) { newres->next = parentElement->children; parentElement->children = newres; /* If the current result is a collection we also need to set its parent */ if (element) element->parent = parentElement; pElement = element; while (pElement) { depth++; pElement = pElement->parent; } if (depth > propfind_recursive_cache_depth) { DEBUG_WEBDAV("propfind_results_recursive %s new maximum tree depth %d", newres->uri, depth); propfind_recursive_cache_depth = depth; } /* DEBUG_WEBDAV("results_recursive Added child %s to collection %s", newres->uri, element->self->uri); */ } else { /* DEBUG_WEBDAV("results_recursive No parent %s found for child %s", parentPath, newres->uri); */ resource_free(newres); newres = NULL; } } }
static void propfind_results_recursive_callback(void *userdata, const ne_uri *uri, const ne_prop_result_set *set) { struct resource *newres = 0; const ne_status *status = NULL; char *path = ne_path_unescape( uri->path ); char *parentPath; propfind_recursive_element_t *element = NULL; propfind_recursive_element_t *pElement = NULL; int depth = 0; csync_owncloud_ctx_t *ctx = (csync_owncloud_ctx_t*) userdata; (void) status; if (!ctx->propfind_recursive_cache) { c_rbtree_create(&ctx->propfind_recursive_cache, _key_cmp, _data_cmp); } /* Fill the resource structure with the data about the file */ newres = c_malloc(sizeof(struct resource)); newres->uri = path; /* no need to strdup because ne_path_unescape already allocates */ newres->name = c_basename( path ); fill_webdav_properties_into_resource(newres, set); if( newres->type == resr_collection) { ctx->propfind_recursive_cache_folder_count++; } else { ctx->propfind_recursive_cache_file_count++; } /* Create new item in rb tree */ if (newres->type == resr_collection) { DEBUG_WEBDAV("propfind_results_recursive %s is a folder", newres->uri); /* Check if in rb tree */ element = c_rbtree_node_data(c_rbtree_find(ctx->propfind_recursive_cache,uri->path)); /* If not, create a new item and insert it */ if (!element) { element = c_malloc(sizeof(propfind_recursive_element_t)); element->self = resource_dup(newres); element->self->next = 0; element->children = NULL; element->parent = NULL; c_rbtree_insert(ctx->propfind_recursive_cache, element); /* DEBUG_WEBDAV("results_recursive Added collection %s", newres->uri); */ } } /* Check for parent in tree. If exists: Insert it into the children elements there */ parentPath = ne_path_parent(uri->path); if (parentPath) { propfind_recursive_element_t *parentElement = NULL; parentElement = c_rbtree_node_data(c_rbtree_find(ctx->propfind_recursive_cache,parentPath)); free(parentPath); if (parentElement) { newres->next = parentElement->children; parentElement->children = newres; /* If the current result is a collection we also need to set its parent */ if (element) element->parent = parentElement; pElement = element; while (pElement) { depth++; pElement = pElement->parent; } if (depth > ctx->propfind_recursive_cache_depth) { DEBUG_WEBDAV("propfind_results_recursive %s new maximum tree depth %d", newres->uri, depth); ctx->propfind_recursive_cache_depth = depth; } /* DEBUG_WEBDAV("results_recursive Added child %s to collection %s", newres->uri, element->self->uri); */ return; } } resource_free(newres); newres = NULL; }
struct stat_cache_value *stat_cache_value_get(stat_cache_t *cache, const char *path, bool skip_freshness_check) { struct stat_cache_value *value = NULL; char *key; leveldb_readoptions_t *options; size_t vallen; char *errptr = NULL; //void *f; time_t current_time; key = path2key(path, false); log_print(LOG_DEBUG, "CGET: %s", key); options = leveldb_readoptions_create(); value = (struct stat_cache_value *) leveldb_get(cache, options, key, strlen(key) + 1, &vallen, &errptr); leveldb_readoptions_destroy(options); free(key); //log_print(LOG_DEBUG, "Mode: %04o", value->st.st_mode); if (errptr != NULL) { log_print(LOG_ERR, "leveldb_get error: %s", errptr); free(errptr); return NULL; } if (value == NULL) { log_print(LOG_DEBUG, "stat_cache_value_get miss on path: %s", path); return NULL; } if (vallen != sizeof(struct stat_cache_value)) { log_print(LOG_ERR, "Length %lu is not expected length %lu.", vallen, sizeof(struct stat_cache_value)); } if (!skip_freshness_check) { current_time = time(NULL); // First, check against the stat item itself. //log_print(LOG_DEBUG, "Current time: %lu", current_time); if (current_time - value->updated > CACHE_TIMEOUT) { char *directory; time_t directory_updated; int is_dir; log_print(LOG_DEBUG, "Stat entry %s is %lu seconds old.", path, current_time - value->updated); // If that's too old, check the last update of the directory. directory = strip_trailing_slash(ne_path_parent(path), &is_dir); directory_updated = stat_cache_read_updated_children(cache, directory); //log_print(LOG_DEBUG, "Directory contents for %s are %lu seconds old.", directory, (current_time - directory_updated)); free(directory); if (current_time - directory_updated > CACHE_TIMEOUT) { log_print(LOG_DEBUG, "%s is too old.", path); free(value); return NULL; } } } /* if ((f = file_cache_get(path))) { value->st.st_size = file_cache_get_size(f); file_cache_unref(cache, f); } */ //print_stat(&value->st, "CGET"); return value; }