Print this page
9696 add /etc/system.d support
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Peter Tribble <peter.tribble@gmail.com>
Reviewed by: Andy Fiddaman <andy@omniosce.org>

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/boot/bootadm/bootadm.c
          +++ new/usr/src/cmd/boot/bootadm/bootadm.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Copyright 2012 Milan Jurik. All rights reserved.
  25   25   * Copyright (c) 2015 by Delphix. All rights reserved.
  26   26   * Copyright 2016 Toomas Soome <tsoome@me.com>
  27      - * Copyright 2016 Nexenta Systems, Inc.
       27 + * Copyright 2017 Nexenta Systems, Inc.
  28   28   * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
  29   29   */
  30   30  
  31   31  /*
  32   32   * bootadm(1M) is a new utility for managing bootability of
  33   33   * Solaris *Newboot* environments. It has two primary tasks:
  34   34   *      - Allow end users to manage bootability of Newboot Solaris instances
  35   35   *      - Provide services to other subsystems in Solaris (primarily Install)
  36   36   */
  37   37  
↓ open down ↓ 115 lines elided ↑ open up ↑
 153  153  #define LULIB                   "/usr/lib/lu/lulib"
 154  154  #define LULIB_PROPAGATE_FILE    "lulib_propagate_file"
 155  155  #define CKSUM                   "/usr/bin/cksum"
 156  156  #define LU_MENU_CKSUM           "/etc/lu/menu.cksum"
 157  157  #define BOOTADM                 "/sbin/bootadm"
 158  158  
 159  159  #define INSTALLGRUB             "/sbin/installgrub"
 160  160  #define STAGE1                  "/boot/grub/stage1"
 161  161  #define STAGE2                  "/boot/grub/stage2"
 162  162  
      163 +#define ETC_SYSTEM_DIR          "etc/system.d"
      164 +#define SELF_ASSEMBLY           "etc/system.d/.self-assembly"
      165 +
 163  166  /*
 164  167   * Default file attributes
 165  168   */
 166  169  #define DEFAULT_DEV_MODE        0644    /* default permissions */
 167  170  #define DEFAULT_DEV_UID         0       /* user root */
 168  171  #define DEFAULT_DEV_GID         3       /* group sys */
 169  172  
 170  173  /*
 171  174   * Menu related
 172  175   * menu_cmd_t and menu_cmds must be kept in sync
↓ open down ↓ 65 lines elided ↑ open up ↑
 238  241  static char **bam_argv;
 239  242  static char *bam_pool;
 240  243  static int bam_argc;
 241  244  static int bam_check;
 242  245  static int bam_saved_check;
 243  246  static int bam_smf_check;
 244  247  static int bam_lock_fd = -1;
 245  248  static int bam_zfs;
 246  249  static int bam_mbr;
 247  250  char rootbuf[PATH_MAX] = "/";
      251 +static char self_assembly[PATH_MAX];
 248  252  static int bam_update_all;
 249  253  static int bam_alt_platform;
 250  254  static char *bam_platform;
 251  255  static char *bam_home_env = NULL;
 252  256  
 253  257  /* function prototypes */
 254  258  static void parse_args_internal(int, char *[]);
 255  259  static void parse_args(int, char *argv[]);
 256  260  static error_t bam_menu(char *, char *, int, char *[]);
 257  261  static error_t bam_install(char *, char *);
↓ open down ↓ 18 lines elided ↑ open up ↑
 276  280  static error_t update_temp(menu_t *mp, char *dummy, char *opt);
 277  281  
 278  282  static error_t install_bootloader(void);
 279  283  static error_t update_archive(char *, char *);
 280  284  static error_t list_archive(char *, char *);
 281  285  static error_t update_all(char *, char *);
 282  286  static error_t read_list(char *, filelist_t *);
 283  287  static error_t set_option(menu_t *, char *, char *);
 284  288  static error_t set_kernel(menu_t *, menu_cmd_t, char *, char *, size_t);
 285  289  static error_t get_kernel(menu_t *, menu_cmd_t, char *, size_t);
      290 +static error_t build_etc_system_dir(char *);
 286  291  static char *expand_path(const char *);
 287  292  
 288  293  static long s_strtol(char *);
 289  294  static int s_fputs(char *, FILE *);
 290  295  
 291  296  static int is_amd64(void);
 292  297  static char *get_machine(void);
 293  298  static void append_to_flist(filelist_t *, char *);
 294  299  static int ufs_add_to_sign_list(char *sign);
 295  300  static error_t synchronize_BE_menu(void);
↓ open down ↓ 2156 lines elided ↑ open up ↑
2452 2457                          set_dir_flag(NEED_UPDATE);
2453 2458                  } else {
2454 2459                          ret = update_dircache(file, flags);
2455 2460                          if (ret == BAM_ERROR) {
2456 2461                                  bam_error(_("directory cache update failed "
2457 2462                                      "for %s\n"), file);
2458 2463                                  return (-1);
2459 2464                          }
2460 2465                  }
2461 2466  
     2467 +                /*
     2468 +                 * Update self-assembly file if there are changes in
     2469 +                 * /etc/system.d directory
     2470 +                 */
     2471 +                if (strstr(file, ETC_SYSTEM_DIR)) {
     2472 +                        ret = update_dircache(self_assembly, flags);
     2473 +                        if (ret == BAM_ERROR) {
     2474 +                                bam_error(_("directory cache update failed "
     2475 +                                    "for %s\n"), file);
     2476 +                                return (-1);
     2477 +                        }
     2478 +                }
     2479 +
2462 2480                  if (bam_verbose) {
2463 2481                          if (bam_smf_check)
2464 2482                                  bam_print("    %s\n", file);
2465 2483                          else
2466 2484                                  bam_print(_("    changed %s\n"), file);
2467 2485                  }
2468 2486          }
2469 2487  
2470 2488          return (0);
2471 2489  }
↓ open down ↓ 1312 lines elided ↑ open up ↑
3784 3802                  bam_print("Successfully created %s\n", boot_archive);
3785 3803  
3786 3804          return (ret);
3787 3805  
3788 3806  out_path_err:
3789 3807          bam_error(_("unable to create path on mountpoint %s, path too long\n"),
3790 3808              root);
3791 3809          return (BAM_ERROR);
3792 3810  }
3793 3811  
     3812 +static int
     3813 +assemble_systemfile(char *infilename, char *outfilename)
     3814 +{
     3815 +        char buf[BUFSIZ];
     3816 +        FILE *infile, *outfile;
     3817 +        size_t n;
     3818 +
     3819 +        if ((infile = fopen(infilename, "r")) == NULL) {
     3820 +                bam_error(_("failed to open file: %s: %s\n"), infilename,
     3821 +                    strerror(errno));
     3822 +                return (BAM_ERROR);
     3823 +        }
     3824 +
     3825 +        if ((outfile = fopen(outfilename, "a")) == NULL) {
     3826 +                bam_error(_("failed to open file: %s: %s\n"), outfilename,
     3827 +                    strerror(errno));
     3828 +                (void) fclose(infile);
     3829 +                return (BAM_ERROR);
     3830 +        }
     3831 +
     3832 +        while ((n = fread(buf, 1, sizeof (buf), infile)) > 0) {
     3833 +                if (fwrite(buf, 1, n, outfile) != n) {
     3834 +                        bam_error(_("failed to write file: %s: %s\n"),
     3835 +                            outfilename, strerror(errno));
     3836 +                        (void) fclose(infile);
     3837 +                        (void) fclose(outfile);
     3838 +                        return (BAM_ERROR);
     3839 +                }
     3840 +        }
     3841 +
     3842 +        (void) fclose(infile);
     3843 +        (void) fclose(outfile);
     3844 +
     3845 +        return (BAM_SUCCESS);
     3846 +}
     3847 +
     3848 +/*
     3849 + * Concatenate all files (except those starting with a dot)
     3850 + * from /etc/system.d directory into a single /etc/system.d/.self-assembly
     3851 + * file. The kernel reads it before /etc/system file.
     3852 + */
3794 3853  static error_t
     3854 +build_etc_system_dir(char *root)
     3855 +{
     3856 +        struct dirent **filelist;
     3857 +        char path[PATH_MAX], tmpfile[PATH_MAX];
     3858 +        int i, files, sysfiles = 0;
     3859 +        int ret = BAM_SUCCESS;
     3860 +        struct stat st;
     3861 +        timespec_t times[2];
     3862 +
     3863 +        (void) snprintf(path, sizeof (path), "%s/%s", root, ETC_SYSTEM_DIR);
     3864 +        (void) snprintf(self_assembly, sizeof (self_assembly),
     3865 +            "%s%s", root, SELF_ASSEMBLY);
     3866 +        (void) snprintf(tmpfile, sizeof (tmpfile), "%s.%ld",
     3867 +            self_assembly, (long)getpid());
     3868 +
     3869 +        if (stat(self_assembly, &st) >= 0 && (st.st_mode & S_IFMT) == S_IFREG) {
     3870 +                times[0] = times[1] = st.st_mtim;
     3871 +        } else {
     3872 +                times[1].tv_nsec = 0;
     3873 +        }
     3874 +
     3875 +        if ((files = scandir(path, &filelist, NULL, alphasort)) < 0) {
     3876 +                /* Don't fail the update if <ROOT>/etc/system.d doesn't exist */
     3877 +                if (errno == ENOENT)
     3878 +                        return (BAM_SUCCESS);
     3879 +                bam_error(_("can't read %s: %s\n"), path, strerror(errno));
     3880 +                return (BAM_ERROR);
     3881 +        }
     3882 +
     3883 +        for (i = 0; i < files; i++) {
     3884 +                char    filepath[PATH_MAX];
     3885 +                char    *fname;
     3886 +
     3887 +                fname = filelist[i]->d_name;
     3888 +
     3889 +                /* skip anything that starts with a dot */
     3890 +                if (strncmp(fname, ".", 1) == 0) {
     3891 +                        free(filelist[i]);
     3892 +                        continue;
     3893 +                }
     3894 +
     3895 +                if (bam_verbose)
     3896 +                        bam_print(_("/etc/system.d adding %s/%s\n"),
     3897 +                            path, fname);
     3898 +
     3899 +                (void) snprintf(filepath, sizeof (filepath), "%s/%s",
     3900 +                    path, fname);
     3901 +
     3902 +                if ((assemble_systemfile(filepath, tmpfile)) < 0) {
     3903 +                        bam_error(_("failed to append file: %s: %s\n"),
     3904 +                            filepath, strerror(errno));
     3905 +                        ret = BAM_ERROR;
     3906 +                        break;
     3907 +                }
     3908 +                sysfiles++;
     3909 +        }
     3910 +
     3911 +        if (sysfiles > 0) {
     3912 +                if (rename(tmpfile, self_assembly) < 0) {
     3913 +                        bam_error(_("failed to rename file: %s: %s\n"), tmpfile,
     3914 +                            strerror(errno));
     3915 +                        return (BAM_ERROR);
     3916 +                }
     3917 +
     3918 +                /*
     3919 +                 * Use previous attribute times to avoid
     3920 +                 * boot archive recreation.
     3921 +                 */
     3922 +                if (times[1].tv_nsec != 0 &&
     3923 +                    utimensat(AT_FDCWD, self_assembly, times, 0) != 0) {
     3924 +                        bam_error(_("failed to change times: %s\n"),
     3925 +                            strerror(errno));
     3926 +                        return (BAM_ERROR);
     3927 +                }
     3928 +        } else {
     3929 +                (void) unlink(tmpfile);
     3930 +                (void) unlink(self_assembly);
     3931 +        }
     3932 +        return (ret);
     3933 +}
     3934 +
     3935 +static error_t
3795 3936  create_ramdisk(char *root)
3796 3937  {
3797 3938          char *cmdline, path[PATH_MAX];
3798 3939          size_t len;
3799 3940          struct stat sb;
3800 3941          int ret, status = BAM_SUCCESS;
3801 3942  
3802 3943          /* If mkisofs should be used, use it to create the required archives */
3803 3944          if (use_mkisofs()) {
3804 3945                  if (has_cachedir() && is_dir_flag_on(NEED_UPDATE)) {
↓ open down ↓ 343 lines elided ↑ open up ↑
4148 4289           * root must be writable. This check applies to alternate
4149 4290           * root (-R option); bam_root_readonly applies to '/' only.
4150 4291           * The behaviour translates into being the one of a 'check'.
4151 4292           */
4152 4293          if (!bam_smf_check && !bam_check && is_readonly(root)) {
4153 4294                  set_flag(RDONLY_FSCHK);
4154 4295                  bam_check = 1;
4155 4296          }
4156 4297  
4157 4298          /*
     4299 +         * Process the /etc/system.d/self-assembly file.
     4300 +         */
     4301 +        if (build_etc_system_dir(bam_root) == BAM_ERROR)
     4302 +                return (BAM_ERROR);
     4303 +
     4304 +        /*
4158 4305           * Now check if an update is really needed.
4159 4306           */
4160 4307          ret = update_required(root);
4161 4308  
4162 4309          /*
4163 4310           * The check command (-n) is *not* a dry run.
4164 4311           * It only checks if the archive is in sync.
4165 4312           * A readonly filesystem has to be considered an error only if an update
4166 4313           * is required.
4167 4314           */
↓ open down ↓ 6004 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX