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