/* ISC license. */ #include #include #include #include #include #include #include #include #include #include #include #include #include int s6rc_repo_compile (char const *repo, char const *set, char const *const *rxs, uint8_t nrxs, char *oldc, unsigned int verbosity, char const *fdhuser) { size_t repolen = strlen(repo) ; size_t setlen = strlen(set) ; size_t totrxlen = 0 ; int needprefix = strcmp(set, ".ref") ; char newc[repolen + setlen + 45] ; memcpy(newc, repo, repolen) ; memcpy(newc + repolen, "/compiled/.", 11) ; memcpy(newc + repolen + 11, set, setlen) ; newc[repolen + 11 + setlen] = ':' ; timestamp_g(newc + repolen + 12 + setlen) ; memcpy(newc + repolen + 37 + setlen, ":XXXXXX", 8) ; memcpy(oldc, newc, repolen + 10) ; if (mkntemp(newc) == -1) { strerr_warnfu2sys("mkntemp ", newc) ; return -1 ; } for (uint8_t i = 0 ; i < nrxs ; i++) totrxlen += strlen(rxs[i]) + 1 ; { pid_t pid ; size_t m = 0 ; int wstat ; char const *argv[9 + nrxs] ; char fmtv[UINT_FMT] ; char src[nrxs * (repolen + 10 + (needprefix ? setlen + 1 : 0)) + totrxlen] ; char *w = src ; fmtv[uint_fmt(fmtv, verbosity)] = 0 ; argv[m++] = S6RC_BINPREFIX "s6-rc-compile" ; argv[m++] = "-v"; argv[m++] = fmtv ; argv[m++] = "-b" ; if (fdhuser) { argv[m++] = "-h" ; argv[m++] = fdhuser ; } argv[m++] = "--" ; argv[m++] = newc ; for (uint8_t i = 0 ; i < nrxs ; i++) { size_t rxlen = strlen(rxs[i]) ; argv[m++] = w ; memcpy(w, repo, repolen) ; w += repolen ; memcpy(w, "/sources/", 9) ; w += 9 ; if (needprefix) { memcpy(w, set, setlen) ; w += setlen ; *w++ = '/' ; } memcpy(w, rxs[i], rxlen+1) ; w += rxlen + 1 ; } argv[m++] = 0 ; pid = cspawn(argv[0], argv, (char const *const *)environ, 0, 0, 0) ; if (!pid) { strerr_warnfu2sys("spawn ", argv[0]) ; return -1 ; } if (wait_pid(pid, &wstat) == -1) { strerr_warnfu2sys("wait for ", argv[0]) ; return -1 ; } if (WIFSIGNALED(wstat)) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, WTERMSIG(wstat))] = 0 ; strerr_warnf3x(argv[0], " crashed with signal ", fmt) ; return -1 ; } if (WEXITSTATUS(wstat)) { char fmt[UINT_FMT] ; fmt[uint_fmt(fmt, WEXITSTATUS(wstat))] = 0 ; strerr_warnf3x(argv[0], " exited with code ", fmt) ; return (WEXITSTATUS(wstat) == 1) - 1 ; } } { char fn[repolen + setlen + 11] ; memcpy(fn, newc, repolen + 10) ; memcpy(fn + repolen + 10, set, setlen + 1) ; if (!atomic_symlink4(newc + repolen + 10, fn, oldc + repolen + 10, setlen + 35)) { int e = errno ; rm_rf(newc) ; errno = e ; strerr_warnfu4sys("atomically symlink ", newc + repolen + 10, " to ", fn) ; return -1 ; } } return 1 + !!oldc[repolen + 10] ; }