--- /dev/null
+#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;
+}
--- /dev/null
+#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("");
+}