ShingledFS 2.0
SMR-AwareFUSE-basedFileSystem

transparency.c

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 }