diff options
-rw-r--r-- | usr/src/cmd/boot/bootadm/Makefile | 3 | ||||
-rw-r--r-- | usr/src/cmd/boot/bootadm/bootadm.c | 589 | ||||
-rw-r--r-- | usr/src/cmd/boot/scripts/boot-archive-update.ksh | 9 | ||||
-rw-r--r-- | usr/src/cmd/boot/scripts/create_ramdisk.ksh | 487 | ||||
-rw-r--r-- | usr/src/cmd/halt/halt.c | 15 | ||||
-rw-r--r-- | usr/src/cmd/svc/milestone/boot-archive.xml | 8 | ||||
-rw-r--r-- | usr/src/man/man1m/bootadm.1m | 102 |
7 files changed, 662 insertions, 551 deletions
diff --git a/usr/src/cmd/boot/bootadm/Makefile b/usr/src/cmd/boot/bootadm/Makefile index b25c45ce04..da5dbf5332 100644 --- a/usr/src/cmd/boot/bootadm/Makefile +++ b/usr/src/cmd/boot/bootadm/Makefile @@ -24,6 +24,7 @@ # # Copyright 2016 Toomas Soome <tsoome@me.com> # Copyright 2016 Nexenta Systems, Inc. +# Copyright 2018 OmniOS Community Edition (OmniOSce) Association. # PROG= bootadm @@ -43,7 +44,7 @@ POFILE= bootadm_cmd.po LDLIBS_i386= -lfdisk LDLIBS += -lficl-sys -lmd -lcryptoutil -lnvpair -lgen -ladm -lefi -LDLIBS += -lz -lbe -lzfs -lofmt $(LDLIBS_$(MACH)) +LDLIBS += -lscf -lz -lbe -lzfs -lofmt $(LDLIBS_$(MACH)) # Writing into string literals is incorrect. We need to match gcc's # behavior, which causes us to take SIGSEGV on such a write. diff --git a/usr/src/cmd/boot/bootadm/bootadm.c b/usr/src/cmd/boot/bootadm/bootadm.c index 0444c5cda7..bedca2a6b5 100644 --- a/usr/src/cmd/boot/bootadm/bootadm.c +++ b/usr/src/cmd/boot/bootadm/bootadm.c @@ -31,7 +31,7 @@ /* * bootadm(1M) is a new utility for managing bootability of * Solaris *Newboot* environments. It has two primary tasks: - * - Allow end users to manage bootability of Newboot Solaris instances + * - Allow end users to manage bootability of Newboot Solaris instances * - Provide services to other subsystems in Solaris (primarily Install) */ @@ -125,6 +125,11 @@ typedef enum { #define UFS_SIGNATURE_LIST "/var/run/grub_ufs_signatures" #define ZFS_LEGACY_MNTPT "/tmp/bootadm_mnt_zfs_legacy" +/* SMF */ +#define BOOT_ARCHIVE_FMRI "system/boot-archive:default" +#define SCF_PG_CONFIG "config" +#define SCF_PROPERTY_FORMAT "format" + /* BE defaults */ #define BE_DEFAULTS "/etc/default/be" #define BE_DFLT_BE_HAS_GRUB "BE_HAS_GRUB=" @@ -184,6 +189,17 @@ char *menu_cmds[] = { NULL }; +char *bam_formats[] = { + "hsfs", + "ufs", + "cpio", + "ufs-nocompress", + NULL +}; +#define BAM_FORMAT_UNSET -1 +#define BAM_FORMAT_HSFS 0 +short bam_format = BAM_FORMAT_UNSET; + #define OPT_ENTRY_NUM "entry" /* @@ -208,6 +224,7 @@ typedef struct { int bam_verbose; int bam_force; int bam_debug; +int bam_skip_lock; static char *prog; static subcmd_t bam_cmd; char *bam_root; @@ -309,29 +326,27 @@ static subcmd_defn_t inst_subcmds[] = { NULL, 0, NULL, 0 /* must be last */ }; -enum dircache_copy_opt { - FILE32 = 0, - FILE64, - CACHEDIR_NUM -}; +#define build_path(buf, len, root, prefix, suffix) \ + snprintf((buf), (len), "%s%s%s%s%s", (root), (prefix), get_machine(), \ + is_flag_on(IS_SPARC_TARGET) ? "" : "/amd64", (suffix)) /* * Directory specific flags: * NEED_UPDATE : the specified archive needs to be updated - * NO_MULTI : don't extend the specified archive, but recreate it + * NO_EXTEND : don't extend the specified archive, but recreate it */ #define NEED_UPDATE 0x00000001 -#define NO_MULTI 0x00000002 +#define NO_EXTEND 0x00000002 -#define set_dir_flag(id, f) (walk_arg.dirinfo[id].flags |= f) -#define unset_dir_flag(id, f) (walk_arg.dirinfo[id].flags &= ~f) -#define is_dir_flag_on(id, f) (walk_arg.dirinfo[id].flags & f ? 1 : 0) +#define set_dir_flag(f) (walk_arg.dirinfo.flags |= (f)) +#define unset_dir_flag(f) (walk_arg.dirinfo.flags &= ~(f)) +#define is_dir_flag_on(f) (walk_arg.dirinfo.flags & (f) ? 1 : 0) -#define get_cachedir(id) (walk_arg.dirinfo[id].cdir_path) -#define get_updatedir(id) (walk_arg.dirinfo[id].update_path) -#define get_count(id) (walk_arg.dirinfo[id].count) -#define has_cachedir(id) (walk_arg.dirinfo[id].has_dir) -#define set_dir_present(id) (walk_arg.dirinfo[id].has_dir = 1) +#define get_cachedir() (walk_arg.dirinfo.cdir_path) +#define get_updatedir() (walk_arg.dirinfo.update_path) +#define get_count() (walk_arg.dirinfo.count) +#define has_cachedir() (walk_arg.dirinfo.has_dir) +#define set_dir_present() (walk_arg.dirinfo.has_dir = 1) /* * dirinfo_t (specific cache directory information): @@ -375,11 +390,11 @@ typedef struct _dirinfo { * sparcfile: list of file paths for mkisofs -path-list (SPARC only) */ static struct { - int update_flags; - nvlist_t *new_nvlp; - nvlist_t *old_nvlp; - FILE *sparcfile; - dirinfo_t dirinfo[CACHEDIR_NUM]; + int update_flags; + nvlist_t *new_nvlp; + nvlist_t *old_nvlp; + FILE *sparcfile; + dirinfo_t dirinfo; } walk_arg; struct safefile { @@ -418,7 +433,7 @@ struct iso_pdesc { /* * COUNT_MAX: maximum number of changed files to justify a multisession update * BA_SIZE_MAX: maximum size of the boot_archive to justify a multisession - * update + * update */ #define COUNT_MAX 50 #define BA_SIZE_MAX (50 * 1024 * 1024) @@ -434,7 +449,8 @@ usage(void) /* archive usage */ (void) fprintf(stderr, - "\t%s update-archive [-vn] [-R altroot [-p platform]]\n", prog); + "\t%s update-archive [-vnf] [-R altroot [-p platform]] " + "[-F format]\n", prog); (void) fprintf(stderr, "\t%s list-archive [-R altroot [-p platform]]\n", prog); #if defined(_OBP) @@ -619,7 +635,7 @@ parse_args(int argc, char *argv[]) * The internal syntax and the corresponding functionality are: * -a update -- update-archive * -a list -- list-archive - * -a update-all -- (reboot to sync all mnted OS archive) + * -a update_all -- (reboot to sync all mnted OS archive) * -i install_bootloader -- install-bootloader * -m update_entry -- update-menu * -m list_entry -- list-menu @@ -630,20 +646,21 @@ parse_args(int argc, char *argv[]) * -m list_setting [entry] [value] -- list_setting * * A set of private flags is there too: - * -F -- purge the cache directories and rebuild them + * -Q -- purge the cache directories and rebuild them * -e -- use the (faster) archive update approach (used by * reboot) + * -L -- skip locking */ static void parse_args_internal(int argc, char *argv[]) { - int c, error; + int c, i, error; extern char *optarg; extern int optind, opterr; #if defined(_OBP) - const char *optstring = "a:d:fi:m:no:veFCR:p:P:XZ"; + const char *optstring = "a:d:fF:i:m:no:veQCLR:p:P:XZ"; #else - const char *optstring = "a:d:fi:m:no:veFCMR:p:P:XZ"; + const char *optstring = "a:d:fF:i:m:no:veQCMLR:p:P:XZ"; #endif /* Suppress error message from getopt */ @@ -673,8 +690,30 @@ parse_args_internal(int argc, char *argv[]) bam_force = 1; break; case 'F': + if (bam_format != BAM_FORMAT_UNSET) { + error = 1; + bam_error( + _("multiple formats specified: -%c\n"), c); + } + for (i = 0; bam_formats[i] != NULL; i++) { + if (strcmp(bam_formats[i], optarg) == 0) { + bam_format = i; + break; + } + } + if (bam_format == BAM_FORMAT_UNSET) { + error = 1; + bam_error( + _("unknown format specified: -%c %s\n"), + c, optarg); + } + break; + case 'Q': bam_purge = 1; break; + case 'L': + bam_skip_lock = 1; + break; case 'i': if (bam_cmd) { error = 1; @@ -1648,6 +1687,9 @@ bam_lock(void) struct flock lock; pid_t pid; + if (bam_skip_lock) + return; + bam_lock_fd = open(BAM_LOCK_FILE, O_CREAT|O_RDWR, LOCK_FILE_PERMS); if (bam_lock_fd < 0) { /* @@ -1707,6 +1749,9 @@ bam_unlock(void) { struct flock unlock; + if (bam_skip_lock) + return; + /* * NOP if we don't hold the lock */ @@ -1910,7 +1955,7 @@ list2file(char *root, char *tmp, char *final, line_t *start) static int setup_path(char *path) { - char *p; + char *p; int ret; struct stat sb; @@ -2047,19 +2092,19 @@ cache_close(cachefile cf) } static int -dircache_updatefile(const char *path, int what) +dircache_updatefile(const char *path) { - int ret, exitcode; - char buf[4096 * 4]; - FILE *infile; - cachefile outfile, outupdt; + int ret, exitcode; + char buf[4096 * 4]; + FILE *infile; + cachefile outfile, outupdt; if (bam_nowrite()) { - set_dir_flag(what, NEED_UPDATE); + set_dir_flag(NEED_UPDATE); return (BAM_SUCCESS); } - if (!has_cachedir(what)) + if (!has_cachedir()) return (BAM_SUCCESS); if ((infile = fopen(path, "rb")) == NULL) { @@ -2068,15 +2113,15 @@ dircache_updatefile(const char *path, int what) return (BAM_ERROR); } - ret = setup_file(get_cachedir(what), path, &outfile); + ret = setup_file(get_cachedir(), path, &outfile); if (ret == BAM_ERROR) { exitcode = BAM_ERROR; goto out; } - if (!is_dir_flag_on(what, NO_MULTI)) { - ret = setup_file(get_updatedir(what), path, &outupdt); + if (!is_dir_flag_on(NO_EXTEND)) { + ret = setup_file(get_updatedir(), path, &outupdt); if (ret == BAM_ERROR) - set_dir_flag(what, NO_MULTI); + set_dir_flag(NO_EXTEND); } while ((ret = fread(buf, 1, sizeof (buf), infile)) > 0) { @@ -2084,21 +2129,21 @@ dircache_updatefile(const char *path, int what) exitcode = BAM_ERROR; goto out; } - if (!is_dir_flag_on(what, NO_MULTI)) + if (!is_dir_flag_on(NO_EXTEND)) if (cache_write(outupdt, buf, ret) == BAM_ERROR) - set_dir_flag(what, NO_MULTI); + set_dir_flag(NO_EXTEND); } - set_dir_flag(what, NEED_UPDATE); - get_count(what)++; - if (get_count(what) > COUNT_MAX) - set_dir_flag(what, NO_MULTI); + set_dir_flag(NEED_UPDATE); + get_count()++; + if (get_count() > COUNT_MAX) + set_dir_flag(NO_EXTEND); exitcode = BAM_SUCCESS; out: (void) fclose(infile); if (cache_close(outfile) == BAM_ERROR) exitcode = BAM_ERROR; - if (!is_dir_flag_on(what, NO_MULTI) && + if (!is_dir_flag_on(NO_EXTEND) && cache_close(outupdt) == BAM_ERROR) exitcode = BAM_ERROR; if (exitcode == BAM_ERROR) @@ -2107,7 +2152,7 @@ out: } static int -dircache_updatedir(const char *path, int what, int updt) +dircache_updatedir(const char *path, int updt) { int ret; char dpath[PATH_MAX]; @@ -2117,7 +2162,7 @@ dircache_updatedir(const char *path, int what, int updt) strip = (char *)path + strlen(rootbuf); ret = snprintf(dpath, sizeof (dpath), "%s/%s", updt ? - get_updatedir(what) : get_cachedir(what), strip); + get_updatedir() : get_cachedir(), strip); if (ret >= sizeof (dpath)) { bam_error(_("unable to create path on mountpoint %s, " @@ -2130,9 +2175,9 @@ dircache_updatedir(const char *path, int what, int updt) return (BAM_SUCCESS); if (updt) { - if (!is_dir_flag_on(what, NO_MULTI)) + if (!is_dir_flag_on(NO_EXTEND)) if (!bam_nowrite() && mkdirp(dpath, DIR_PERMS) == -1) - set_dir_flag(what, NO_MULTI); + set_dir_flag(NO_EXTEND); } else { if (!bam_nowrite() && mkdirp(dpath, DIR_PERMS) == -1) { set_flag(UPDATE_ERROR); @@ -2140,7 +2185,7 @@ dircache_updatedir(const char *path, int what, int updt) } } - set_dir_flag(what, NEED_UPDATE); + set_dir_flag(NEED_UPDATE); return (BAM_SUCCESS); } @@ -2190,51 +2235,33 @@ update_dircache(const char *path, int flags) } (void) close(fd); - /* - * If the file is not an executable and is not inside an amd64 - * directory, we copy it in both the cache directories, - * otherwise, we only copy it inside the 64-bit one. - */ if (memcmp(elf.e_ident, ELFMAG, 4) != 0) { - if (strstr(path, "/amd64")) { - rc = dircache_updatefile(path, FILE64); - } else { - rc = dircache_updatefile(path, FILE32); - if (rc == BAM_SUCCESS) - rc = dircache_updatefile(path, FILE64); - } + /* Not an ELF file, include in archive */ + rc = dircache_updatefile(path); } else { - /* - * Based on the ELF class we copy the file in the 32-bit - * or the 64-bit cache directory. - */ - if (elf.e_ident[EI_CLASS] == ELFCLASS32) { - rc = dircache_updatefile(path, FILE32); - } else if (elf.e_ident[EI_CLASS] == ELFCLASS64) { - rc = dircache_updatefile(path, FILE64); - } else { - bam_print(_("WARNING: file %s is neither a " - "32-bit nor a 64-bit ELF\n"), path); - /* paranoid */ - rc = dircache_updatefile(path, FILE32); - if (rc == BAM_SUCCESS) - rc = dircache_updatefile(path, FILE64); + /* Include 64-bit ELF files only */ + switch (elf.e_ident[EI_CLASS]) { + case ELFCLASS32: + bam_print(_("WARNING: ELF file %s is 32-bit " + "and will be excluded\n"), path); + break; + case ELFCLASS64: + rc = dircache_updatefile(path); + break; + default: + bam_print(_("WARNING: ELF file %s is neither " + "32-bit nor 64-bit\n"), path); + break; } } break; } case FTW_D: - if (strstr(path, "/amd64") == NULL) { - rc = dircache_updatedir(path, FILE32, DO_UPDATE_DIR); - if (rc == BAM_SUCCESS) - rc = dircache_updatedir(path, FILE32, - DO_CACHE_DIR); - } else { - if (has_cachedir(FILE64)) { - rc = dircache_updatedir(path, FILE64, - DO_UPDATE_DIR); + if (strstr(path, "/amd64") != NULL) { + if (has_cachedir()) { + rc = dircache_updatedir(path, DO_UPDATE_DIR); if (rc == BAM_SUCCESS) - rc = dircache_updatedir(path, FILE64, + rc = dircache_updatedir(path, DO_CACHE_DIR); } } @@ -2255,13 +2282,13 @@ cmpstat( int flags, struct FTW *ftw) { - uint_t sz; - uint64_t *value; - uint64_t filestat[2]; - int error, ret, status; + uint_t sz; + uint64_t *value; + uint64_t filestat[2]; + int error, ret, status; struct safefile *safefilep; - FILE *fp; + FILE *fp; struct stat sb; regex_t re; @@ -2347,7 +2374,7 @@ cmpstat( bam_print(_(" new %s\n"), file); if (is_flag_on(IS_SPARC_TARGET)) { - set_dir_flag(FILE64, NEED_UPDATE); + set_dir_flag(NEED_UPDATE); return (0); } @@ -2371,7 +2398,7 @@ cmpstat( return (0); if (is_flag_on(IS_SPARC_TARGET)) { - set_dir_flag(FILE64, NEED_UPDATE); + set_dir_flag(NEED_UPDATE); } else { ret = update_dircache(file, flags); if (ret == BAM_ERROR) { @@ -2391,7 +2418,7 @@ cmpstat( * iso image. We just need to know if we are going to rebuild it or not */ if (is_flag_on(IS_SPARC_TARGET) && - is_dir_flag_on(FILE64, NEED_UPDATE) && !bam_nowrite()) + is_dir_flag_on(NEED_UPDATE) && !bam_nowrite()) return (0); /* * File exists in old archive. Check if file has changed @@ -2422,7 +2449,7 @@ cmpstat( } if (is_flag_on(IS_SPARC_TARGET)) { - set_dir_flag(FILE64, NEED_UPDATE); + set_dir_flag(NEED_UPDATE); } else { ret = update_dircache(file, flags); if (ret == BAM_ERROR) { @@ -2449,10 +2476,10 @@ cmpstat( static int rmdir_r(char *path) { - struct dirent *d = NULL; - DIR *dir = NULL; - char tpath[PATH_MAX]; - struct stat sb; + struct dirent *d = NULL; + DIR *dir = NULL; + char tpath[PATH_MAX]; + struct stat sb; if ((dir = opendir(path)) == NULL) return (-1); @@ -2480,105 +2507,93 @@ rmdir_r(char *path) * If the user requested a 'purge', always recreate the directory from scratch. */ static int -set_cache_dir(char *root, int what) +set_cache_dir(char *root) { struct stat sb; int ret = 0; - ret = snprintf(get_cachedir(what), sizeof (get_cachedir(what)), - "%s%s%s%s%s", root, ARCHIVE_PREFIX, get_machine(), what == FILE64 ? - "/amd64" : "", CACHEDIR_SUFFIX); + ret = build_path(get_cachedir(), sizeof (get_cachedir()), + root, ARCHIVE_PREFIX, CACHEDIR_SUFFIX); - if (ret >= sizeof (get_cachedir(what))) { + if (ret >= sizeof (get_cachedir())) { bam_error(_("unable to create path on mountpoint %s, " "path too long\n"), rootbuf); return (BAM_ERROR); } if (bam_purge || is_flag_on(INVALIDATE_CACHE)) - (void) rmdir_r(get_cachedir(what)); + (void) rmdir_r(get_cachedir()); - if (stat(get_cachedir(what), &sb) != 0 || !(S_ISDIR(sb.st_mode))) { + if (stat(get_cachedir(), &sb) != 0 || !(S_ISDIR(sb.st_mode))) { /* best effort unlink attempt, mkdir will catch errors */ - (void) unlink(get_cachedir(what)); + (void) unlink(get_cachedir()); if (bam_verbose) bam_print(_("archive cache directory not found: %s\n"), - get_cachedir(what)); - ret = mkdir(get_cachedir(what), DIR_PERMS); + get_cachedir()); + ret = mkdir(get_cachedir(), DIR_PERMS); if (ret < 0) { bam_error(_("mkdir of %s failed: %s\n"), - get_cachedir(what), strerror(errno)); - get_cachedir(what)[0] = '\0'; + get_cachedir(), strerror(errno)); + get_cachedir()[0] = '\0'; return (ret); } set_flag(NEED_CACHE_DIR); - set_dir_flag(what, NO_MULTI); + set_dir_flag(NO_EXTEND); } return (BAM_SUCCESS); } static int -set_update_dir(char *root, int what) +set_update_dir(char *root) { struct stat sb; int ret; - if (is_dir_flag_on(what, NO_MULTI)) + if (is_dir_flag_on(NO_EXTEND)) return (BAM_SUCCESS); if (!bam_extend) { - set_dir_flag(what, NO_MULTI); + set_dir_flag(NO_EXTEND); return (BAM_SUCCESS); } - if (what == FILE64 && !is_flag_on(IS_SPARC_TARGET)) - ret = snprintf(get_updatedir(what), - sizeof (get_updatedir(what)), "%s%s%s/amd64%s", root, - ARCHIVE_PREFIX, get_machine(), UPDATEDIR_SUFFIX); - else - ret = snprintf(get_updatedir(what), - sizeof (get_updatedir(what)), "%s%s%s%s", root, - ARCHIVE_PREFIX, get_machine(), UPDATEDIR_SUFFIX); + ret = build_path(get_updatedir(), sizeof (get_updatedir()), + root, ARCHIVE_PREFIX, UPDATEDIR_SUFFIX); - if (ret >= sizeof (get_updatedir(what))) { + if (ret >= sizeof (get_updatedir())) { bam_error(_("unable to create path on mountpoint %s, " "path too long\n"), rootbuf); return (BAM_ERROR); } - if (stat(get_updatedir(what), &sb) == 0) { + if (stat(get_updatedir(), &sb) == 0) { if (S_ISDIR(sb.st_mode)) - ret = rmdir_r(get_updatedir(what)); + ret = rmdir_r(get_updatedir()); else - ret = unlink(get_updatedir(what)); + ret = unlink(get_updatedir()); if (ret != 0) - set_dir_flag(what, NO_MULTI); + set_dir_flag(NO_EXTEND); } - if (mkdir(get_updatedir(what), DIR_PERMS) < 0) - set_dir_flag(what, NO_MULTI); + if (mkdir(get_updatedir(), DIR_PERMS) < 0) + set_dir_flag(NO_EXTEND); return (BAM_SUCCESS); } static int -is_valid_archive(char *root, int what) +is_valid_archive(char *root) { - char archive_path[PATH_MAX]; + char archive_path[PATH_MAX]; char timestamp_path[PATH_MAX]; - struct stat sb, timestamp; - int ret; + struct stat sb, timestamp; + int ret; - if (what == FILE64 && !is_flag_on(IS_SPARC_TARGET)) - ret = snprintf(archive_path, sizeof (archive_path), - "%s%s%s/amd64%s", root, ARCHIVE_PREFIX, get_machine(), - ARCHIVE_SUFFIX); - else - ret = snprintf(archive_path, sizeof (archive_path), "%s%s%s%s", - root, ARCHIVE_PREFIX, get_machine(), ARCHIVE_SUFFIX); + ret = build_path(archive_path, sizeof (archive_path), + root, ARCHIVE_PREFIX, ARCHIVE_SUFFIX); if (ret >= sizeof (archive_path)) { bam_error(_("unable to create path on mountpoint %s, " @@ -2589,8 +2604,7 @@ is_valid_archive(char *root, int what) if (stat(archive_path, &sb) != 0) { if (bam_verbose && !bam_check) bam_print(_("archive not found: %s\n"), archive_path); - set_dir_flag(what, NEED_UPDATE); - set_dir_flag(what, NO_MULTI); + set_dir_flag(NEED_UPDATE | NO_EXTEND); return (BAM_SUCCESS); } @@ -2630,8 +2644,7 @@ is_valid_archive(char *root, int what) } set_flag(INVALIDATE_CACHE); - set_dir_flag(what, NEED_UPDATE); - set_dir_flag(what, NO_MULTI); + set_dir_flag(NEED_UPDATE | NO_EXTEND); return (BAM_SUCCESS); } @@ -2642,7 +2655,7 @@ is_valid_archive(char *root, int what) if (bam_verbose && !bam_check) bam_print(_("archive %s is bigger than %d bytes and " "will be rebuilt\n"), archive_path, BA_SIZE_MAX); - set_dir_flag(what, NO_MULTI); + set_dir_flag(NO_EXTEND); } return (BAM_SUCCESS); @@ -2659,80 +2672,62 @@ static int check_flags_and_files(char *root) { - struct stat sb; - int ret; + struct stat sb; + int ret; /* * If archive is missing, create archive */ - if (is_flag_on(IS_SPARC_TARGET)) { - ret = is_valid_archive(root, FILE64); - if (ret == BAM_ERROR) - return (BAM_ERROR); - } else { - int what = FILE32; - do { - ret = is_valid_archive(root, what); - if (ret == BAM_ERROR) - return (BAM_ERROR); - what++; - } while (bam_direct == BAM_DIRECT_DBOOT && what < CACHEDIR_NUM); - } + ret = is_valid_archive(root); + if (ret == BAM_ERROR) + return (BAM_ERROR); if (bam_nowrite()) return (BAM_SUCCESS); - /* * check if cache directories exist on x86. * check (and always open) the cache file on SPARC. */ if (is_sparc()) { - ret = snprintf(get_cachedir(FILE64), - sizeof (get_cachedir(FILE64)), "%s%s%s/%s", root, + ret = snprintf(get_cachedir(), + sizeof (get_cachedir()), "%s%s%s/%s", root, ARCHIVE_PREFIX, get_machine(), CACHEDIR_SUFFIX); - if (ret >= sizeof (get_cachedir(FILE64))) { + if (ret >= sizeof (get_cachedir())) { bam_error(_("unable to create path on mountpoint %s, " "path too long\n"), rootbuf); return (BAM_ERROR); } - if (stat(get_cachedir(FILE64), &sb) != 0) { + if (stat(get_cachedir(), &sb) != 0) { set_flag(NEED_CACHE_DIR); - set_dir_flag(FILE64, NEED_UPDATE); + set_dir_flag(NEED_UPDATE); } - walk_arg.sparcfile = fopen(get_cachedir(FILE64), "w"); + walk_arg.sparcfile = fopen(get_cachedir(), "w"); if (walk_arg.sparcfile == NULL) { bam_error(_("failed to open file: %s: %s\n"), - get_cachedir(FILE64), strerror(errno)); + get_cachedir(), strerror(errno)); return (BAM_ERROR); } - set_dir_present(FILE64); + set_dir_present(); } else { - int what = FILE32; - - do { - if (set_cache_dir(root, what) != 0) - return (BAM_ERROR); + if (set_cache_dir(root) != 0) + return (BAM_ERROR); - set_dir_present(what); + set_dir_present(); - if (set_update_dir(root, what) != 0) - return (BAM_ERROR); - what++; - } while (bam_direct == BAM_DIRECT_DBOOT && what < CACHEDIR_NUM); + if (set_update_dir(root) != 0) + return (BAM_ERROR); } /* * if force, create archive unconditionally */ if (bam_force) { - if (!is_sparc()) - set_dir_flag(FILE32, NEED_UPDATE); - set_dir_flag(FILE64, NEED_UPDATE); + set_dir_flag(NEED_UPDATE); if (bam_verbose) bam_print(_("forced update of archive requested\n")); return (BAM_SUCCESS); @@ -2744,10 +2739,10 @@ check_flags_and_files(char *root) static error_t read_one_list(char *root, filelist_t *flistp, char *filelist) { - char path[PATH_MAX]; - FILE *fp; - char buf[BAM_MAXLINE]; - const char *fcn = "read_one_list()"; + char path[PATH_MAX]; + FILE *fp; + char buf[BAM_MAXLINE]; + const char *fcn = "read_one_list()"; (void) snprintf(path, sizeof (path), "%s%s", root, filelist); @@ -2774,11 +2769,11 @@ read_one_list(char *root, filelist_t *flistp, char *filelist) static error_t read_list(char *root, filelist_t *flistp) { - char path[PATH_MAX]; - char cmd[PATH_MAX]; - struct stat sb; - int n, rval; - const char *fcn = "read_list()"; + char path[PATH_MAX]; + char cmd[PATH_MAX]; + struct stat sb; + int n, rval; + const char *fcn = "read_list()"; flistp->head = flistp->tail = NULL; @@ -2855,10 +2850,10 @@ read_list(char *root, filelist_t *flistp) static void getoldstat(char *root) { - char path[PATH_MAX]; - int fd, error; - struct stat sb; - char *ostat; + char path[PATH_MAX]; + int fd, error; + struct stat sb; + char *ostat; (void) snprintf(path, sizeof (path), "%s%s", root, FILE_STAT); fd = open(path, O_RDONLY); @@ -2904,26 +2899,24 @@ getoldstat(char *root) out_err: if (fd != -1) (void) close(fd); - if (!is_flag_on(IS_SPARC_TARGET)) - set_dir_flag(FILE32, NEED_UPDATE); - set_dir_flag(FILE64, NEED_UPDATE); + set_dir_flag(NEED_UPDATE); } /* Best effort stale entry removal */ static void -delete_stale(char *file, int what) +delete_stale(char *file) { char path[PATH_MAX]; struct stat sb; - (void) snprintf(path, sizeof (path), "%s/%s", get_cachedir(what), file); + (void) snprintf(path, sizeof (path), "%s/%s", get_cachedir(), file); if (!bam_check && stat(path, &sb) == 0) { if (sb.st_mode & S_IFDIR) (void) rmdir_r(path); else (void) unlink(path); - set_dir_flag(what, (NEED_UPDATE | NO_MULTI)); + set_dir_flag(NEED_UPDATE | NO_EXTEND); } } @@ -2938,7 +2931,7 @@ check4stale(char *root) { nvpair_t *nvp; nvlist_t *nvlp; - char *file; + char *file; char path[PATH_MAX]; /* @@ -2966,17 +2959,14 @@ check4stale(char *root) (void) snprintf(path, sizeof (path), "%s/%s", root, file); if (access(path, F_OK) < 0) { - int what; - if (bam_verbose) bam_print(_(" stale %s\n"), path); if (is_flag_on(IS_SPARC_TARGET)) { - set_dir_flag(FILE64, NEED_UPDATE); + set_dir_flag(NEED_UPDATE); } else { - for (what = FILE32; what < CACHEDIR_NUM; what++) - if (has_cachedir(what)) - delete_stale(file, what); + if (has_cachedir()) + delete_stale(file); } } } @@ -3058,11 +3048,11 @@ update_timestamp(char *root) static void savenew(char *root) { - char path[PATH_MAX]; - char path2[PATH_MAX]; - size_t sz; - char *nstat; - int fd, wrote, error; + char path[PATH_MAX]; + char path2[PATH_MAX]; + size_t sz; + char *nstat; + int fd, wrote, error; nstat = NULL; sz = 0; @@ -3131,11 +3121,11 @@ clear_walk_args(void) static int update_required(char *root) { - struct stat sb; - char path[PATH_MAX]; - filelist_t flist; - filelist_t *flistp = &flist; - int ret; + struct stat sb; + char path[PATH_MAX]; + filelist_t flist; + filelist_t *flistp = &flist; + int ret; flistp->head = flistp->tail = NULL; @@ -3189,7 +3179,7 @@ update_required(char *root) create_newstat(); /* * This walk does 2 things: - * - gets new stat data for every file + * - gets new stat data for every file * - (optional) compare old and new stat data */ ret = walk_list(root, &flist); @@ -3213,8 +3203,7 @@ update_required(char *root) /* If nothing was updated, discard newstat. */ - if (!is_dir_flag_on(FILE32, NEED_UPDATE) && - !is_dir_flag_on(FILE64, NEED_UPDATE)) { + if (!is_dir_flag_on(NEED_UPDATE)) { clear_walk_args(); return (0); } @@ -3346,14 +3335,61 @@ is_be(char *root) } /* - * Returns 1 if mkiso is in the expected PATH, 0 otherwise + * Returns B_TRUE if mkiso is in the expected PATH and should be used, + * B_FALSE otherwise */ -static int -is_mkisofs() +static boolean_t +use_mkisofs() { - if (access(MKISOFS_PATH, X_OK) == 0) - return (1); - return (0); + scf_simple_prop_t *prop; + char *format = NULL; + boolean_t ret; + + /* Check whether the mkisofs binary is in the expected location */ + if (access(MKISOFS_PATH, X_OK) != 0) { + if (bam_verbose) + bam_print("mkisofs not found\n"); + return (B_FALSE); + } + + if (bam_format == BAM_FORMAT_HSFS) { + if (bam_verbose) + bam_print("-F specified HSFS"); + return (B_TRUE); + } + + /* If working on an alt-root, do not use HSFS unless asked via -F */ + if (bam_alt_root) + return (B_FALSE); + + /* + * Then check that the system/boot-archive config/format property + * is "hsfs" or empty. + */ + if ((prop = scf_simple_prop_get(NULL, BOOT_ARCHIVE_FMRI, SCF_PG_CONFIG, + SCF_PROPERTY_FORMAT)) == NULL) { + /* Could not find property, use mkisofs */ + if (bam_verbose) { + bam_print( + "%s does not have %s/%s property, using mkisofs\n", + BOOT_ARCHIVE_FMRI, SCF_PG_CONFIG, + SCF_PROPERTY_FORMAT); + } + return (B_TRUE); + } + if (scf_simple_prop_numvalues(prop) < 0 || + (format = scf_simple_prop_next_astring(prop)) == NULL) + ret = B_TRUE; + else + ret = strcmp(format, "hsfs") == 0 ? B_TRUE : B_FALSE; + if (bam_verbose) { + if (ret) + bam_print("Creating hsfs boot archive\n"); + else + bam_print("Creating %s boot archive\n", format); + } + scf_simple_prop_free(prop); + return (ret); } #define MKISO_PARAMS " -quiet -graft-points -dlrDJN -relaxed-filenames " @@ -3668,37 +3704,31 @@ create_x86_archive(char *archive, char *tempname, char *update_dir) } static int -mkisofs_archive(char *root, int what) +mkisofs_archive(char *root) { int ret; + char suffix[20]; char temp[PATH_MAX]; - char bootblk[PATH_MAX]; + char bootblk[PATH_MAX]; char boot_archive[PATH_MAX]; - if (what == FILE64 && !is_flag_on(IS_SPARC_TARGET)) - ret = snprintf(temp, sizeof (temp), - "%s%s%s/amd64/archive-new-%d", root, ARCHIVE_PREFIX, - get_machine(), getpid()); - else - ret = snprintf(temp, sizeof (temp), "%s%s%s/archive-new-%d", - root, ARCHIVE_PREFIX, get_machine(), getpid()); + ret = snprintf(suffix, sizeof (suffix), "/archive-new-%d", getpid()); + if (ret >= sizeof (suffix)) + goto out_path_err; + + ret = build_path(temp, sizeof (temp), root, ARCHIVE_PREFIX, suffix); if (ret >= sizeof (temp)) goto out_path_err; - if (what == FILE64 && !is_flag_on(IS_SPARC_TARGET)) - ret = snprintf(boot_archive, sizeof (boot_archive), - "%s%s%s/amd64%s", root, ARCHIVE_PREFIX, get_machine(), - ARCHIVE_SUFFIX); - else - ret = snprintf(boot_archive, sizeof (boot_archive), - "%s%s%s%s", root, ARCHIVE_PREFIX, get_machine(), - ARCHIVE_SUFFIX); + ret = build_path(boot_archive, sizeof (boot_archive), root, + ARCHIVE_PREFIX, ARCHIVE_SUFFIX); if (ret >= sizeof (boot_archive)) goto out_path_err; - bam_print("updating %s\n", boot_archive); + bam_print("updating %s (HSFS)\n", + boot_archive[1] == '/' ? boot_archive + 1 : boot_archive); if (is_flag_on(IS_SPARC_TARGET)) { ret = snprintf(bootblk, sizeof (bootblk), @@ -3707,21 +3737,21 @@ mkisofs_archive(char *root, int what) goto out_path_err; ret = create_sparc_archive(boot_archive, temp, bootblk, - get_cachedir(what)); + get_cachedir()); } else { - if (!is_dir_flag_on(what, NO_MULTI)) { + if (!is_dir_flag_on(NO_EXTEND)) { if (bam_verbose) bam_print("Attempting to extend x86 archive: " "%s\n", boot_archive); ret = extend_iso_archive(boot_archive, temp, - get_updatedir(what)); + get_updatedir()); if (ret == BAM_SUCCESS) { if (bam_verbose) bam_print("Successfully extended %s\n", boot_archive); - (void) rmdir_r(get_updatedir(what)); + (void) rmdir_r(get_updatedir()); return (BAM_SUCCESS); } } @@ -3739,12 +3769,12 @@ mkisofs_archive(char *root, int what) bam_print("Unable to extend %s... rebuilding archive\n", boot_archive); - if (get_updatedir(what)[0] != '\0') - (void) rmdir_r(get_updatedir(what)); + if (get_updatedir()[0] != '\0') + (void) rmdir_r(get_updatedir()); ret = create_x86_archive(boot_archive, temp, - get_cachedir(what)); + get_cachedir()); } if (digest_archive(boot_archive) == BAM_ERROR && bam_verbose) @@ -3767,27 +3797,25 @@ create_ramdisk(char *root) char *cmdline, path[PATH_MAX]; size_t len; struct stat sb; - int ret, what, status = BAM_SUCCESS; - - /* If there is mkisofs, use it to create the required archives */ - if (is_mkisofs()) { - for (what = FILE32; what < CACHEDIR_NUM; what++) { - if (has_cachedir(what) && is_dir_flag_on(what, - NEED_UPDATE)) { - ret = mkisofs_archive(root, what); - if (ret != 0) - status = BAM_ERROR; - } + int ret, status = BAM_SUCCESS; + + /* If mkisofs should be used, use it to create the required archives */ + if (use_mkisofs()) { + if (has_cachedir() && is_dir_flag_on(NEED_UPDATE)) { + ret = mkisofs_archive(root); + if (ret != 0) + status = BAM_ERROR; } return (status); + } else if (bam_format == BAM_FORMAT_HSFS) { + bam_error(_("cannot create hsfs archive\n")); + return (BAM_ERROR); } /* - * Else setup command args for create_ramdisk.ksh for the UFS archives + * Else setup command args for create_ramdisk.ksh for the archive * Note: we will not create hash here, CREATE_RAMDISK should create it. */ - if (bam_verbose) - bam_print("mkisofs not found, creating UFS archive\n"); (void) snprintf(path, sizeof (path), "%s/%s", root, CREATE_RAMDISK); if (stat(path, &sb) != 0) { @@ -3801,7 +3829,9 @@ create_ramdisk(char *root) len = strlen(path) + strlen(root) + 10; /* room for space + -R */ if (bam_alt_platform) - len += strlen(bam_platform) + strlen("-p "); + len += strlen(bam_platform) + strlen(" -p "); + if (bam_format != BAM_FORMAT_UNSET) + len += strlen(bam_formats[bam_format]) + strlen(" -f "); cmdline = s_calloc(1, len); if (bam_alt_platform) { @@ -3817,6 +3847,15 @@ create_ramdisk(char *root) } else (void) snprintf(cmdline, len, "%s", path); + if (bam_format != BAM_FORMAT_UNSET) { + if (strlcat(cmdline, " -f ", len) >= len || + strlcat(cmdline, bam_formats[bam_format], len) >= len) { + bam_error(_("boot-archive command line too long\n")); + free(cmdline); + return (BAM_ERROR); + } + } + if (exec_cmd(cmdline, NULL) != 0) { bam_error(_("boot-archive creation FAILED, command: '%s'\n"), cmdline); @@ -5812,7 +5851,7 @@ get_mountpoint(char *special, char *fstype) /* * Mounts a "legacy" top dataset (if needed) * Returns: The mountpoint of the legacy top dataset or NULL on error - * mnted returns one of the above values defined for zfs_mnted_t + * mnted returns one of the above values defined for zfs_mnted_t */ static char * mount_legacy_dataset(char *pool, zfs_mnted_t *mnted) @@ -5906,7 +5945,7 @@ mount_legacy_dataset(char *pool, zfs_mnted_t *mnted) /* * Mounts the top dataset (if needed) * Returns: The mountpoint of the top dataset or NULL on error - * mnted returns one of the above values defined for zfs_mnted_t + * mnted returns one of the above values defined for zfs_mnted_t */ char * mount_top_dataset(char *pool, zfs_mnted_t *mnted) @@ -6349,7 +6388,7 @@ search_hash(mhash_t *mhp, char *special, char **mntpt) { int idx; mcache_t *mcp; - const char *fcn = "search_hash()"; + const char *fcn = "search_hash()"; assert(mntpt); @@ -7754,7 +7793,7 @@ get_special(char *mountp) struct mnttab mpref = {0}; int error; int ret; - const char *fcn = "get_special()"; + const char *fcn = "get_special()"; INJECT_ERROR1("GET_SPECIAL_MNTPT", mountp = NULL); if (mountp == NULL) { diff --git a/usr/src/cmd/boot/scripts/boot-archive-update.ksh b/usr/src/cmd/boot/scripts/boot-archive-update.ksh index 693c715c73..deae20e814 100644 --- a/usr/src/cmd/boot/scripts/boot-archive-update.ksh +++ b/usr/src/cmd/boot/scripts/boot-archive-update.ksh @@ -22,6 +22,7 @@ # # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. +# Copyright 2018 OmniOS Community Edition (OmniOSce) Association. # . /lib/svc/share/smf_include.sh @@ -31,14 +32,18 @@ UPDATEFILE=/etc/svc/volatile/boot_archive_safefile_update smf_is_globalzone || exit $SMF_EXIT_OK -# on x86 get rid of transient reboot entry in the GRUB menu -# if [ `uname -p` = "i386" ]; then + # on x86 get rid of transient reboot entry in the GRUB menu if [ -f /stubboot/boot/grub/menu.lst ]; then /sbin/bootadm -m update_temp -R /stubboot else /sbin/bootadm -m update_temp fi + # Remove old 32-bit archives if present. + plat=/platform/`uname -i` + [ -f $plat/boot_archive ] && rm -f $plat/boot_archive + [ -f $plat/boot_archive.hash ] && rm -f $plat/boot_archive.hash + [ -d $plat/archive_cache ] && rm -rf $plat/archive_cache fi if [ -f $UPDATEFILE ] || [ -f /reconfigure ]; then diff --git a/usr/src/cmd/boot/scripts/create_ramdisk.ksh b/usr/src/cmd/boot/scripts/create_ramdisk.ksh index 6ccd546bfd..1f6f4a4dfd 100644 --- a/usr/src/cmd/boot/scripts/create_ramdisk.ksh +++ b/usr/src/cmd/boot/scripts/create_ramdisk.ksh @@ -27,23 +27,25 @@ # # Copyright (c) 2014 by Delphix. All rights reserved. +# Copyright 2018 OmniOS Community Edition (OmniOSce) Association. # ALT_ROOT= EXTRACT_ARGS= +FORMAT= +format_set=0 compress=yes -SPLIT=unknown -ERROR=0 -dirsize32=0 -dirsize64=0 +dirsize=0 usage() { - echo "This utility is a component of the bootadm(1M) implementation" - echo "and it is not recommended for stand-alone use." - echo "Please use bootadm(1M) instead." - echo "" - echo "Usage: ${0##*/}: [-R \<root\>] [-p \<platform\>] [--nocompress]" - echo "where \<platform\> is one of i86pc, sun4u or sun4v" + cat <<- EOM +This utility is a component of the bootadm(1M) implementation and it is not +recommended for stand-alone use. Please use bootadm(1M) instead. + +Usage: ${0##*/}: [-R <root>] [-p <platform>] [ -f <format> ] [--nocompress] +where <platform> is one of i86pc, sun4u or sun4v + and <format> is one of ufs, ufs-nocompress or cpio + EOM exit } @@ -52,15 +54,25 @@ PLATFORM=`uname -m` export PATH=/usr/sbin:/usr/bin:/sbin export GZIP_CMD=/usr/bin/gzip +export CPIO_CMD=/usr/bin/cpio EXTRACT_FILELIST="/boot/solaris/bin/extract_boot_filelist" # # Parse options # -while [ "$1" != "" ] -do +while [ -n "$1" ]; do case $1 in + -f) shift + FORMAT="$1" + format_set=1 + ;; + -n|--nocompress) compress=no + ;; + -p) shift + PLATFORM="$1" + EXTRACT_ARGS="${EXTRACT_ARGS} -p ${PLATFORM}" + ;; -R) shift ALT_ROOT="$1" if [ "$ALT_ROOT" != "/" ]; then @@ -69,12 +81,6 @@ do EXTRACT_FILELIST="${ALT_ROOT}${EXTRACT_FILELIST}" fi ;; - -n|--nocompress) compress=no - ;; - -p) shift - PLATFORM="$1" - EXTRACT_ARGS="${EXTRACT_ARGS} -p ${PLATFORM}" - ;; *) usage ;; esac @@ -88,73 +94,56 @@ if [ $# -eq 1 ]; then echo "Creating boot_archive for $ALT_ROOT" fi -case $PLATFORM in -i386) PLATFORM=i86pc - ISA=i386 - ARCH64=amd64 - ;; -i86pc) ISA=i386 - ARCH64=amd64 - ;; -sun4u) ISA=sparc - ARCH64=sparcv9 - ;; -sun4v) ISA=sparc - ARCH64=sparcv9 - ;; -*) usage - ;; -esac - -BOOT_ARCHIVE=platform/$PLATFORM/boot_archive -BOOT_ARCHIVE_64=platform/$PLATFORM/$ARCH64/boot_archive +if [ -z "$FORMAT" ]; then + if [ -n "$ALT_ROOT" ]; then + SVCCFG_DTD=/$ALT_ROOT/usr/share/lib/xml/dtd/service_bundle.dtd.1 + SVCCFG_REPOSITORY=/$ALT_ROOT/etc/svc/repository.db + export SVCCFG_DTD SVCCFG_REPOSITORY + fi + FORMAT=`svccfg -s system/boot-archive listprop config/format \ + | awk '{print $3}'` +fi -if [ $PLATFORM = i86pc ] ; then - SPLIT=yes -else # must be sparc - SPLIT=no # there's only 64-bit (sparcv9), so don't split - compress=no +if [ $format_set -eq 0 -a "$FORMAT" = hsfs ]; then + if /sbin/bootadm update-archive -R ${ALT_ROOT:-/} -f -L -F hsfs; then + exit 0 + else + echo "Failed to create HSFS archive, falling back." + fi fi -[ -x $GZIP_CMD ] || compress=no +[[ "$FORMAT" =~ ^(cpio|ufs|ufs-nocompress)$ ]] || FORMAT=ufs + +case $PLATFORM in +i386|i86pc) PLATFORM=i86pc + ISA=i386 + ARCH64=amd64 + BOOT_ARCHIVE_SUFFIX=$ARCH64/boot_archive + ;; +sun4u|sun4v) ISA=sparc + ARCH64=sparcv9 + BOOT_ARCHIVE_SUFFIX=boot_archive + compress=no + ;; +*) usage + ;; +esac + +BOOT_ARCHIVE=platform/$PLATFORM/$BOOT_ARCHIVE_SUFFIX -function cleanup +function fatal_error { - umount -f "$rdmnt32" 2>/dev/null - umount -f "$rdmnt64" 2>/dev/null - lofiadm -d "$rdfile32" 2>/dev/null - lofiadm -d "$rdfile64" 2>/dev/null - [ -n "$rddir" ] && rm -fr "$rddir" 2> /dev/null - [ -n "$new_rddir" ] && rm -fr "$new_rddir" 2>/dev/null + print -u2 $* + exit 1 } -function getsize -{ - # Estimate image size and add 10% overhead for ufs stuff. - # Note, we can't use du here in case we're on a filesystem, e.g. zfs, - # in which the disk usage is less than the sum of the file sizes. - # The nawk code - # - # {t += ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5} - # - # below rounds up the size of a file/directory, in bytes, to the - # next multiple of 1024. This mimics the behavior of ufs especially - # with directories. This results in a total size that's slightly - # bigger than if du was called on a ufs directory. - size32=$(cat "$list32" | xargs -I {} ls -lLd "{}" 2> /dev/null | - nawk '{t += ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5} - END {print int(t * 1.10 / 1024)}') - (( size32 += dirsize32 )) - size64=$(cat "$list64" | xargs -I {} ls -lLd "{}" 2> /dev/null | - nawk '{t += ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5} - END {print int(t * 1.10 / 1024)}') - (( size64 += dirsize64 )) - (( total_size = size32 + size64 )) +[ -x $GZIP_CMD ] || compress=no - if [ $compress = yes ] ; then - total_size=`echo $total_size | nawk '{print int($1 / 2)}'` - fi -} +case $FORMAT in +cpio) [ -x $CPIO_CMD ] || FORMAT=ufs ;; +ufs-nocompress) FORMAT=ufs; compress=no ;; +ufs) ;; +esac # # Copies all desired files to a target directory. One argument should be @@ -167,7 +156,7 @@ function getsize # function copy_files { - list="$1" + typeset listfile="$1" # # If compress is set, the files are gzip'd and put in the correct @@ -177,8 +166,7 @@ function copy_files # If compress is not set, the file names are printed, which causes # the cpio at the end to do the copy. # - while read path - do + while read path; do if [ $compress = yes ]; then dir="${path%/*}" [ -d "$rdmnt/$dir" ] || mkdir -p "$rdmnt/$dir" @@ -186,7 +174,7 @@ function copy_files else print "$path" fi - done <"$list" | cpio -pdum "$rdmnt" 2>/dev/null + done <"$listfile" | cpio -pdum "$rdmnt" 2>/dev/null if [ $ISA = sparc ] ; then # copy links @@ -201,39 +189,112 @@ function copy_files } -# -# The first argument can be: -# -# "both" - create an archive with both 32-bit and 64-bit binaries -# "32-bit" - create an archive with only 32-bit binaries -# "64-bit" - create an archive with only 64-bit binaries -# -function create_ufs +function ufs_cleanup { - which=$1 - archive=$2 - lofidev=$3 - - # should we exclude amd64 binaries? - if [ "$which" = "32-bit" ]; then - rdfile="$rdfile32" - rdmnt="$rdmnt32" - list="$list32" - elif [ "$which" = "64-bit" ]; then - rdfile="$rdfile64" - rdmnt="$rdmnt64" - list="$list64" - else - rdfile="$rdfile32" - rdmnt="$rdmnt32" - list="$list32" + umount -f "$rdmnt" 2>/dev/null + lofiadm -d "$rdfile" 2>/dev/null + [ -n "$rddir" ] && rm -fr "$rddir" 2> /dev/null + [ -n "$new_rddir" ] && rm -fr "$new_rddir" 2>/dev/null +} + +function ufs_getsize +{ + # Estimate image size and add 10% overhead for ufs stuff. + # Note, we can't use du here in case we're on a filesystem, e.g. zfs, + # in which the disk usage is less than the sum of the file sizes. + # The nawk code + # + # {t += ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5} + # + # below rounds up the size of a file/directory, in bytes, to the + # next multiple of 1024. This mimics the behavior of ufs especially + # with directories. This results in a total size that's slightly + # bigger than if du was called on a ufs directory. + size=$(cat "$list" | xargs -I {} ls -lLd "{}" 2> /dev/null | + nawk '{t += ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5} + END {print int(t * 1.10 / 1024)}') + (( size += dirsize )) + (( total_size = size )) + # If compression is enabled, then each file within the archive will + # be individually compressed. The compression ratio is around 60% + # across the archive so make the image smaller. + [ $compress = yes ] && (( total_size = total_size / 2 )) +} + +function create_ufs_archive +{ + typeset archive="$ALT_ROOT/$BOOT_ARCHIVE" + + [ "$compress" = yes ] && \ + echo "updating $archive (UFS)" || \ + echo "updating $archive (UFS-nocompress)" + + # + # We use /tmp/ for scratch space now. This will be changed later to + # $ALT_ROOT/var/tmp if there is insufficient space in /tmp/. + # + rddir="/tmp/create_ramdisk.$$.tmp" + new_rddir= + rm -rf "$rddir" + mkdir "$rddir" || fatal_error "Could not create directory $rddir" + + # Clean up upon exit. + trap 'ufs_cleanup' EXIT + + list="$rddir/filelist" + + cd "/$ALT_ROOT" || fatal_error "Cannot chdir to $ALT_ROOT" + find $filelist -print 2>/dev/null | while read path; do + if [ -d "$path" ]; then + size=`ls -lLd "$path" | nawk ' + {print ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5}'` + (( dirsize += size / 1024 )) + else + print "$path" + fi + done >"$list" + + # calculate image size + ufs_getsize + + # check to see if there is sufficient space in tmpfs + # + tmp_free=`df -b /tmp | tail -1 | awk '{ print $2 }'` + (( tmp_free = tmp_free / 3 )) + + if [ $total_size -gt $tmp_free ] ; then + echo "Insufficient space in /tmp, using $ALT_ROOT/var/tmp" + # assumes we have enough scratch space on $ALT_ROOT + new_rddir="/$ALT_ROOT/var/tmp/create_ramdisk.$$.tmp" + rm -rf "$new_rddir" + mkdir "$new_rddir" || fatal_error \ + "Could not create temporary directory $new_rddir" + + # Save the file lists + mv "$list" "$new_rddir"/ + list="/$new_rddir/filelist" + + # Remove the old $rddir and set the new value of rddir + rm -rf "$rddir" + rddir="$new_rddir" + new_rddir= fi - NOINUSE_CHECK=1 newfs $lofidev < /dev/null 2> /dev/null + rdfile="$rddir/rd.file" + rdmnt="$rddir/rd.mount" + errlog="$rddir/rd.errlog" + lofidev="" + + mkfile ${total_size}k "$rdfile" || \ + fatal_error "Could not create backing file" + lofidev=`lofiadm -a "$rdfile"` || \ + fatal_error "Could not create lofi device" + + NOINUSE_CHECK=1 newfs -m 0 $lofidev < /dev/null 2> /dev/null mkdir "$rdmnt" mount -F mntfs mnttab /etc/mnttab > /dev/null 2>&1 mount -F ufs -o nologging $lofidev "$rdmnt" - files= + rm -rf "$rdmnt/lost+found" # do the actual copy copy_files "$list" @@ -241,12 +302,14 @@ function create_ufs rmdir "$rdmnt" if [ $ISA = sparc ] ; then - rlofidev=`echo "$lofidev" | sed -e "s/dev\/lofi/dev\/rlofi/"` - bb="$ALT_ROOT/platform/$PLATFORM/lib/fs/ufs/bootblk" + rlofidev="${lofidev/lofi/rlofi}" + bb="/$ALT_ROOT/platform/$PLATFORM/lib/fs/ufs/bootblk" # installboot is not available on all platforms dd if=$bb of=$rlofidev bs=1b oseek=1 count=15 conv=sync 2>&1 fi + lofiadm -d "$rdfile" + # # Check if gzip exists in /usr/bin, so we only try to run gzip # on systems that have gzip. Then run gzip out of the patch to @@ -256,27 +319,15 @@ function create_ufs # compressed, and the final compression will accomplish very # little. To save time, we skip the gzip in this case. # - if [ $ISA = i386 ] && [ $compress = no ] && \ - [ -x $GZIP_CMD ] ; then - gzip -c "$rdfile" > "${archive}-new" + if [ $ISA = i386 ] && [ $compress = no ] && [ -x $GZIP_CMD ] ; then + $GZIP_CMD -c "$rdfile" > "${archive}-new" else cat "$rdfile" > "${archive}-new" fi - + if [ $? -ne 0 ] ; then rm -f "${archive}-new" fi -} - -function create_archive -{ - which=$1 - archive=$2 - lofidev=$3 - - echo "updating $archive" - - create_ufs "$which" "$archive" "$lofidev" # sanity check the archive before moving it into place # @@ -298,27 +349,59 @@ function create_archive if [ $? = 1 ] && [ -x $GZIP_CMD ] || [ "$ARCHIVE_SIZE" -lt 10000 ] then - # - # Two of these functions may be run in parallel. We - # need to allow the other to clean up, so we can't - # exit immediately. Instead, we set a flag. - # - echo "update of $archive failed" - ERROR=1 + fatal_error "update of $archive failed" else lockfs -f "/$ALT_ROOT" 2>/dev/null - mv "${archive}-new" "$archive" rm -f "$archive.hash" - digest -a sha1 "$archive" > "$archive.hash" + mv "${archive}-new" "$archive" + digest -a sha1 "$rdfile" > "$archive.hash" lockfs -f "/$ALT_ROOT" 2>/dev/null fi + [ -n "$rddir" ] && rm -rf "$rddir" +} +function cpio_cleanup +{ + [ -f "/$ALT_ROOT/$tarchive" ] && rm -f "/$ALT_ROOT/$tarchive" + [ -f "/$ALT_ROOT/$tarchive.cpio" ] && rm -f "/$ALT_ROOT/$tarchive.cpio" + [ -f "/$ALT_ROOT/$tarchive.hash" ] && rm -f "/$ALT_ROOT/$tarchive.hash" } -function fatal_error +function create_cpio_archive { - print -u2 $* - exit 1 + typeset archive="$ALT_ROOT/$BOOT_ARCHIVE" + + echo "updating $archive (CPIO)" + + tarchive="$archive.$$.new" + + # Clean up upon exit. + trap 'cpio_cleanup' EXIT + + cd "/$ALT_ROOT" || fatal_error "Cannot chdir to $ALT_ROOT" + + touch "$tarchive" \ + || fatal_error "Cannot create temporary archive $tarchive" + + find $filelist 2>/dev/null | cpio -qo -H odc > "$tarchive.cpio" \ + || fatal_error "Problem creating archive" + + [ -x /usr/bin/digest ] \ + && /usr/bin/digest -a sha1 "$tarchive.cpio" \ + > "$tarchive.hash" + + if [ -x "$GZIP_CMD" ]; then + $GZIP_CMD -c "$tarchive.cpio" > "$tarchive" + rm -f "$tarchive.cpio" + else + mv "$tarchive.cpio" "$tarchive" + fi + + # Move new archive into place + [ -f "$archive.hash" ] && rm -f "$archive.hash" + mv "$tarchive" "$archive" + [ $? -eq 0 -a -f "$tarchive.hash" ] \ + && mv "$tarchive.hash" "$archive.hash" } # @@ -335,119 +418,15 @@ filelist=$($EXTRACT_FILELIST $EXTRACT_ARGS \ /etc/boot/solaris/filelist.ramdisk \ 2>/dev/null | sort -u) -# -# We use /tmp/ for scratch space now. This may be changed later if there -# is insufficient space in /tmp/. -# -rddir="/tmp/create_ramdisk.$$.tmp" -new_rddir= -rm -rf "$rddir" -mkdir "$rddir" || fatal_error "Could not create temporary directory $rddir" - -# Clean up upon exit. -trap 'cleanup' EXIT - -list32="$rddir/filelist.32" -list64="$rddir/filelist.64" - -touch $list32 $list64 - -# -# This loop creates the 32-bit and 64-bit lists of files. The 32-bit list -# is written to stdout, which is redirected at the end of the loop. The -# 64-bit list is appended with each write. -# -cd "/$ALT_ROOT" -find $filelist -print 2>/dev/null | while read path -do - if [ $SPLIT = no ]; then - print "$path" - elif [ -d "$path" ]; then - size=`ls -lLd "$path" | nawk ' - {print ($5 % 1024) ? (int($5 / 1024) + 1) * 1024 : $5}'` - if [ `basename "$path"` != "amd64" ]; then - (( dirsize32 += size )) - fi - (( dirsize64 += size )) - else - case `LC_MESSAGES=C /usr/bin/file -m /dev/null "$path" 2>/dev/null` in - *ELF\ 64-bit*) - print "$path" >> "$list64" - ;; - *ELF\ 32-bit*) - print "$path" - ;; - *) - # put in both lists - print "$path" - print "$path" >> "$list64" - esac - fi -done >"$list32" - -# calculate image size -getsize - -# check to see if there is sufficient space in tmpfs -# -tmp_free=`df -b /tmp | tail -1 | awk '{ printf ($2) }'` -(( tmp_free = tmp_free / 3 )) -if [ $SPLIT = yes ]; then - (( tmp_free = tmp_free / 2 )) -fi - -if [ $total_size -gt $tmp_free ] ; then - # assumes we have enough scratch space on $ALT_ROOT - new_rddir="/$ALT_ROOT/var/tmp/create_ramdisk.$$.tmp" - rm -rf "$new_rddir" - mkdir "$new_rddir" || fatal_error \ - "Could not create temporary directory $new_rddir" - - # Save the file lists - mv "$list32" "$new_rddir"/ - mv "$list64" "$new_rddir"/ - list32="/$new_rddir/filelist.32" - list64="/$new_rddir/filelist.64" - - # Remove the old $rddir and set the new value of rddir - rm -rf "$rddir" - rddir="$new_rddir" - new_rddir= -fi +# Now that we have the list of files, we can create the archive. -rdfile32="$rddir/rd.file.32" -rdfile64="$rddir/rd.file.64" -rdmnt32="$rddir/rd.mount.32" -rdmnt64="$rddir/rd.mount.64" -errlog32="$rddir/rd.errlog.32" -errlog64="$rddir/rd.errlog.64" -lofidev32="" -lofidev64="" - -if [ $SPLIT = yes ]; then - # - # We can't run lofiadm commands in parallel, so we have to do - # them here. - # - mkfile ${size32}k "$rdfile32" - lofidev32=`lofiadm -a "$rdfile32"` - mkfile ${size64}k "$rdfile64" - lofidev64=`lofiadm -a "$rdfile64"` - create_archive "32-bit" "$ALT_ROOT/$BOOT_ARCHIVE" $lofidev32 & - create_archive "64-bit" "$ALT_ROOT/$BOOT_ARCHIVE_64" $lofidev64 - wait - lofiadm -d "$rdfile32" - lofiadm -d "$rdfile64" -else - mkfile ${total_size}k "$rdfile32" - lofidev32=`lofiadm -a "$rdfile32"` - create_archive "both" "$ALT_ROOT/$BOOT_ARCHIVE" $lofidev32 - lofiadm -d "$rdfile32" -fi -if [ $ERROR = 1 ]; then - cleanup - exit 1 -fi +case "$FORMAT" in + cpio) create_cpio_archive ;; + ufs) create_ufs_archive ;; + *) print -u2 "Unknown boot archive format, $FORMAT" + exit 1 + ;; +esac # # For the diskless case, hardlink archive to /boot to make it @@ -456,11 +435,7 @@ fi # grep "[ ]/[ ]*nfs[ ]" "$ALT_ROOT/etc/vfstab" > /dev/null if [ $? = 0 ]; then - rm -f "$ALT_ROOT/boot/boot_archive" "$ALT_ROOT/boot/amd64/boot_archive" - ln "$ALT_ROOT/$BOOT_ARCHIVE" "$ALT_ROOT/boot/boot_archive" - if [ $SPLIT = yes ]; then - ln "$ALT_ROOT/$BOOT_ARCHIVE_64" \ - "$ALT_ROOT/boot/amd64/boot_archive" - fi + rm -f "$ALT_ROOT/boot/$BOOT_ARCHIVE_SUFFIX" + mkdir -p "$ALT_ROOT/boot/`dirname $BOOT_ARCHIVE_SUFFIX`" + ln "$ALT_ROOT/$BOOT_ARCHIVE" "$ALT_ROOT/boot/$BOOT_ARCHIVE_SUFFIX" fi -[ -n "$rddir" ] && rm -rf "$rddir" diff --git a/usr/src/cmd/halt/halt.c b/usr/src/cmd/halt/halt.c index 166e5a163b..a98360d6c2 100644 --- a/usr/src/cmd/halt/halt.c +++ b/usr/src/cmd/halt/halt.c @@ -19,13 +19,14 @@ * CDDL HEADER END */ /* - * Copyright 2016 Toomas Soome <tsoome@me.com> * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright (c) 2013, Joyent, Inc. All rights reserved. * Copyright (c) 2015 by Delphix. All rights reserved. + * Copyright 2016 Toomas Soome <tsoome@me.com> + * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -1582,18 +1583,10 @@ main(int argc, char *argv[]) * handle a SIGTERM and clean up properly. */ if (cmd != A_DUMP) { - int start, end, delta; - - (void) kill(-1, SIGTERM); - start = time(NULL); - if (zoneid == GLOBAL_ZONEID && !nosync) do_archives_update(fast_reboot); - - end = time(NULL); - delta = end - start; - if (delta < 5) - (void) sleep(5 - delta); + (void) kill(-1, SIGTERM); + (void) sleep(5); } (void) signal(SIGINT, SIG_IGN); diff --git a/usr/src/cmd/svc/milestone/boot-archive.xml b/usr/src/cmd/svc/milestone/boot-archive.xml index ca8f947321..a342834cab 100644 --- a/usr/src/cmd/svc/milestone/boot-archive.xml +++ b/usr/src/cmd/svc/milestone/boot-archive.xml @@ -24,12 +24,12 @@ CDDL HEADER END - ident "%Z%%M% %I% %E% SMI" - NOTE: This service manifest is not editable; its contents will be overwritten by package or patch operations, including operating system upgrade. Make customizations in a different file. + + Copyright 2018 OmniOS Community Edition (OmniOSce) Association. --> <service_bundle type='manifest' name='SUNWcsr:boot-archive'> @@ -71,6 +71,10 @@ <propval name='duration' type='astring' value='transient' /> </property_group> + <property_group name='config' type='application'> + <propval name='format' type='astring' value='cpio' /> + </property_group> + <stability value='Unstable' /> <template> diff --git a/usr/src/man/man1m/bootadm.1m b/usr/src/man/man1m/bootadm.1m index 5276786d82..608807a7fe 100644 --- a/usr/src/man/man1m/bootadm.1m +++ b/usr/src/man/man1m/bootadm.1m @@ -4,13 +4,15 @@ .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] .\" Copyright 2016 Toomas Soome <tsoome@me.com> -.TH BOOTADM 1M "Aug 18, 2016" +.\" Copyright 2018 OmniOS Community Edition (OmniOSce) Association. +.TH BOOTADM 1M "Jul 05, 2018" .SH NAME bootadm \- manage bootability of the operating system .SH SYNOPSIS .LP .nf -\fB/sbin/bootadm\fR update-archive [\fB-vn\fR] [\fB-R\fR \fIaltroot\fR [\fB-p\fR \fIplatform\fR]] +\fB/sbin/bootadm\fR update-archive [\fB-vnf\fR] [\fB-R\fR \fIaltroot\fR [\fB-p\fR \fIplatform\fR]] + [\fB-F \fIformat\fR] .fi .LP @@ -87,7 +89,68 @@ The \fBbootadm\fR command has the following subcommands: .sp .6 .RS 4n Updates current boot archive if required. Applies to both SPARC and x86 -platforms. +platforms. The boot archive can be created in a number of different formats; +the default format is an IEEE/P1003 Data Interchange Standard cpio archive. +The format is configured through the following service management facility +(\fBsmf\fR(5)) property: +.sp +.in +2 +.nf +svc:/system/boot-archive:default/config/format +.fi +.in -2 + +.sp +.LP +This property takes one of the following values: +.RS 8n + +.sp +.ne 2 +.na +\fBcpio\fR +.ad +.sp .6 +.RS 4n +IEEE/P1003 Data Interchange Standard cpio archive (default). +.RE + +.sp +.ne 2 +.na +\fBhsfs\fR +.ad +.sp .6 +.RS 4n +ISO 9660 filesystem image (only supported if \fI/usr/bin/mkisofs\fR is +available). +.RE + +.sp +.ne 2 +.na +\fBufs\fR +.ad +.sp .6 +.RS 4n +UFS filesystem in which the files within are compressed using gzip if +\fI/usr/bin/gzip\fR is available. +.RE + +.sp +.ne 2 +.na +\fBufs-nocompress\fR +.ad +.sp .6 +.RS 4n +UFS filesystem. The files within are not compressed but the resulting overall +boot archive will still be compressed if \fI/usr/bin/gzip\fR is available. +.RE +.RE + +See \fBEXAMPLES\fR for how to change this value. + .RE .sp @@ -163,6 +226,7 @@ title of each entry. Applies to x86 platforms only. .SH OPTIONS .LP The \fBbootadm\fR command has the following options: + .sp .ne 2 .na @@ -170,6 +234,9 @@ The \fBbootadm\fR command has the following options: .ad .sp .6 .RS 4n +In an \fBupdate-archive\fR operation, force re-generation of the boot-archive +even if no files have changed. + In an \fBinstall-bootloader\fR operation, override the boot loader versioning constraints. .RE @@ -177,6 +244,18 @@ constraints. .sp .ne 2 .na +\fB-F \fIformat\fR\fR +.ad +.sp .6 +.RS 4n +In an \fBupdate-archive\fR operation, select the desired archive format. The +format can be any of the values shown above for the +svc:/system/boot-archive:default/config/format property. +.RE + +.sp +.ne 2 +.na \fB\fB-n\fR\fR .ad .sp .6 @@ -367,7 +446,22 @@ user selects test-183 (item 1). .in -2 .LP -\fBExample 5 \fRDetailed information about menu entry. +\fBExample 5 \fRChanging archive format +.sp +.LP +The following command changes the boot archive format to \fIufs\fR + +.sp +.in +2 +.nf +# svccfg -s system/boot-archive:default setprop config/format = ufs +# svcadm refresh system/boot-archive:default +# bootadm update-archive -f +.fi +.in -2 + +.LP +\fBExample 6 \fRDetailed information about menu entry. .sp .LP The following command lists more detailed information about a boot menu entry: |