static int cfs_chmod(const char* path, mode_t mode) { debugf(DBG_LEVEL_NORM, KBLU"cfs_chmod(%s,%d)", path, mode); dir_entry* de = check_path_info(path); if (de) { if (de->chmod != mode) { debugf(DBG_LEVEL_NORM, "cfs_chmod(%s): change mode from %d to %d", path, de->chmod, mode); de->chmod = mode; //todo: issue a PUT request to update metadata (empty request just to update headers?) int response = cloudfs_update_meta(de); } } return 0; }
static int cfs_chown(const char* path, uid_t uid, gid_t gid) { debugf(DBG_LEVEL_NORM, KBLU "cfs_chown(%s,%d,%d)", path, uid, gid); dir_entry* de = check_path_info(path); if (de) { if (de->uid != uid || de->gid != gid) { debugf(DBG_LEVEL_NORM, "cfs_chown(%s): change from uid:gid %d:%d to %d:%d", path, de->uid, de->gid, uid, gid); de->uid = uid; de->gid = gid; //issue a PUT request to update metadata (quick request just to update headers) int response = cloudfs_update_meta(de); } } return 0; }
static int fixurl(char *gfarm_url) { char *gfarm_file, *local_path, *e; char sec[GFARM_INT32STRLEN]; struct stat sb; int rank; e = gfarm_url_make_path(gfarm_url, &gfarm_file); if (e != NULL) { fprintf(stderr, "%s on %s: %s\n", gfarm_url, gfarm_host_get_self_name(), e); return 1; } /* check whether gfarm_url is directory or not. */ e = gfarm_path_localize(gfarm_file, &local_path); if (e == NULL && stat(local_path, &sb) == 0 && S_ISDIR(sb.st_mode)) { int r = 1; if (chdir(local_path) == 0) r = fixdir(".", gfarm_url); free(gfarm_file); free(local_path); return (r); } if (e != NULL) { fprintf(stderr, "%s on %s: %s\n", gfarm_url, gfarm_host_get_self_name(), e); free(gfarm_file); return (1); } free(local_path); /* XXX - assume gfarm_url is a fragmented file. */ e = gfs_pio_get_node_rank(&rank); if (e != NULL) { fprintf(stderr, "%s on %s: %s\n", gfarm_url, gfarm_host_get_self_name(), e); goto error_gfarm_file; } e = gfarm_path_localize_file_fragment(gfarm_file, rank, &local_path); if (e != NULL) { fprintf(stderr, "%s on %s: %s\n", gfarm_url, gfarm_host_get_self_name(), e); goto error_gfarm_file; } e = check_path_info(gfarm_file); if (e != NULL) { fprintf(stderr, "%s on %s: %s\n", gfarm_url, gfarm_host_get_self_name(), e); if (delete_invalid_file) { if (unlink(local_path) == 0) printf("%s on %s: deleted\n", local_path, gfarm_host_get_self_name()); else perror(local_path); } goto error_local_path; } sprintf(sec, "%d", rank); e = fixfrag_i(local_path, gfarm_file, sec); if (e != NULL && e != GFARM_ERR_ALREADY_EXISTS) { fprintf(stderr, "%s (%s) on %s: %s\n", gfarm_url, sec, gfarm_host_get_self_name(), e); if (delete_invalid_file) { if (unlink(local_path) == 0) printf("%s on %s: deleted\n", local_path, gfarm_host_get_self_name()); else perror(local_path); } goto error_local_path; } /* printf("%s (%s): fixed\n", gfarm_url, sec); */ return (0); error_local_path: free(local_path); error_gfarm_file: free(gfarm_file); return (1); }
static int fixfrag(char *pathname, char *gfarm_prefix) { char *gfarm_url, *sec, *gfarm_file, *e; int r = 0; gfarm_url = malloc(strlen(gfarm_prefix) + strlen(pathname) + 2); if (gfarm_url == NULL) { fputs("not enough memory", stderr); return 1; } strcpy(gfarm_url, gfarm_prefix); if (gfarm_url[strlen(gfarm_url) - 1] != '/' && gfarm_url[strlen(gfarm_url) - 1] != ':') strcat(gfarm_url, "/"); strcat(gfarm_url, pathname); /* divide into file and section parts. */ sec = gfarm_url + strlen(gfarm_prefix); while (*sec) { if (*sec == ':') { *sec = '\0'; ++sec; break; } ++sec; } if (*sec == '\0') { fprintf(stderr, "%s on %s: invalid filename\n", pathname, gfarm_host_get_self_name()); free(gfarm_url); return 1; } e = gfarm_url_make_path(gfarm_url, &gfarm_file); if (e != NULL) { fprintf(stderr, "%s on %s: %s\n", gfarm_url, gfarm_host_get_self_name(), e); free(gfarm_url); return 1; } /* check whether the path info is already registered. */ e = check_path_info(gfarm_file); if (e != NULL) { fprintf(stderr, "%s (%s) on %s: %s\n", gfarm_url, sec, gfarm_host_get_self_name(), e); if (delete_invalid_file) { if (unlink(pathname) == 0) printf("%s on %s: deleted\n", pathname, gfarm_host_get_self_name()); else perror(pathname); } r = 1; goto finish; } /* check whether the fragment is already registered. */ e = fixfrag_i(pathname, gfarm_file, sec); if (e != NULL) { if (e != GFARM_ERR_ALREADY_EXISTS) { fprintf(stderr, "%s on %s: %s\n", pathname, gfarm_host_get_self_name(), e); if (delete_invalid_file) { if (unlink(pathname) == 0) printf("%s on %s: deleted\n", pathname, gfarm_host_get_self_name()); else perror(pathname); } r = 1; } else /* no message */; } else printf("%s (%s) on %s: fixed\n", gfarm_url, sec, gfarm_host_get_self_name()); finish: free(gfarm_file); free(gfarm_url); return (r); }
//todo: flush will upload a file again even if just file attributes are changed. //optimisation needed to detect if content is changed and to only save meta when just attribs are modified. static int cfs_flush(const char* path, struct fuse_file_info* info) { debugf(DBG_LEVEL_NORM, KBLU "cfs_flush(%s)", path); debug_print_descriptor(info); openfile* of = (openfile*)(uintptr_t)info->fh; int errsv = 0; if (of) { // get the actual file size and truncate it. This ensures that if the new file is smaller // than the previous one, the proper size is uploaded. struct stat stbuf; cfs_getattr(path, &stbuf); update_dir_cache(path, stbuf.st_size, 0, 0); ftruncate(of->fd, stbuf.st_size); if (of->flags & O_RDWR || of->flags & O_WRONLY) { FILE* fp = fdopen(dup(of->fd), "r"); errsv = errno; if (fp != NULL) { rewind(fp); //calculate md5 hash, compare with cloud hash to determine if file content is changed char md5_file_hash_str[MD5_DIGEST_HEXA_STRING_LEN] = "\0"; file_md5(fp, md5_file_hash_str); dir_entry* de = check_path_info(path); if (de && de->md5sum != NULL && (!strcasecmp(md5_file_hash_str, de->md5sum))) { //file content is identical, no need to upload entire file, just update metadata debugf(DBG_LEVEL_NORM, KBLU "cfs_flush(%s): skip full upload as content did not change", path); cloudfs_update_meta(de); } else { rewind(fp); debugf(DBG_LEVEL_NORM, KBLU "cfs_flush(%s): perform full upload as content changed (or no file found in cache)", path); if (!cloudfs_object_read_fp(path, fp)) { fclose(fp); errsv = errno; debugf(DBG_LEVEL_NORM, KRED"exit 0: cfs_flush(%s) result=%d:%s", path, errsv, strerror(errno)); return -ENOENT; } } fclose(fp); errsv = errno; } else debugf(DBG_LEVEL_EXT, KRED "status: cfs_flush, err=%d:%s", errsv, strerror(errno)); } } debugf(DBG_LEVEL_NORM, KBLU "exit 1: cfs_flush(%s) result=%d:%s", path, errsv, strerror(errno)); return 0; }
static int cfs_create(const char* path, mode_t mode, struct fuse_file_info* info) { debugf(DBG_LEVEL_NORM, KBLU "cfs_create(%s)", path); FILE* temp_file; int errsv; char file_path_safe[NAME_MAX] = ""; if (*temp_dir) { get_safe_cache_file_path(path, file_path_safe, temp_dir); temp_file = fopen(file_path_safe, "w+b"); errsv = errno; if (temp_file == NULL) { debugf(DBG_LEVEL_NORM, KRED "exit 0: cfs_create cannot open temp file %s.error %s\n", file_path_safe, strerror(errsv)); return -EIO; } } else { temp_file = tmpfile(); errsv = errno; if (temp_file == NULL) { debugf(DBG_LEVEL_NORM, KRED "exit 1: cfs_create cannot open tmp file for path %s.error %s\n", path, strerror(errsv)); return -EIO; } } openfile* of = (openfile*)malloc(sizeof(openfile)); of->fd = dup(fileno(temp_file)); fclose(temp_file); of->flags = info->flags; info->fh = (uintptr_t)of; update_dir_cache(path, 0, 0, 0); info->direct_io = 1; dir_entry* de = check_path_info(path); if (de) { debugf(DBG_LEVEL_EXT, KCYN"cfs_create(%s): found in cache", path); struct timespec now; clock_gettime(CLOCK_REALTIME, &now); debugf(DBG_LEVEL_EXT, KCYN"cfs_create(%s) set utimes as now", path); de->atime.tv_sec = now.tv_sec; de->atime.tv_nsec = now.tv_nsec; de->mtime.tv_sec = now.tv_sec; de->mtime.tv_nsec = now.tv_nsec; de->ctime.tv_sec = now.tv_sec; de->ctime.tv_nsec = now.tv_nsec; char time_str[TIME_CHARS] = ""; get_timespec_as_str(&(de->atime), time_str, sizeof(time_str)); debugf(DBG_LEVEL_EXT, KCYN"cfs_create: atime=[%s]", time_str); get_timespec_as_str(&(de->mtime), time_str, sizeof(time_str)); debugf(DBG_LEVEL_EXT, KCYN"cfs_create: mtime=[%s]", time_str); get_timespec_as_str(&(de->ctime), time_str, sizeof(time_str)); debugf(DBG_LEVEL_EXT, KCYN"cfs_create: ctime=[%s]", time_str); //set chmod & chown de->chmod = mode; de->uid = geteuid(); de->gid = getegid(); } else debugf(DBG_LEVEL_EXT, KBLU "cfs_create(%s) "KYEL"dir-entry not found", path); debugf(DBG_LEVEL_NORM, KBLU "exit 2: cfs_create(%s)=(%s) result=%d:%s", path, file_path_safe, errsv, strerror(errsv)); return 0; }