From 23467f490475c1c4c52ad2e585afe947ddbbc5f3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Franti=C5=A1ek=20Dvo=C5=99=C3=A1k?= Date: Sun, 13 Oct 2013 21:17:16 +0200 Subject: [PATCH] Initial import. --- Makefile | 20 +++++++ scan.cpp | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ walk.cpp | 92 ++++++++++++++++++++++++++++++ 3 files changed, 307 insertions(+) create mode 100644 Makefile create mode 100644 scan.cpp create mode 100644 walk.cpp diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..64d01f2 --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +-include Makefile.inc + +libarch?=lib +CXXFLAGS:=-W -Wall -g -O2 $(CXXFLAGS) +LDFLAGS:=$(LDFLAGS) + +DMLITE_PREFIX?=/usr +DMLITE_CPPFLAGS?=-I$(DMLITE_PREFIX)/include +DMLITE_LIBS?=-L$(DMLITE_PREFIX)/$(libarch) -ldmlite + +all: scan + +scan: scan.o walk.o + $(CXX) $(LDFLAGS) $(DMLITE_LIBS) $+ -o $@ + +clean: + rm -fv scan *.o + +.cpp.o: + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(DMLITE_CPPFLAGS) -c $< -o $@ diff --git a/scan.cpp b/scan.cpp new file mode 100644 index 0000000..d6143c2 --- /dev/null +++ b/scan.cpp @@ -0,0 +1,195 @@ +#include +#include +#include +#include + +#include +#include +#include + + + +#define DMLITE_CONFIG_DEFAULT "/etc/dmlite.conf" +#define ADDRESS_DEFAULT "127.0.0.1" +#define USER_DEFAULT "/C=UG/L=Tropic/O=Utopia/OU=Relaxation/CN=dpmtest" + + +struct option longopts[] = { + { "config", required_argument, NULL, 'c' }, + { "help", no_argument, NULL, 'h' }, +}; + +const char *optstring = "c:h"; + + + +void walk(dmlite::Catalog *catalog, const char *path) throw(dmlite::DmException); + + + +static void usage(const char *prg) { + printf("Usage: %s [OPTIONS] DIRECTORY\n\n", prg); + printf("OPTIONS are:\n"); + printf(" -h,--help ...... usage information\n"); + printf(" -a,--address ... host address (for credentials) [%s]\n", ADDRESS_DEFAULT); + printf(" -c,--config .... dmlite config file [/etc/dmlite.conf,~/.dmlite.conf]\n"); + printf(" -u,--user ...... user name (for credentials) [%s]\n", USER_DEFAULT); + printf("DIRECTORY ........ path to browse and import\n"); +} + + + +#define TEST_FILE "/tmp/scan-test.XXX" +#define TEST_STRING "123456\n" +int check(dmlite::Catalog *catalog) throw(dmlite::DmException) { + FILE *f; + char buffer[20]; + + if ((f = fopen(TEST_FILE, "w")) == NULL) throw dmlite::DmException(errno, "could not create file for check"); + fputs(TEST_STRING, f); + fclose(f); + + try { + catalog->create(TEST_FILE, 0775); + + if ((f = fopen(TEST_FILE, "r")) == NULL) throw dmlite::DmException(errno, "test file vanished (this should not happen)"); + if (fgets(buffer, sizeof buffer, f) == NULL) { + fclose(f); + printf("check: empty or non-readable file after catalog->create()\n"); + unlink(TEST_FILE); + return 0; + } + fclose(f); + + if (strcmp(buffer, TEST_STRING) != 0) { + printf("check: different content after catalog->create()\n"); + return 0; + } + } catch (dmlite::DmException& e) { + // OK, can't create there at all + return 1; + } + + // OK, file remains the same, just cleanups yet + try { + catalog->unlink(TEST_FILE); + } catch (dmlite::DmException& e) { + } + unlink(TEST_FILE); + + return 1; +} + + + +int main(int argc, char *argv[]) { + dmlite::PluginManager manager; + dmlite::StackInstance *stack = NULL; + dmlite::Catalog* catalog = NULL; + //dmlite::PoolManager* poolManager = NULL; + dmlite::SecurityCredentials creds; + char *dmlite_config = NULL, *user = NULL, *address = NULL; + int opt; + bool safetyCheck = true; + + try { + while ((opt = getopt_long(argc, argv, optstring, longopts, NULL)) != -1) { + switch (opt) { + case 'a': + free(address); + address = strdup(optarg); + break; + case 'c': + free(dmlite_config); + dmlite_config = strdup(optarg); + break; + case 'h': + usage(argv[0]); + return 0; + break; + case 'u': + free(user); + user = strdup(optarg); + break; + default: + usage(argv[0]); + throw dmlite::DmException(); + } + } + + if (optind >= argc) { + printf("Missing DIRECTORY.\n"); + usage(argv[0]); + throw dmlite::DmException(); + } + + // load configuration + try { + manager.loadConfiguration(dmlite_config ? : DMLITE_CONFIG_DEFAULT); + } catch (dmlite::DmException& e) { + std::cout << "Could not load the configuration file." << std::endl + << "Reason: " << e.what() << std::endl; + throw; + } + stack = new dmlite::StackInstance(&manager); + + // security credentials + creds.clientName = user ? : USER_DEFAULT; + creds.remoteAddress = address ? : ADDRESS_DEFAULT; + try { + stack->setSecurityCredentials(creds); + } catch (dmlite::DmException& e) { + std::cout << "Could not set the credentials." << std::endl + << "Reason: " << e.what() << std::endl; + throw; + } + + catalog = stack->getCatalog(); + + // first check if we're safe + try { + if (!check(catalog)) { + printf("It is checked that VFS plugin overwrites files! Please set NSPrefix to place catalog namespace into subdirectory.\n"); + safetyCheck = false; + } + } catch (dmlite::DmException& e) { + std::cout << "Could not check safety (if NSPrefix is set in case of VFS plugin)." << std::endl + << "Reason: " << e.what() << std::endl; + throw; + } + if (!safetyCheck) { + delete stack; + return 2; + } + + + // now we can walk safely + try { + walk(catalog, argv[optind]); + } catch (dmlite::DmException& e) { + std::cout << "Could not walk." << std::endl + << "Reason: " << e.what() << std::endl; + throw; + } + //poolManager = stack->getPoolManager(); + + delete stack; + } catch (dmlite::DmException& e) { + free(address); + free(dmlite_config); + free(user); + delete stack; + return 1; + } catch (...) { + free(address); + free(dmlite_config); + free(user); + delete stack; + throw; + } + + free(address); + free(dmlite_config); + free(user); + return 0; +} diff --git a/walk.cpp b/walk.cpp new file mode 100644 index 0000000..a2e8b70 --- /dev/null +++ b/walk.cpp @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include + +//#include + +#include +#include + + +static dmlite::Catalog *catalog; +static const char *prefix; +static struct utimbuf utimbuf; +static struct dirent *entry; +static std::string lpath; +static struct stat pathstat; +int level; + + +static void wrapCall(int retval, std::string msg) throw(dmlite::DmException) { + if (retval < 0) throw dmlite::DmException(errno, "[level %d] %s: %s", level, msg.c_str(), strerror(errno)); +} + + +static void wrapCall(void *p, std::string msg) throw(dmlite::DmException) { + if (!p) throw dmlite::DmException(errno, "[level %d] %s: %s", level, msg.c_str(), strerror(errno)); +} + + +static void walk_recursive(const char *path) throw(dmlite::DmException) { + mode_t dirmode; + time_t diratime, dirmtime; + DIR *dir = NULL; + + lpath = std::string(prefix) + path; + +//printf("[level %d] '%s'/'%s'\n", level, prefix, path); + wrapCall(lstat(lpath.c_str(), &pathstat), "can't lstat() '" + lpath + "'"); + if (S_ISREG(pathstat.st_mode)) { + catalog->create(path, pathstat.st_mode); + utimbuf.actime = pathstat.st_atime; + utimbuf.modtime = pathstat.st_mtime; + catalog->utime(path, &utimbuf); + //catalog->setSize(path, stat.st_size); + } else if (S_ISDIR(pathstat.st_mode)) { + // create under permissive modes + if (path[0]) catalog->makeDir(path, 0775); + + // remember for later + dirmode = pathstat.st_mode; + diratime = pathstat.st_atime; + dirmtime = pathstat.st_mtime; + + // walk! + wrapCall(dir = opendir(lpath.c_str()), "can't open directory '" + lpath + "'"); + level++; + try { + if (level > 10) throw dmlite::DmException(E2BIG, "[level %d] maximul level reached at '%s/%s'", level, prefix, path); + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { + walk_recursive((std::string(path) + "/" + entry->d_name).c_str()); + } + } + } catch (dmlite::DmException& e) { + closedir(dir); + throw; + } + level--; + closedir(dir); + +//printf("[level %d] finalize '%s'/'%s'\n", level, prefix, path); + // set remebered values + if (path[0]) { + utimbuf.actime = diratime; + utimbuf.modtime = dirmtime; + catalog->utime(path, &utimbuf); + catalog->setMode(path, dirmode); + } + } +} + + + +void walk(dmlite::Catalog *acatalog, const char *path) throw(dmlite::DmException) { + prefix = path; + level = 0; + catalog = acatalog; + acatalog->changeDir("/"); + walk_recursive(""); +} -- 1.8.2.3