urbackup_backend/fileservplugin/PipeFileTar.h

163 lines
3.9 KiB
C++

#pragma once
#include "../Interface/Mutex.h"
#include "PipeFile.h"
#include <memory>
#include <set>
#include <sys/stat.h>
#include "../stringtools.h"
#if defined(_WIN32) || defined(__APPLE__) || defined(__FreeBSD__)
#define stat64 stat
#endif
class PipeFileTar : public IPipeFile
{
public:
struct STarFile
{
STarFile()
: available(false), pos(0),
size(0), is_dir(false), is_special(false)
{}
bool available;
int64 pos;
int64 size;
std::string fn;
std::string symlink_target;
bool is_dir;
bool is_special;
bool is_symlink;
struct stat64 buf;
};
struct PipeFileStore
{
PipeFileStore(IPipeFile* pipe_file)
: refcount(1), pipe_file(pipe_file), mutex(Server->createMutex())
{}
void decr()
{
IScopedLock lock(mutex.get());
--refcount;
}
void inc()
{
IScopedLock lock(mutex.get());
++refcount;
}
void add_path(const std::string& path)
{
IScopedLock lock(mutex.get());
std::set<std::string>::iterator it = paths.lower_bound(path);
if (it == paths.end())
{
paths.insert(path);
return;
}
if ((*it) != path)
{
if (next(path, 0, *it + "/"))
{
paths.erase(it);
}
paths.insert(path);
}
}
bool has_path(const std::string& path)
{
IScopedLock lock(mutex.get());
std::set<std::string>::iterator it = paths.lower_bound(path);
return it!=paths.end() && (*it == path
|| next(*it, 0, path + "/") );
}
size_t refcount;
IPipeFile* pipe_file;
std::unique_ptr<IMutex> mutex;
std::set<std::string> paths;
};
PipeFileTar(const std::string& pCmd, int backupnum, int64 fn_random, std::string output_fn, const std::string& server_token, const std::string& identity);
PipeFileTar(PipeFileStore* pipe_file, const STarFile& tar_file, int64 file_offset, int backupnum, int64 fn_random, std::string output_fn, const std::string& server_token, const std::string& identity);
~PipeFileTar();
virtual std::string Read(_u32 tr, bool *has_error = NULL);
virtual std::string Read(int64 spos, _u32 tr, bool *has_error = NULL);
virtual _u32 Read(char* buffer, _u32 bsize, bool *has_error = NULL);
virtual _u32 Read(int64 spos, char* buffer, _u32 bsize, bool *has_error = NULL);
virtual bool Seek(_i64 spos);
bool switchNext(std::string& fn, bool& is_dir, bool& is_symlink, bool& is_special, std::string& symlink_target, int64& size, std::string & stderr_ret, bool *has_error = NULL);
virtual _i64 Size();
// Inherited via IPipeFile
virtual _u32 Write(const std::string & tw, bool * has_error = NULL);
virtual _u32 Write(int64 spos, const std::string & tw, bool * has_error = NULL);
virtual _u32 Write(const char * buffer, _u32 bsiz, bool * has_error = NULL);
virtual _u32 Write(int64 spos, const char * buffer, _u32 bsiz, bool * has_error = NULL);
virtual _i64 RealSize();
virtual bool PunchHole(_i64 spos, _i64 size);
virtual bool Sync();
virtual std::string getFilename(void);
virtual int64 getLastRead();
virtual bool getHasError();
virtual std::string getStdErr();
virtual bool getExitCode(int & exit_code);
virtual void forceExitWait();
virtual void addUser();
virtual void removeUser();
virtual bool hasUser();
virtual int64 getPos();
virtual bool waitForStderr(int64 timeoutms);
private:
void hashReadData(int64 spos, const char* buffer, _u32 bsize);
std::string buildCurrMetadata();
bool readHeader(bool* has_error, std::string & stderr_ret);
void addErrMsg(const std::string& msg, std::string& stderr_ret);
int64 file_offset;
STarFile tar_file;
sha_def_ctx sha_ctx;
int64 hash_pos;
std::unique_ptr<IMutex> mutex;
PipeFileStore* pipe_file;
int backupnum;
int64 fn_random;
bool free_pipe_file;
bool has_next;
std::string output_fn;
std::string server_token;
std::string identity;
};
#if defined(_WIN32) || defined(__APPLE__) || defined(__FreeBSD__)
#undef stat64
#endif