mirror of
https://github.com/uroni/urbackup_backend.git
synced 2025-10-26 11:36:50 +00:00
238 lines
5.4 KiB
C++
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 |