]> arthur.barton.de Git - netatalk.git/commitdiff
system() replacement, fixes problems with quoting in command args
authorFrank Lahm <franklahm@googlemail.com>
Mon, 26 Mar 2012 09:05:54 +0000 (11:05 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Mon, 26 Mar 2012 09:05:54 +0000 (11:05 +0200)
etc/cnid_dbd/cnid_metad.c
include/atalk/util.h
libatalk/util/unix.c

index d6fbcb060696c3b502a1cc5ee2196a31b0380f58..b140fd0945cd23661c686e56ab4d18eceb86d008 100644 (file)
@@ -288,36 +288,41 @@ static int set_dbdir(const char *dbdir, const char *vpath)
     EC_INIT;
     int status;
     struct stat st;
-    bstring oldpath, newpath, cmd = NULL;
+    bstring oldpath, newpath;
+    char *cmd_argv[4];
+
+    LOG(log_note, logtype_cnid, "set_dbdir: volume: %s, db path: %s", vpath, dbdir);
 
     EC_NULL_LOG( oldpath = bformat("%s/%s/", vpath, DBHOME) );
     EC_NULL_LOG( newpath = bformat("%s/%s/", dbdir, DBHOME) );
 
     if (lstat(dbdir, &st) < 0 && mkdir(dbdir, 0755) < 0) {
         LOG(log_error, logtype_cnid, "set_dbdir: mkdir failed for %s", dbdir);
-        return -1;
+        EC_FAIL;
     }
 
     if (lstat(bdata(oldpath), &st) == 0 && lstat(bdata(newpath), &st) != 0 && errno == ENOENT) {
         /* There's an .AppleDB in the volume root, we move it */
-        EC_NULL_LOG( cmd = bformat("mv '%s' '%s'", bdata(oldpath), dbdir) );
-        LOG(log_debug, logtype_cnid, "set_dbdir: cmd: %s", bdata(cmd));
-        if (WEXITSTATUS(system(bdata(cmd))) != 0) {
+        cmd_argv[0] = "mv";
+        cmd_argv[1] = bdata(oldpath);
+        cmd_argv[2] = (char *)dbdir;
+        cmd_argv[3] = NULL;
+        if (run_cmd("mv", cmd_argv) != 0) {
             LOG(log_error, logtype_cnid, "set_dbdir: moving CNID db from \"%s\" to \"%s\" failed",
                 bdata(oldpath), dbdir);
             EC_FAIL;
         }
+
     }
 
     if (lstat(bdata(newpath), &st) < 0 && mkdir(bdata(newpath), 0755 ) < 0) {
         LOG(log_error, logtype_cnid, "set_dbdir: mkdir failed for %s", bdata(newpath));
-        return -1;
+        EC_FAIL;
     }
 
 EC_CLEANUP:
     bdestroy(oldpath);
     bdestroy(newpath);
-    bdestroy(cmd);
     EC_EXIT;
 }
 
index 7fbae2dfc07838c91bce2aa1d5975eafcd5b902a..25067af051bdb22219f500ce48cbf295003dda52 100644 (file)
@@ -181,6 +181,7 @@ extern char *stripped_slashes_basename(char *p);
 extern int lchdir(const char *dir);
 extern void randombytes(void *buf, int n);
 extern int daemonize(int nochdir, int noclose);
+extern int run_cmd(const char *cmd, char **cmd_argv);
 
 /******************************************************************
  * cnid.c
index 7d66fb615360dbc39efdc29a9e9733300e4ab2d9..56c3e168eaea05c05705464a0f21830aedf60c03 100644 (file)
@@ -32,6 +32,7 @@
 #include <dirent.h>
 #include <sys/time.h>
 #include <time.h>
+#include <sys/wait.h>
 
 #include <atalk/adouble.h>
 #include <atalk/ea.h>
@@ -41,6 +42,7 @@
 #include <atalk/util.h>
 #include <atalk/unix.h>
 #include <atalk/compat.h>
+#include <atalk/errchk.h>
 
 /* close all FDs >= a specified value */
 static void closeall(int fd)
@@ -51,6 +53,55 @@ static void closeall(int fd)
         close(fd++);
 }
 
+/*!
+ * Run command in a child and wait for it to finish
+ */
+int run_cmd(const char *cmd, char **cmd_argv)
+{
+    EC_INIT;
+    pid_t pid, wpid;
+    sigset_t sigs, oldsigs;
+       int status = 0;
+
+    sigfillset(&sigs);
+    pthread_sigmask(SIG_SETMASK, &sigs, &oldsigs);
+
+    if ((pid = fork()) < 0) {
+        LOG(log_error, logtype_default, "run_cmd: fork: %s", strerror(errno));
+        return -1;
+    }
+
+    if (pid == 0) {
+        /* child */
+        closeall(3);
+        execvp("mv", cmd_argv);
+    }
+
+    /* parent */
+       while ((wpid = waitpid(pid, &status, 0)) < 0) {
+           if (errno == EINTR)
+            continue;
+           break;
+       }
+       if (wpid != pid) {
+           LOG(log_error, logtype_default, "waitpid(%d): %s", (int)pid, strerror(errno));
+        EC_FAIL;
+       }
+
+    if (WIFEXITED(status))
+        status = WEXITSTATUS(status);
+    else if (WIFSIGNALED(status))
+        status = WTERMSIG(status);
+
+    LOG(log_note, logtype_default, "run_cmd(\"%s\"): status: %d", cmd, status);
+
+EC_CLEANUP:
+    if (status != 0)
+        ret = status;
+    pthread_sigmask(SIG_SETMASK, &oldsigs, NULL);
+    EC_EXIT;
+}
+
 /*!
  * Daemonize
  *