runsvchdir.c (2185B)
1 #include <sys/types.h> 2 #include <sys/stat.h> 3 #include <unistd.h> 4 #include <stdio.h> 5 #include "strerr.h" 6 #include "error.h" 7 #include "buffer.h" 8 9 #define USAGE " dir" 10 #define SVDIR "/etc/runit/runsvdir" 11 12 static char *progname; 13 static char *new; 14 15 static void usage( void ) { strerr_die4x(1, "usage: ", progname, USAGE, "\n"); } 16 17 static void fatal(char *m1, char *m2) 18 { 19 strerr_die5sys(111, progname, ": fatal: ", m1, m2, ": "); 20 } 21 static void fatalx(char *m1, char *m2) 22 { 23 strerr_die4x(111, progname, ": fatal: ", m1, m2); 24 } 25 static void warn(char *m1, char *m2) 26 { 27 strerr_warn5(progname, ": fatal: ", m1, m2, ": ", &strerr_sys); 28 } 29 30 int main (int argc, char **argv) 31 { 32 struct stat s; 33 int dev; 34 int ino; 35 36 progname =*argv++; 37 if (! argv || ! *argv) usage(); 38 39 new =*argv; 40 if (new[0] == '.') fatalx(new, ": must not start with a dot."); 41 if (chdir(SVDIR) == -1) fatal("unable to chdir: ", SVDIR); 42 43 if (stat(new, &s) == -1) { 44 if (errno == error_noent) fatal(new, 0); 45 fatal("unable to stat: ", new); 46 } 47 if (! S_ISDIR(s.st_mode)) fatalx(new, "not a directory."); 48 ino =s.st_ino; 49 dev =s.st_dev; 50 if (stat("current", &s) == -1) fatal("unable to stat: ", "current"); 51 if ((s.st_ino == ino) && (s.st_dev == dev)) { 52 buffer_puts(buffer_1, "runsvchdir: "); 53 buffer_puts(buffer_1, new); 54 buffer_puts(buffer_1, ": current.\n"); 55 buffer_flush(buffer_1); 56 _exit(0); 57 } 58 59 if (unlink("current.new") == -1) 60 if (errno != error_noent) fatal("unable to unlink: ", "current.new"); 61 if (symlink(new, "current.new") == -1) 62 fatal("unable to create: current.new -> ", new); 63 if (unlink("previous") == -1) 64 if (errno != error_noent) fatal("unable to unlink: ", "previous"); 65 if (rename("current", "previous") == -1) 66 fatal("unable to copy: current to ", "previous"); 67 if (rename("current.new", "current") == -1) { 68 warn("unable to move: current.new to ", "current"); 69 if (rename("previous", "current") == -1) 70 fatal("unable to move previous back to ", "current"); 71 _exit(111); 72 } 73 buffer_puts(buffer_1, "runsvchdir: "); 74 buffer_puts(buffer_1, new); 75 buffer_puts(buffer_1, ": now current.\n"); 76 buffer_flush(buffer_1); 77 _exit(0); 78 }