266 lines
6.9 KiB
C++
266 lines
6.9 KiB
C++
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
#include <string>
|
|
#include <iostream>
|
|
#include <memory>
|
|
|
|
#include "circache.h"
|
|
#include "fileudi.h"
|
|
#include "conftree.h"
|
|
#include "readfile.h"
|
|
#include "log.h"
|
|
|
|
#include "smallut.h"
|
|
|
|
using namespace std;
|
|
|
|
static char *thisprog;
|
|
|
|
static char usage [] =
|
|
" -c [-u] <dirname> <sizekbs>: create new store or possibly resize existing one\n"
|
|
" -u: set the 'unique' flag (else unset it)\n"
|
|
" None of this changes the existing data\n"
|
|
" -p <dirname> <apath> [apath ...] : put files\n"
|
|
" -d <dirname> : dump\n"
|
|
" -g [-i instance] [-D] <dirname> <udi>: get\n"
|
|
" -D: also dump data\n"
|
|
" -e <dirname> <udi> : erase\n"
|
|
" -a <targetdir> <dir> [<dir> ...]: append content from existing cache(s) to target\n"
|
|
" The target should be first resized to hold all the data, else only\n"
|
|
" as many entries as capacity permit will be retained\n"
|
|
" -C <dir> : recover space from erased entries. May temporarily need twice the current "
|
|
" space used by the cache\n";
|
|
;
|
|
|
|
static void
|
|
Usage(FILE *fp = stderr)
|
|
{
|
|
fprintf(fp, "%s: usage:\n%s", thisprog, usage);
|
|
exit(1);
|
|
}
|
|
|
|
static int op_flags;
|
|
#define OPT_a 0x1
|
|
#define OPT_b 0x2
|
|
#define OPT_C 0x4
|
|
#define OPT_c 0x8
|
|
#define OPT_D 0x10
|
|
#define OPT_d 0x20
|
|
#define OPT_e 0x40
|
|
#define OPT_g 0x80
|
|
#define OPT_i 0x100
|
|
#define OPT_p 0x200
|
|
#define OPT_u 0x400
|
|
|
|
bool storeFile(CirCache& cc, const std::string fn);
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int instance = -1;
|
|
|
|
thisprog = argv[0];
|
|
argc--;
|
|
argv++;
|
|
|
|
while (argc > 0 && **argv == '-') {
|
|
(*argv)++;
|
|
if (!(**argv))
|
|
/* Cas du "adb - core" */
|
|
{
|
|
Usage();
|
|
}
|
|
while (**argv)
|
|
switch (*(*argv)++) {
|
|
case 'a': op_flags |= OPT_a; break;
|
|
case 'b': op_flags |= OPT_b; break;
|
|
case 'C': op_flags |= OPT_C; break;
|
|
case 'c': op_flags |= OPT_c; break;
|
|
case 'D': op_flags |= OPT_D; break;
|
|
case 'd': op_flags |= OPT_d; break;
|
|
case 'e': op_flags |= OPT_e; break;
|
|
case 'g': op_flags |= OPT_g; break;
|
|
case 'i':
|
|
op_flags |= OPT_i;
|
|
if (argc < 2) {
|
|
Usage();
|
|
}
|
|
if ((sscanf(*(++argv), "%d", &instance)) != 1) {
|
|
Usage();
|
|
}
|
|
argc--;
|
|
goto b1;
|
|
case 'p': op_flags |= OPT_p; break;
|
|
case 'u': op_flags |= OPT_u; break;
|
|
default: Usage(); break;
|
|
}
|
|
b1:
|
|
argc--;
|
|
argv++;
|
|
}
|
|
|
|
Logger::getTheLog("")->setLogLevel(Logger::LLDEB1);
|
|
|
|
if (argc < 1) {
|
|
Usage();
|
|
}
|
|
string dir = *argv++;
|
|
argc--;
|
|
|
|
CirCache cc(dir);
|
|
|
|
if (op_flags & OPT_c) {
|
|
if (argc != 1) {
|
|
Usage();
|
|
}
|
|
int64_t sizekb = atoi(*argv++);
|
|
argc--;
|
|
int flags = 0;
|
|
if (op_flags & OPT_u) {
|
|
flags |= CirCache::CC_CRUNIQUE;
|
|
}
|
|
if (!cc.create(sizekb * 1024, flags)) {
|
|
cerr << "Create failed:" << cc.getReason() << endl;
|
|
exit(1);
|
|
}
|
|
} else if (op_flags & OPT_C) {
|
|
if (argc) {
|
|
Usage();
|
|
}
|
|
std::string reason;
|
|
if (!CirCache::compact(dir, &reason)) {
|
|
std::cerr << "Compact failed: " << reason << "\n";
|
|
return 1;
|
|
}
|
|
return 0;
|
|
} else if (op_flags & OPT_a) {
|
|
if (argc < 1) {
|
|
Usage();
|
|
}
|
|
while (argc) {
|
|
string reason;
|
|
if (CirCache::appendCC(dir, *argv++, &reason) < 0) {
|
|
cerr << reason << endl;
|
|
return 1;
|
|
}
|
|
argc--;
|
|
}
|
|
} else if (op_flags & OPT_b) {
|
|
if (argc < 1) {
|
|
Usage();
|
|
}
|
|
std::string ddir = *argv++; argc--;
|
|
string reason;
|
|
if (!CirCache::burst(dir, ddir, &reason)) {
|
|
cerr << reason << endl;
|
|
return 1;
|
|
}
|
|
} else if (op_flags & OPT_p) {
|
|
if (argc < 1) {
|
|
Usage();
|
|
}
|
|
if (!cc.open(CirCache::CC_OPWRITE)) {
|
|
cerr << "Open failed: " << cc.getReason() << endl;
|
|
exit(1);
|
|
}
|
|
while (argc) {
|
|
string fn = *argv++;
|
|
argc--;
|
|
if (!storeFile(cc, fn)) {
|
|
return 1;
|
|
}
|
|
}
|
|
cc.open(CirCache::CC_OPREAD);
|
|
} else if (op_flags & OPT_g) {
|
|
if (!cc.open(CirCache::CC_OPREAD)) {
|
|
cerr << "Open failed: " << cc.getReason() << endl;
|
|
exit(1);
|
|
}
|
|
while (argc) {
|
|
string udi = *argv++;
|
|
argc--;
|
|
string dic, data;
|
|
if (!cc.get(udi, dic, &data, instance)) {
|
|
cerr << "Get failed: " << cc.getReason() << endl;
|
|
exit(1);
|
|
}
|
|
cout << "Dict: [" << dic << "]" << endl;
|
|
if (op_flags & OPT_D) {
|
|
cout << "Data: [" << data << "]" << endl;
|
|
}
|
|
}
|
|
} else if (op_flags & OPT_e) {
|
|
if (!cc.open(CirCache::CC_OPWRITE)) {
|
|
cerr << "Open failed: " << cc.getReason() << endl;
|
|
exit(1);
|
|
}
|
|
while (argc) {
|
|
string udi = *argv++;
|
|
argc--;
|
|
string dic, data;
|
|
if (!cc.erase(udi)) {
|
|
cerr << "Erase failed: " << cc.getReason() << endl;
|
|
exit(1);
|
|
}
|
|
}
|
|
} else if (op_flags & OPT_d) {
|
|
if (!cc.open(CirCache::CC_OPREAD)) {
|
|
cerr << "Open failed: " << cc.getReason() << endl;
|
|
exit(1);
|
|
}
|
|
cc.dump();
|
|
} else {
|
|
Usage();
|
|
}
|
|
|
|
exit(0);
|
|
}
|
|
|
|
|
|
bool storeFile(CirCache& cc, const std::string fn)
|
|
{
|
|
char dic[1000];
|
|
string data, reason;
|
|
if (!file_to_string(fn, data, &reason)) {
|
|
std::cerr << "File_to_string: " << reason << endl;
|
|
return false;
|
|
}
|
|
string udi;
|
|
make_udi(fn, "", udi);
|
|
string cmd("xdg-mime query filetype ");
|
|
// Should do more quoting here...
|
|
cmd += "'" + fn + "'";
|
|
FILE *fp = popen(cmd.c_str(), "r");
|
|
char* buf=0;
|
|
size_t sz = 0;
|
|
if (::getline(&buf, &sz, fp) -1) {
|
|
std::cerr << "Could not read from xdg-mime output\n";
|
|
return false;
|
|
}
|
|
pclose(fp);
|
|
string mimetype(buf);
|
|
free(buf);
|
|
trimstring(mimetype, "\n\r");
|
|
//std::cerr << "Got [" << mimetype << "]\n";
|
|
|
|
string s;
|
|
ConfSimple conf(s);
|
|
conf.set("udi", udi);
|
|
conf.set("mimetype", mimetype);
|
|
//ostringstream str; conf.write(str); cout << str.str() << endl;
|
|
|
|
if (!cc.put(udi, &conf, data, 0)) {
|
|
std::cerr << "Put failed: " << cc.getReason() << endl;
|
|
std::cerr << "conf: [";
|
|
conf.write(std::cerr);
|
|
std::cerr << "]" << endl;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|