diff -r 000000000000 -r c9bf2537109a ait/os/bin/shadowfuse/main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ait/os/bin/shadowfuse/main.cpp Tue Nov 12 11:31:34 2013 +0100 @@ -0,0 +1,421 @@ +/* + * main.cpp + * + * This is the shadowfuse main startup file. + * + * Autor: Oliver Maurhart, + * + * Copyright (C) 2013 AIT Austrian Institute of Technology + * AIT Austrian Institute of Technology GmbH + * Donau-City-Strasse 1 | 1220 Vienna | Austria + * http://www.ait.ac.at + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + + +// ------------------------------------------------------------ +// incs + +#include "baseinc.h" + + +// ------------------------------------------------------------ +// defs + + +/** + * shadowfuse version + */ +#define SHADOWFUSE_VERSION "0.1" + + +// ------------------------------------------------------------ +// vars + + +/** + * keys for FUSE_OPT_ options + */ +enum { + KEY_VERSION, + KEY_HELP, +}; + + +/** + * array of options we know + */ +static struct fuse_opt shadowfuse_opts[] = { + FUSE_OPT_KEY("-V", KEY_VERSION), + FUSE_OPT_KEY("--version", KEY_VERSION), + FUSE_OPT_KEY("-h", KEY_HELP), + FUSE_OPT_KEY("--help", KEY_HELP), + FUSE_OPT_END +}; + + +/** + * configuration of shadowfuse + */ +static struct shadowfuse_config { + + std::string sShadowedPath; + std::string sMountPoint; + + /** + * check for paths been set + */ + inline bool is_paths_set() const { return !(sShadowedPath.empty() || sMountPoint.empty()); }; + +} g_cShadowFuseConfig; + + +// ------------------------------------------------------------ +// fwd + +static int option_processor(void * cData, const char * sArg, int nKey, struct fuse_args * cOutArgs); +static void usage(const char * sProgName); + + +// ------------------------------------------------------------ +// code + + + +/** + * get file attributes. + */ +static int shadow_getattr(const char * sPath, struct stat * cFileStat) { + + // open the shadow file + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath; +std::cerr << "=== INSERT HOOK HERE. Getting file attributes of " << sShadow << std::endl; + + memset(cFileStat, 0, sizeof(struct stat)); + if (stat(sShadow.c_str(), cFileStat) == -1) return -errno; + + return 0; +} + + + +/** + * create a directory + */ +static int shadow_mkdir(const char * sPath, mode_t cMode) { + + // create directory + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath; +std::cerr << "=== INSERT HOOK HERE. Create directory " << sShadow << std::endl; + + if (mkdir(sShadow.c_str(), cMode) == -1) return -errno; + return 0; +} + + +/** + * create a file + */ +static int shadow_mknod(const char * sPath, mode_t cMode, dev_t cDev) { + + // create file + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath; +std::cerr << "=== INSERT HOOK HERE. Create file " << sShadow << std::endl; + + if (mknod(sShadow.c_str(), cMode, cDev) == -1) return -errno; + return 0; +} + + +/** + * open file + */ +static int shadow_open(const char * sPath, struct fuse_file_info * cFileInfo) { + + // open the shadow file + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath; +std::cerr << "=== INSERT HOOK HERE. Opening file " << sShadow << std::endl; + + if (open(sShadow.c_str(), cFileInfo->flags) == -1) return -errno; + return 0; +} + + +/** + * read from file + */ +static int shadow_read(const char * sPath, char * cBuffer, size_t nSize, off_t nOffset, UNUSED struct fuse_file_info * cFileInfo) { + + // read from shadow file + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath; +std::cerr << "=== INSERT HOOK HERE. Reading file " << sShadow << " [offset=" << nOffset << ", fetch max bytes=" << nSize << "]" << std::endl; + + // open, pick bytes, close & out + int fd = open(sShadow.c_str(), O_RDONLY); + if (fd == -1) return -errno; + int res = pread(fd, cBuffer, nSize, nOffset); + if (res == -1) res = -errno; + close(fd); + + return res; +} + + +/** + * read directory + */ +static int shadow_readdir(const char * sPath, void * cBuffer, fuse_fill_dir_t fFiller, UNUSED off_t nOffset, UNUSED struct fuse_file_info * cFileInfo) { + + DIR * cDIR; + struct dirent * cDirEntry; + int res = 0; + + // open the shadow folder + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath; +std::cerr << "=== INSERT HOOK HERE. Reading content of " << sShadow << std::endl; + + cDIR = opendir(sShadow.c_str()); + if (!cDIR) return -errno; + + // walk over the entries + while ((cDirEntry = readdir(cDIR)) != NULL) { + + // pick file stat as well + struct stat cFileStat; + stat(sShadow.c_str(), &cFileStat); + res = fFiller(cBuffer, cDirEntry->d_name, &cFileStat, 0); + if (res != 0) break; + } + + // free directory + closedir(cDIR); + return res; +} + + +/** + * move file + */ +static int shadow_rename(const char * sFromPath, const char * sToPath) { + + // move file + std::string sShadowFrom = g_cShadowFuseConfig.sShadowedPath + sFromPath; + std::string sShadowTo = g_cShadowFuseConfig.sShadowedPath + sToPath; +std::cerr << "=== INSERT HOOK HERE. Moving file from " << sShadowFrom << " to " << sShadowTo << std::endl; + + if (rename(sShadowFrom.c_str(), sShadowTo.c_str()) == -1) return -errno; + return 0; +} + + +/** + * delete a folder + */ +static int shadow_rmdir(const char * sPath) { + + // delete the shadow folder + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath; +std::cerr << "=== INSERT HOOK HERE. Delete folder " << sShadow << std::endl; + + if (rmdir(sShadow.c_str()) == -1) return -errno; + return 0; +} + + +/** + * delete a file + */ +static int shadow_unlink(const char * sPath) { + + // delete the shadow file + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath; +std::cerr << "=== INSERT HOOK HERE. Delete file " << sShadow << std::endl; + + if (unlink(sShadow.c_str()) == -1) return -errno; + return 0; +} + + +/** + * write int file + */ +static int shadow_write(const char * sPath, const char * cBuffer, size_t nSize, off_t nOffset, UNUSED struct fuse_file_info * cFileInfo) { + + // write into file + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath; +std::cerr << "=== INSERT HOOK HERE. Write into file " << sShadow << std::endl; + + // open, push bytes, close & out + int fd = open(sShadow.c_str(), O_WRONLY); + if (fd == -1) return -errno; + int res = pwrite(fd, cBuffer, nSize, nOffset); + if (res == -1) res = -errno; + close(fd); + + return res; +} + + +/** + * the shadowfuse function table + */ +static struct fuse_operations shadowfuse_operations { + + shadow_getattr, // getattr + nullptr, // readlink + nullptr, // getdir + shadow_mknod, // mknod + shadow_mkdir, // mkdir + shadow_unlink, // unlink + shadow_rmdir, // rmdir + nullptr, // symlink + shadow_rename, // rename + nullptr, // link + nullptr, // chmod + nullptr, // chown + nullptr, // truncate + nullptr, // utime + shadow_open, // open + shadow_read, // read + shadow_write, // write + nullptr, // statfs + nullptr, // flush + nullptr, // release + nullptr, // fsync + nullptr, // setxattr + nullptr, // getxattr + nullptr, // listxattr + nullptr, // removexattr + nullptr, // opendir + shadow_readdir, // readdir + nullptr, // releasedir + nullptr, // fsyncdir + nullptr, // init + nullptr, // destroy + nullptr, // access + nullptr, // create + nullptr, // ftruncate + nullptr, // fgetattr + nullptr, // lock + nullptr, // utimens + nullptr, // bmap + 0, // flag_nullpath_ok + 0, // flag_nopath + 0, // flag_utime_omit_ok + 0, // flag_reserved + nullptr, // ioctl + nullptr, // poll + nullptr, // write_buf + nullptr, // read_buf + nullptr, // flock + nullptr // fallocate +}; + + +/** + * start + * + * @param argc as usual + * @param argv as usual + * @return as usual + */ +int main(int argc, char ** argv) { + + // option parsing + struct fuse_args cFUSEArgs = FUSE_ARGS_INIT(argc, argv); + if (fuse_opt_parse(&cFUSEArgs, NULL, shadowfuse_opts, option_processor) == -1) { + return -1; + } + + // test if our config is setup ok + if (!g_cShadowFuseConfig.is_paths_set()) { + std::cerr << "sourcefolder and/or mount point not given" << std::endl; + exit(1); + } + + // do FUSE + int ret = fuse_main(cFUSEArgs.argc, cFUSEArgs.argv, &shadowfuse_operations, NULL); + if (ret) printf("\n"); + fuse_opt_free_args(&cFUSEArgs); + + return ret; +} + + +/** + * option parser processor + * + * @param cData is the user data passed to the fuse_opt_parse() function + * @param sArg is the whole argument or option + * @param nKey determines why the processing function was called + * @param cOutArgs the current output argument list + * @return -1 on error, 0 if arg is to be discarded, 1 if arg should be kept + */ +static int option_processor(UNUSED void * cData, UNUSED const char * sArg, int nKey, struct fuse_args * cOutArgs) { + + // select by key + switch (nKey) { + + case FUSE_OPT_KEY_OPT: + return 1; + + case FUSE_OPT_KEY_NONOPT: + // the non-options + if (g_cShadowFuseConfig.sShadowedPath.empty()) { + // first non-option is the path to be shadowed + g_cShadowFuseConfig.sShadowedPath = sArg; + return 0; + } + else + if (g_cShadowFuseConfig.sMountPoint.empty()) { + // the mount point + g_cShadowFuseConfig.sMountPoint = sArg; + return 1; + } + return 1; + + case KEY_HELP: + usage(cOutArgs->argv[0]); + exit(1); + + case KEY_VERSION: + printf("shadowfuse version %s\n", SHADOWFUSE_VERSION); + exit(0); + + default: + fprintf(stderr, "internal error\n"); + abort(); + } +} + + +/** + * print usage + * + * @param sProgName name of the current program + */ +static void usage(const char * sProgName) { + printf( +"usage: %s sourcefolder mountpoint\n" +"\n" +"general options:\n" +" -f foreground\n" +" -d -odebug foreground, but keep the debug option\n" +" -h --help print help\n" +" -V --version print version\n" +"\n", sProgName); +} +