ShingledFS 2.0
SMR-AwareFUSE-basedFileSystem
|
00001 00014 #define FUSE_USE_VERSION 26 00015 00016 #define _XOPEN_SOURCE 500 00017 00018 #include <fuse.h> 00019 #include <fcntl.h> 00020 #include <stdio.h> 00021 #include <errno.h> 00022 #include <dirent.h> 00023 #include <limits.h> 00024 #include <string.h> 00025 #include <stdlib.h> 00026 #include <unistd.h> 00027 #include <sys/xattr.h> 00028 #include <sys/types.h> 00029 00030 00031 00032 FILE *file_log; 00033 #ifdef GENERATE_LOGS 00034 #define log(...) \ 00035 do { \ 00036 fprintf(file_log, "%20s: ", __FUNCTION__); \ 00037 fprintf(file_log, __VA_ARGS__); \ 00038 } while(0) 00039 #else 00040 #define log(...) 00041 #endif 00042 00043 00044 char base[PATH_MAX]; 00045 00046 00051 void 00052 fullpath (const char *path, char *buf) 00053 { 00054 char *basedir = (char *) fuse_get_context ()->private_data; 00055 00056 strcpy (buf, basedir); 00057 strcat (buf, path); 00058 } 00059 00060 00061 /* The following functions describe FUSE operations. Each operation appends 00062 the path of the root filesystem to the given path in order to give the 00063 mirrored path. All quota checking takes place in fuse_write. */ 00064 00065 int 00066 fuse_getattr (const char *path, struct stat *buf) 00067 { 00068 char fpath[PATH_MAX]; 00069 int retval; 00070 fullpath (path, fpath); 00071 00072 log("path=%s\n", path); 00073 retval = lstat (fpath, buf) ? -errno : 0; 00074 log("\tReturning %d\n", retval); 00075 return retval; 00076 } 00077 00078 int 00079 fuse_readlink (const char *path, char *target, size_t size) 00080 { 00081 char fpath[PATH_MAX]; 00082 int retval; 00083 fullpath (path, fpath); 00084 00085 log("path=%s, target=%s, size=%ld\n", path, target, size); 00086 retval = readlink (fpath, target, size); 00087 if (retval > 0) { 00088 if (retval == size) 00089 retval--; 00090 target[retval] = '\0'; 00091 retval = 0; 00092 } 00093 log("\tReturning %d\n", retval); 00094 return retval; 00095 } 00096 00097 int 00098 fuse_mknod (const char *path, mode_t mode, dev_t dev) 00099 { 00100 char fpath[PATH_MAX]; 00101 int retval; 00102 fullpath (path, fpath); 00103 00104 log("path=%s, mode=0%o, dev=%ld\n", path, mode, dev); 00105 retval = mknod (fpath, mode | S_IRUSR | S_IWUSR, dev) ? -errno : 0; 00106 log("\tReturning %d\n", retval); 00107 return retval; 00108 } 00109 00110 int 00111 fuse_mkdir (const char *path, mode_t mode) 00112 { 00113 char fpath[PATH_MAX]; 00114 int retval; 00115 fullpath (path, fpath); 00116 00117 log("path=%s, mode=0%o\n", path, mode); 00118 retval = mkdir (fpath, mode | S_IFDIR) ? -errno : 0; 00119 log("\tReturning %d\n", retval); 00120 return retval; 00121 } 00122 00123 int 00124 fuse_unlink (const char *path) 00125 { 00126 char fpath[PATH_MAX]; 00127 int retval; 00128 fullpath (path, fpath); 00129 00130 log("path=%s\n", path); 00131 retval = unlink (fpath) ? -errno : 0; 00132 log("\tReturning %d\n", retval); 00133 return retval; 00134 } 00135 00136 int 00137 fuse_rmdir (const char *path) 00138 { 00139 char fpath[PATH_MAX]; 00140 int retval; 00141 fullpath (path, fpath); 00142 00143 log("path=%s\n", path); 00144 retval = rmdir (fpath) ? -errno : 0; 00145 log("\tReturning %d\n", retval); 00146 return retval; 00147 } 00148 00149 int 00150 fuse_symlink (const char *path, const char *link) 00151 { 00152 char flink[PATH_MAX]; 00153 int retval; 00154 fullpath (link, flink); 00155 00156 log("path=%s, link=%s\n", path, link); 00157 log("path=%s, flink=%s\n", path, flink); 00158 retval = symlink (path, flink) ? -errno : 0; 00159 log("\tReturning %d\n", retval); 00160 return retval; 00161 } 00162 00163 int 00164 fuse_rename (const char *src, const char *dst) 00165 { 00166 char fsrc[PATH_MAX]; 00167 char fdst[PATH_MAX]; 00168 int retval; 00169 fullpath (src, fsrc); 00170 fullpath (dst, fdst); 00171 00172 log("src=%s, dst=%s\n", src, dst); 00173 retval = rename (fsrc, fdst) ? -errno : 0; 00174 log("\tReturning %d\n", retval); 00175 return retval; 00176 } 00177 00178 int 00179 fuse_link (const char *src, const char *dst) 00180 { 00181 char fsrc[PATH_MAX]; 00182 char fdst[PATH_MAX]; 00183 int retval; 00184 fullpath (src, fsrc); 00185 fullpath (dst, fdst); 00186 00187 log("src=%s, dst=%s\n", src, dst); 00188 retval = link (fsrc, fdst) ? -errno : 0; 00189 log("\tReturning %d\n", retval); 00190 return retval; 00191 } 00192 00193 int 00194 fuse_chmod (const char *path, mode_t mode) 00195 { 00196 char fpath[PATH_MAX]; 00197 int retval; 00198 fullpath (path, fpath); 00199 00200 log("path=%s, mode=0%o\n", path, mode); 00201 retval = chmod (fpath, mode) ? -errno : 0; 00202 log("\tReturning %d\n", retval); 00203 return retval; 00204 } 00205 00206 int 00207 fuse_chown (const char *path, uid_t uid, gid_t gid) 00208 { 00209 char fpath[PATH_MAX]; 00210 int retval; 00211 fullpath (path, fpath); 00212 00213 log("path=%s, uid=%d, gid=%d\n", path, uid, gid); 00214 retval = chown (fpath, uid, gid) ? -errno : 0; 00215 log("\tReturning %d\n", retval); 00216 return retval; 00217 } 00218 00219 int 00220 fuse_truncate (const char *path, off_t off) 00221 { 00222 char fpath[PATH_MAX]; 00223 int retval; 00224 fullpath (path, fpath); 00225 00226 log("path=%s, off=%ld\n", path, off); 00227 retval = truncate (fpath, off) ? -errno : 0; 00228 log("\tReturning %d\n", retval); 00229 return retval; 00230 } 00231 00232 int 00233 fuse_utime (const char *path, struct utimbuf *buf) 00234 { 00235 char fpath[PATH_MAX]; 00236 int retval; 00237 fullpath (path, fpath); 00238 00239 log("path=%s\n", path); 00240 retval = utime (fpath, buf) ? -errno : 0; 00241 log("\tReturning %d\n", retval); 00242 return retval; 00243 } 00244 00245 int 00246 fuse_open (const char *path, struct fuse_file_info *fi) 00247 { 00248 char fpath[PATH_MAX]; 00249 int retval; 00250 fullpath (path, fpath); 00251 00252 log("path=%s, flags=0%o\n", path, fi->flags); 00253 int fh = open (fpath, fi->flags); 00254 if (fh < 0) 00255 retval = -errno; 00256 else { 00257 fi->fh = fh; 00258 retval = 0; 00259 } 00260 00261 log("\tReturning %d\n", retval); 00262 return retval; 00263 } 00264 00265 int 00266 fuse_read (const char *path, char *buf, size_t size, off_t off, 00267 struct fuse_file_info *fi) 00268 { 00269 int retval; 00270 00271 log("path=%s\n", path); 00272 retval = pread (fi->fh, buf, size, off) < 0 ? -errno : size; 00273 log("\tReturning %d\n", retval); 00274 return retval; 00275 } 00276 00277 int 00278 fuse_write (const char *path, const char *buf, size_t size, off_t off, 00279 struct fuse_file_info *fi) 00280 { 00281 int retval; 00282 00283 log("path=%s\n", path); 00284 retval = pwrite (fi->fh, buf, size, off) < 0 ? -errno : size; 00285 log("\tReturning %d\n", retval); 00286 return retval; 00287 } 00288 00289 int 00290 fuse_statfs (const char *path, struct statvfs *buf) 00291 { 00292 char fpath[PATH_MAX]; 00293 int retval; 00294 fullpath (path, fpath); 00295 00296 log("path=%s\n", path); 00297 retval = statvfs (fpath, buf) ? -errno : 0; 00298 log("\tReturning %d\n", retval); 00299 return retval; 00300 } 00301 00302 int 00303 fuse_release (const char *path, struct fuse_file_info *fi) 00304 { 00305 int retval; 00306 00307 log("path=%s\n", path); 00308 retval = close (fi->fh) ? -errno : 0; 00309 log("\tReturning %d\n", retval); 00310 return retval; 00311 } 00312 00313 int 00314 fuse_fsync (const char *path, int datasync, struct fuse_file_info *fi) 00315 { 00316 int retval; 00317 00318 log("path=%s\n", path); 00319 if (datasync) 00320 retval = fdatasync (fi->fh) ? -errno : 0; 00321 else 00322 retval = fsync (fi->fh) ? -errno : 0; 00323 00324 log("\tReturning %d\n", retval); 00325 return retval; 00326 } 00327 00328 int 00329 fuse_setxattr (const char *path, const char *name, const char *value, 00330 size_t size, int flags) 00331 { 00332 char fpath[PATH_MAX]; 00333 int retval; 00334 fullpath (path, fpath); 00335 00336 log("path=%s\n", path); 00337 retval = lsetxattr (fpath, name, value, size, flags) ? -errno : 0; 00338 log("\tReturning %d\n", retval); 00339 return retval; 00340 } 00341 00342 int 00343 fuse_getxattr (const char *path, const char *name, char *value, size_t size) 00344 { 00345 char fpath[PATH_MAX]; 00346 int retval; 00347 fullpath (path, fpath); 00348 00349 log("path=%s\n", path); 00350 ssize_t s = lgetxattr (fpath, name, value, size); 00351 retval = s < 0 ? -errno : s; 00352 log("\tReturning %d\n", retval); 00353 return retval; 00354 } 00355 00356 int 00357 fuse_listxattr (const char *path, char *list, size_t size) 00358 { 00359 char fpath[PATH_MAX]; 00360 int retval; 00361 fullpath (path, fpath); 00362 00363 log("path=%s\n", path); 00364 retval = llistxattr (fpath, list, size) < 0 ? -errno : 0; 00365 log("\tReturning %d\n", retval); 00366 return retval; 00367 } 00368 00369 int 00370 fuse_removexattr (const char *path, const char *name) 00371 { 00372 char fpath[PATH_MAX]; 00373 int retval; 00374 fullpath (path, fpath); 00375 00376 log("path=%s\n", path); 00377 retval = lremovexattr (fpath, name) ? -errno : 0; 00378 log("\tReturning %d\n", retval); 00379 return retval; 00380 } 00381 00382 int 00383 fuse_opendir (const char *path, struct fuse_file_info *fi) 00384 { 00385 char fpath[PATH_MAX]; 00386 int retval; 00387 fullpath (path, fpath); 00388 00389 log("path=%s\n", path); 00390 DIR *dir = opendir (fpath); 00391 if (dir == NULL) 00392 retval = -errno; 00393 else { 00394 fi->fh = (uint64_t) dir; 00395 retval = 0; 00396 } 00397 00398 log("\tReturning %d\n", retval); 00399 return retval; 00400 } 00401 00402 int 00403 fuse_readdir (const char *path, void *buf, fuse_fill_dir_t fill, off_t off, 00404 struct fuse_file_info *fi) 00405 { 00406 struct dirent *de = NULL; 00407 00408 log("path=%s\n", path); 00409 while ((de = readdir ((DIR *) fi->fh)) != NULL) 00410 { 00411 struct stat st; 00412 memset (&st, 0, sizeof (struct stat)); 00413 st.st_ino = de->d_ino; 00414 st.st_mode = de->d_type << 12; 00415 00416 if (fill (buf, de->d_name, &st, 0)) 00417 break; 00418 } 00419 00420 log("\tReturning 0\n"); 00421 return 0; 00422 } 00423 00424 int 00425 fuse_releasedir (const char *path, struct fuse_file_info *fi) 00426 { 00427 int retval; 00428 00429 log("path=%s\n", path); 00430 retval = closedir ((DIR *) fi->fh) ? -errno : 0; 00431 log("\tReturning %d\n", retval); 00432 return retval; 00433 } 00434 00435 int 00436 fuse_access (const char *path, int mode) 00437 { 00438 char fpath[PATH_MAX]; 00439 int retval; 00440 fullpath (path, fpath); 00441 00442 log("path=%s\n", path); 00443 retval = access (fpath, mode) ? -errno : 0; 00444 log("\tReturning %d\n", retval); 00445 return retval; 00446 } 00447 00448 void * 00449 fuse_init (struct fuse_conn_info *conn) 00450 { 00451 #ifdef GENERATE_LOGS 00452 file_log = fopen("/tmp/transparency.log", "w+"); 00453 #endif 00454 return (fuse_get_context())->private_data; 00455 } 00456 00457 void 00458 fuse_dest(void *conn) 00459 { 00460 #ifdef GENERATE_LOGS 00461 fclose(file_log); 00462 #endif 00463 } 00464 00465 00466 00467 struct fuse_operations fuse_ops = { 00468 .getattr = fuse_getattr, 00469 .readlink = fuse_readlink, 00470 .mknod = fuse_mknod, 00471 .mkdir = fuse_mkdir, 00472 .unlink = fuse_unlink, 00473 .rmdir = fuse_rmdir, 00474 .symlink = fuse_symlink, 00475 .rename = fuse_rename, 00476 .link = fuse_link, 00477 .chmod = fuse_chmod, 00478 .chown = fuse_chown, 00479 .truncate = fuse_truncate, 00480 .utime = fuse_utime, 00481 .open = fuse_open, 00482 .read = fuse_read, 00483 .write = fuse_write, 00484 .statfs = fuse_statfs, 00485 .release = fuse_release, 00486 .fsync = fuse_fsync, 00487 .setxattr = fuse_setxattr, 00488 .getxattr = fuse_getxattr, 00489 .listxattr = fuse_listxattr, 00490 .removexattr = fuse_removexattr, 00491 .opendir = fuse_opendir, 00492 .readdir = fuse_readdir, 00493 .releasedir = fuse_releasedir, 00494 .access = fuse_access, 00495 .init = fuse_init, 00496 .destroy = fuse_dest 00497 }; 00498 00499 00500 00501 void 00502 usage () 00503 { 00504 printf ("transparency <basedir> <mountpoint>\n"); 00505 exit (0); 00506 } 00507 00508 00509 00510 int 00511 main (int argc, char *argv[]) 00512 { 00513 if (argc < 3) 00514 usage (); 00515 00516 if (realpath(argv[1], base) == NULL) 00517 printf("The base directory path %s is invalid!\n", argv[1]); 00518 00519 int i = 1; 00520 for (; i < argc; i++) 00521 argv[i] = argv[i + 1]; 00522 argc -= 1; 00523 00524 umask(0); 00525 int ret = fuse_main (argc, argv, &fuse_ops, base); 00526 00527 if (ret < 0) 00528 printf("Error in FUSE main()\n"); 00529 00530 return ret; 00531 }