ait/os/bin/shadowfuse/main.cpp
author om
Tue, 12 Nov 2013 11:31:34 +0100
branchom
changeset 2 c9bf2537109a
permissions -rw-r--r--
added C/C++ and Python sources
     1 /*
     2  * main.cpp
     3  * 
     4  * This is the shadowfuse main startup file.
     5  *
     6  * Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
     7  *
     8  * Copyright (C) 2013 AIT Austrian Institute of Technology
     9  * AIT Austrian Institute of Technology GmbH
    10  * Donau-City-Strasse 1 | 1220 Vienna | Austria
    11  * http://www.ait.ac.at
    12  *
    13  * This program is free software; you can redistribute it and/or
    14  * modify it under the terms of the GNU General Public License
    15  * as published by the Free Software Foundation version 2.
    16  * 
    17  * This program is distributed in the hope that it will be useful,
    18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    20  * GNU General Public License for more details.
    21  * 
    22  * You should have received a copy of the GNU General Public License
    23  * along with this program; if not, write to the Free Software
    24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
    25  * Boston, MA  02110-1301, USA.
    26  */
    27 
    28  
    29 // ------------------------------------------------------------
    30 // incs
    31 
    32 #include "baseinc.h"
    33 
    34 
    35 // ------------------------------------------------------------
    36 // defs
    37 
    38 
    39 /**
    40  * shadowfuse version
    41  */
    42 #define SHADOWFUSE_VERSION  "0.1"
    43 
    44 
    45 // ------------------------------------------------------------
    46 // vars
    47 
    48 
    49 /**
    50  * keys for FUSE_OPT_ options 
    51  */
    52 enum {
    53    KEY_VERSION,
    54    KEY_HELP,
    55 };
    56 
    57 
    58 /**
    59  * array of options we know
    60  */
    61 static struct fuse_opt shadowfuse_opts[] = {
    62     FUSE_OPT_KEY("-V",             KEY_VERSION),
    63     FUSE_OPT_KEY("--version",      KEY_VERSION),
    64     FUSE_OPT_KEY("-h",             KEY_HELP),
    65     FUSE_OPT_KEY("--help",         KEY_HELP),
    66     FUSE_OPT_END
    67 };
    68 
    69 
    70 /**
    71  * configuration of shadowfuse
    72  */
    73 static struct shadowfuse_config {
    74 
    75     std::string sShadowedPath;
    76     std::string sMountPoint;
    77     
    78     /**
    79      * check for paths been set
    80      */
    81     inline bool is_paths_set() const { return !(sShadowedPath.empty() || sMountPoint.empty()); };
    82     
    83 } g_cShadowFuseConfig;
    84 
    85 
    86 // ------------------------------------------------------------
    87 // fwd
    88 
    89 static int option_processor(void * cData, const char * sArg, int nKey, struct fuse_args * cOutArgs);
    90 static void usage(const char * sProgName);
    91 
    92 
    93 // ------------------------------------------------------------
    94 // code
    95 
    96 
    97 
    98 /** 
    99  * get file attributes.
   100  */
   101 static int shadow_getattr(const char * sPath, struct stat * cFileStat) {
   102     
   103     // open the shadow file
   104     std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
   105 std::cerr << "=== INSERT HOOK HERE. Getting file attributes of " << sShadow << std::endl;
   106 
   107     memset(cFileStat, 0, sizeof(struct stat));
   108     if (stat(sShadow.c_str(), cFileStat) == -1) return -errno;
   109     
   110     return 0;
   111 }
   112 
   113 
   114 
   115 /** 
   116  * create a directory 
   117  */
   118 static int shadow_mkdir(const char * sPath, mode_t cMode) {
   119     
   120     // create directory
   121     std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
   122 std::cerr << "=== INSERT HOOK HERE. Create directory " << sShadow << std::endl;
   123 
   124     if (mkdir(sShadow.c_str(), cMode) == -1) return -errno;
   125     return 0;
   126 }
   127 
   128 
   129 /** 
   130  * create a file
   131  */
   132 static int shadow_mknod(const char * sPath, mode_t cMode, dev_t cDev) {
   133     
   134     // create file
   135     std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
   136 std::cerr << "=== INSERT HOOK HERE. Create file " << sShadow << std::endl;
   137 
   138     if (mknod(sShadow.c_str(), cMode, cDev) == -1) return -errno;
   139     return 0;
   140 }
   141 
   142 
   143 /**
   144  * open file
   145  */
   146 static int shadow_open(const char * sPath, struct fuse_file_info * cFileInfo) {
   147     
   148     // open the shadow file
   149     std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
   150 std::cerr << "=== INSERT HOOK HERE. Opening file " << sShadow << std::endl;
   151 
   152     if (open(sShadow.c_str(), cFileInfo->flags) == -1) return -errno;
   153     return 0;
   154 }
   155 
   156 
   157 /**
   158  * read from file
   159  */
   160 static int shadow_read(const char * sPath, char * cBuffer, size_t nSize, off_t nOffset, UNUSED struct fuse_file_info * cFileInfo) {
   161     
   162     // read from shadow file
   163     std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
   164 std::cerr << "=== INSERT HOOK HERE. Reading file " << sShadow << " [offset=" << nOffset << ", fetch max bytes=" << nSize << "]" << std::endl;
   165 
   166     // open, pick bytes, close & out
   167     int fd = open(sShadow.c_str(), O_RDONLY);
   168     if (fd == -1) return -errno;
   169     int res = pread(fd, cBuffer, nSize, nOffset);
   170     if (res == -1) res = -errno;
   171     close(fd);
   172     
   173     return res;
   174 }
   175 
   176 
   177 /**
   178  * read directory
   179  */
   180 static int shadow_readdir(const char * sPath, void * cBuffer, fuse_fill_dir_t fFiller, UNUSED off_t nOffset, UNUSED struct fuse_file_info * cFileInfo) {
   181 
   182     DIR * cDIR;
   183     struct dirent * cDirEntry;
   184     int res = 0;
   185 
   186     // open the shadow folder
   187     std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
   188 std::cerr << "=== INSERT HOOK HERE. Reading content of " << sShadow << std::endl;
   189     
   190     cDIR = opendir(sShadow.c_str());
   191     if (!cDIR) return -errno;
   192 
   193     // walk over the entries
   194     while ((cDirEntry = readdir(cDIR)) != NULL) {
   195         
   196         // pick file stat as well
   197         struct stat cFileStat;
   198         stat(sShadow.c_str(), &cFileStat);
   199         res = fFiller(cBuffer, cDirEntry->d_name, &cFileStat, 0);
   200          if (res != 0) break;
   201     }
   202 
   203     // free directory
   204     closedir(cDIR);
   205     return res;
   206 }
   207 
   208 
   209 /**
   210  * move file
   211  */
   212 static int shadow_rename(const char * sFromPath, const char * sToPath) {
   213     
   214     // move file
   215     std::string sShadowFrom = g_cShadowFuseConfig.sShadowedPath + sFromPath;
   216     std::string sShadowTo = g_cShadowFuseConfig.sShadowedPath + sToPath;
   217 std::cerr << "=== INSERT HOOK HERE. Moving file from " << sShadowFrom << " to " << sShadowTo << std::endl;
   218 
   219     if (rename(sShadowFrom.c_str(), sShadowTo.c_str()) == -1) return -errno;
   220     return 0;
   221 }
   222 
   223 
   224 /**
   225  * delete a folder
   226  */
   227 static int shadow_rmdir(const char * sPath) {
   228     
   229     // delete the shadow folder
   230     std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
   231 std::cerr << "=== INSERT HOOK HERE. Delete folder " << sShadow << std::endl;
   232 
   233     if (rmdir(sShadow.c_str()) == -1) return -errno;
   234     return 0;
   235 }
   236 
   237 
   238 /**
   239  * delete a file
   240  */
   241 static int shadow_unlink(const char * sPath) {
   242     
   243     // delete the shadow file
   244     std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
   245 std::cerr << "=== INSERT HOOK HERE. Delete file " << sShadow << std::endl;
   246 
   247     if (unlink(sShadow.c_str()) == -1) return -errno;
   248     return 0;
   249 }
   250 
   251 
   252 /**
   253  * write int file
   254  */
   255 static int shadow_write(const char * sPath, const char * cBuffer, size_t nSize, off_t nOffset, UNUSED struct fuse_file_info * cFileInfo) {
   256     
   257     // write into file
   258     std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
   259 std::cerr << "=== INSERT HOOK HERE. Write into file " << sShadow << std::endl;
   260 
   261     // open, push bytes, close & out
   262     int fd = open(sShadow.c_str(), O_WRONLY);
   263     if (fd == -1) return -errno;
   264     int res = pwrite(fd, cBuffer, nSize, nOffset);
   265     if (res == -1) res = -errno;
   266     close(fd);
   267     
   268     return res;
   269 }
   270 
   271 
   272 /**
   273  * the shadowfuse function table
   274  */
   275 static struct fuse_operations shadowfuse_operations {
   276     
   277     shadow_getattr,     // getattr
   278     nullptr,            // readlink
   279     nullptr,            // getdir
   280     shadow_mknod,       // mknod
   281     shadow_mkdir,       // mkdir
   282     shadow_unlink,      // unlink
   283     shadow_rmdir,       // rmdir
   284     nullptr,            // symlink
   285     shadow_rename,      // rename
   286     nullptr,            // link
   287     nullptr,            // chmod
   288     nullptr,            // chown
   289     nullptr,            // truncate
   290     nullptr,            // utime
   291     shadow_open,        // open
   292     shadow_read,        // read
   293     shadow_write,       // write
   294     nullptr,            // statfs
   295     nullptr,            // flush
   296     nullptr,            // release
   297     nullptr,            // fsync
   298     nullptr,            // setxattr
   299     nullptr,            // getxattr
   300     nullptr,            // listxattr
   301     nullptr,            // removexattr
   302     nullptr,            // opendir
   303     shadow_readdir,     // readdir
   304     nullptr,            // releasedir
   305     nullptr,            // fsyncdir
   306     nullptr,            // init
   307     nullptr,            // destroy
   308     nullptr,            // access
   309     nullptr,            // create
   310     nullptr,            // ftruncate
   311     nullptr,            // fgetattr
   312     nullptr,            // lock
   313     nullptr,            // utimens
   314     nullptr,            // bmap
   315     0,                  // flag_nullpath_ok
   316     0,                  // flag_nopath
   317     0,                  // flag_utime_omit_ok
   318     0,                  // flag_reserved
   319     nullptr,            // ioctl
   320     nullptr,            // poll
   321     nullptr,            // write_buf
   322     nullptr,            // read_buf
   323     nullptr,            // flock
   324     nullptr             // fallocate
   325 };
   326 
   327 
   328 /**
   329  * start
   330  * 
   331  * @param   argc        as usual
   332  * @param   argv        as usual
   333  * @return  as usual
   334  */
   335 int main(int argc, char ** argv) {
   336     
   337     // option parsing
   338     struct fuse_args cFUSEArgs = FUSE_ARGS_INIT(argc, argv);
   339     if (fuse_opt_parse(&cFUSEArgs, NULL, shadowfuse_opts, option_processor) == -1) {
   340         return -1;
   341     }
   342     
   343     // test if our config is setup ok
   344     if (!g_cShadowFuseConfig.is_paths_set()) {
   345         std::cerr << "sourcefolder and/or mount point not given" << std::endl;
   346         exit(1);
   347     }
   348 
   349     // do FUSE
   350     int ret = fuse_main(cFUSEArgs.argc, cFUSEArgs.argv, &shadowfuse_operations, NULL);
   351     if (ret) printf("\n");
   352     fuse_opt_free_args(&cFUSEArgs);
   353         
   354     return ret;
   355 }
   356 
   357 
   358 /**
   359  * option parser processor
   360  * 
   361  * @param   cData       is the user data passed to the fuse_opt_parse() function
   362  * @param   sArg        is the whole argument or option
   363  * @param   nKey        determines why the processing function was called
   364  * @param   cOutArgs    the current output argument list
   365  * @return  -1 on error, 0 if arg is to be discarded, 1 if arg should be kept
   366  */
   367 static int option_processor(UNUSED void * cData, UNUSED const char * sArg, int nKey, struct fuse_args * cOutArgs) {
   368 
   369     // select by key
   370     switch (nKey) {
   371         
   372     case FUSE_OPT_KEY_OPT:
   373         return 1;
   374 
   375     case FUSE_OPT_KEY_NONOPT:
   376         // the non-options
   377         if (g_cShadowFuseConfig.sShadowedPath.empty()) {
   378             // first non-option is the path to be shadowed
   379             g_cShadowFuseConfig.sShadowedPath = sArg;
   380             return 0;
   381         }
   382         else
   383         if (g_cShadowFuseConfig.sMountPoint.empty()) {
   384             // the mount point
   385             g_cShadowFuseConfig.sMountPoint = sArg;
   386             return 1;
   387         }
   388         return 1;
   389 
   390     case KEY_HELP:
   391         usage(cOutArgs->argv[0]);
   392         exit(1);
   393 
   394     case KEY_VERSION:
   395         printf("shadowfuse version %s\n", SHADOWFUSE_VERSION);
   396         exit(0);
   397 
   398     default:
   399         fprintf(stderr, "internal error\n");
   400         abort();
   401     }
   402 }
   403 
   404 
   405 /**
   406  * print usage
   407  * 
   408  * @param   sProgName       name of the current program
   409  */
   410 static void usage(const char * sProgName) {
   411     printf(
   412 "usage: %s sourcefolder mountpoint\n"
   413 "\n"
   414 "general options:\n"
   415 "    -f                     foreground\n"
   416 "    -d   -odebug           foreground, but keep the debug option\n"
   417 "    -h   --help            print help\n"
   418 "    -V   --version         print version\n"
   419 "\n", sProgName);
   420 }
   421