1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/ait/os/bin/shadowfuse/main.cpp Tue Nov 12 11:31:34 2013 +0100
1.3 @@ -0,0 +1,421 @@
1.4 +/*
1.5 + * main.cpp
1.6 + *
1.7 + * This is the shadowfuse main startup file.
1.8 + *
1.9 + * Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
1.10 + *
1.11 + * Copyright (C) 2013 AIT Austrian Institute of Technology
1.12 + * AIT Austrian Institute of Technology GmbH
1.13 + * Donau-City-Strasse 1 | 1220 Vienna | Austria
1.14 + * http://www.ait.ac.at
1.15 + *
1.16 + * This program is free software; you can redistribute it and/or
1.17 + * modify it under the terms of the GNU General Public License
1.18 + * as published by the Free Software Foundation version 2.
1.19 + *
1.20 + * This program is distributed in the hope that it will be useful,
1.21 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.22 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.23 + * GNU General Public License for more details.
1.24 + *
1.25 + * You should have received a copy of the GNU General Public License
1.26 + * along with this program; if not, write to the Free Software
1.27 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.28 + * Boston, MA 02110-1301, USA.
1.29 + */
1.30 +
1.31 +
1.32 +// ------------------------------------------------------------
1.33 +// incs
1.34 +
1.35 +#include "baseinc.h"
1.36 +
1.37 +
1.38 +// ------------------------------------------------------------
1.39 +// defs
1.40 +
1.41 +
1.42 +/**
1.43 + * shadowfuse version
1.44 + */
1.45 +#define SHADOWFUSE_VERSION "0.1"
1.46 +
1.47 +
1.48 +// ------------------------------------------------------------
1.49 +// vars
1.50 +
1.51 +
1.52 +/**
1.53 + * keys for FUSE_OPT_ options
1.54 + */
1.55 +enum {
1.56 + KEY_VERSION,
1.57 + KEY_HELP,
1.58 +};
1.59 +
1.60 +
1.61 +/**
1.62 + * array of options we know
1.63 + */
1.64 +static struct fuse_opt shadowfuse_opts[] = {
1.65 + FUSE_OPT_KEY("-V", KEY_VERSION),
1.66 + FUSE_OPT_KEY("--version", KEY_VERSION),
1.67 + FUSE_OPT_KEY("-h", KEY_HELP),
1.68 + FUSE_OPT_KEY("--help", KEY_HELP),
1.69 + FUSE_OPT_END
1.70 +};
1.71 +
1.72 +
1.73 +/**
1.74 + * configuration of shadowfuse
1.75 + */
1.76 +static struct shadowfuse_config {
1.77 +
1.78 + std::string sShadowedPath;
1.79 + std::string sMountPoint;
1.80 +
1.81 + /**
1.82 + * check for paths been set
1.83 + */
1.84 + inline bool is_paths_set() const { return !(sShadowedPath.empty() || sMountPoint.empty()); };
1.85 +
1.86 +} g_cShadowFuseConfig;
1.87 +
1.88 +
1.89 +// ------------------------------------------------------------
1.90 +// fwd
1.91 +
1.92 +static int option_processor(void * cData, const char * sArg, int nKey, struct fuse_args * cOutArgs);
1.93 +static void usage(const char * sProgName);
1.94 +
1.95 +
1.96 +// ------------------------------------------------------------
1.97 +// code
1.98 +
1.99 +
1.100 +
1.101 +/**
1.102 + * get file attributes.
1.103 + */
1.104 +static int shadow_getattr(const char * sPath, struct stat * cFileStat) {
1.105 +
1.106 + // open the shadow file
1.107 + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
1.108 +std::cerr << "=== INSERT HOOK HERE. Getting file attributes of " << sShadow << std::endl;
1.109 +
1.110 + memset(cFileStat, 0, sizeof(struct stat));
1.111 + if (stat(sShadow.c_str(), cFileStat) == -1) return -errno;
1.112 +
1.113 + return 0;
1.114 +}
1.115 +
1.116 +
1.117 +
1.118 +/**
1.119 + * create a directory
1.120 + */
1.121 +static int shadow_mkdir(const char * sPath, mode_t cMode) {
1.122 +
1.123 + // create directory
1.124 + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
1.125 +std::cerr << "=== INSERT HOOK HERE. Create directory " << sShadow << std::endl;
1.126 +
1.127 + if (mkdir(sShadow.c_str(), cMode) == -1) return -errno;
1.128 + return 0;
1.129 +}
1.130 +
1.131 +
1.132 +/**
1.133 + * create a file
1.134 + */
1.135 +static int shadow_mknod(const char * sPath, mode_t cMode, dev_t cDev) {
1.136 +
1.137 + // create file
1.138 + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
1.139 +std::cerr << "=== INSERT HOOK HERE. Create file " << sShadow << std::endl;
1.140 +
1.141 + if (mknod(sShadow.c_str(), cMode, cDev) == -1) return -errno;
1.142 + return 0;
1.143 +}
1.144 +
1.145 +
1.146 +/**
1.147 + * open file
1.148 + */
1.149 +static int shadow_open(const char * sPath, struct fuse_file_info * cFileInfo) {
1.150 +
1.151 + // open the shadow file
1.152 + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
1.153 +std::cerr << "=== INSERT HOOK HERE. Opening file " << sShadow << std::endl;
1.154 +
1.155 + if (open(sShadow.c_str(), cFileInfo->flags) == -1) return -errno;
1.156 + return 0;
1.157 +}
1.158 +
1.159 +
1.160 +/**
1.161 + * read from file
1.162 + */
1.163 +static int shadow_read(const char * sPath, char * cBuffer, size_t nSize, off_t nOffset, UNUSED struct fuse_file_info * cFileInfo) {
1.164 +
1.165 + // read from shadow file
1.166 + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
1.167 +std::cerr << "=== INSERT HOOK HERE. Reading file " << sShadow << " [offset=" << nOffset << ", fetch max bytes=" << nSize << "]" << std::endl;
1.168 +
1.169 + // open, pick bytes, close & out
1.170 + int fd = open(sShadow.c_str(), O_RDONLY);
1.171 + if (fd == -1) return -errno;
1.172 + int res = pread(fd, cBuffer, nSize, nOffset);
1.173 + if (res == -1) res = -errno;
1.174 + close(fd);
1.175 +
1.176 + return res;
1.177 +}
1.178 +
1.179 +
1.180 +/**
1.181 + * read directory
1.182 + */
1.183 +static int shadow_readdir(const char * sPath, void * cBuffer, fuse_fill_dir_t fFiller, UNUSED off_t nOffset, UNUSED struct fuse_file_info * cFileInfo) {
1.184 +
1.185 + DIR * cDIR;
1.186 + struct dirent * cDirEntry;
1.187 + int res = 0;
1.188 +
1.189 + // open the shadow folder
1.190 + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
1.191 +std::cerr << "=== INSERT HOOK HERE. Reading content of " << sShadow << std::endl;
1.192 +
1.193 + cDIR = opendir(sShadow.c_str());
1.194 + if (!cDIR) return -errno;
1.195 +
1.196 + // walk over the entries
1.197 + while ((cDirEntry = readdir(cDIR)) != NULL) {
1.198 +
1.199 + // pick file stat as well
1.200 + struct stat cFileStat;
1.201 + stat(sShadow.c_str(), &cFileStat);
1.202 + res = fFiller(cBuffer, cDirEntry->d_name, &cFileStat, 0);
1.203 + if (res != 0) break;
1.204 + }
1.205 +
1.206 + // free directory
1.207 + closedir(cDIR);
1.208 + return res;
1.209 +}
1.210 +
1.211 +
1.212 +/**
1.213 + * move file
1.214 + */
1.215 +static int shadow_rename(const char * sFromPath, const char * sToPath) {
1.216 +
1.217 + // move file
1.218 + std::string sShadowFrom = g_cShadowFuseConfig.sShadowedPath + sFromPath;
1.219 + std::string sShadowTo = g_cShadowFuseConfig.sShadowedPath + sToPath;
1.220 +std::cerr << "=== INSERT HOOK HERE. Moving file from " << sShadowFrom << " to " << sShadowTo << std::endl;
1.221 +
1.222 + if (rename(sShadowFrom.c_str(), sShadowTo.c_str()) == -1) return -errno;
1.223 + return 0;
1.224 +}
1.225 +
1.226 +
1.227 +/**
1.228 + * delete a folder
1.229 + */
1.230 +static int shadow_rmdir(const char * sPath) {
1.231 +
1.232 + // delete the shadow folder
1.233 + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
1.234 +std::cerr << "=== INSERT HOOK HERE. Delete folder " << sShadow << std::endl;
1.235 +
1.236 + if (rmdir(sShadow.c_str()) == -1) return -errno;
1.237 + return 0;
1.238 +}
1.239 +
1.240 +
1.241 +/**
1.242 + * delete a file
1.243 + */
1.244 +static int shadow_unlink(const char * sPath) {
1.245 +
1.246 + // delete the shadow file
1.247 + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
1.248 +std::cerr << "=== INSERT HOOK HERE. Delete file " << sShadow << std::endl;
1.249 +
1.250 + if (unlink(sShadow.c_str()) == -1) return -errno;
1.251 + return 0;
1.252 +}
1.253 +
1.254 +
1.255 +/**
1.256 + * write int file
1.257 + */
1.258 +static int shadow_write(const char * sPath, const char * cBuffer, size_t nSize, off_t nOffset, UNUSED struct fuse_file_info * cFileInfo) {
1.259 +
1.260 + // write into file
1.261 + std::string sShadow = g_cShadowFuseConfig.sShadowedPath + sPath;
1.262 +std::cerr << "=== INSERT HOOK HERE. Write into file " << sShadow << std::endl;
1.263 +
1.264 + // open, push bytes, close & out
1.265 + int fd = open(sShadow.c_str(), O_WRONLY);
1.266 + if (fd == -1) return -errno;
1.267 + int res = pwrite(fd, cBuffer, nSize, nOffset);
1.268 + if (res == -1) res = -errno;
1.269 + close(fd);
1.270 +
1.271 + return res;
1.272 +}
1.273 +
1.274 +
1.275 +/**
1.276 + * the shadowfuse function table
1.277 + */
1.278 +static struct fuse_operations shadowfuse_operations {
1.279 +
1.280 + shadow_getattr, // getattr
1.281 + nullptr, // readlink
1.282 + nullptr, // getdir
1.283 + shadow_mknod, // mknod
1.284 + shadow_mkdir, // mkdir
1.285 + shadow_unlink, // unlink
1.286 + shadow_rmdir, // rmdir
1.287 + nullptr, // symlink
1.288 + shadow_rename, // rename
1.289 + nullptr, // link
1.290 + nullptr, // chmod
1.291 + nullptr, // chown
1.292 + nullptr, // truncate
1.293 + nullptr, // utime
1.294 + shadow_open, // open
1.295 + shadow_read, // read
1.296 + shadow_write, // write
1.297 + nullptr, // statfs
1.298 + nullptr, // flush
1.299 + nullptr, // release
1.300 + nullptr, // fsync
1.301 + nullptr, // setxattr
1.302 + nullptr, // getxattr
1.303 + nullptr, // listxattr
1.304 + nullptr, // removexattr
1.305 + nullptr, // opendir
1.306 + shadow_readdir, // readdir
1.307 + nullptr, // releasedir
1.308 + nullptr, // fsyncdir
1.309 + nullptr, // init
1.310 + nullptr, // destroy
1.311 + nullptr, // access
1.312 + nullptr, // create
1.313 + nullptr, // ftruncate
1.314 + nullptr, // fgetattr
1.315 + nullptr, // lock
1.316 + nullptr, // utimens
1.317 + nullptr, // bmap
1.318 + 0, // flag_nullpath_ok
1.319 + 0, // flag_nopath
1.320 + 0, // flag_utime_omit_ok
1.321 + 0, // flag_reserved
1.322 + nullptr, // ioctl
1.323 + nullptr, // poll
1.324 + nullptr, // write_buf
1.325 + nullptr, // read_buf
1.326 + nullptr, // flock
1.327 + nullptr // fallocate
1.328 +};
1.329 +
1.330 +
1.331 +/**
1.332 + * start
1.333 + *
1.334 + * @param argc as usual
1.335 + * @param argv as usual
1.336 + * @return as usual
1.337 + */
1.338 +int main(int argc, char ** argv) {
1.339 +
1.340 + // option parsing
1.341 + struct fuse_args cFUSEArgs = FUSE_ARGS_INIT(argc, argv);
1.342 + if (fuse_opt_parse(&cFUSEArgs, NULL, shadowfuse_opts, option_processor) == -1) {
1.343 + return -1;
1.344 + }
1.345 +
1.346 + // test if our config is setup ok
1.347 + if (!g_cShadowFuseConfig.is_paths_set()) {
1.348 + std::cerr << "sourcefolder and/or mount point not given" << std::endl;
1.349 + exit(1);
1.350 + }
1.351 +
1.352 + // do FUSE
1.353 + int ret = fuse_main(cFUSEArgs.argc, cFUSEArgs.argv, &shadowfuse_operations, NULL);
1.354 + if (ret) printf("\n");
1.355 + fuse_opt_free_args(&cFUSEArgs);
1.356 +
1.357 + return ret;
1.358 +}
1.359 +
1.360 +
1.361 +/**
1.362 + * option parser processor
1.363 + *
1.364 + * @param cData is the user data passed to the fuse_opt_parse() function
1.365 + * @param sArg is the whole argument or option
1.366 + * @param nKey determines why the processing function was called
1.367 + * @param cOutArgs the current output argument list
1.368 + * @return -1 on error, 0 if arg is to be discarded, 1 if arg should be kept
1.369 + */
1.370 +static int option_processor(UNUSED void * cData, UNUSED const char * sArg, int nKey, struct fuse_args * cOutArgs) {
1.371 +
1.372 + // select by key
1.373 + switch (nKey) {
1.374 +
1.375 + case FUSE_OPT_KEY_OPT:
1.376 + return 1;
1.377 +
1.378 + case FUSE_OPT_KEY_NONOPT:
1.379 + // the non-options
1.380 + if (g_cShadowFuseConfig.sShadowedPath.empty()) {
1.381 + // first non-option is the path to be shadowed
1.382 + g_cShadowFuseConfig.sShadowedPath = sArg;
1.383 + return 0;
1.384 + }
1.385 + else
1.386 + if (g_cShadowFuseConfig.sMountPoint.empty()) {
1.387 + // the mount point
1.388 + g_cShadowFuseConfig.sMountPoint = sArg;
1.389 + return 1;
1.390 + }
1.391 + return 1;
1.392 +
1.393 + case KEY_HELP:
1.394 + usage(cOutArgs->argv[0]);
1.395 + exit(1);
1.396 +
1.397 + case KEY_VERSION:
1.398 + printf("shadowfuse version %s\n", SHADOWFUSE_VERSION);
1.399 + exit(0);
1.400 +
1.401 + default:
1.402 + fprintf(stderr, "internal error\n");
1.403 + abort();
1.404 + }
1.405 +}
1.406 +
1.407 +
1.408 +/**
1.409 + * print usage
1.410 + *
1.411 + * @param sProgName name of the current program
1.412 + */
1.413 +static void usage(const char * sProgName) {
1.414 + printf(
1.415 +"usage: %s sourcefolder mountpoint\n"
1.416 +"\n"
1.417 +"general options:\n"
1.418 +" -f foreground\n"
1.419 +" -d -odebug foreground, but keep the debug option\n"
1.420 +" -h --help print help\n"
1.421 +" -V --version print version\n"
1.422 +"\n", sProgName);
1.423 +}
1.424 +