7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2012 Milan Jurik. All rights reserved.
25 * Copyright (c) 2015 by Delphix. All rights reserved.
26 * Copyright 2016 Toomas Soome <tsoome@me.com>
27 * Copyright 2016 Nexenta Systems, Inc.
28 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
29 */
30
31 /*
32 * bootadm(1M) is a new utility for managing bootability of
33 * Solaris *Newboot* environments. It has two primary tasks:
34 * - Allow end users to manage bootability of Newboot Solaris instances
35 * - Provide services to other subsystems in Solaris (primarily Install)
36 */
37
38 /* Headers */
39 #include <stdio.h>
40 #include <errno.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <alloca.h>
47 #include <stdarg.h>
138 #define CREATE_RAMDISK "boot/solaris/bin/create_ramdisk"
139 #define CREATE_DISKMAP "boot/solaris/bin/create_diskmap"
140 #define EXTRACT_BOOT_FILELIST "boot/solaris/bin/extract_boot_filelist"
141 #define GRUBDISK_MAP "/var/run/solaris_grubdisk.map"
142
143 #define GRUB_slice "/etc/lu/GRUB_slice"
144 #define GRUB_root "/etc/lu/GRUB_root"
145 #define GRUB_fdisk "/etc/lu/GRUB_fdisk"
146 #define GRUB_fdisk_target "/etc/lu/GRUB_fdisk_target"
147 #define FINDROOT_INSTALLGRUB "/etc/lu/installgrub.findroot"
148 #define LULIB "/usr/lib/lu/lulib"
149 #define LULIB_PROPAGATE_FILE "lulib_propagate_file"
150 #define CKSUM "/usr/bin/cksum"
151 #define LU_MENU_CKSUM "/etc/lu/menu.cksum"
152 #define BOOTADM "/sbin/bootadm"
153
154 #define INSTALLGRUB "/sbin/installgrub"
155 #define STAGE1 "/boot/grub/stage1"
156 #define STAGE2 "/boot/grub/stage2"
157
158 /*
159 * Default file attributes
160 */
161 #define DEFAULT_DEV_MODE 0644 /* default permissions */
162 #define DEFAULT_DEV_UID 0 /* user root */
163 #define DEFAULT_DEV_GID 3 /* group sys */
164
165 /*
166 * Menu related
167 * menu_cmd_t and menu_cmds must be kept in sync
168 */
169 char *menu_cmds[] = {
170 "default", /* DEFAULT_CMD */
171 "timeout", /* TIMEOUT_CMD */
172 "title", /* TITLE_CMD */
173 "root", /* ROOT_CMD */
174 "kernel", /* KERNEL_CMD */
175 "kernel$", /* KERNEL_DOLLAR_CMD */
176 "module", /* MODULE_CMD */
177 "module$", /* MODULE_DOLLAR_CMD */
211 static char *prog;
212 static subcmd_t bam_cmd;
213 char *bam_root;
214 int bam_rootlen;
215 static int bam_root_readonly;
216 int bam_alt_root;
217 static int bam_extend = 0;
218 static int bam_purge = 0;
219 static char *bam_subcmd;
220 static char *bam_opt;
221 static char **bam_argv;
222 static char *bam_pool;
223 static int bam_argc;
224 static int bam_check;
225 static int bam_saved_check;
226 static int bam_smf_check;
227 static int bam_lock_fd = -1;
228 static int bam_zfs;
229 static int bam_mbr;
230 char rootbuf[PATH_MAX] = "/";
231 static int bam_update_all;
232 static int bam_alt_platform;
233 static char *bam_platform;
234 static char *bam_home_env = NULL;
235
236 /* function prototypes */
237 static void parse_args_internal(int, char *[]);
238 static void parse_args(int, char *argv[]);
239 static error_t bam_menu(char *, char *, int, char *[]);
240 static error_t bam_install(char *, char *);
241 static error_t bam_archive(char *, char *);
242
243 static void bam_lock(void);
244 static void bam_unlock(void);
245
246 static int exec_cmd(char *, filelist_t *);
247 static error_t read_globals(menu_t *, char *, char *, int);
248 static int menu_on_bootdisk(char *os_root, char *menu_root);
249 static menu_t *menu_read(char *);
250 static error_t menu_write(char *, menu_t *);
251 static void linelist_free(line_t *);
252 static void menu_free(menu_t *);
253 static void filelist_free(filelist_t *);
254 static error_t list2file(char *, char *, char *, line_t *);
255 static error_t list_entry(menu_t *, char *, char *);
256 static error_t list_setting(menu_t *, char *, char *);
257 static error_t delete_all_entries(menu_t *, char *, char *);
258 static error_t update_entry(menu_t *mp, char *menu_root, char *opt);
259 static error_t update_temp(menu_t *mp, char *dummy, char *opt);
260
261 static error_t install_bootloader(void);
262 static error_t update_archive(char *, char *);
263 static error_t list_archive(char *, char *);
264 static error_t update_all(char *, char *);
265 static error_t read_list(char *, filelist_t *);
266 static error_t set_option(menu_t *, char *, char *);
267 static error_t set_kernel(menu_t *, menu_cmd_t, char *, char *, size_t);
268 static error_t get_kernel(menu_t *, menu_cmd_t, char *, size_t);
269 static char *expand_path(const char *);
270
271 static long s_strtol(char *);
272 static int s_fputs(char *, FILE *);
273
274 static int is_amd64(void);
275 static char *get_machine(void);
276 static void append_to_flist(filelist_t *, char *);
277 static int ufs_add_to_sign_list(char *sign);
278 static error_t synchronize_BE_menu(void);
279
280 #if !defined(_OBP)
281 static void ucode_install();
282 #endif
283
284 /* Menu related sub commands */
285 static subcmd_defn_t menu_subcmds[] = {
286 "set_option", OPT_ABSENT, set_option, 0, /* PUB */
287 "list_entry", OPT_OPTIONAL, list_entry, 1, /* PUB */
288 "delete_all_entries", OPT_ABSENT, delete_all_entries, 0, /* PVT */
2376 ret = update_dircache(file, flags);
2377 if (ret == BAM_ERROR) {
2378 bam_error(_("directory cache update "
2379 "failed for %s\n"), file);
2380 return (-1);
2381 }
2382 }
2383
2384 if (bam_verbose)
2385 bam_print(_(" new %s\n"), file);
2386 return (0);
2387 }
2388
2389 /*
2390 * If we got there, the file is already listed as to be included in the
2391 * iso image. We just need to know if we are going to rebuild it or not
2392 */
2393 if (is_flag_on(IS_SPARC_TARGET) &&
2394 is_dir_flag_on(FILE64, NEED_UPDATE) && !bam_nowrite())
2395 return (0);
2396 /*
2397 * File exists in old archive. Check if file has changed
2398 */
2399 assert(sz == 2);
2400 bcopy(value, filestat, sizeof (filestat));
2401
2402 if (flags != FTW_D && (filestat[0] != st->st_size ||
2403 filestat[1] != st->st_mtime)) {
2404 if (bam_smf_check) {
2405 safefilep = safefiles;
2406 while (safefilep != NULL &&
2407 safefilep->name[0] != '\0') {
2408 if (regcomp(&re, safefilep->name,
2409 REG_EXTENDED|REG_NOSUB) == 0) {
2410 status = regexec(&re,
2411 file + bam_rootlen, 0, NULL, 0);
2412 regfree(&re);
2413 if (status == 0) {
2414 (void) creat(
2415 NEED_UPDATE_SAFE_FILE,
2416 0644);
2417 return (0);
2418 }
2419 }
2420 safefilep = safefilep->next;
2421 }
2422 }
2423
2424 if (is_flag_on(IS_SPARC_TARGET)) {
2425 set_dir_flag(FILE64, NEED_UPDATE);
2426 } else {
2427 ret = update_dircache(file, flags);
2428 if (ret == BAM_ERROR) {
2429 bam_error(_("directory cache update failed "
2430 "for %s\n"), file);
2431 return (-1);
2432 }
2433 }
2434
2435 if (bam_verbose) {
2436 if (bam_smf_check)
2437 bam_print(" %s\n", file);
2438 else
2439 bam_print(_(" changed %s\n"), file);
2440 }
2441 }
2442
2443 return (0);
2444 }
2445
2446 /*
2447 * Remove a directory path recursively
2448 */
2449 static int
2450 rmdir_r(char *path)
2451 {
2452 struct dirent *d = NULL;
2453 DIR *dir = NULL;
2454 char tpath[PATH_MAX];
3744
3745
3746 ret = create_x86_archive(boot_archive, temp,
3747 get_cachedir(what));
3748 }
3749
3750 if (digest_archive(boot_archive) == BAM_ERROR && bam_verbose)
3751 bam_print("boot archive hashing failed\n");
3752
3753 if (ret == BAM_SUCCESS && bam_verbose)
3754 bam_print("Successfully created %s\n", boot_archive);
3755
3756 return (ret);
3757
3758 out_path_err:
3759 bam_error(_("unable to create path on mountpoint %s, path too long\n"),
3760 root);
3761 return (BAM_ERROR);
3762 }
3763
3764 static error_t
3765 create_ramdisk(char *root)
3766 {
3767 char *cmdline, path[PATH_MAX];
3768 size_t len;
3769 struct stat sb;
3770 int ret, what, status = BAM_SUCCESS;
3771
3772 /* If there is mkisofs, use it to create the required archives */
3773 if (is_mkisofs()) {
3774 for (what = FILE32; what < CACHEDIR_NUM; what++) {
3775 if (has_cachedir(what) && is_dir_flag_on(what,
3776 NEED_UPDATE)) {
3777 ret = mkisofs_archive(root, what);
3778 if (ret != 0)
3779 status = BAM_ERROR;
3780 }
3781 }
3782 return (status);
3783 }
3784
4099 if (bam_smf_check && !bam_root_readonly && !is_zfs(root))
4100 return (BAM_SUCCESS);
4101
4102 /*
4103 * Don't generate archive on ramdisk.
4104 */
4105 if (is_ramdisk(root))
4106 return (BAM_SUCCESS);
4107
4108 /*
4109 * root must be writable. This check applies to alternate
4110 * root (-R option); bam_root_readonly applies to '/' only.
4111 * The behaviour translates into being the one of a 'check'.
4112 */
4113 if (!bam_smf_check && !bam_check && is_readonly(root)) {
4114 set_flag(RDONLY_FSCHK);
4115 bam_check = 1;
4116 }
4117
4118 /*
4119 * Now check if an update is really needed.
4120 */
4121 ret = update_required(root);
4122
4123 /*
4124 * The check command (-n) is *not* a dry run.
4125 * It only checks if the archive is in sync.
4126 * A readonly filesystem has to be considered an error only if an update
4127 * is required.
4128 */
4129 if (bam_nowrite()) {
4130 if (is_flag_on(RDONLY_FSCHK)) {
4131 bam_check = bam_saved_check;
4132 if (ret > 0)
4133 bam_error(_("%s filesystem is read-only, "
4134 "skipping archives update\n"), root);
4135 if (bam_update_all)
4136 return ((ret != 0) ? BAM_ERROR : BAM_SUCCESS);
4137 }
4138
|
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2012 Milan Jurik. All rights reserved.
25 * Copyright (c) 2015 by Delphix. All rights reserved.
26 * Copyright 2016 Toomas Soome <tsoome@me.com>
27 * Copyright 2017 Nexenta Systems, Inc.
28 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
29 */
30
31 /*
32 * bootadm(1M) is a new utility for managing bootability of
33 * Solaris *Newboot* environments. It has two primary tasks:
34 * - Allow end users to manage bootability of Newboot Solaris instances
35 * - Provide services to other subsystems in Solaris (primarily Install)
36 */
37
38 /* Headers */
39 #include <stdio.h>
40 #include <errno.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <alloca.h>
47 #include <stdarg.h>
138 #define CREATE_RAMDISK "boot/solaris/bin/create_ramdisk"
139 #define CREATE_DISKMAP "boot/solaris/bin/create_diskmap"
140 #define EXTRACT_BOOT_FILELIST "boot/solaris/bin/extract_boot_filelist"
141 #define GRUBDISK_MAP "/var/run/solaris_grubdisk.map"
142
143 #define GRUB_slice "/etc/lu/GRUB_slice"
144 #define GRUB_root "/etc/lu/GRUB_root"
145 #define GRUB_fdisk "/etc/lu/GRUB_fdisk"
146 #define GRUB_fdisk_target "/etc/lu/GRUB_fdisk_target"
147 #define FINDROOT_INSTALLGRUB "/etc/lu/installgrub.findroot"
148 #define LULIB "/usr/lib/lu/lulib"
149 #define LULIB_PROPAGATE_FILE "lulib_propagate_file"
150 #define CKSUM "/usr/bin/cksum"
151 #define LU_MENU_CKSUM "/etc/lu/menu.cksum"
152 #define BOOTADM "/sbin/bootadm"
153
154 #define INSTALLGRUB "/sbin/installgrub"
155 #define STAGE1 "/boot/grub/stage1"
156 #define STAGE2 "/boot/grub/stage2"
157
158 #define ETC_SYSTEM_DIR "etc/system.d"
159 #define SELF_ASSEMBLY "etc/system.d/.self-assembly"
160
161 /*
162 * Default file attributes
163 */
164 #define DEFAULT_DEV_MODE 0644 /* default permissions */
165 #define DEFAULT_DEV_UID 0 /* user root */
166 #define DEFAULT_DEV_GID 3 /* group sys */
167
168 /*
169 * Menu related
170 * menu_cmd_t and menu_cmds must be kept in sync
171 */
172 char *menu_cmds[] = {
173 "default", /* DEFAULT_CMD */
174 "timeout", /* TIMEOUT_CMD */
175 "title", /* TITLE_CMD */
176 "root", /* ROOT_CMD */
177 "kernel", /* KERNEL_CMD */
178 "kernel$", /* KERNEL_DOLLAR_CMD */
179 "module", /* MODULE_CMD */
180 "module$", /* MODULE_DOLLAR_CMD */
214 static char *prog;
215 static subcmd_t bam_cmd;
216 char *bam_root;
217 int bam_rootlen;
218 static int bam_root_readonly;
219 int bam_alt_root;
220 static int bam_extend = 0;
221 static int bam_purge = 0;
222 static char *bam_subcmd;
223 static char *bam_opt;
224 static char **bam_argv;
225 static char *bam_pool;
226 static int bam_argc;
227 static int bam_check;
228 static int bam_saved_check;
229 static int bam_smf_check;
230 static int bam_lock_fd = -1;
231 static int bam_zfs;
232 static int bam_mbr;
233 char rootbuf[PATH_MAX] = "/";
234 static char self_assembly[PATH_MAX];
235 static int bam_update_all;
236 static int bam_alt_platform;
237 static char *bam_platform;
238 static char *bam_home_env = NULL;
239
240 /* function prototypes */
241 static void parse_args_internal(int, char *[]);
242 static void parse_args(int, char *argv[]);
243 static error_t bam_menu(char *, char *, int, char *[]);
244 static error_t bam_install(char *, char *);
245 static error_t bam_archive(char *, char *);
246
247 static void bam_lock(void);
248 static void bam_unlock(void);
249
250 static int exec_cmd(char *, filelist_t *);
251 static error_t read_globals(menu_t *, char *, char *, int);
252 static int menu_on_bootdisk(char *os_root, char *menu_root);
253 static menu_t *menu_read(char *);
254 static error_t menu_write(char *, menu_t *);
255 static void linelist_free(line_t *);
256 static void menu_free(menu_t *);
257 static void filelist_free(filelist_t *);
258 static error_t list2file(char *, char *, char *, line_t *);
259 static error_t list_entry(menu_t *, char *, char *);
260 static error_t list_setting(menu_t *, char *, char *);
261 static error_t delete_all_entries(menu_t *, char *, char *);
262 static error_t update_entry(menu_t *mp, char *menu_root, char *opt);
263 static error_t update_temp(menu_t *mp, char *dummy, char *opt);
264
265 static error_t install_bootloader(void);
266 static error_t update_archive(char *, char *);
267 static error_t list_archive(char *, char *);
268 static error_t update_all(char *, char *);
269 static error_t read_list(char *, filelist_t *);
270 static error_t set_option(menu_t *, char *, char *);
271 static error_t set_kernel(menu_t *, menu_cmd_t, char *, char *, size_t);
272 static error_t get_kernel(menu_t *, menu_cmd_t, char *, size_t);
273 static error_t build_etc_system_dir(char *);
274 static char *expand_path(const char *);
275
276 static long s_strtol(char *);
277 static int s_fputs(char *, FILE *);
278
279 static int is_amd64(void);
280 static char *get_machine(void);
281 static void append_to_flist(filelist_t *, char *);
282 static int ufs_add_to_sign_list(char *sign);
283 static error_t synchronize_BE_menu(void);
284
285 #if !defined(_OBP)
286 static void ucode_install();
287 #endif
288
289 /* Menu related sub commands */
290 static subcmd_defn_t menu_subcmds[] = {
291 "set_option", OPT_ABSENT, set_option, 0, /* PUB */
292 "list_entry", OPT_OPTIONAL, list_entry, 1, /* PUB */
293 "delete_all_entries", OPT_ABSENT, delete_all_entries, 0, /* PVT */
2381 ret = update_dircache(file, flags);
2382 if (ret == BAM_ERROR) {
2383 bam_error(_("directory cache update "
2384 "failed for %s\n"), file);
2385 return (-1);
2386 }
2387 }
2388
2389 if (bam_verbose)
2390 bam_print(_(" new %s\n"), file);
2391 return (0);
2392 }
2393
2394 /*
2395 * If we got there, the file is already listed as to be included in the
2396 * iso image. We just need to know if we are going to rebuild it or not
2397 */
2398 if (is_flag_on(IS_SPARC_TARGET) &&
2399 is_dir_flag_on(FILE64, NEED_UPDATE) && !bam_nowrite())
2400 return (0);
2401
2402
2403 /*
2404 * File exists in old archive. Check if file has changed
2405 */
2406 assert(sz == 2);
2407 bcopy(value, filestat, sizeof (filestat));
2408
2409 if (flags != FTW_D && (filestat[0] != st->st_size ||
2410 filestat[1] != st->st_mtime)) {
2411 if (bam_smf_check) {
2412 safefilep = safefiles;
2413 while (safefilep != NULL &&
2414 safefilep->name[0] != '\0') {
2415 if (regcomp(&re, safefilep->name,
2416 REG_EXTENDED|REG_NOSUB) == 0) {
2417 status = regexec(&re,
2418 file + bam_rootlen, 0, NULL, 0);
2419 regfree(&re);
2420 if (status == 0) {
2421 (void) creat(
2422 NEED_UPDATE_SAFE_FILE,
2423 0644);
2424 return (0);
2425 }
2426 }
2427 safefilep = safefilep->next;
2428 }
2429 }
2430
2431 if (is_flag_on(IS_SPARC_TARGET)) {
2432 set_dir_flag(FILE64, NEED_UPDATE);
2433 } else {
2434 ret = update_dircache(file, flags);
2435 if (ret == BAM_ERROR) {
2436 bam_error(_("directory cache update failed "
2437 "for %s\n"), file);
2438 return (-1);
2439 }
2440 }
2441
2442 /*
2443 * Update self-assembly file if there are changes in
2444 * /etc/system.d directory
2445 */
2446 if (strstr(file, ETC_SYSTEM_DIR)) {
2447 ret = update_dircache(self_assembly, flags);
2448 if (ret == BAM_ERROR) {
2449 bam_error(_("directory cache update failed "
2450 "for %s\n"), file);
2451 return (-1);
2452 }
2453 }
2454
2455 if (bam_verbose) {
2456 if (bam_smf_check)
2457 bam_print(" %s\n", file);
2458 else
2459 bam_print(_(" changed %s\n"), file);
2460 }
2461 }
2462
2463 return (0);
2464 }
2465
2466 /*
2467 * Remove a directory path recursively
2468 */
2469 static int
2470 rmdir_r(char *path)
2471 {
2472 struct dirent *d = NULL;
2473 DIR *dir = NULL;
2474 char tpath[PATH_MAX];
3764
3765
3766 ret = create_x86_archive(boot_archive, temp,
3767 get_cachedir(what));
3768 }
3769
3770 if (digest_archive(boot_archive) == BAM_ERROR && bam_verbose)
3771 bam_print("boot archive hashing failed\n");
3772
3773 if (ret == BAM_SUCCESS && bam_verbose)
3774 bam_print("Successfully created %s\n", boot_archive);
3775
3776 return (ret);
3777
3778 out_path_err:
3779 bam_error(_("unable to create path on mountpoint %s, path too long\n"),
3780 root);
3781 return (BAM_ERROR);
3782 }
3783
3784 static int
3785 assemble_systemfile(char *infilename, char *outfilename)
3786 {
3787 char buf[BUFSIZ];
3788 FILE *infile, *outfile;
3789 size_t n;
3790
3791 if ((infile = fopen(infilename, "r")) == NULL) {
3792 bam_error(_("failed to open file: %s: %s\n"), infilename,
3793 strerror(errno));
3794 return (BAM_ERROR);
3795 }
3796
3797 if ((outfile = fopen(outfilename, "a")) == NULL) {
3798 bam_error(_("failed to open file: %s: %s\n"), outfilename,
3799 strerror(errno));
3800 (void) fclose(infile);
3801 return (BAM_ERROR);
3802 }
3803
3804 while ((n = fread(buf, 1, sizeof (buf), infile)) > 0) {
3805 if (fwrite(buf, 1, n, outfile) != n) {
3806 bam_error(_("failed to write file: %s: %s\n"),
3807 outfilename, strerror(errno));
3808 (void) fclose(infile);
3809 (void) fclose(outfile);
3810 return (BAM_ERROR);
3811 }
3812 }
3813
3814 (void) fclose(infile);
3815 (void) fclose(outfile);
3816
3817 return (BAM_SUCCESS);
3818 }
3819
3820 /*
3821 * Concatenate all files (except those starting with a dot)
3822 * from /etc/system.d directory into a single /etc/system.d/.self-assembly
3823 * file. The kernel reads it before /etc/system file.
3824 */
3825 static error_t
3826 build_etc_system_dir(char *root)
3827 {
3828 struct dirent **filelist;
3829 char path[PATH_MAX], tmpfile[PATH_MAX];
3830 int i, files, sysfiles = 0;
3831 int ret = BAM_SUCCESS;
3832 struct stat st;
3833 timespec_t times[2];
3834
3835 (void) snprintf(path, sizeof (path), "%s/%s", root, ETC_SYSTEM_DIR);
3836 (void) snprintf(self_assembly, sizeof (self_assembly),
3837 "%s%s", root, SELF_ASSEMBLY);
3838 (void) snprintf(tmpfile, sizeof (tmpfile), "%s.%ld",
3839 self_assembly, (long)getpid());
3840
3841 if (stat(self_assembly, &st) >= 0 && (st.st_mode & S_IFMT) == S_IFREG) {
3842 times[0] = times[1] = st.st_mtim;
3843 } else {
3844 times[1].tv_nsec = 0;
3845 }
3846
3847 if ((files = scandir(path, &filelist, NULL, alphasort)) < 0) {
3848 /* Don't fail the update if <ROOT>/etc/system.d doesn't exist */
3849 if (errno == ENOENT)
3850 return (BAM_SUCCESS);
3851 bam_error(_("can't read %s: %s\n"), path, strerror(errno));
3852 return (BAM_ERROR);
3853 }
3854
3855 for (i = 0; i < files; i++) {
3856 char filepath[PATH_MAX];
3857 char *fname;
3858
3859 fname = filelist[i]->d_name;
3860
3861 /* skip anything that starts with a dot */
3862 if (strncmp(fname, ".", 1) == 0) {
3863 free(filelist[i]);
3864 continue;
3865 }
3866
3867 if (bam_verbose)
3868 bam_print(_("/etc/system.d adding %s/%s\n"),
3869 path, fname);
3870
3871 (void) snprintf(filepath, sizeof (filepath), "%s/%s",
3872 path, fname);
3873
3874 if ((assemble_systemfile(filepath, tmpfile)) < 0) {
3875 bam_error(_("failed to append file: %s: %s\n"),
3876 filepath, strerror(errno));
3877 ret = BAM_ERROR;
3878 break;
3879 }
3880 sysfiles++;
3881 }
3882
3883 if (sysfiles > 0) {
3884 if (rename(tmpfile, self_assembly) < 0) {
3885 bam_error(_("failed to rename file: %s: %s\n"), tmpfile,
3886 strerror(errno));
3887 return (BAM_ERROR);
3888 }
3889
3890 /*
3891 * Use previous attribute times to avoid
3892 * boot archive recreation.
3893 */
3894 if (times[1].tv_nsec != 0 &&
3895 utimensat(AT_FDCWD, self_assembly, times, 0) != 0) {
3896 bam_error(_("failed to change times: %s\n"),
3897 strerror(errno));
3898 return (BAM_ERROR);
3899 }
3900 } else {
3901 (void) unlink(tmpfile);
3902 (void) unlink(self_assembly);
3903 }
3904 return (ret);
3905 }
3906
3907 static error_t
3908 create_ramdisk(char *root)
3909 {
3910 char *cmdline, path[PATH_MAX];
3911 size_t len;
3912 struct stat sb;
3913 int ret, what, status = BAM_SUCCESS;
3914
3915 /* If there is mkisofs, use it to create the required archives */
3916 if (is_mkisofs()) {
3917 for (what = FILE32; what < CACHEDIR_NUM; what++) {
3918 if (has_cachedir(what) && is_dir_flag_on(what,
3919 NEED_UPDATE)) {
3920 ret = mkisofs_archive(root, what);
3921 if (ret != 0)
3922 status = BAM_ERROR;
3923 }
3924 }
3925 return (status);
3926 }
3927
4242 if (bam_smf_check && !bam_root_readonly && !is_zfs(root))
4243 return (BAM_SUCCESS);
4244
4245 /*
4246 * Don't generate archive on ramdisk.
4247 */
4248 if (is_ramdisk(root))
4249 return (BAM_SUCCESS);
4250
4251 /*
4252 * root must be writable. This check applies to alternate
4253 * root (-R option); bam_root_readonly applies to '/' only.
4254 * The behaviour translates into being the one of a 'check'.
4255 */
4256 if (!bam_smf_check && !bam_check && is_readonly(root)) {
4257 set_flag(RDONLY_FSCHK);
4258 bam_check = 1;
4259 }
4260
4261 /*
4262 * Process the /etc/system.d/self-assembly file.
4263 */
4264 if (build_etc_system_dir(bam_root) == BAM_ERROR)
4265 return (BAM_ERROR);
4266
4267 /*
4268 * Now check if an update is really needed.
4269 */
4270 ret = update_required(root);
4271
4272 /*
4273 * The check command (-n) is *not* a dry run.
4274 * It only checks if the archive is in sync.
4275 * A readonly filesystem has to be considered an error only if an update
4276 * is required.
4277 */
4278 if (bam_nowrite()) {
4279 if (is_flag_on(RDONLY_FSCHK)) {
4280 bam_check = bam_saved_check;
4281 if (ret > 0)
4282 bam_error(_("%s filesystem is read-only, "
4283 "skipping archives update\n"), root);
4284 if (bam_update_all)
4285 return ((ret != 0) ? BAM_ERROR : BAM_SUCCESS);
4286 }
4287
|