Changeset View
Changeset View
Standalone View
Standalone View
sbin/reboot/reboot.c
| Show First 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | if (WIFEXITED(status)) { | ||||
| E("zfsbootcfg returned %d", e); | E("zfsbootcfg returned %d", e); | ||||
| } | } | ||||
| if (WIFSIGNALED(status)) | if (WIFSIGNALED(status)) | ||||
| E("zfsbootcfg died with signal %d", WTERMSIG(status)); | E("zfsbootcfg died with signal %d", WTERMSIG(status)); | ||||
| E("zfsbootcfg unexpected status %d", status); | E("zfsbootcfg unexpected status %d", status); | ||||
| } | } | ||||
| static void | static void | ||||
| write_nextboot(const char *fn, const char *env, bool force) | write_nextboot(const char *fn, const char *env, bool append, bool force) | ||||
| { | { | ||||
| char tmp[PATH_MAX]; | char tmp[PATH_MAX]; | ||||
| FILE *fp; | FILE *fp; | ||||
| struct statfs sfs; | struct statfs sfs; | ||||
| int tmpfd; | ssize_t ret; | ||||
| int fd, tmpfd; | |||||
| bool supported = false; | bool supported = false; | ||||
| bool zfs = false; | bool zfs = false; | ||||
| if (statfs("/boot", &sfs) != 0) | if (statfs("/boot", &sfs) != 0) | ||||
| err(1, "statfs /boot"); | err(1, "statfs /boot"); | ||||
| if (strcmp(sfs.f_fstypename, "ufs") == 0) { | if (strcmp(sfs.f_fstypename, "ufs") == 0) { | ||||
| /* | /* | ||||
| * Only UFS supports the full nextboot protocol. | * Only UFS supports the full nextboot protocol. | ||||
| Show All 11 Lines | if (slash != NULL) | ||||
| *slash = '\0'; | *slash = '\0'; | ||||
| zfsbootcfg(sfs.f_mntfromname, force); | zfsbootcfg(sfs.f_mntfromname, force); | ||||
| } | } | ||||
| if (strlcpy(tmp, fn, sizeof(tmp)) >= sizeof(tmp)) | if (strlcpy(tmp, fn, sizeof(tmp)) >= sizeof(tmp)) | ||||
| E("Path too long %s", fn); | E("Path too long %s", fn); | ||||
| if (strlcat(tmp, ".XXXXXX", sizeof(tmp)) >= sizeof(tmp)) | if (strlcat(tmp, ".XXXXXX", sizeof(tmp)) >= sizeof(tmp)) | ||||
| E("Path too long %s", fn); | E("Path too long %s", fn); | ||||
| tmpfd = mkstemp(tmp); | tmpfd = mkstemp(tmp); | ||||
| if (tmpfd == -1) | if (tmpfd == -1) | ||||
| E("mkstemp %s", tmp); | E("mkstemp %s", tmp); | ||||
| fp = fdopen(tmpfd, "w"); | fp = fdopen(tmpfd, "w"); | ||||
| if (fp == NULL) | if (fp == NULL) | ||||
| E("fdopen %s", tmp); | E("fdopen %s", tmp); | ||||
| if (append) { | |||||
| if ((fd = open(fn, O_RDONLY)) < 0) { | |||||
| if (errno != ENOENT) | |||||
| E("open %s", fn); | |||||
| } else { | |||||
| do { | |||||
| ret = copy_file_range(fd, NULL, tmpfd, NULL, | |||||
| SSIZE_MAX, 0); | |||||
| if (ret < 0) | |||||
| E("copy %s to %s", fn, tmp); | |||||
| } while (ret > 0); | |||||
| close(fd); | |||||
| } | |||||
| } | |||||
| if (fprintf(fp, "%s%s", | if (fprintf(fp, "%s%s", | ||||
| supported ? "nextboot_enable=\"YES\"\n" : "", | supported ? "nextboot_enable=\"YES\"\n" : "", | ||||
| env != NULL ? env : "") < 0) { | env != NULL ? env : "") < 0) { | ||||
| int e; | int e; | ||||
| e = errno; | e = errno; | ||||
| if (unlink(tmp)) | if (unlink(tmp)) | ||||
| warn("unlink %s", tmp); | warn("unlink %s", tmp); | ||||
| ▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | if (env == NULL) | ||||
| errx(1, "No memory to build env array"); | errx(1, "No memory to build env array"); | ||||
| free(oldenv); | free(oldenv); | ||||
| } | } | ||||
| /* | /* | ||||
| * Different options are valid for different programs. | * Different options are valid for different programs. | ||||
| */ | */ | ||||
| #define GETOPT_REBOOT "cDde:fk:lNno:pqr" | #define GETOPT_REBOOT "cDde:fk:lNno:pqr" | ||||
| #define GETOPT_NEXTBOOT "De:fk:o:" | #define GETOPT_NEXTBOOT "aDe:fk:o:" | ||||
| int | int | ||||
| main(int argc, char *argv[]) | main(int argc, char *argv[]) | ||||
| { | { | ||||
| struct utmpx utx; | struct utmpx utx; | ||||
| const struct passwd *pw; | const struct passwd *pw; | ||||
| struct stat st; | struct stat st; | ||||
| int ch, howto = 0, i, sverrno; | int ch, howto = 0, i, sverrno; | ||||
| bool Dflag, fflag, lflag, Nflag, nflag, qflag; | bool aflag, Dflag, fflag, lflag, Nflag, nflag, qflag; | ||||
| uint64_t pageins; | uint64_t pageins; | ||||
| const char *user, *kernel = NULL, *getopts = GETOPT_REBOOT; | const char *user, *kernel = NULL, *getopts = GETOPT_REBOOT; | ||||
| char *env = NULL, *v; | char *env = NULL, *v; | ||||
| if (strstr(getprogname(), "halt") != NULL) { | if (strstr(getprogname(), "halt") != NULL) { | ||||
| dohalt = true; | dohalt = true; | ||||
| howto = RB_HALT; | howto = RB_HALT; | ||||
| } else if (strcmp(getprogname(), "nextboot") == 0) { | } else if (strcmp(getprogname(), "nextboot") == 0) { | ||||
| donextboot = true; | donextboot = true; | ||||
| getopts = GETOPT_NEXTBOOT; /* Note: reboot's extra opts return '?' */ | getopts = GETOPT_NEXTBOOT; /* Note: reboot's extra opts return '?' */ | ||||
| } else { | } else { | ||||
| /* reboot */ | /* reboot */ | ||||
| howto = 0; | howto = 0; | ||||
| } | } | ||||
| Dflag = fflag = lflag = Nflag = nflag = qflag = false; | aflag = Dflag = fflag = lflag = Nflag = nflag = qflag = false; | ||||
| while ((ch = getopt(argc, argv, getopts)) != -1) { | while ((ch = getopt(argc, argv, getopts)) != -1) { | ||||
| switch(ch) { | switch(ch) { | ||||
| case 'a': | |||||
| aflag = true; | |||||
| break; | |||||
| case 'c': | case 'c': | ||||
| howto |= RB_POWERCYCLE; | howto |= RB_POWERCYCLE; | ||||
| break; | break; | ||||
| case 'D': | case 'D': | ||||
| Dflag = true; | Dflag = true; | ||||
| break; | break; | ||||
| case 'd': | case 'd': | ||||
| howto |= RB_DUMP; | howto |= RB_DUMP; | ||||
| ▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | if (!fflag) { | ||||
| if (!S_ISREG(sb.st_mode)) | if (!S_ISREG(sb.st_mode)) | ||||
| errx(1, "%s is not a file", k); | errx(1, "%s is not a file", k); | ||||
| free(k); | free(k); | ||||
| } | } | ||||
| add_env(&env, "kernel", kernel); | add_env(&env, "kernel", kernel); | ||||
| } | } | ||||
| if (env != NULL) | if (env != NULL) | ||||
| write_nextboot(PATH_NEXTBOOT, env, fflag); | write_nextboot(PATH_NEXTBOOT, env, aflag, fflag); | ||||
| if (donextboot) | if (donextboot) | ||||
| exit (0); | exit (0); | ||||
| /* Log the reboot. */ | /* Log the reboot. */ | ||||
| if (!lflag) { | if (!lflag) { | ||||
| if ((user = getlogin()) == NULL) | if ((user = getlogin()) == NULL) | ||||
| user = (pw = getpwuid(getuid())) ? | user = (pw = getpwuid(getuid())) ? | ||||
| pw->pw_name : "???"; | pw->pw_name : "???"; | ||||
| ▲ Show 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | restart: | ||||
| errx(1, "%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "", | errx(1, "%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "", | ||||
| strerror(sverrno)); | strerror(sverrno)); | ||||
| /* NOTREACHED */ | /* NOTREACHED */ | ||||
| } | } | ||||
| static void | static void | ||||
| usage(void) | usage(void) | ||||
| { | { | ||||
| if (donextboot) { | |||||
| (void)fprintf(stderr, dohalt ? | fprintf(stderr, "usage: nextboot [-aDf] " | ||||
| "[-e name=value] [-k kernel] [-o options]\n"); | |||||
| } else { | |||||
| fprintf(stderr, dohalt ? | |||||
| "usage: halt [-clNnpq] [-k kernel]\n" : | "usage: halt [-clNnpq] [-k kernel]\n" : | ||||
| "usage: reboot [-cdlNnpqr] [-k kernel]\n"); | "usage: reboot [-cdlNnpqr] [-k kernel]\n"); | ||||
| } | |||||
| exit(1); | exit(1); | ||||
| } | } | ||||
| static uint64_t | static uint64_t | ||||
| get_pageins(void) | get_pageins(void) | ||||
| { | { | ||||
| uint64_t pageins; | uint64_t pageins; | ||||
| size_t len; | size_t len; | ||||
| Show All 9 Lines | |||||