/************************************************************************* * UrBackup - Client/Server backup system * Copyright (C) 2011-2014 Martin Raiber * * 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, either version 3 of the License, or * (at your option) any later version. * * 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, see . **************************************************************************/ #include "../vld.h" #ifdef _WIN32 #define DLLEXPORT extern "C" __declspec (dllexport) #else #define DLLEXPORT extern "C" #endif #include #include #ifndef STATIC_PLUGIN #define DEF_SERVER #endif #include "../Interface/Server.h" #ifndef STATIC_PLUGIN IServer *Server; #else #include "../StaticPluginRegistration.h" extern IServer* Server; #define LoadActions LoadActions_fuseplugin #define UnloadActions UnloadActions_fuseplugin #endif #include "../Interface/Types.h" #include "../fsimageplugin/IFSImageFactory.h" #include "../fsimageplugin/IVHDFile.h" #include "../stringtools.h" #define FUSE_USE_VERSION 26 #include #include #include #include #include #include namespace { IVHDFile* vhdfile = NULL; __int64 global_offset = 0; static const char* volume_path = "/volume"; static int vhdfile_getattr(const char* path, struct stat* stbuf) { int res = 0; memset(stbuf, 0, sizeof(struct stat)); if(strcmp(path, "/") == 0) { stbuf->st_mode = S_IFDIR | 0755; stbuf->st_nlink = 2; } else if(strcmp(path, volume_path) == 0) { stbuf->st_mode = S_IFREG | 0444; stbuf->st_nlink = 1; stbuf->st_size = vhdfile->getSize()-global_offset; } else { res = -ENOENT; } return res; } static int vhdfile_readdir(const char* path, void* buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info* fi) { if(strcmp(path, "/") != 0) return -ENOENT; filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); filler(buf, volume_path + 1, NULL, 0); return 0; } static int vhdfile_open(const char* path, struct fuse_file_info* fi) { if(strcmp(path, volume_path) != 0) return -ENOENT; if((fi->flags & 3) != O_RDONLY) return -EACCES; return 0; } static int vhdfile_read(const char* path, char* buf, size_t size, off_t offset, struct fuse_file_info* fi) { size_t len; if(strcmp(path, volume_path) != 0) return -ENOENT; if(!vhdfile->Seek(offset+global_offset)) { return -EINVAL; } size_t read; if(!vhdfile->Read(buf, size, read)) { return -EINVAL; } return static_cast(read); } static struct fuse_operations vhdfile_oper = {}; } DLLEXPORT void LoadActions(IServer* pServer) { Server=pServer; std::string vhd_filename = Server->getServerParameter("mount"); if(vhd_filename.empty()) { return; } else { Server->Log("Mounting VHD via fuse...", LL_INFO); } std::string mountpoint = Server->getServerParameter("mountpoint"); if(mountpoint.empty()) { Server->Log("Please specify the mountpoint using the --mountpoint parameter", LL_ERROR); exit(1); } str_map params; IFSImageFactory* image_fak=(IFSImageFactory *)Server->getPlugin(Server->getThreadID(), Server->StartPlugin("fsimageplugin", params)); if( image_fak==NULL ) { Server->Log("Error loading fsimageplugin", LL_ERROR); exit(2); } vhdfile = image_fak->createVHDFile(vhd_filename, true, 0); if(vhdfile==NULL || !vhdfile->isOpen()) { Server->Log("Error opening VHD file", LL_ERROR); exit(3); } std::string offset_s=Server->getServerParameter("offset"); global_offset=1024*512; if(!offset_s.empty()) { global_offset=atoi(offset_s.c_str()); } Server->Log("Volume offset is "+convert(global_offset)+" bytes. Configure via --offset", LL_DEBUG); struct fuse_args args = FUSE_ARGS_INIT(0, NULL); fuse_chan * ch = fuse_mount(mountpoint.c_str(), &args); if(!ch) { Server->Log("Error mounting fuse filesystem", LL_ERROR); exit(4); } vhdfile_oper.getattr = vhdfile_getattr; vhdfile_oper.readdir = vhdfile_readdir; vhdfile_oper.open = vhdfile_open; vhdfile_oper.read = vhdfile_read; fuse* ffuse = fuse_new(ch, &args, &vhdfile_oper, sizeof(vhdfile_oper), NULL); fuse_opt_free_args(&args); if(!ffuse) { Server->Log("Could not initialize fuse", LL_ERROR); fuse_unmount(mountpoint.c_str(), ch); exit(5); } fuse_set_signal_handlers(fuse_get_session(ffuse)); int rc = fuse_loop(ffuse); fuse_unmount(mountpoint.c_str(), ch); if(rc!=0) { Server->Log("Error occurred while processing fuse events", LL_ERROR); exit(6); } fuse_destroy(ffuse); exit(0); } DLLEXPORT void UnloadActions(void) { Server->Log("Unload"); } #ifdef STATIC_PLUGIN namespace { static RegisterPluginHelper register_plugin(LoadActions, UnloadActions, 2); } #endif