Initial import.
authorFrantišek Dvořák <valtri@civ.zcu.cz>
Sun, 13 Oct 2013 19:17:16 +0000 (21:17 +0200)
committerFrantišek Dvořák <valtri@civ.zcu.cz>
Sun, 13 Oct 2013 19:17:16 +0000 (21:17 +0200)
Makefile [new file with mode: 0644]
scan.cpp [new file with mode: 0644]
walk.cpp [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (file)
index 0000000..d6143c2
--- /dev/null
+++ b/scan.cpp
@@ -0,0 +1,195 @@
+#include <getopt.h>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include <dmlite/cpp/dmlite.h>
+#include <dmlite/cpp/catalog.h>
+#include <dmlite/cpp/poolmanager.h>
+
+
+
+#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 (file)
index 0000000..a2e8b70
--- /dev/null
+++ b/walk.cpp
@@ -0,0 +1,92 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <utime.h>
+
+//#include <cstdio>
+
+#include <dmlite/cpp/dmlite.h>
+#include <dmlite/cpp/catalog.h>
+
+
+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("");
+}