static int cfs_flush(const char *path, struct fuse_file_info *info) { openfile *of = (openfile *)(uintptr_t)info->fh; if (of) { update_dir_cache(path, cloudfs_file_size(of->fd), 0, 0); if (of->flags & O_RDWR || of->flags & O_WRONLY) { FILE *fp = fdopen(dup(of->fd), "r"); rewind(fp); if (!cloudfs_object_read_fp(path, fp)) { fclose(fp); return -ENOENT; } fclose(fp); } } return 0; }
//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; }