diff options
| author | Michael Forney <mforney@mforney.org> | 2017-02-27 09:26:59 -0800 |
|---|---|---|
| committer | Michael Forney <mforney@mforney.org> | 2017-02-27 09:28:37 -0800 |
| commit | 2513d3050282a0870eb22c8d394c4b50dca9bd1b (patch) | |
| tree | c2b0c3dde228fab6ad1b03039528a977c65457b1 /util | |
| parent | 858e99ecdbb611c149434bf0381a2155ec3f3bf4 (diff) | |
Move util -> src
Diffstat (limited to 'util')
| -rw-r--r-- | util/applyperms.c | 436 | ||||
| -rw-r--r-- | util/gen.rc | 10 | ||||
| -rw-r--r-- | util/shutdown.c | 87 |
3 files changed, 0 insertions, 533 deletions
diff --git a/util/applyperms.c b/util/applyperms.c deleted file mode 100644 index f707af34..00000000 --- a/util/applyperms.c +++ /dev/null @@ -1,436 +0,0 @@ -/* -See LICENSE file for copyright and license details. - -This program is meant to be run by a git hook to fix the permissions of files -based on a .perms file in the repository - -It can also be run with the -d flag on any directory containing .perms in order -to apply the permissions specified by that file. - -Security considerations: -If the repository previously contained a world or group readable directory which -has become secret, the names of the new files in that directory will become -temporarily visible because git checks out the files before this program is run. -*/ -#define _POSIX_C_SOURCE 200809L -#include <errno.h> -#include <fcntl.h> -#include <libgen.h> -#include <spawn.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdnoreturn.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <unistd.h> - -#define PERMS_FILE ".perms" - -struct perm { - mode_t mode; - char *name; - bool attempted; -}; - -struct special { - struct perm *perms; - int len; -}; - -extern char **environ; - -static char *prog; -static dev_t rootdev; -static int rootfd = AT_FDCWD; -static struct special oldsp, newsp; -static int status; - -static void -verror(char *fmt, va_list ap) -{ - status = 1; - vfprintf(stderr, fmt, ap); - if (fmt[0] && fmt[strlen(fmt)-1] == ':') - fprintf(stderr, " %s", strerror(errno)); - fputc('\n', stderr); -} - -static void -error(char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - verror(fmt, ap); - va_end(ap); -} - -static noreturn void -die(char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - verror(fmt, ap); - va_end(ap); - - exit(1); -} - -static FILE * -spawn(char **argv, pid_t *pid) -{ - FILE *f; - int fd[2]; - posix_spawn_file_actions_t actions; - - if (pipe(fd) < 0) - die("pipe:"); - f = fdopen(fd[0], "r"); - if (!f) - die("fdopen:"); - if ((errno = posix_spawn_file_actions_init(&actions)) > 0) - die("posix_spawn_file_actions_init:"); - if ((errno = posix_spawn_file_actions_addclose(&actions, fd[0])) > 0) - die("posix_spawn_file_actions_adddup2:"); - if ((errno = posix_spawn_file_actions_adddup2(&actions, fd[1], 1)) > 0) - die("posix_spawn_file_actions_adddup2:"); - if ((errno = posix_spawnp(pid, argv[0], &actions, NULL, argv, environ)) > 0) - die("posix_spawnp:"); - posix_spawn_file_actions_destroy(&actions); - close(fd[1]); - - return f; -} - -static void -readspecial(struct special *sp, FILE *f) -{ - char *line = NULL, *s, *mode; - size_t size = 0; - ssize_t n; - - while ((n = getline(&line, &size, f)) >= 0) { - if (line[n-1] == '\n') - line[--n] = '\0'; - mode = s = line; - s = strchr(s, ' '); - if (!s || s == mode) - die("malformed permissions file: %s", PERMS_FILE); - *s++ = '\0'; - sp->perms = realloc(sp->perms, (sp->len + 1) * sizeof(*sp->perms)); - if (!sp->perms) - die("realloc:"); - sp->perms[sp->len].name = strdup(s); - if (!sp->perms[sp->len].name) - die("strdup:"); - sp->perms[sp->len].mode = strtoul(mode, &s, 8); - sp->perms[sp->len].attempted = false; - if (*s) - die("invalid mode: %s", mode); - ++sp->len; - } -} - -static void -gitspecial(struct special *sp, const char *rev) -{ - char object[41 + sizeof(PERMS_FILE)]; - char *argv[] = {"git", "show", object, 0}; - FILE *f; - pid_t pid; - int st; - - if (snprintf(object, sizeof(object), "%s:%s", rev, PERMS_FILE) >= (int)sizeof(object)) - die("revision is too large: %s", rev); - f = spawn(argv, &pid); - readspecial(sp, f); - fclose(f); - - if (waitpid(pid, &st, 0) < 0) - die("waitpid:"); - if (!(WIFEXITED(st) && WEXITSTATUS(st) == 0)) - die("child process failed"); -} - -static int -chmod_v(const char *path, mode_t mode) -{ - printf("chmod(\"%s\", %#o)\n", path, mode); - return fchmodat(rootfd, path, mode, 0); -} - -static int -mkdir_v(const char *path, mode_t mode) -{ - printf("mkdir(\"%s\", %#o)\n", path, mode); - return mkdirat(rootfd, path, mode); -} - -static int -defperm(const char *name) -{ - struct stat st; - mode_t mode; - - if (fstatat(rootfd, name, &st, AT_SYMLINK_NOFOLLOW) < 0) - return -1; - if (st.st_dev != rootdev) { - errno = EXDEV; - return -1; - } - switch (st.st_mode & S_IFMT) { - case S_IFREG: - mode = st.st_mode&S_IXUSR ? 0755 : 0644; - break; - case S_IFDIR: - mode = 0755; - break; - case S_IFLNK: - return 0; - default: - errno = EINVAL; - return -1; - } - if ((st.st_mode&~S_IFMT) == mode) - return 0; - return chmod_v(name, mode); -} - -static int -specialperm(struct perm *p) -{ - struct stat st; - - if (p->attempted) - return 0; - p->attempted = true; - if (fstatat(rootfd, p->name, &st, AT_SYMLINK_NOFOLLOW) < 0) { - if (errno != ENOENT || !S_ISDIR(p->mode)) - return -1; - if (mkdir_v(p->name, p->mode & ~S_IFMT) < 0) - return -1; - return 0; - } - if (st.st_dev != rootdev) { - errno = EXDEV; - return -1; - } - if (st.st_mode == p->mode) - return 0; - if ((st.st_mode&S_IFMT) != (p->mode&S_IFMT)) { - errno = EINVAL; - return -1; - } - return chmod_v(p->name, p->mode & ~S_IFMT); -} - -static void -specialperms(void) -{ - int i = 0, j = 0, n; - char *dirs[oldsp.len], **dir = dirs; - - while (i < oldsp.len || j < newsp.len) { - if (i == oldsp.len) - n = 1; - else if (j == newsp.len) - n = -1; - else - n = strcmp(oldsp.perms[i].name, newsp.perms[j].name); - if (n >= 0) { - if (specialperm(&newsp.perms[j]) < 0 && errno != EXDEV) - error("specialperm:"); - ++j; - if (n == 0) - ++i; - continue; - } - switch (oldsp.perms[i].mode&S_IFMT) { - case S_IFDIR: - *dir++ = oldsp.perms[i].name; - break; - default: - if (defperm(oldsp.perms[i].name) < 0) switch (errno) { - case ENOENT: - case EXDEV: - break; - default: - error("defperm:"); - } - } - ++i; - } - /* delete directories in reverse order */ - while (dir > dirs) { - --dir; - if (rmdir(*dir) < 0) switch (errno) { - case ENOENT: - case ENOTEMPTY: - break; - default: - error("rmdir:"); - } - } -} - -static int -setperm(const char *name) -{ - int i; - - for (i = 0; i < newsp.len; ++i) { - if (strcmp(name, newsp.perms[i].name) == 0) - return specialperm(&newsp.perms[i]); - } - return defperm(name); -} - -static void -setroot(const char *root) -{ - struct stat st; - - rootfd = open(root, O_RDONLY); - if (rootfd < 0) - die("open %s:", root); - if (fstat(rootfd, &st) < 0) - die("fstat:", root); - rootdev = st.st_dev; -} - -static void -gitupdate(char *old, char *new) -{ - char *argv_diff[] = {"git", "diff", "--name-only", "-z", old, new, 0}; - char *argv_new[] = {"git", "ls-tree", "--name-only", "--full-tree", "-z", "-r", new, 0}; - FILE *f; - pid_t pid; - struct { - char *buf; - size_t size; - } lines[2] = {0}; - ssize_t n; - int cur = 0, st; - char *root, *path, *diff, *s; - - root = getenv("GIT_WORK_TREE"); - setroot(root ? root : "."); - if (old) - gitspecial(&oldsp, old); - gitspecial(&newsp, new); - - f = spawn(old ? argv_diff : argv_new, &pid); - umask(0); - while ((n = getdelim(&lines[cur].buf, &lines[cur].size, '\0', f)) >= 0) { - path = lines[cur].buf; - if (strcmp(path, PERMS_FILE) == 0) { - specialperms(); - continue; - } - if (setperm(path) < 0) switch (errno) { - case ENOENT: - continue; - case EXDEV: - break; - default: - error("setperm %s:", path); - } - /* find the first difference from the previous path */ - diff = path; - if (lines[!cur].buf) - for (s = lines[!cur].buf; *s && *s == *diff; ++s, ++diff); - /* set permissions on each parent directory after that difference */ - for (s = path + n; s >= diff; --s) { - if (*s != '/') - continue; - *s = '\0'; - if (setperm(path) < 0) - error("setperm %s:", path); - *s = '/'; - } - cur = !cur; - } - fclose(f); - - if (waitpid(pid, &st, 0) < 0) - die("waitpid:"); - if (!(WIFEXITED(st) && WEXITSTATUS(st) == 0)) - die("child process failed"); -} - -static void -applyspecial(void) -{ - int fd; - FILE *f; - - fd = openat(rootfd, ".perms", O_RDONLY); - if (fd < 0) - die("open .perms:"); - f = fdopen(fd, "r"); - if (!f) - die("fdopen:"); - readspecial(&newsp, f); - fclose(f); - umask(0); - specialperms(); -} - -static void -usage() -{ - fprintf(stderr, "usage: %s [[old] new] | %s -d dir\n", prog, prog); - exit(2); -} - -int -main(int argc, char *argv[]) -{ - int dflag = 0; - char *old, *new; - - prog = basename(argv[0]); - for (++argv, --argc; argc && (*argv)[0] == '-' && (*argv)[1]; ++argv, --argc) { - switch ((*argv)[1]) { - case 'd': - if (!*++argv) - usage(); - --argc; - setroot(*argv); - dflag = 1; - break; - default: - usage(); - } - } - - if (dflag) { - if (argc) - usage(); - applyspecial(); - return status; - } - - switch (argc) { - case 0: - old = NULL; - new = "HEAD"; - break; - case 1: - old = NULL; - new = argv[0]; - break; - case 2: - old = argv[0]; - new = argv[1]; - break; - default: - usage(); - } - gitupdate(old, new); - return status; -} diff --git a/util/gen.rc b/util/gen.rc deleted file mode 100644 index b58854a5..00000000 --- a/util/gen.rc +++ /dev/null @@ -1,10 +0,0 @@ -set srcdir '$dir' -cflags\ - -Wall -Wextra -Wno-unused-parameter -pedantic\ - '-std=c11' - -exe applyperms applyperms.c -file libexec/oasis/applyperms '$outdir'/applyperms 755 - -exe shutdown shutdown.c -file libexec/oasis/shutdown '$outdir'/shutdown 755 diff --git a/util/shutdown.c b/util/shutdown.c deleted file mode 100644 index 06ff3e55..00000000 --- a/util/shutdown.c +++ /dev/null @@ -1,87 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#define _XOPEN_SOURCE 700 -#include <errno.h> -#include <mntent.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdnoreturn.h> -#include <string.h> -#include <sys/mount.h> -#include <sys/reboot.h> -#include <unistd.h> - -static noreturn void -usage() -{ - fprintf(stderr, "usage: shutdown [-hpr]\n"); - exit(2); -} - -int -main(int argc, char *argv[]) -{ - FILE *fp; - char **dirs = NULL; - size_t n = 0; - struct mntent *mnt; - int cmd = RB_POWER_OFF; - - while (*++argv && (*argv)[0] == '-' && (*argv)[1]) { - switch ((*argv)[1]) { - case 'h': - cmd = RB_HALT_SYSTEM; - break; - case 'p': - cmd = RB_POWER_OFF; - break; - case 'r': - cmd = RB_AUTOBOOT; - break; - default: - usage(); - } - } - if (*argv) - usage(); - - if (getsid(0) != getpid()) { - fprintf(stderr, "must be session leader\n"); - return 1; - } - - sync(); - kill(-1, SIGTERM); - sleep(2); - kill(-1, SIGKILL); - - sync(); - fp = setmntent("/proc/mounts", "r"); - if (!fp) { - perror("setmntent"); - goto reboot; - } - while ((mnt = getmntent(fp))) { - if (!(dirs = realloc(dirs, ++n * sizeof(*dirs)))) { - perror("realloc"); - break; - } - if (!(dirs[n - 1] = strdup(mnt->mnt_dir))) { - perror("strdup"); - break; - } - } - endmntent(fp); - while (n) { - if (umount(dirs[--n]) < 0) - fprintf(stderr, "umount %s: %s\n", dirs[n], strerror(errno)); - free(dirs[n]); - } - free(dirs); - -reboot: - if (reboot(cmd) < 0) { - perror("reboot"); - return 1; - } -} |
