chiark / gitweb /
Get permissions right on restored databases (issue #56).
[disorder] / server / dump.c
index fb0741503808e261ad532481ba32c08a23564017..74f1c466360a62fccfffc0310b4eb04e053ac313 100644 (file)
  */
 #include "disorder-server.h"
 
+enum {
+  NO_SETUID = UCHAR_MAX + 1,
+};
+
 static const struct option options[] = {
   { "help", no_argument, 0, 'h' },
   { "version", no_argument, 0, 'V' },
@@ -31,6 +35,7 @@ static const struct option options[] = {
   { "recover-fatal", no_argument, 0, 'R' },
   { "recompute-aliases", no_argument, 0, 'a' },
   { "remove-pathless", no_argument, 0, 'P' },
+  { "no-setuid", no_argument, 0, NO_SETUID },
   { 0, 0, 0, 0 }
 };
 
@@ -48,6 +53,7 @@ static void help(void) {
          "  --recover, -r            Run database recovery\n"
          "  --recompute-aliases, -a  Recompute aliases\n"
          "  --remove-pathless, -P    Remove pathless tracks\n"
+          "  --no-setuid              Do not become jukebox user\n"
          "  --debug                  Debug mode\n");
   xfclose(stdout);
   exit(0);
@@ -365,12 +371,13 @@ fail:
 int main(int argc, char **argv) {
   int n, dump = 0, undump = 0, recover = TRACKDB_NO_RECOVER, recompute = 0;
   int remove_pathless = 0, fd;
+  int changeuid = !getuid();
   const char *path;
   char *tmp;
   FILE *fp;
 
   mem_init();
-  while((n = getopt_long(argc, argv, "hVc:dDurRaP", options, 0)) >= 0) {
+  while((n = getopt_long(argc, argv, "hVc:dDurRaPR", options, 0)) >= 0) {
     switch(n) {
     case 'h': help();
     case 'V': version("disorder-dump");
@@ -382,6 +389,7 @@ int main(int argc, char **argv) {
     case 'R': recover = TRACKDB_FATAL_RECOVER; break;
     case 'a': recompute = 1; break;
     case 'P': remove_pathless = 1; break;
+    case NO_SETUID: changeuid = 0; break;
     default: disorder_fatal(0, "invalid option");
     }
   }
@@ -415,12 +423,15 @@ int main(int argc, char **argv) {
     if(rename(tmp, path) < 0)
       disorder_fatal(errno, "error renaming %s to %s", tmp, path);
   } else if(undump) {
+    /* Open the dump file before changing UID */
+    if(!(fp = fopen(path, "r")))
+      disorder_fatal(errno, "error opening %s", path);
+    if(changeuid)
+      become_mortal();
     /* the databases or logfiles might end up with wrong permissions
      * if new ones are created */
     if(getuid() == 0)
       disorder_info("you might need to chown database files");
-    if(!(fp = fopen(path, "r")))
-      disorder_fatal(errno, "error opening %s", path);
     do_undump(fp, path, remove_pathless);
     xfclose(fp);
   } else if(recompute) {