Print this page
9696 add /etc/system.d support
Portions contributed by: Andy Fiddaman <andy@omniosce.org>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@joyent.com>
Reviewed by: Peter Tribble <peter.tribble@gmail.com>
Reviewed by: C Fraire <cfraire@me.com>
Reviewed by: Toomas Soome <tsoome@me.com>

*** 22,32 **** /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2012 Milan Jurik. All rights reserved. * Copyright (c) 2015 by Delphix. All rights reserved. * Copyright 2016 Toomas Soome <tsoome@me.com> ! * Copyright 2016 Nexenta Systems, Inc. * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. */ /* * bootadm(1M) is a new utility for managing bootability of --- 22,32 ---- /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2012 Milan Jurik. All rights reserved. * Copyright (c) 2015 by Delphix. All rights reserved. * Copyright 2016 Toomas Soome <tsoome@me.com> ! * Copyright 2017 Nexenta Systems, Inc. * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. */ /* * bootadm(1M) is a new utility for managing bootability of
*** 158,167 **** --- 158,170 ---- #define INSTALLGRUB "/sbin/installgrub" #define STAGE1 "/boot/grub/stage1" #define STAGE2 "/boot/grub/stage2" + #define ETC_SYSTEM_DIR "etc/system.d" + #define SELF_ASSEMBLY "etc/system.d/.self-assembly" + /* * Default file attributes */ #define DEFAULT_DEV_MODE 0644 /* default permissions */ #define DEFAULT_DEV_UID 0 /* user root */
*** 243,252 **** --- 246,256 ---- static int bam_smf_check; static int bam_lock_fd = -1; static int bam_zfs; static int bam_mbr; char rootbuf[PATH_MAX] = "/"; + static char self_assembly[PATH_MAX]; static int bam_update_all; static int bam_alt_platform; static char *bam_platform; static char *bam_home_env = NULL;
*** 281,290 **** --- 285,295 ---- static error_t update_all(char *, char *); static error_t read_list(char *, filelist_t *); static error_t set_option(menu_t *, char *, char *); static error_t set_kernel(menu_t *, menu_cmd_t, char *, char *, size_t); static error_t get_kernel(menu_t *, menu_cmd_t, char *, size_t); + static error_t build_etc_system_dir(char *); static char *expand_path(const char *); static long s_strtol(char *); static int s_fputs(char *, FILE *);
*** 2457,2466 **** --- 2462,2484 ---- "for %s\n"), file); return (-1); } } + /* + * Update self-assembly file if there are changes in + * /etc/system.d directory + */ + if (strstr(file, ETC_SYSTEM_DIR)) { + ret = update_dircache(self_assembly, flags); + if (ret == BAM_ERROR) { + bam_error(_("directory cache update failed " + "for %s\n"), file); + return (-1); + } + } + if (bam_verbose) { if (bam_smf_check) bam_print(" %s\n", file); else bam_print(_(" changed %s\n"), file);
*** 3789,3799 **** --- 3807,3942 ---- bam_error(_("unable to create path on mountpoint %s, path too long\n"), root); return (BAM_ERROR); } + static int + assemble_systemfile(char *infilename, char *outfilename) + { + char buf[BUFSIZ]; + FILE *infile, *outfile; + size_t n; + + if ((infile = fopen(infilename, "r")) == NULL) { + bam_error(_("failed to open file: %s: %s\n"), infilename, + strerror(errno)); + return (BAM_ERROR); + } + + if ((outfile = fopen(outfilename, "a")) == NULL) { + bam_error(_("failed to open file: %s: %s\n"), outfilename, + strerror(errno)); + (void) fclose(infile); + return (BAM_ERROR); + } + + while ((n = fread(buf, 1, sizeof (buf), infile)) > 0) { + if (fwrite(buf, 1, n, outfile) != n) { + bam_error(_("failed to write file: %s: %s\n"), + outfilename, strerror(errno)); + (void) fclose(infile); + (void) fclose(outfile); + return (BAM_ERROR); + } + } + + (void) fclose(infile); + (void) fclose(outfile); + + return (BAM_SUCCESS); + } + + /* + * Concatenate all files (except those starting with a dot) + * from /etc/system.d directory into a single /etc/system.d/.self-assembly + * file. The kernel reads it before /etc/system file. + */ static error_t + build_etc_system_dir(char *root) + { + struct dirent **filelist; + char path[PATH_MAX], tmpfile[PATH_MAX]; + int i, files, sysfiles = 0; + int ret = BAM_SUCCESS; + struct stat st; + timespec_t times[2]; + + (void) snprintf(path, sizeof (path), "%s/%s", root, ETC_SYSTEM_DIR); + (void) snprintf(self_assembly, sizeof (self_assembly), + "%s%s", root, SELF_ASSEMBLY); + (void) snprintf(tmpfile, sizeof (tmpfile), "%s.%ld", + self_assembly, (long)getpid()); + + if (stat(self_assembly, &st) >= 0 && (st.st_mode & S_IFMT) == S_IFREG) { + times[0] = times[1] = st.st_mtim; + } else { + times[1].tv_nsec = 0; + } + + if ((files = scandir(path, &filelist, NULL, alphasort)) < 0) { + /* Don't fail the update if <ROOT>/etc/system.d doesn't exist */ + if (errno == ENOENT) + return (BAM_SUCCESS); + bam_error(_("can't read %s: %s\n"), path, strerror(errno)); + return (BAM_ERROR); + } + + (void) unlink(tmpfile); + + for (i = 0; i < files; i++) { + char filepath[PATH_MAX]; + char *fname; + + fname = filelist[i]->d_name; + + /* skip anything that starts with a dot */ + if (strncmp(fname, ".", 1) == 0) { + free(filelist[i]); + continue; + } + + if (bam_verbose) + bam_print(_("/etc/system.d adding %s/%s\n"), + path, fname); + + (void) snprintf(filepath, sizeof (filepath), "%s/%s", + path, fname); + + if ((assemble_systemfile(filepath, tmpfile)) < 0) { + bam_error(_("failed to append file: %s: %s\n"), + filepath, strerror(errno)); + ret = BAM_ERROR; + break; + } + sysfiles++; + } + + if (sysfiles > 0) { + if (rename(tmpfile, self_assembly) < 0) { + bam_error(_("failed to rename file: %s: %s\n"), tmpfile, + strerror(errno)); + return (BAM_ERROR); + } + + /* + * Use previous attribute times to avoid + * boot archive recreation. + */ + if (times[1].tv_nsec != 0 && + utimensat(AT_FDCWD, self_assembly, times, 0) != 0) { + bam_error(_("failed to change times: %s\n"), + strerror(errno)); + return (BAM_ERROR); + } + } else { + (void) unlink(tmpfile); + (void) unlink(self_assembly); + } + return (ret); + } + + static error_t create_ramdisk(char *root) { char *cmdline, path[PATH_MAX]; size_t len; struct stat sb;
*** 4153,4162 **** --- 4296,4311 ---- set_flag(RDONLY_FSCHK); bam_check = 1; } /* + * Process the /etc/system.d/.self-assembly file. + */ + if (build_etc_system_dir(bam_root) == BAM_ERROR) + return (BAM_ERROR); + + /* * Now check if an update is really needed. */ ret = update_required(root); /*