static int cfs_readlink(const char* path, char* buf, size_t size) { FILE *temp_file = tmpfile(); int ret = 0; if (!cloudfs_object_write_fp(path, temp_file)) { ret = -ENOENT; } if (!pread(fileno(temp_file), buf, size, 0)) { ret = -ENOENT; } fclose(temp_file); return ret; }
static int cfs_open(const char *path, struct fuse_file_info *info) { FILE *temp_file = tmpfile(); dir_entry *de = path_info(path); if (!(info->flags & O_WRONLY)) { if (!cloudfs_object_write_fp(path, temp_file)) { fclose(temp_file); return -ENOENT; } update_dir_cache(path, (de ? de->size : 0), 0); } openfile *of = (openfile *)malloc(sizeof(openfile)); of->fd = dup(fileno(temp_file)); fclose(temp_file); of->flags = info->flags; info->fh = (uintptr_t)of; info->direct_io = 1; return 0; }
static int cfs_readlink(const char* path, char* buf, size_t size) { debugf(DBG_LEVEL_NORM, KBLU"cfs_readlink(%s)", path); //fixme: use temp file specified in config FILE* temp_file = tmpfile(); int ret = 0; if (!cloudfs_object_write_fp(path, temp_file)) { debugf(DBG_LEVEL_NORM, KRED"exit 1: cfs_readlink(%s) not found", path); ret = -ENOENT; } if (!pread(fileno(temp_file), buf, size, 0)) { debugf(DBG_LEVEL_NORM, KRED"exit 2: cfs_readlink(%s) not found", path); ret = -ENOENT; } fclose(temp_file); debugf(DBG_LEVEL_NORM, KBLU"exit 3: cfs_readlink(%s)", path); return ret; }
static int cfs_open(const char *path, struct fuse_file_info *info) { FILE *temp_file; dir_entry *de = path_info(path); if (*temp_dir) { char tmp_path[PATH_MAX]; strncpy(tmp_path, path, PATH_MAX); char *pch; while((pch = strchr(tmp_path, '/'))) { *pch = '.'; } char file_path[PATH_MAX]; snprintf(file_path, PATH_MAX, "%s/.cloudfuse%ld-%s", temp_dir, (long)getpid(), tmp_path); if(access(file_path, F_OK) != -1) { // file exists temp_file = fopen(file_path, "r"); } else if (!(info->flags & O_WRONLY)) { // we need to lock on the filename another process could open the file // while we are writing to it and then only read part of the file // duplicate the directory caching datastructure to make the code easier // to understand. // each file in the cache needs: // filename, is_writing, last_closed, is_removing // the first time a file is opened a new entry is created in the cache // setting the filename and is_writing to true. This check needs to be // wrapped with a lock. // // each time a file is closed we set the last_closed for the file to now // and we check the cache for files whose last // closed is greater than cache_timeout, then start a new thread rming // that file. // TODO: just to prevent this craziness for now temp_file = fopen(file_path, "w+b"); if (!cloudfs_object_write_fp(path, temp_file)) { fclose(temp_file); return -ENOENT; } } } else { temp_file = tmpfile(); if (!(info->flags & O_WRONLY)) { if (!cloudfs_object_write_fp(path, temp_file)) { fclose(temp_file); return -ENOENT; } } } update_dir_cache(path, (de ? de->size : 0), 0, 0); openfile *of = (openfile *)malloc(sizeof(openfile)); of->fd = dup(fileno(temp_file)); if (of->fd == -1) return -ENOENT; fclose(temp_file); of->flags = info->flags; info->fh = (uintptr_t)of; info->direct_io = 1; return 0; }
// open (download) file from cloud // todo: implement etag optimisation, download only if content changed, http://www.17od.com/2012/12/19/ten-useful-openstack-swift-features/ static int cfs_open(const char* path, struct fuse_file_info* info) { debugf(DBG_LEVEL_NORM, KBLU "cfs_open(%s)", path); FILE* temp_file = NULL; int errsv; dir_entry* de = path_info(path); if (*temp_dir) { char file_path_safe[NAME_MAX]; get_safe_cache_file_path(path, file_path_safe, temp_dir); debugf(DBG_LEVEL_EXT, "cfs_open: try open (%s)", file_path_safe); if (access(file_path_safe, F_OK) != -1) { // file exists temp_file = fopen(file_path_safe, "r"); errsv = errno; if (temp_file == NULL) { debugf(DBG_LEVEL_NORM, KRED"exit 0: cfs_open can't open temp_file=[%s] err=%d:%s", file_path_safe, errsv, strerror(errsv)); return -ENOENT; } else debugf(DBG_LEVEL_EXT, "cfs_open: file exists"); } else { errsv = errno; debugf(DBG_LEVEL_EXT, "cfs_open: file not in cache, err=%s", strerror(errsv)); //FIXME: commented out as this condition will not be meet in some odd cases and program will crash //if (!(info->flags & O_WRONLY)) { debugf(DBG_LEVEL_EXT, "cfs_open: opening for write"); // we need to lock on the filename another process could open the file // while we are writing to it and then only read part of the file // duplicate the directory caching datastructure to make the code easier // to understand. // each file in the cache needs: // filename, is_writing, last_closed, is_removing // the first time a file is opened a new entry is created in the cache // setting the filename and is_writing to true. This check needs to be // wrapped with a lock. // // each time a file is closed we set the last_closed for the file to now // and we check the cache for files whose last // closed is greater than cache_timeout, then start a new thread rming // that file. // TODO: just to prevent this craziness for now temp_file = fopen(file_path_safe, "w+b"); errsv = errno; if (temp_file == NULL) { debugf(DBG_LEVEL_NORM, KRED"exit 1: cfs_open cannot open temp_file=[%s] err=%d:%s", file_path_safe, errsv, strerror(errsv)); return -ENOENT; } if (!cloudfs_object_write_fp(path, temp_file)) { fclose(temp_file); debugf(DBG_LEVEL_NORM, KRED "exit 2: cfs_open(%s) cannot download/write", path); return -ENOENT; } } } else { temp_file = tmpfile(); if (temp_file == NULL) { debugf(DBG_LEVEL_NORM, KRED"exit 3: cfs_open cannot create temp_file err=%s", strerror(errno)); return -ENOENT; } if (!(info->flags & O_TRUNC)) { if (!cloudfs_object_write_fp(path, temp_file) && !(info->flags & O_CREAT)) { fclose(temp_file); debugf(DBG_LEVEL_NORM, KRED"exit 4: cfs_open(%s) cannot download/write", path); return -ENOENT; } } } update_dir_cache(path, (de ? de->size : 0), 0, 0); openfile* of = (openfile*)malloc(sizeof(openfile)); of->fd = dup(fileno(temp_file)); if (of->fd == -1) { //FIXME: potential leak if free not used? free(of); debugf(DBG_LEVEL_NORM, KRED "exit 5: cfs_open(%s) of->fd", path); return -ENOENT; } fclose(temp_file); //TODO: why this allocation to of? of->flags = info->flags; info->fh = (uintptr_t)of; info->direct_io = 1; info->nonseekable = 0; //FIXME: potential leak if free(of) not used? although if free(of) is used will generate bad descriptor errors debugf(DBG_LEVEL_NORM, KBLU "exit 6: cfs_open(%s)", path); return 0; }