urbackup_backend/fuseplugin/dllmain.cpp

238 lines
5.4 KiB
C++

/*************************************************************************
* 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 <http://www.gnu.org/licenses/>.
**************************************************************************/
#include "../vld.h"
#ifdef _WIN32
#define DLLEXPORT extern "C" __declspec (dllexport)
#else
#define DLLEXPORT extern "C"
#endif
#include <iostream>
#include <memory.h>
#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 <fuse.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
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<int>(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