s6-instance-create.c (2882B)
1 /* ISC license. */ 2 3 #include <errno.h> 4 #include <stdint.h> 5 #include <string.h> 6 #include <sys/stat.h> 7 8 #include <skalibs/bytestr.h> 9 #include <skalibs/types.h> 10 #include <skalibs/sgetopt.h> 11 #include <skalibs/tai.h> 12 #include <skalibs/strerr.h> 13 #include <skalibs/djbunix.h> 14 15 #include <s6/supervise.h> 16 17 #define USAGE "s6-instance-create [ -d | -D ] [ -f ] [ -P ] [ -t timeout ] service instancename" 18 #define dieusage() strerr_dieusage(100, USAGE) 19 20 static void cleanup (char const *s) 21 { 22 int e = errno ; 23 rm_rf(s) ; 24 errno = e ; 25 } 26 27 int main (int argc, char const *const *argv) 28 { 29 tain tto = TAIN_INFINITE_RELATIVE ; 30 size_t namelen ; 31 uint32_t options = 16 ; 32 PROG = "s6-instance-create" ; 33 { 34 unsigned int t = 0 ; 35 subgetopt l = SUBGETOPT_ZERO ; 36 for (;;) 37 { 38 int opt = subgetopt_r(argc, argv, "dDfPt:", &l) ; 39 if (opt == -1) break ; 40 switch (opt) 41 { 42 case 'd' : options |= 12 ; break ; 43 case 'D' : options |= 4 ; options &= ~8U ; break ; 44 case 'f' : options |= 1 ; break ; 45 case 'P' : options |= 2 ; break ; 46 case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ; 47 default : dieusage() ; 48 } 49 } 50 argc -= l.ind ; argv += l.ind ; 51 if (t) tain_from_millisecs(&tto, t) ; 52 } 53 if (argc < 2) dieusage() ; 54 55 namelen = strlen(argv[1]) ; 56 if (!argv[1][0] || argv[1][0] == '.' || byte_in(argv[1], namelen, " \t\f\r\n", 5) < namelen) 57 strerr_dief1x(100, "invalid instance name") ; 58 59 { 60 mode_t m = umask(0) ; 61 size_t svlen = strlen(argv[0]) ; 62 char fn[svlen + 11] ; 63 memcpy(fn, argv[0], svlen) ; 64 memcpy(fn + svlen, "/instances", 11) ; 65 if (mkdir(fn, 0755) == -1 && errno != EEXIST) 66 strerr_diefu2sys(111, "mkdir ", fn) ; 67 fn[svlen + 9] = 0 ; 68 if (mkdir(fn, 0755) == -1 && errno != EEXIST) 69 strerr_diefu2sys(111, "mkdir ", fn) ; 70 umask(m) ; 71 } 72 73 s6_instance_chdirservice(argv[0]) ; 74 75 tain_now_set_stopwatch_g() ; 76 tain_add_g(&tto, &tto) ; 77 78 { 79 char sv[namelen + 14] ; 80 char const *p = sv ; 81 memcpy(sv, "../instances/", 13) ; 82 memcpy(sv + 13, argv[1], namelen + 1) ; 83 { 84 struct stat st ; 85 if (stat(sv, &st) == 0) 86 if (!S_ISDIR(st.st_mode)) 87 strerr_dief3x(100, "unexpected file preventing instance creation at ", argv[0], sv+2) ; 88 else 89 strerr_dief3x(100, "instance appears to already exist at ", argv[0], sv+2) ; 90 else if (errno != ENOENT) 91 strerr_diefu3sys(111, "stat ", argv[0], sv+2) ; 92 } 93 if (!hiercopy("../template", sv)) 94 { 95 cleanup(sv) ; 96 strerr_diefu5sys(111, "copy ", argv[0], "/template to ", argv[0], sv+2) ; 97 } 98 if (s6_supervise_link_names_g(".", &p, argv + 1, 1, options, &tto) == -1) 99 { 100 cleanup(sv) ; 101 strerr_diefu4sys(errno == ETIMEDOUT ? 99 : 111, "create instance of ", argv[0], " named ", argv[1]) ; 102 } 103 } 104 return 0 ; 105 }