17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5fbac2b2bSvikram * Common Development and Distribution License (the "License"). 6fbac2b2bSvikram * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 2237eb779cSVikram Hegde * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * bootadm(1M) is a new utility for managing bootability of 287c478bd9Sstevel@tonic-gate * Solaris *Newboot* environments. It has two primary tasks: 297c478bd9Sstevel@tonic-gate * - Allow end users to manage bootability of Newboot Solaris instances 307c478bd9Sstevel@tonic-gate * - Provide services to other subsystems in Solaris (primarily Install) 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 337c478bd9Sstevel@tonic-gate /* Headers */ 347c478bd9Sstevel@tonic-gate #include <stdio.h> 357c478bd9Sstevel@tonic-gate #include <errno.h> 367c478bd9Sstevel@tonic-gate #include <stdlib.h> 377c478bd9Sstevel@tonic-gate #include <string.h> 387c478bd9Sstevel@tonic-gate #include <unistd.h> 397c478bd9Sstevel@tonic-gate #include <sys/types.h> 407c478bd9Sstevel@tonic-gate #include <sys/stat.h> 417c478bd9Sstevel@tonic-gate #include <stdarg.h> 427c478bd9Sstevel@tonic-gate #include <limits.h> 437c478bd9Sstevel@tonic-gate #include <signal.h> 447c478bd9Sstevel@tonic-gate #include <sys/wait.h> 457c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 46f904d32dSJerry Gilliam #include <sys/mntent.h> 477c478bd9Sstevel@tonic-gate #include <sys/statvfs.h> 487c478bd9Sstevel@tonic-gate #include <libnvpair.h> 497c478bd9Sstevel@tonic-gate #include <ftw.h> 507c478bd9Sstevel@tonic-gate #include <fcntl.h> 517c478bd9Sstevel@tonic-gate #include <strings.h> 522449e17fSsherrym #include <utime.h> 537c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 547c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h> 5558091fd8Ssetje #include <sys/param.h> 56eb2bd662Svikram #include <dirent.h> 57eb2bd662Svikram #include <ctype.h> 58eb2bd662Svikram #include <libgen.h> 59e7cbe64fSgw25295 #include <sys/sysmacros.h> 60*48847494SEnrico Perla - Sun Microsystems #include <sys/elf.h> 61963390b4Svikram #include <libscf.h> 62*48847494SEnrico Perla - Sun Microsystems #include <zlib.h> 63*48847494SEnrico Perla - Sun Microsystems #include <sys/lockfs.h> 64*48847494SEnrico Perla - Sun Microsystems #include <sys/filio.h> 65986fd29aSsetje 66986fd29aSsetje #if !defined(_OPB) 672449e17fSsherrym #include <sys/ucode.h> 682449e17fSsherrym #endif 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate #include <pwd.h> 717c478bd9Sstevel@tonic-gate #include <grp.h> 727c478bd9Sstevel@tonic-gate #include <device_info.h> 73eb2bd662Svikram #include <sys/vtoc.h> 74eb2bd662Svikram #include <sys/efi_partition.h> 75eb2bd662Svikram 767c478bd9Sstevel@tonic-gate #include <locale.h> 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate #include "message.h" 79ae115bc7Smrj #include "bootadm.h" 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate #ifndef TEXT_DOMAIN 827c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SUNW_OST_OSCMD" 837c478bd9Sstevel@tonic-gate #endif /* TEXT_DOMAIN */ 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate /* Type definitions */ 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* Primary subcmds */ 887c478bd9Sstevel@tonic-gate typedef enum { 897c478bd9Sstevel@tonic-gate BAM_MENU = 3, 907c478bd9Sstevel@tonic-gate BAM_ARCHIVE 917c478bd9Sstevel@tonic-gate } subcmd_t; 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate typedef enum { 947c478bd9Sstevel@tonic-gate OPT_ABSENT = 0, /* No option */ 957c478bd9Sstevel@tonic-gate OPT_REQ, /* option required */ 967c478bd9Sstevel@tonic-gate OPT_OPTIONAL /* option may or may not be present */ 977c478bd9Sstevel@tonic-gate } option_t; 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate typedef struct { 1007c478bd9Sstevel@tonic-gate char *subcmd; 1017c478bd9Sstevel@tonic-gate option_t option; 1027c478bd9Sstevel@tonic-gate error_t (*handler)(); 1031a97e40eSvikram int unpriv; /* is this an unprivileged command */ 1047c478bd9Sstevel@tonic-gate } subcmd_defn_t; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate #define LINE_INIT 0 /* lineNum initial value */ 1077c478bd9Sstevel@tonic-gate #define ENTRY_INIT -1 /* entryNum initial value */ 1087c478bd9Sstevel@tonic-gate #define ALL_ENTRIES -2 /* selects all boot entries */ 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate #define GRUB_DIR "/boot/grub" 111963390b4Svikram #define GRUB_STAGE2 GRUB_DIR "/stage2" 1127c478bd9Sstevel@tonic-gate #define GRUB_MENU "/boot/grub/menu.lst" 1137c478bd9Sstevel@tonic-gate #define MENU_TMP "/boot/grub/menu.lst.tmp" 114963390b4Svikram #define GRUB_BACKUP_MENU "/etc/lu/GRUB_backup_menu" 1157c478bd9Sstevel@tonic-gate #define RAMDISK_SPECIAL "/ramdisk" 11640541d5dSvikram #define STUBBOOT "/stubboot" 117eb2bd662Svikram #define MULTIBOOT "/platform/i86pc/multiboot" 118eb2bd662Svikram #define GRUBSIGN_DIR "/boot/grub/bootsign" 119eb2bd662Svikram #define GRUBSIGN_BACKUP "/etc/bootsign" 120eb2bd662Svikram #define GRUBSIGN_UFS_PREFIX "rootfs" 121eb2bd662Svikram #define GRUBSIGN_ZFS_PREFIX "pool_" 122eb2bd662Svikram #define GRUBSIGN_LU_PREFIX "BE_" 123eb2bd662Svikram #define UFS_SIGNATURE_LIST "/var/run/grub_ufs_signatures" 124eb2bd662Svikram #define ZFS_LEGACY_MNTPT "/tmp/bootadm_mnt_zfs_legacy" 125eb2bd662Svikram 126eb2bd662Svikram #define BOOTADM_RDONLY_TEST "BOOTADM_RDONLY_TEST" 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate /* lock related */ 1297c478bd9Sstevel@tonic-gate #define BAM_LOCK_FILE "/var/run/bootadm.lock" 1307c478bd9Sstevel@tonic-gate #define LOCK_FILE_PERMS (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) 1317c478bd9Sstevel@tonic-gate 132986fd29aSsetje #define CREATE_RAMDISK "boot/solaris/bin/create_ramdisk" 133986fd29aSsetje #define CREATE_DISKMAP "boot/solaris/bin/create_diskmap" 134986fd29aSsetje #define EXTRACT_BOOT_FILELIST "boot/solaris/bin/extract_boot_filelist" 1357c478bd9Sstevel@tonic-gate #define GRUBDISK_MAP "/var/run/solaris_grubdisk.map" 1367c478bd9Sstevel@tonic-gate 137b610f78eSvikram #define GRUB_slice "/etc/lu/GRUB_slice" 138b610f78eSvikram #define GRUB_root "/etc/lu/GRUB_root" 139fbac2b2bSvikram #define GRUB_fdisk "/etc/lu/GRUB_fdisk" 140fbac2b2bSvikram #define GRUB_fdisk_target "/etc/lu/GRUB_fdisk_target" 141963390b4Svikram #define FINDROOT_INSTALLGRUB "/etc/lu/installgrub.findroot" 142963390b4Svikram #define LULIB "/usr/lib/lu/lulib" 143963390b4Svikram #define LULIB_PROPAGATE_FILE "lulib_propagate_file" 144963390b4Svikram #define CKSUM "/usr/bin/cksum" 145963390b4Svikram #define LU_MENU_CKSUM "/etc/lu/menu.cksum" 146963390b4Svikram #define BOOTADM "/sbin/bootadm" 147b610f78eSvikram 148b610f78eSvikram #define INSTALLGRUB "/sbin/installgrub" 149b610f78eSvikram #define STAGE1 "/boot/grub/stage1" 150b610f78eSvikram #define STAGE2 "/boot/grub/stage2" 151b610f78eSvikram 152eb2bd662Svikram typedef enum zfs_mnted { 153eb2bd662Svikram ZFS_MNT_ERROR = -1, 154eb2bd662Svikram LEGACY_MOUNTED = 1, 155eb2bd662Svikram LEGACY_ALREADY, 156eb2bd662Svikram ZFS_MOUNTED, 157eb2bd662Svikram ZFS_ALREADY 158eb2bd662Svikram } zfs_mnted_t; 159eb2bd662Svikram 1607c478bd9Sstevel@tonic-gate /* 16198892a30Snadkarni * The following two defines are used to detect and create the correct 16298892a30Snadkarni * boot archive when safemode patching is underway. LOFS_PATCH_FILE is a 16398892a30Snadkarni * contracted private interface between bootadm and the install 16498892a30Snadkarni * consolidation. It is set by pdo.c when a patch with SUNW_PATCH_SAFEMODE 16598892a30Snadkarni * is applied. 16698892a30Snadkarni */ 16798892a30Snadkarni #define LOFS_PATCH_FILE "/var/run/.patch_loopback_mode" 16898892a30Snadkarni #define LOFS_PATCH_MNT "/var/run/.patch_root_loopbackmnt" 16998892a30Snadkarni 17098892a30Snadkarni /* 1717c478bd9Sstevel@tonic-gate * Default file attributes 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate #define DEFAULT_DEV_MODE 0644 /* default permissions */ 1747c478bd9Sstevel@tonic-gate #define DEFAULT_DEV_UID 0 /* user root */ 1757c478bd9Sstevel@tonic-gate #define DEFAULT_DEV_GID 3 /* group sys */ 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate /* 1787c478bd9Sstevel@tonic-gate * Menu related 1797c478bd9Sstevel@tonic-gate * menu_cmd_t and menu_cmds must be kept in sync 1807c478bd9Sstevel@tonic-gate */ 181ae115bc7Smrj char *menu_cmds[] = { 1827c478bd9Sstevel@tonic-gate "default", /* DEFAULT_CMD */ 1837c478bd9Sstevel@tonic-gate "timeout", /* TIMEOUT_CMD */ 1847c478bd9Sstevel@tonic-gate "title", /* TITLE_CMD */ 1857c478bd9Sstevel@tonic-gate "root", /* ROOT_CMD */ 1867c478bd9Sstevel@tonic-gate "kernel", /* KERNEL_CMD */ 187ae115bc7Smrj "kernel$", /* KERNEL_DOLLAR_CMD */ 1887c478bd9Sstevel@tonic-gate "module", /* MODULE_CMD */ 189ae115bc7Smrj "module$", /* MODULE_DOLLAR_CMD */ 1907c478bd9Sstevel@tonic-gate " ", /* SEP_CMD */ 1917c478bd9Sstevel@tonic-gate "#", /* COMMENT_CMD */ 192ae115bc7Smrj "chainloader", /* CHAINLOADER_CMD */ 193ae115bc7Smrj "args", /* ARGS_CMD */ 194eb2bd662Svikram "findroot", /* FINDROOT_CMD */ 1957c478bd9Sstevel@tonic-gate NULL 1967c478bd9Sstevel@tonic-gate }; 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate #define OPT_ENTRY_NUM "entry" 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate /* 201eb2bd662Svikram * exec_cmd related 2027c478bd9Sstevel@tonic-gate */ 2037c478bd9Sstevel@tonic-gate typedef struct { 2047c478bd9Sstevel@tonic-gate line_t *head; 2057c478bd9Sstevel@tonic-gate line_t *tail; 2067c478bd9Sstevel@tonic-gate } filelist_t; 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate #define BOOT_FILE_LIST "boot/solaris/filelist.ramdisk" 2097c478bd9Sstevel@tonic-gate #define ETC_FILE_LIST "etc/boot/solaris/filelist.ramdisk" 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate #define FILE_STAT "boot/solaris/filestat.ramdisk" 2127c478bd9Sstevel@tonic-gate #define FILE_STAT_TMP "boot/solaris/filestat.ramdisk.tmp" 2137c478bd9Sstevel@tonic-gate #define DIR_PERMS (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) 2147c478bd9Sstevel@tonic-gate #define FILE_STAT_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate /* Globals */ 217ae115bc7Smrj int bam_verbose; 218ae115bc7Smrj int bam_force; 219eb2bd662Svikram int bam_debug; 2207c478bd9Sstevel@tonic-gate static char *prog; 2217c478bd9Sstevel@tonic-gate static subcmd_t bam_cmd; 2227c478bd9Sstevel@tonic-gate static char *bam_root; 2237c478bd9Sstevel@tonic-gate static int bam_rootlen; 2247c478bd9Sstevel@tonic-gate static int bam_root_readonly; 22540541d5dSvikram static int bam_alt_root; 226*48847494SEnrico Perla - Sun Microsystems static int bam_extend = 0; 227*48847494SEnrico Perla - Sun Microsystems static int bam_purge = 0; 2287c478bd9Sstevel@tonic-gate static char *bam_subcmd; 2297c478bd9Sstevel@tonic-gate static char *bam_opt; 2307c478bd9Sstevel@tonic-gate static char **bam_argv; 2317c478bd9Sstevel@tonic-gate static int bam_argc; 2327c478bd9Sstevel@tonic-gate static int bam_check; 2337c478bd9Sstevel@tonic-gate static int bam_smf_check; 2347c478bd9Sstevel@tonic-gate static int bam_lock_fd = -1; 235e7cbe64fSgw25295 static int bam_zfs; 2367c478bd9Sstevel@tonic-gate static char rootbuf[PATH_MAX] = "/"; 237b610f78eSvikram static int bam_update_all; 238d876c67dSjg static int bam_alt_platform; 239d876c67dSjg static char *bam_platform; 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* function prototypes */ 242986fd29aSsetje static void parse_args_internal(int, char *[]); 243986fd29aSsetje static void parse_args(int, char *argv[]); 244986fd29aSsetje static error_t bam_menu(char *, char *, int, char *[]); 245986fd29aSsetje static error_t bam_archive(char *, char *); 2467c478bd9Sstevel@tonic-gate 247986fd29aSsetje static void bam_exit(int); 2487c478bd9Sstevel@tonic-gate static void bam_lock(void); 2497c478bd9Sstevel@tonic-gate static void bam_unlock(void); 2507c478bd9Sstevel@tonic-gate 251986fd29aSsetje static int exec_cmd(char *, filelist_t *); 252986fd29aSsetje static error_t read_globals(menu_t *, char *, char *, int); 253eb2bd662Svikram static int menu_on_bootdisk(char *os_root, char *menu_root); 254986fd29aSsetje static menu_t *menu_read(char *); 255986fd29aSsetje static error_t menu_write(char *, menu_t *); 256986fd29aSsetje static void linelist_free(line_t *); 257986fd29aSsetje static void menu_free(menu_t *); 258986fd29aSsetje static void filelist_free(filelist_t *); 259986fd29aSsetje static error_t list2file(char *, char *, char *, line_t *); 260986fd29aSsetje static error_t list_entry(menu_t *, char *, char *); 261986fd29aSsetje static error_t delete_all_entries(menu_t *, char *, char *); 262eb2bd662Svikram static error_t update_entry(menu_t *mp, char *menu_root, char *opt); 263eb2bd662Svikram static error_t update_temp(menu_t *mp, char *dummy, char *opt); 2647c478bd9Sstevel@tonic-gate 265986fd29aSsetje static error_t update_archive(char *, char *); 266986fd29aSsetje static error_t list_archive(char *, char *); 267986fd29aSsetje static error_t update_all(char *, char *); 268986fd29aSsetje static error_t read_list(char *, filelist_t *); 269986fd29aSsetje static error_t set_global(menu_t *, char *, int); 270986fd29aSsetje static error_t set_option(menu_t *, char *, char *); 271986fd29aSsetje static error_t set_kernel(menu_t *, menu_cmd_t, char *, char *, size_t); 272eb2bd662Svikram static error_t get_kernel(menu_t *, menu_cmd_t, char *, size_t); 273986fd29aSsetje static char *expand_path(const char *); 2747c478bd9Sstevel@tonic-gate 275986fd29aSsetje static long s_strtol(char *); 276986fd29aSsetje static int s_fputs(char *, FILE *); 2777c478bd9Sstevel@tonic-gate 278eb2bd662Svikram static int is_zfs(char *root); 279eb2bd662Svikram static int is_ufs(char *root); 280eb2bd662Svikram static int is_pcfs(char *root); 2817c478bd9Sstevel@tonic-gate static int is_amd64(void); 28279755401Ssetje static char *get_machine(void); 2837c478bd9Sstevel@tonic-gate static void append_to_flist(filelist_t *, char *); 284eb2bd662Svikram static char *mount_top_dataset(char *pool, zfs_mnted_t *mnted); 285eb2bd662Svikram static int umount_top_dataset(char *pool, zfs_mnted_t mnted, char *mntpt); 286eb2bd662Svikram static int ufs_add_to_sign_list(char *sign); 287963390b4Svikram static error_t synchronize_BE_menu(void); 2887c478bd9Sstevel@tonic-gate 289986fd29aSsetje #if !defined(_OPB) 2902449e17fSsherrym static void ucode_install(); 2912449e17fSsherrym #endif 2922449e17fSsherrym 2937c478bd9Sstevel@tonic-gate /* Menu related sub commands */ 2947c478bd9Sstevel@tonic-gate static subcmd_defn_t menu_subcmds[] = { 295eb2bd662Svikram "set_option", OPT_ABSENT, set_option, 0, /* PUB */ 2961a97e40eSvikram "list_entry", OPT_OPTIONAL, list_entry, 1, /* PUB */ 2971a97e40eSvikram "delete_all_entries", OPT_ABSENT, delete_all_entries, 0, /* PVT */ 2981a97e40eSvikram "update_entry", OPT_REQ, update_entry, 0, /* menu */ 2991a97e40eSvikram "update_temp", OPT_OPTIONAL, update_temp, 0, /* reboot */ 300ae115bc7Smrj "upgrade", OPT_ABSENT, upgrade_menu, 0, /* menu */ 3011a97e40eSvikram NULL, 0, NULL, 0 /* must be last */ 3027c478bd9Sstevel@tonic-gate }; 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate /* Archive related sub commands */ 3057c478bd9Sstevel@tonic-gate static subcmd_defn_t arch_subcmds[] = { 3061a97e40eSvikram "update", OPT_ABSENT, update_archive, 0, /* PUB */ 3071a97e40eSvikram "update_all", OPT_ABSENT, update_all, 0, /* PVT */ 3081a97e40eSvikram "list", OPT_OPTIONAL, list_archive, 1, /* PUB */ 3091a97e40eSvikram NULL, 0, NULL, 0 /* must be last */ 3107c478bd9Sstevel@tonic-gate }; 3117c478bd9Sstevel@tonic-gate 312*48847494SEnrico Perla - Sun Microsystems enum dircache_copy_opt { 313*48847494SEnrico Perla - Sun Microsystems FILE32 = 0, 314*48847494SEnrico Perla - Sun Microsystems FILE64, 315*48847494SEnrico Perla - Sun Microsystems CACHEDIR_NUM 316*48847494SEnrico Perla - Sun Microsystems }; 317*48847494SEnrico Perla - Sun Microsystems 318*48847494SEnrico Perla - Sun Microsystems /* 319*48847494SEnrico Perla - Sun Microsystems * Directory specific flags: 320*48847494SEnrico Perla - Sun Microsystems * NEED_UPDATE : the specified archive needs to be updated 321*48847494SEnrico Perla - Sun Microsystems * NO_MULTI : don't extend the specified archive, but recreate it 322*48847494SEnrico Perla - Sun Microsystems */ 323*48847494SEnrico Perla - Sun Microsystems #define NEED_UPDATE 0x00000001 324*48847494SEnrico Perla - Sun Microsystems #define NO_MULTI 0x00000002 325*48847494SEnrico Perla - Sun Microsystems 326*48847494SEnrico Perla - Sun Microsystems #define set_dir_flag(id, f) (walk_arg.dirinfo[id].flags |= f) 327*48847494SEnrico Perla - Sun Microsystems #define unset_dir_flag(id, f) (walk_arg.dirinfo[id].flags &= ~f) 328*48847494SEnrico Perla - Sun Microsystems #define is_dir_flag_on(id, f) (walk_arg.dirinfo[id].flags & f ? 1 : 0) 329*48847494SEnrico Perla - Sun Microsystems 330*48847494SEnrico Perla - Sun Microsystems #define get_cachedir(id) (walk_arg.dirinfo[id].cdir_path) 331*48847494SEnrico Perla - Sun Microsystems #define get_updatedir(id) (walk_arg.dirinfo[id].update_path) 332*48847494SEnrico Perla - Sun Microsystems #define get_count(id) (walk_arg.dirinfo[id].count) 333*48847494SEnrico Perla - Sun Microsystems #define has_cachedir(id) (walk_arg.dirinfo[id].has_dir) 334*48847494SEnrico Perla - Sun Microsystems #define set_dir_present(id) (walk_arg.dirinfo[id].has_dir = 1) 335*48847494SEnrico Perla - Sun Microsystems 336*48847494SEnrico Perla - Sun Microsystems /* 337*48847494SEnrico Perla - Sun Microsystems * dirinfo_t (specific cache directory information): 338*48847494SEnrico Perla - Sun Microsystems * cdir_path: path to the archive cache directory 339*48847494SEnrico Perla - Sun Microsystems * update_path: path to the update directory (contains the files that will be 340*48847494SEnrico Perla - Sun Microsystems * used to extend the archive) 341*48847494SEnrico Perla - Sun Microsystems * has_dir: the specified cache directory is active 342*48847494SEnrico Perla - Sun Microsystems * count: the number of files to update 343*48847494SEnrico Perla - Sun Microsystems * flags: directory specific flags 344*48847494SEnrico Perla - Sun Microsystems */ 345*48847494SEnrico Perla - Sun Microsystems typedef struct _dirinfo { 346*48847494SEnrico Perla - Sun Microsystems char cdir_path[PATH_MAX]; 347*48847494SEnrico Perla - Sun Microsystems char update_path[PATH_MAX]; 348*48847494SEnrico Perla - Sun Microsystems int has_dir; 349*48847494SEnrico Perla - Sun Microsystems int count; 350*48847494SEnrico Perla - Sun Microsystems int flags; 351*48847494SEnrico Perla - Sun Microsystems } dirinfo_t; 352*48847494SEnrico Perla - Sun Microsystems 353*48847494SEnrico Perla - Sun Microsystems /* 354*48847494SEnrico Perla - Sun Microsystems * Update flags: 355*48847494SEnrico Perla - Sun Microsystems * NEED_CACHE_DIR : cache directory is missing and needs to be created 356*48847494SEnrico Perla - Sun Microsystems * IS_SPARC_TARGET : the target mountpoint is a SPARC environment 357*48847494SEnrico Perla - Sun Microsystems * UPDATE_ERROR : an error occourred while traversing the list of files 358*48847494SEnrico Perla - Sun Microsystems * RDONLY_FSCHK : the target filesystem is read-only 359*48847494SEnrico Perla - Sun Microsystems * RAMDSK_FSCHK : the target filesystem is on a ramdisk 360*48847494SEnrico Perla - Sun Microsystems */ 361*48847494SEnrico Perla - Sun Microsystems #define NEED_CACHE_DIR 0x00000001 362*48847494SEnrico Perla - Sun Microsystems #define IS_SPARC_TARGET 0x00000002 363*48847494SEnrico Perla - Sun Microsystems #define UPDATE_ERROR 0x00000004 364*48847494SEnrico Perla - Sun Microsystems #define RDONLY_FSCHK 0x00000008 365*48847494SEnrico Perla - Sun Microsystems #define RAMDSK_FSCHK 0x00000010 366*48847494SEnrico Perla - Sun Microsystems 367*48847494SEnrico Perla - Sun Microsystems #define is_flag_on(flag) (walk_arg.update_flags & flag ? 1 : 0) 368*48847494SEnrico Perla - Sun Microsystems #define set_flag(flag) (walk_arg.update_flags |= flag) 369*48847494SEnrico Perla - Sun Microsystems #define unset_flag(flag) (walk_arg.update_flags &= ~flag) 370*48847494SEnrico Perla - Sun Microsystems 371*48847494SEnrico Perla - Sun Microsystems /* 372*48847494SEnrico Perla - Sun Microsystems * struct walk_arg : 373*48847494SEnrico Perla - Sun Microsystems * update_flags: flags related to the current updating process 374*48847494SEnrico Perla - Sun Microsystems * new_nvlp/old_nvlp: new and old list of archive-files / attributes pairs 375*48847494SEnrico Perla - Sun Microsystems * sparcfile: list of file paths for mkisofs -path-list (SPARC only) 376*48847494SEnrico Perla - Sun Microsystems */ 3777c478bd9Sstevel@tonic-gate static struct { 378*48847494SEnrico Perla - Sun Microsystems int update_flags; 3797c478bd9Sstevel@tonic-gate nvlist_t *new_nvlp; 3807c478bd9Sstevel@tonic-gate nvlist_t *old_nvlp; 381*48847494SEnrico Perla - Sun Microsystems FILE *sparcfile; 382*48847494SEnrico Perla - Sun Microsystems dirinfo_t dirinfo[CACHEDIR_NUM]; 3837c478bd9Sstevel@tonic-gate } walk_arg; 3847c478bd9Sstevel@tonic-gate 3859632cfadSsetje struct safefile { 38658091fd8Ssetje char *name; 38758091fd8Ssetje struct safefile *next; 38858091fd8Ssetje }; 38958091fd8Ssetje 390ae115bc7Smrj static struct safefile *safefiles = NULL; 39158091fd8Ssetje #define NEED_UPDATE_FILE "/etc/svc/volatile/boot_archive_needs_update" 39258091fd8Ssetje 393*48847494SEnrico Perla - Sun Microsystems /* Thanks growisofs */ 394*48847494SEnrico Perla - Sun Microsystems #define CD_BLOCK ((off64_t)2048) 395*48847494SEnrico Perla - Sun Microsystems #define VOLDESC_OFF 16 396*48847494SEnrico Perla - Sun Microsystems #define DVD_BLOCK (32*1024) 397*48847494SEnrico Perla - Sun Microsystems #define MAX_IVDs 16 398*48847494SEnrico Perla - Sun Microsystems 399*48847494SEnrico Perla - Sun Microsystems struct iso_pdesc { 400*48847494SEnrico Perla - Sun Microsystems unsigned char type [1]; 401*48847494SEnrico Perla - Sun Microsystems unsigned char id [5]; 402*48847494SEnrico Perla - Sun Microsystems unsigned char void1 [80-5-1]; 403*48847494SEnrico Perla - Sun Microsystems unsigned char volume_space_size [8]; 404*48847494SEnrico Perla - Sun Microsystems unsigned char void2 [2048-80-8]; 405*48847494SEnrico Perla - Sun Microsystems }; 406*48847494SEnrico Perla - Sun Microsystems 407*48847494SEnrico Perla - Sun Microsystems /* 408*48847494SEnrico Perla - Sun Microsystems * COUNT_MAX: maximum number of changed files to justify a multisession update 409*48847494SEnrico Perla - Sun Microsystems * BA_SIZE_MAX: maximum size of the boot_archive to justify a multisession 410*48847494SEnrico Perla - Sun Microsystems * update 411*48847494SEnrico Perla - Sun Microsystems */ 412*48847494SEnrico Perla - Sun Microsystems #define COUNT_MAX 50 413*48847494SEnrico Perla - Sun Microsystems #define BA_SIZE_MAX (50 * 1024 * 1024) 414*48847494SEnrico Perla - Sun Microsystems 415*48847494SEnrico Perla - Sun Microsystems #define bam_nowrite() (bam_check || bam_smf_check) 416*48847494SEnrico Perla - Sun Microsystems 41719397407SSherry Moore static int sync_menu = 1; /* whether we need to sync the BE menus */ 41819397407SSherry Moore 4197c478bd9Sstevel@tonic-gate static void 4207c478bd9Sstevel@tonic-gate usage(void) 4217c478bd9Sstevel@tonic-gate { 4227c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "USAGE:\n"); 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate /* archive usage */ 425d876c67dSjg (void) fprintf(stderr, 426d876c67dSjg "\t%s update-archive [-vn] [-R altroot [-p platform>]]\n", prog); 427d876c67dSjg (void) fprintf(stderr, 428d876c67dSjg "\t%s list-archive [-R altroot [-p platform>]]\n", prog); 429986fd29aSsetje #if !defined(_OPB) 4307c478bd9Sstevel@tonic-gate /* x86 only */ 4317c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\t%s set-menu [-R altroot] key=value\n", prog); 4327c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\t%s list-menu [-R altroot]\n", prog); 4337c478bd9Sstevel@tonic-gate #endif 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate int 4377c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 4387c478bd9Sstevel@tonic-gate { 4397c478bd9Sstevel@tonic-gate error_t ret; 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 4427c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate if ((prog = strrchr(argv[0], '/')) == NULL) { 4457c478bd9Sstevel@tonic-gate prog = argv[0]; 4467c478bd9Sstevel@tonic-gate } else { 4477c478bd9Sstevel@tonic-gate prog++; 4487c478bd9Sstevel@tonic-gate } 4497c478bd9Sstevel@tonic-gate 450eb2bd662Svikram INJECT_ERROR1("ASSERT_ON", assert(0)) 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate /* 4537c478bd9Sstevel@tonic-gate * Don't depend on caller's umask 4547c478bd9Sstevel@tonic-gate */ 4557c478bd9Sstevel@tonic-gate (void) umask(0022); 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate parse_args(argc, argv); 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate switch (bam_cmd) { 4607c478bd9Sstevel@tonic-gate case BAM_MENU: 4617c478bd9Sstevel@tonic-gate ret = bam_menu(bam_subcmd, bam_opt, bam_argc, bam_argv); 4627c478bd9Sstevel@tonic-gate break; 4637c478bd9Sstevel@tonic-gate case BAM_ARCHIVE: 4647c478bd9Sstevel@tonic-gate ret = bam_archive(bam_subcmd, bam_opt); 4657c478bd9Sstevel@tonic-gate break; 4667c478bd9Sstevel@tonic-gate default: 4677c478bd9Sstevel@tonic-gate usage(); 4687c478bd9Sstevel@tonic-gate bam_exit(1); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate if (ret != BAM_SUCCESS) 4727c478bd9Sstevel@tonic-gate bam_exit(1); 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate bam_unlock(); 4757c478bd9Sstevel@tonic-gate return (0); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate /* 4797c478bd9Sstevel@tonic-gate * Equivalence of public and internal commands: 4807c478bd9Sstevel@tonic-gate * update-archive -- -a update 4817c478bd9Sstevel@tonic-gate * list-archive -- -a list 4827c478bd9Sstevel@tonic-gate * set-menu -- -m set_option 4837c478bd9Sstevel@tonic-gate * list-menu -- -m list_entry 4847c478bd9Sstevel@tonic-gate * update-menu -- -m update_entry 4857c478bd9Sstevel@tonic-gate */ 4867c478bd9Sstevel@tonic-gate static struct cmd_map { 4877c478bd9Sstevel@tonic-gate char *bam_cmdname; 4887c478bd9Sstevel@tonic-gate int bam_cmd; 4897c478bd9Sstevel@tonic-gate char *bam_subcmd; 4907c478bd9Sstevel@tonic-gate } cmd_map[] = { 4917c478bd9Sstevel@tonic-gate { "update-archive", BAM_ARCHIVE, "update"}, 4927c478bd9Sstevel@tonic-gate { "list-archive", BAM_ARCHIVE, "list"}, 4937c478bd9Sstevel@tonic-gate { "set-menu", BAM_MENU, "set_option"}, 4947c478bd9Sstevel@tonic-gate { "list-menu", BAM_MENU, "list_entry"}, 4957c478bd9Sstevel@tonic-gate { "update-menu", BAM_MENU, "update_entry"}, 4967c478bd9Sstevel@tonic-gate { NULL, 0, NULL} 4977c478bd9Sstevel@tonic-gate }; 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate /* 5007c478bd9Sstevel@tonic-gate * Commands syntax published in bootadm(1M) are parsed here 5017c478bd9Sstevel@tonic-gate */ 5027c478bd9Sstevel@tonic-gate static void 5037c478bd9Sstevel@tonic-gate parse_args(int argc, char *argv[]) 5047c478bd9Sstevel@tonic-gate { 5057c478bd9Sstevel@tonic-gate struct cmd_map *cmp = cmd_map; 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate /* command conforming to the final spec */ 5087c478bd9Sstevel@tonic-gate if (argc > 1 && argv[1][0] != '-') { 5097c478bd9Sstevel@tonic-gate /* 5107c478bd9Sstevel@tonic-gate * Map commands to internal table. 5117c478bd9Sstevel@tonic-gate */ 5127c478bd9Sstevel@tonic-gate while (cmp->bam_cmdname) { 5137c478bd9Sstevel@tonic-gate if (strcmp(argv[1], cmp->bam_cmdname) == 0) { 5147c478bd9Sstevel@tonic-gate bam_cmd = cmp->bam_cmd; 5157c478bd9Sstevel@tonic-gate bam_subcmd = cmp->bam_subcmd; 5167c478bd9Sstevel@tonic-gate break; 5177c478bd9Sstevel@tonic-gate } 5187c478bd9Sstevel@tonic-gate cmp++; 5197c478bd9Sstevel@tonic-gate } 5207c478bd9Sstevel@tonic-gate if (cmp->bam_cmdname == NULL) { 5217c478bd9Sstevel@tonic-gate usage(); 5227c478bd9Sstevel@tonic-gate bam_exit(1); 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate argc--; 5257c478bd9Sstevel@tonic-gate argv++; 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate parse_args_internal(argc, argv); 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate /* 5327c478bd9Sstevel@tonic-gate * A combination of public and private commands are parsed here. 5337c478bd9Sstevel@tonic-gate * The internal syntax and the corresponding functionality are: 5347c478bd9Sstevel@tonic-gate * -a update -- update-archive 5357c478bd9Sstevel@tonic-gate * -a list -- list-archive 5367c478bd9Sstevel@tonic-gate * -a update-all -- (reboot to sync all mounted OS archive) 5377c478bd9Sstevel@tonic-gate * -m update_entry -- update-menu 5387c478bd9Sstevel@tonic-gate * -m list_entry -- list-menu 5397c478bd9Sstevel@tonic-gate * -m update_temp -- (reboot -- [boot-args]) 5407c478bd9Sstevel@tonic-gate * -m delete_all_entries -- (called from install) 541*48847494SEnrico Perla - Sun Microsystems * A set of private flags is there too: 542*48847494SEnrico Perla - Sun Microsystems * -F -- purge the cache directories and rebuild them 543*48847494SEnrico Perla - Sun Microsystems * -e -- use the (faster) archive update approach (used by 544*48847494SEnrico Perla - Sun Microsystems * reboot) 5457c478bd9Sstevel@tonic-gate */ 5467c478bd9Sstevel@tonic-gate static void 5477c478bd9Sstevel@tonic-gate parse_args_internal(int argc, char *argv[]) 5487c478bd9Sstevel@tonic-gate { 5497c478bd9Sstevel@tonic-gate int c, error; 5507c478bd9Sstevel@tonic-gate extern char *optarg; 5517c478bd9Sstevel@tonic-gate extern int optind, opterr; 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate /* Suppress error message from getopt */ 5547c478bd9Sstevel@tonic-gate opterr = 0; 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate error = 0; 557*48847494SEnrico Perla - Sun Microsystems while ((c = getopt(argc, argv, "a:d:fm:no:veFCR:p:Z")) != -1) { 5587c478bd9Sstevel@tonic-gate switch (c) { 5597c478bd9Sstevel@tonic-gate case 'a': 5607c478bd9Sstevel@tonic-gate if (bam_cmd) { 5617c478bd9Sstevel@tonic-gate error = 1; 5627c478bd9Sstevel@tonic-gate bam_error(MULT_CMDS, c); 5637c478bd9Sstevel@tonic-gate } 5647c478bd9Sstevel@tonic-gate bam_cmd = BAM_ARCHIVE; 5657c478bd9Sstevel@tonic-gate bam_subcmd = optarg; 5667c478bd9Sstevel@tonic-gate break; 5677c478bd9Sstevel@tonic-gate case 'd': 5687c478bd9Sstevel@tonic-gate if (bam_debug) { 5697c478bd9Sstevel@tonic-gate error = 1; 5707c478bd9Sstevel@tonic-gate bam_error(DUP_OPT, c); 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate bam_debug = s_strtol(optarg); 5737c478bd9Sstevel@tonic-gate break; 5747c478bd9Sstevel@tonic-gate case 'f': 5757c478bd9Sstevel@tonic-gate bam_force = 1; 5767c478bd9Sstevel@tonic-gate break; 577*48847494SEnrico Perla - Sun Microsystems case 'F': 578*48847494SEnrico Perla - Sun Microsystems bam_purge = 1; 579*48847494SEnrico Perla - Sun Microsystems break; 5807c478bd9Sstevel@tonic-gate case 'm': 5817c478bd9Sstevel@tonic-gate if (bam_cmd) { 5827c478bd9Sstevel@tonic-gate error = 1; 5837c478bd9Sstevel@tonic-gate bam_error(MULT_CMDS, c); 5847c478bd9Sstevel@tonic-gate } 5857c478bd9Sstevel@tonic-gate bam_cmd = BAM_MENU; 5867c478bd9Sstevel@tonic-gate bam_subcmd = optarg; 5877c478bd9Sstevel@tonic-gate break; 5887c478bd9Sstevel@tonic-gate case 'n': 5897c478bd9Sstevel@tonic-gate bam_check = 1; 5907c478bd9Sstevel@tonic-gate break; 5917c478bd9Sstevel@tonic-gate case 'o': 5927c478bd9Sstevel@tonic-gate if (bam_opt) { 5937c478bd9Sstevel@tonic-gate error = 1; 5947c478bd9Sstevel@tonic-gate bam_error(DUP_OPT, c); 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate bam_opt = optarg; 5977c478bd9Sstevel@tonic-gate break; 5987c478bd9Sstevel@tonic-gate case 'v': 5997c478bd9Sstevel@tonic-gate bam_verbose = 1; 6007c478bd9Sstevel@tonic-gate break; 6018c1b6884Sszhou case 'C': 6028c1b6884Sszhou bam_smf_check = 1; 6038c1b6884Sszhou break; 6047c478bd9Sstevel@tonic-gate case 'R': 6057c478bd9Sstevel@tonic-gate if (bam_root) { 6067c478bd9Sstevel@tonic-gate error = 1; 6077c478bd9Sstevel@tonic-gate bam_error(DUP_OPT, c); 6087c478bd9Sstevel@tonic-gate break; 6097c478bd9Sstevel@tonic-gate } else if (realpath(optarg, rootbuf) == NULL) { 6107c478bd9Sstevel@tonic-gate error = 1; 6117c478bd9Sstevel@tonic-gate bam_error(CANT_RESOLVE, optarg, 6127c478bd9Sstevel@tonic-gate strerror(errno)); 6137c478bd9Sstevel@tonic-gate break; 6147c478bd9Sstevel@tonic-gate } 61540541d5dSvikram bam_alt_root = 1; 6167c478bd9Sstevel@tonic-gate bam_root = rootbuf; 6177c478bd9Sstevel@tonic-gate bam_rootlen = strlen(rootbuf); 6187c478bd9Sstevel@tonic-gate break; 619d876c67dSjg case 'p': 620d876c67dSjg bam_alt_platform = 1; 621d876c67dSjg bam_platform = optarg; 622d876c67dSjg if ((strcmp(bam_platform, "i86pc") != 0) && 623d876c67dSjg (strcmp(bam_platform, "sun4u") != 0) && 624d876c67dSjg (strcmp(bam_platform, "sun4v") != 0)) { 625d876c67dSjg error = 1; 626d876c67dSjg bam_error(INVALID_PLAT, bam_platform); 627d876c67dSjg } 628d876c67dSjg break; 629e7cbe64fSgw25295 case 'Z': 630e7cbe64fSgw25295 bam_zfs = 1; 631e7cbe64fSgw25295 break; 632*48847494SEnrico Perla - Sun Microsystems case 'e': 633*48847494SEnrico Perla - Sun Microsystems bam_extend = 1; 634*48847494SEnrico Perla - Sun Microsystems break; 6357c478bd9Sstevel@tonic-gate case '?': 6367c478bd9Sstevel@tonic-gate error = 1; 6377c478bd9Sstevel@tonic-gate bam_error(BAD_OPT, optopt); 6387c478bd9Sstevel@tonic-gate break; 6397c478bd9Sstevel@tonic-gate default : 6407c478bd9Sstevel@tonic-gate error = 1; 6417c478bd9Sstevel@tonic-gate bam_error(BAD_OPT, c); 6427c478bd9Sstevel@tonic-gate break; 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate /* 647d876c67dSjg * An alternate platform requires an alternate root 648d876c67dSjg */ 649d876c67dSjg if (bam_alt_platform && bam_alt_root == 0) { 650d876c67dSjg usage(); 651d876c67dSjg bam_exit(0); 652d876c67dSjg } 653d876c67dSjg 654d876c67dSjg /* 6557c478bd9Sstevel@tonic-gate * A command option must be specfied 6567c478bd9Sstevel@tonic-gate */ 6577c478bd9Sstevel@tonic-gate if (!bam_cmd) { 6587c478bd9Sstevel@tonic-gate if (bam_opt && strcmp(bam_opt, "all") == 0) { 6597c478bd9Sstevel@tonic-gate usage(); 6607c478bd9Sstevel@tonic-gate bam_exit(0); 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate bam_error(NEED_CMD); 6637c478bd9Sstevel@tonic-gate error = 1; 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate if (error) { 6677c478bd9Sstevel@tonic-gate usage(); 6687c478bd9Sstevel@tonic-gate bam_exit(1); 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate if (optind > argc) { 6727c478bd9Sstevel@tonic-gate bam_error(INT_ERROR, "parse_args"); 6737c478bd9Sstevel@tonic-gate bam_exit(1); 6747c478bd9Sstevel@tonic-gate } else if (optind < argc) { 6757c478bd9Sstevel@tonic-gate bam_argv = &argv[optind]; 6767c478bd9Sstevel@tonic-gate bam_argc = argc - optind; 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate /* 6807c478bd9Sstevel@tonic-gate * -n implies verbose mode 6817c478bd9Sstevel@tonic-gate */ 6827c478bd9Sstevel@tonic-gate if (bam_check) 6837c478bd9Sstevel@tonic-gate bam_verbose = 1; 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate static error_t 6877c478bd9Sstevel@tonic-gate check_subcmd_and_options( 6887c478bd9Sstevel@tonic-gate char *subcmd, 6897c478bd9Sstevel@tonic-gate char *opt, 6907c478bd9Sstevel@tonic-gate subcmd_defn_t *table, 6917c478bd9Sstevel@tonic-gate error_t (**fp)()) 6927c478bd9Sstevel@tonic-gate { 6937c478bd9Sstevel@tonic-gate int i; 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate if (subcmd == NULL) { 6967c478bd9Sstevel@tonic-gate bam_error(NEED_SUBCMD); 6977c478bd9Sstevel@tonic-gate return (BAM_ERROR); 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate 700eb2bd662Svikram if (strcmp(subcmd, "set_option") == 0) { 701eb2bd662Svikram if (bam_argc == 0 || bam_argv == NULL || bam_argv[0] == NULL) { 702eb2bd662Svikram bam_error(MISSING_ARG); 703eb2bd662Svikram usage(); 704eb2bd662Svikram return (BAM_ERROR); 705eb2bd662Svikram } else if (bam_argc > 1 || bam_argv[1] != NULL) { 7061a97e40eSvikram bam_error(TRAILING_ARGS); 7071a97e40eSvikram usage(); 7081a97e40eSvikram return (BAM_ERROR); 7091a97e40eSvikram } 71019397407SSherry Moore } else if (strcmp(subcmd, "update_all") == 0) { 71119397407SSherry Moore /* 71219397407SSherry Moore * The only option we accept for the "update_all" 71319397407SSherry Moore * subcmd is "fastboot". 71419397407SSherry Moore */ 71519397407SSherry Moore if (bam_argc > 1 || (bam_argc == 1 && 71619397407SSherry Moore strcmp(bam_argv[0], "fastboot") != 0)) { 71719397407SSherry Moore bam_error(TRAILING_ARGS); 71819397407SSherry Moore usage(); 71919397407SSherry Moore return (BAM_ERROR); 72019397407SSherry Moore } 72119397407SSherry Moore if (bam_argc == 1) 72219397407SSherry Moore sync_menu = 0; 723eb2bd662Svikram } else if (bam_argc || bam_argv) { 724eb2bd662Svikram bam_error(TRAILING_ARGS); 725eb2bd662Svikram usage(); 726eb2bd662Svikram return (BAM_ERROR); 7271a97e40eSvikram } 7281a97e40eSvikram 7297c478bd9Sstevel@tonic-gate if (bam_root == NULL) { 7307c478bd9Sstevel@tonic-gate bam_root = rootbuf; 7317c478bd9Sstevel@tonic-gate bam_rootlen = 1; 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate /* verify that subcmd is valid */ 7357c478bd9Sstevel@tonic-gate for (i = 0; table[i].subcmd != NULL; i++) { 7367c478bd9Sstevel@tonic-gate if (strcmp(table[i].subcmd, subcmd) == 0) 7377c478bd9Sstevel@tonic-gate break; 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate if (table[i].subcmd == NULL) { 7417c478bd9Sstevel@tonic-gate bam_error(INVALID_SUBCMD, subcmd); 7427c478bd9Sstevel@tonic-gate return (BAM_ERROR); 7437c478bd9Sstevel@tonic-gate } 7447c478bd9Sstevel@tonic-gate 7451a97e40eSvikram if (table[i].unpriv == 0 && geteuid() != 0) { 7461a97e40eSvikram bam_error(MUST_BE_ROOT); 7471a97e40eSvikram return (BAM_ERROR); 7481a97e40eSvikram } 7491a97e40eSvikram 7501a97e40eSvikram /* 7511a97e40eSvikram * Currently only privileged commands need a lock 7521a97e40eSvikram */ 7531a97e40eSvikram if (table[i].unpriv == 0) 7541a97e40eSvikram bam_lock(); 7551a97e40eSvikram 7567c478bd9Sstevel@tonic-gate /* subcmd verifies that opt is appropriate */ 7577c478bd9Sstevel@tonic-gate if (table[i].option != OPT_OPTIONAL) { 7587c478bd9Sstevel@tonic-gate if ((table[i].option == OPT_REQ) ^ (opt != NULL)) { 7597c478bd9Sstevel@tonic-gate if (opt) 7607c478bd9Sstevel@tonic-gate bam_error(NO_OPT_REQ, subcmd); 7617c478bd9Sstevel@tonic-gate else 7627c478bd9Sstevel@tonic-gate bam_error(MISS_OPT, subcmd); 7637c478bd9Sstevel@tonic-gate return (BAM_ERROR); 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate 7677c478bd9Sstevel@tonic-gate *fp = table[i].handler; 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate return (BAM_SUCCESS); 7707c478bd9Sstevel@tonic-gate } 7717c478bd9Sstevel@tonic-gate 77240541d5dSvikram /* 77340541d5dSvikram * NOTE: A single "/" is also considered a trailing slash and will 77440541d5dSvikram * be deleted. 77540541d5dSvikram */ 77640541d5dSvikram static void 77740541d5dSvikram elide_trailing_slash(const char *src, char *dst, size_t dstsize) 77840541d5dSvikram { 77940541d5dSvikram size_t dstlen; 78040541d5dSvikram 78140541d5dSvikram assert(src); 78240541d5dSvikram assert(dst); 78340541d5dSvikram 78440541d5dSvikram (void) strlcpy(dst, src, dstsize); 78540541d5dSvikram 78640541d5dSvikram dstlen = strlen(dst); 78740541d5dSvikram if (dst[dstlen - 1] == '/') { 78840541d5dSvikram dst[dstlen - 1] = '\0'; 78940541d5dSvikram } 79040541d5dSvikram } 79140541d5dSvikram 7927c478bd9Sstevel@tonic-gate static error_t 7937c478bd9Sstevel@tonic-gate bam_menu(char *subcmd, char *opt, int largc, char *largv[]) 7947c478bd9Sstevel@tonic-gate { 7957c478bd9Sstevel@tonic-gate error_t ret; 7967c478bd9Sstevel@tonic-gate char menu_path[PATH_MAX]; 797eb2bd662Svikram char clean_menu_root[PATH_MAX]; 798ae115bc7Smrj char path[PATH_MAX]; 7997c478bd9Sstevel@tonic-gate menu_t *menu; 800eb2bd662Svikram char menu_root[PATH_MAX]; 801b610f78eSvikram struct stat sb; 8027c478bd9Sstevel@tonic-gate error_t (*f)(menu_t *mp, char *menu_path, char *opt); 803eb2bd662Svikram char *special; 804eb2bd662Svikram char *pool = NULL; 805eb2bd662Svikram zfs_mnted_t zmnted; 806eb2bd662Svikram char *zmntpt; 807eb2bd662Svikram char *osdev; 808eb2bd662Svikram char *osroot; 809eb2bd662Svikram const char *fcn = "bam_menu()"; 810986fd29aSsetje 811986fd29aSsetje /* 812986fd29aSsetje * Menu sub-command only applies to GRUB (i.e. x86) 813986fd29aSsetje */ 814eb2bd662Svikram if (!is_grub(bam_alt_root ? bam_root : "/")) { 815eb2bd662Svikram bam_error(NOT_GRUB_BOOT); 816986fd29aSsetje return (BAM_ERROR); 817986fd29aSsetje } 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate /* 8207c478bd9Sstevel@tonic-gate * Check arguments 8217c478bd9Sstevel@tonic-gate */ 8227c478bd9Sstevel@tonic-gate ret = check_subcmd_and_options(subcmd, opt, menu_subcmds, &f); 8237c478bd9Sstevel@tonic-gate if (ret == BAM_ERROR) { 8247c478bd9Sstevel@tonic-gate return (BAM_ERROR); 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate 827eb2bd662Svikram assert(bam_root); 828eb2bd662Svikram 829eb2bd662Svikram (void) strlcpy(menu_root, bam_root, sizeof (menu_root)); 830eb2bd662Svikram osdev = osroot = NULL; 831eb2bd662Svikram 832eb2bd662Svikram if (strcmp(subcmd, "update_entry") == 0) { 833eb2bd662Svikram assert(opt); 834eb2bd662Svikram 835eb2bd662Svikram osdev = strtok(opt, ","); 836eb2bd662Svikram assert(osdev); 837eb2bd662Svikram osroot = strtok(NULL, ","); 838eb2bd662Svikram if (osroot) { 839eb2bd662Svikram /* fixup bam_root so that it points at osroot */ 840eb2bd662Svikram if (realpath(osroot, rootbuf) == NULL) { 841eb2bd662Svikram bam_error(CANT_RESOLVE, osroot, 842eb2bd662Svikram strerror(errno)); 843eb2bd662Svikram return (BAM_ERROR); 844eb2bd662Svikram } 845eb2bd662Svikram bam_alt_root = 1; 846eb2bd662Svikram bam_root = rootbuf; 847eb2bd662Svikram bam_rootlen = strlen(rootbuf); 848eb2bd662Svikram } 849eb2bd662Svikram } 85040541d5dSvikram 85140541d5dSvikram /* 852eb2bd662Svikram * We support menu on PCFS (under certain conditions), but 853eb2bd662Svikram * not the OS root 85440541d5dSvikram */ 855eb2bd662Svikram if (is_pcfs(bam_root)) { 856eb2bd662Svikram bam_error(PCFS_ROOT_NOTSUP, bam_root); 857eb2bd662Svikram return (BAM_ERROR); 858ae115bc7Smrj } 859ae115bc7Smrj 860eb2bd662Svikram if (stat(menu_root, &sb) == -1) { 86140541d5dSvikram bam_error(CANNOT_LOCATE_GRUB_MENU); 86240541d5dSvikram return (BAM_ERROR); 86340541d5dSvikram } 86440541d5dSvikram 865eb2bd662Svikram BAM_DPRINTF((D_MENU_ROOT, fcn, menu_root)); 866e7cbe64fSgw25295 867eb2bd662Svikram /* 868eb2bd662Svikram * We no longer use the GRUB slice file. If it exists, then 869eb2bd662Svikram * the user is doing something that is unsupported (such as 870eb2bd662Svikram * standard upgrading an old Live Upgrade BE). If that 871eb2bd662Svikram * happens, mimic existing behavior i.e. pretend that it is 872eb2bd662Svikram * not a BE. Emit a warning though. 873eb2bd662Svikram */ 874eb2bd662Svikram if (bam_alt_root) { 875eb2bd662Svikram (void) snprintf(path, sizeof (path), "%s%s", bam_root, 876eb2bd662Svikram GRUB_slice); 877eb2bd662Svikram } else { 878eb2bd662Svikram (void) snprintf(path, sizeof (path), "%s", GRUB_slice); 879e7cbe64fSgw25295 } 880e7cbe64fSgw25295 88137eb779cSVikram Hegde if (bam_verbose && stat(path, &sb) == 0) 882eb2bd662Svikram bam_error(GRUB_SLICE_FILE_EXISTS, path); 883eb2bd662Svikram 884eb2bd662Svikram if (is_zfs(menu_root)) { 885eb2bd662Svikram assert(strcmp(menu_root, bam_root) == 0); 886eb2bd662Svikram special = get_special(menu_root); 887eb2bd662Svikram INJECT_ERROR1("Z_MENU_GET_SPECIAL", special = NULL); 888eb2bd662Svikram if (special == NULL) { 889eb2bd662Svikram bam_error(CANT_FIND_SPECIAL, menu_root); 890eb2bd662Svikram return (BAM_ERROR); 891eb2bd662Svikram } 892eb2bd662Svikram pool = strtok(special, "/"); 893eb2bd662Svikram INJECT_ERROR1("Z_MENU_GET_POOL", pool = NULL); 894eb2bd662Svikram if (pool == NULL) { 895eb2bd662Svikram free(special); 896eb2bd662Svikram bam_error(CANT_FIND_POOL, menu_root); 897eb2bd662Svikram return (BAM_ERROR); 898eb2bd662Svikram } 899eb2bd662Svikram BAM_DPRINTF((D_Z_MENU_GET_POOL_FROM_SPECIAL, fcn, pool)); 900eb2bd662Svikram 901eb2bd662Svikram zmntpt = mount_top_dataset(pool, &zmnted); 902eb2bd662Svikram INJECT_ERROR1("Z_MENU_MOUNT_TOP_DATASET", zmntpt = NULL); 903eb2bd662Svikram if (zmntpt == NULL) { 904eb2bd662Svikram bam_error(CANT_MOUNT_POOL_DATASET, pool); 905eb2bd662Svikram free(special); 906eb2bd662Svikram return (BAM_ERROR); 907eb2bd662Svikram } 908eb2bd662Svikram BAM_DPRINTF((D_Z_GET_MENU_MOUNT_TOP_DATASET, fcn, zmntpt)); 909eb2bd662Svikram 910eb2bd662Svikram (void) strlcpy(menu_root, zmntpt, sizeof (menu_root)); 911eb2bd662Svikram BAM_DPRINTF((D_Z_GET_MENU_MENU_ROOT, fcn, menu_root)); 912eb2bd662Svikram } 913eb2bd662Svikram 914eb2bd662Svikram elide_trailing_slash(menu_root, clean_menu_root, 915eb2bd662Svikram sizeof (clean_menu_root)); 916eb2bd662Svikram 917eb2bd662Svikram BAM_DPRINTF((D_CLEAN_MENU_ROOT, fcn, clean_menu_root)); 918eb2bd662Svikram 919eb2bd662Svikram (void) strlcpy(menu_path, clean_menu_root, sizeof (menu_path)); 92040541d5dSvikram (void) strlcat(menu_path, GRUB_MENU, sizeof (menu_path)); 92140541d5dSvikram 922eb2bd662Svikram BAM_DPRINTF((D_MENU_PATH, fcn, menu_path)); 923eb2bd662Svikram 92440541d5dSvikram /* 925eb2bd662Svikram * If listing the menu, display the menu location 92640541d5dSvikram */ 92740541d5dSvikram if (strcmp(subcmd, "list_entry") == 0) { 928eb2bd662Svikram bam_print(GRUB_MENU_PATH, menu_path); 92940541d5dSvikram } 9307c478bd9Sstevel@tonic-gate 931eb2bd662Svikram 9327c478bd9Sstevel@tonic-gate menu = menu_read(menu_path); 9337c478bd9Sstevel@tonic-gate assert(menu); 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate /* 936eb2bd662Svikram * We already checked the following case in 937eb2bd662Svikram * check_subcmd_and_suboptions() above. Complete the 938eb2bd662Svikram * final step now. 9397c478bd9Sstevel@tonic-gate */ 9407c478bd9Sstevel@tonic-gate if (strcmp(subcmd, "set_option") == 0) { 941eb2bd662Svikram assert(largc == 1 && largv[0] && largv[1] == NULL); 9427c478bd9Sstevel@tonic-gate opt = largv[0]; 943eb2bd662Svikram } else { 944eb2bd662Svikram assert(largc == 0 && largv == NULL); 9457c478bd9Sstevel@tonic-gate } 9467c478bd9Sstevel@tonic-gate 947eb2bd662Svikram ret = get_boot_cap(bam_root); 948eb2bd662Svikram if (ret != BAM_SUCCESS) { 949eb2bd662Svikram BAM_DPRINTF((D_BOOT_GET_CAP_FAILED, fcn)); 950eb2bd662Svikram goto out; 951eb2bd662Svikram } 952ae115bc7Smrj 9537c478bd9Sstevel@tonic-gate /* 9547c478bd9Sstevel@tonic-gate * Once the sub-cmd handler has run 9557c478bd9Sstevel@tonic-gate * only the line field is guaranteed to have valid values 9567c478bd9Sstevel@tonic-gate */ 957eb2bd662Svikram if (strcmp(subcmd, "update_entry") == 0) 958eb2bd662Svikram ret = f(menu, menu_root, osdev); 959eb2bd662Svikram else if (strcmp(subcmd, "upgrade") == 0) 960eb2bd662Svikram ret = f(menu, bam_root, menu_root); 961eb2bd662Svikram else if (strcmp(subcmd, "list_entry") == 0) 9627c478bd9Sstevel@tonic-gate ret = f(menu, menu_path, opt); 963eb2bd662Svikram else 964eb2bd662Svikram ret = f(menu, NULL, opt); 965eb2bd662Svikram 9667c478bd9Sstevel@tonic-gate if (ret == BAM_WRITE) { 967eb2bd662Svikram BAM_DPRINTF((D_WRITING_MENU_ROOT, fcn, clean_menu_root)); 968eb2bd662Svikram ret = menu_write(clean_menu_root, menu); 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate 971eb2bd662Svikram out: 972eb2bd662Svikram INJECT_ERROR1("POOL_SET", pool = "/pooldata"); 973eb2bd662Svikram assert((is_zfs(menu_root)) ^ (pool == NULL)); 974eb2bd662Svikram if (pool) { 975eb2bd662Svikram (void) umount_top_dataset(pool, zmnted, zmntpt); 976eb2bd662Svikram free(special); 977eb2bd662Svikram } 9787c478bd9Sstevel@tonic-gate menu_free(menu); 9797c478bd9Sstevel@tonic-gate return (ret); 9807c478bd9Sstevel@tonic-gate } 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate static error_t 9847c478bd9Sstevel@tonic-gate bam_archive( 9857c478bd9Sstevel@tonic-gate char *subcmd, 9867c478bd9Sstevel@tonic-gate char *opt) 9877c478bd9Sstevel@tonic-gate { 9887c478bd9Sstevel@tonic-gate error_t ret; 9897c478bd9Sstevel@tonic-gate error_t (*f)(char *root, char *opt); 990eb2bd662Svikram const char *fcn = "bam_archive()"; 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate /* 9938c1b6884Sszhou * Add trailing / for archive subcommands 9948c1b6884Sszhou */ 9958c1b6884Sszhou if (rootbuf[strlen(rootbuf) - 1] != '/') 9968c1b6884Sszhou (void) strcat(rootbuf, "/"); 9978c1b6884Sszhou bam_rootlen = strlen(rootbuf); 9988c1b6884Sszhou 9998c1b6884Sszhou /* 10007c478bd9Sstevel@tonic-gate * Check arguments 10017c478bd9Sstevel@tonic-gate */ 10027c478bd9Sstevel@tonic-gate ret = check_subcmd_and_options(subcmd, opt, arch_subcmds, &f); 10037c478bd9Sstevel@tonic-gate if (ret != BAM_SUCCESS) { 10047c478bd9Sstevel@tonic-gate return (BAM_ERROR); 10057c478bd9Sstevel@tonic-gate } 10067c478bd9Sstevel@tonic-gate 1007eb2bd662Svikram ret = get_boot_cap(rootbuf); 1008eb2bd662Svikram if (ret != BAM_SUCCESS) { 1009eb2bd662Svikram BAM_DPRINTF((D_BOOT_GET_CAP_FAILED, fcn)); 1010ae115bc7Smrj return (ret); 1011eb2bd662Svikram } 1012ae115bc7Smrj 10137c478bd9Sstevel@tonic-gate /* 10147c478bd9Sstevel@tonic-gate * Check archive not supported with update_all 10157c478bd9Sstevel@tonic-gate * since it is awkward to display out-of-sync 10167c478bd9Sstevel@tonic-gate * information for each BE. 10177c478bd9Sstevel@tonic-gate */ 10187c478bd9Sstevel@tonic-gate if (bam_check && strcmp(subcmd, "update_all") == 0) { 10197c478bd9Sstevel@tonic-gate bam_error(CHECK_NOT_SUPPORTED, subcmd); 10207c478bd9Sstevel@tonic-gate return (BAM_ERROR); 10217c478bd9Sstevel@tonic-gate } 10227c478bd9Sstevel@tonic-gate 1023b610f78eSvikram if (strcmp(subcmd, "update_all") == 0) 1024b610f78eSvikram bam_update_all = 1; 1025b610f78eSvikram 1026986fd29aSsetje #if !defined(_OPB) 10272449e17fSsherrym ucode_install(bam_root); 10282449e17fSsherrym #endif 10292449e17fSsherrym 1030b610f78eSvikram ret = f(bam_root, opt); 1031b610f78eSvikram 1032b610f78eSvikram bam_update_all = 0; 1033b610f78eSvikram 1034b610f78eSvikram return (ret); 10357c478bd9Sstevel@tonic-gate } 10367c478bd9Sstevel@tonic-gate 10377c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 1038ae115bc7Smrj void 10397c478bd9Sstevel@tonic-gate bam_error(char *format, ...) 10407c478bd9Sstevel@tonic-gate { 10417c478bd9Sstevel@tonic-gate va_list ap; 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate va_start(ap, format); 10447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", prog); 10457c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, format, ap); 10467c478bd9Sstevel@tonic-gate va_end(ap); 10477c478bd9Sstevel@tonic-gate } 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 1050eb2bd662Svikram void 1051eb2bd662Svikram bam_derror(char *format, ...) 1052eb2bd662Svikram { 1053eb2bd662Svikram va_list ap; 1054eb2bd662Svikram 1055eb2bd662Svikram assert(bam_debug); 1056eb2bd662Svikram 1057eb2bd662Svikram va_start(ap, format); 1058eb2bd662Svikram (void) fprintf(stderr, "DEBUG: "); 1059eb2bd662Svikram (void) vfprintf(stderr, format, ap); 1060eb2bd662Svikram va_end(ap); 1061eb2bd662Svikram } 1062eb2bd662Svikram 1063eb2bd662Svikram /*PRINTFLIKE1*/ 1064eb2bd662Svikram void 10657c478bd9Sstevel@tonic-gate bam_print(char *format, ...) 10667c478bd9Sstevel@tonic-gate { 10677c478bd9Sstevel@tonic-gate va_list ap; 10687c478bd9Sstevel@tonic-gate 10697c478bd9Sstevel@tonic-gate va_start(ap, format); 10707c478bd9Sstevel@tonic-gate (void) vfprintf(stdout, format, ap); 10717c478bd9Sstevel@tonic-gate va_end(ap); 10727c478bd9Sstevel@tonic-gate } 10737c478bd9Sstevel@tonic-gate 1074ae115bc7Smrj /*PRINTFLIKE1*/ 1075ae115bc7Smrj void 1076ae115bc7Smrj bam_print_stderr(char *format, ...) 1077ae115bc7Smrj { 1078ae115bc7Smrj va_list ap; 1079ae115bc7Smrj 1080ae115bc7Smrj va_start(ap, format); 1081ae115bc7Smrj (void) vfprintf(stderr, format, ap); 1082ae115bc7Smrj va_end(ap); 1083ae115bc7Smrj } 1084ae115bc7Smrj 10857c478bd9Sstevel@tonic-gate static void 10867c478bd9Sstevel@tonic-gate bam_exit(int excode) 10877c478bd9Sstevel@tonic-gate { 10887c478bd9Sstevel@tonic-gate bam_unlock(); 10897c478bd9Sstevel@tonic-gate exit(excode); 10907c478bd9Sstevel@tonic-gate } 10917c478bd9Sstevel@tonic-gate 10927c478bd9Sstevel@tonic-gate static void 10937c478bd9Sstevel@tonic-gate bam_lock(void) 10947c478bd9Sstevel@tonic-gate { 10957c478bd9Sstevel@tonic-gate struct flock lock; 10967c478bd9Sstevel@tonic-gate pid_t pid; 10977c478bd9Sstevel@tonic-gate 10987c478bd9Sstevel@tonic-gate bam_lock_fd = open(BAM_LOCK_FILE, O_CREAT|O_RDWR, LOCK_FILE_PERMS); 10997c478bd9Sstevel@tonic-gate if (bam_lock_fd < 0) { 11007c478bd9Sstevel@tonic-gate /* 11017c478bd9Sstevel@tonic-gate * We may be invoked early in boot for archive verification. 11027c478bd9Sstevel@tonic-gate * In this case, root is readonly and /var/run may not exist. 11037c478bd9Sstevel@tonic-gate * Proceed without the lock 11047c478bd9Sstevel@tonic-gate */ 11057c478bd9Sstevel@tonic-gate if (errno == EROFS || errno == ENOENT) { 11067c478bd9Sstevel@tonic-gate bam_root_readonly = 1; 11077c478bd9Sstevel@tonic-gate return; 11087c478bd9Sstevel@tonic-gate } 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate bam_error(OPEN_FAIL, BAM_LOCK_FILE, strerror(errno)); 11117c478bd9Sstevel@tonic-gate bam_exit(1); 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate lock.l_type = F_WRLCK; 11157c478bd9Sstevel@tonic-gate lock.l_whence = SEEK_SET; 11167c478bd9Sstevel@tonic-gate lock.l_start = 0; 11177c478bd9Sstevel@tonic-gate lock.l_len = 0; 11187c478bd9Sstevel@tonic-gate 11197c478bd9Sstevel@tonic-gate if (fcntl(bam_lock_fd, F_SETLK, &lock) == -1) { 11207c478bd9Sstevel@tonic-gate if (errno != EACCES && errno != EAGAIN) { 11217c478bd9Sstevel@tonic-gate bam_error(LOCK_FAIL, BAM_LOCK_FILE, strerror(errno)); 11227c478bd9Sstevel@tonic-gate (void) close(bam_lock_fd); 11237c478bd9Sstevel@tonic-gate bam_lock_fd = -1; 11247c478bd9Sstevel@tonic-gate bam_exit(1); 11257c478bd9Sstevel@tonic-gate } 11267c478bd9Sstevel@tonic-gate pid = 0; 11277c478bd9Sstevel@tonic-gate (void) pread(bam_lock_fd, &pid, sizeof (pid_t), 0); 11287c478bd9Sstevel@tonic-gate bam_print(FILE_LOCKED, pid); 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate lock.l_type = F_WRLCK; 11317c478bd9Sstevel@tonic-gate lock.l_whence = SEEK_SET; 11327c478bd9Sstevel@tonic-gate lock.l_start = 0; 11337c478bd9Sstevel@tonic-gate lock.l_len = 0; 11347c478bd9Sstevel@tonic-gate if (fcntl(bam_lock_fd, F_SETLKW, &lock) == -1) { 11357c478bd9Sstevel@tonic-gate bam_error(LOCK_FAIL, BAM_LOCK_FILE, strerror(errno)); 11367c478bd9Sstevel@tonic-gate (void) close(bam_lock_fd); 11377c478bd9Sstevel@tonic-gate bam_lock_fd = -1; 11387c478bd9Sstevel@tonic-gate bam_exit(1); 11397c478bd9Sstevel@tonic-gate } 11407c478bd9Sstevel@tonic-gate } 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate /* We own the lock now */ 11437c478bd9Sstevel@tonic-gate pid = getpid(); 11447c478bd9Sstevel@tonic-gate (void) write(bam_lock_fd, &pid, sizeof (pid)); 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate static void 11487c478bd9Sstevel@tonic-gate bam_unlock(void) 11497c478bd9Sstevel@tonic-gate { 11507c478bd9Sstevel@tonic-gate struct flock unlock; 11517c478bd9Sstevel@tonic-gate 11527c478bd9Sstevel@tonic-gate /* 11537c478bd9Sstevel@tonic-gate * NOP if we don't hold the lock 11547c478bd9Sstevel@tonic-gate */ 11557c478bd9Sstevel@tonic-gate if (bam_lock_fd < 0) { 11567c478bd9Sstevel@tonic-gate return; 11577c478bd9Sstevel@tonic-gate } 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate unlock.l_type = F_UNLCK; 11607c478bd9Sstevel@tonic-gate unlock.l_whence = SEEK_SET; 11617c478bd9Sstevel@tonic-gate unlock.l_start = 0; 11627c478bd9Sstevel@tonic-gate unlock.l_len = 0; 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate if (fcntl(bam_lock_fd, F_SETLK, &unlock) == -1) { 11657c478bd9Sstevel@tonic-gate bam_error(UNLOCK_FAIL, BAM_LOCK_FILE, strerror(errno)); 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate if (close(bam_lock_fd) == -1) { 11697c478bd9Sstevel@tonic-gate bam_error(CLOSE_FAIL, BAM_LOCK_FILE, strerror(errno)); 11707c478bd9Sstevel@tonic-gate } 11717c478bd9Sstevel@tonic-gate bam_lock_fd = -1; 11727c478bd9Sstevel@tonic-gate } 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate static error_t 11757c478bd9Sstevel@tonic-gate list_archive(char *root, char *opt) 11767c478bd9Sstevel@tonic-gate { 11777c478bd9Sstevel@tonic-gate filelist_t flist; 11787c478bd9Sstevel@tonic-gate filelist_t *flistp = &flist; 11797c478bd9Sstevel@tonic-gate line_t *lp; 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate assert(root); 11827c478bd9Sstevel@tonic-gate assert(opt == NULL); 11837c478bd9Sstevel@tonic-gate 11847c478bd9Sstevel@tonic-gate flistp->head = flistp->tail = NULL; 11857c478bd9Sstevel@tonic-gate if (read_list(root, flistp) != BAM_SUCCESS) { 11867c478bd9Sstevel@tonic-gate return (BAM_ERROR); 11877c478bd9Sstevel@tonic-gate } 11887c478bd9Sstevel@tonic-gate assert(flistp->head && flistp->tail); 11897c478bd9Sstevel@tonic-gate 11907c478bd9Sstevel@tonic-gate for (lp = flistp->head; lp; lp = lp->next) { 11917c478bd9Sstevel@tonic-gate bam_print(PRINT, lp->line); 11927c478bd9Sstevel@tonic-gate } 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate filelist_free(flistp); 11957c478bd9Sstevel@tonic-gate 11967c478bd9Sstevel@tonic-gate return (BAM_SUCCESS); 11977c478bd9Sstevel@tonic-gate } 11987c478bd9Sstevel@tonic-gate 11997c478bd9Sstevel@tonic-gate /* 12007c478bd9Sstevel@tonic-gate * This routine writes a list of lines to a file. 12017c478bd9Sstevel@tonic-gate * The list is *not* freed 12027c478bd9Sstevel@tonic-gate */ 12037c478bd9Sstevel@tonic-gate static error_t 12047c478bd9Sstevel@tonic-gate list2file(char *root, char *tmp, char *final, line_t *start) 12057c478bd9Sstevel@tonic-gate { 12067c478bd9Sstevel@tonic-gate char tmpfile[PATH_MAX]; 12077c478bd9Sstevel@tonic-gate char path[PATH_MAX]; 12087c478bd9Sstevel@tonic-gate FILE *fp; 12097c478bd9Sstevel@tonic-gate int ret; 12107c478bd9Sstevel@tonic-gate struct stat sb; 12117c478bd9Sstevel@tonic-gate mode_t mode; 12127c478bd9Sstevel@tonic-gate uid_t root_uid; 12137c478bd9Sstevel@tonic-gate gid_t sys_gid; 12147c478bd9Sstevel@tonic-gate struct passwd *pw; 12157c478bd9Sstevel@tonic-gate struct group *gp; 1216eb2bd662Svikram const char *fcn = "list2file()"; 12177c478bd9Sstevel@tonic-gate 12187c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s%s", root, final); 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate if (start == NULL) { 1221eb2bd662Svikram /* Empty GRUB menu */ 12227c478bd9Sstevel@tonic-gate if (stat(path, &sb) != -1) { 12237c478bd9Sstevel@tonic-gate bam_print(UNLINK_EMPTY, path); 12247c478bd9Sstevel@tonic-gate if (unlink(path) != 0) { 12257c478bd9Sstevel@tonic-gate bam_error(UNLINK_FAIL, path, strerror(errno)); 12267c478bd9Sstevel@tonic-gate return (BAM_ERROR); 12277c478bd9Sstevel@tonic-gate } else { 12287c478bd9Sstevel@tonic-gate return (BAM_SUCCESS); 12297c478bd9Sstevel@tonic-gate } 12307c478bd9Sstevel@tonic-gate } 1231eb2bd662Svikram return (BAM_SUCCESS); 12327c478bd9Sstevel@tonic-gate } 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate /* 12357c478bd9Sstevel@tonic-gate * Preserve attributes of existing file if possible, 12367c478bd9Sstevel@tonic-gate * otherwise ask the system for uid/gid of root/sys. 12377c478bd9Sstevel@tonic-gate * If all fails, fall back on hard-coded defaults. 12387c478bd9Sstevel@tonic-gate */ 12397c478bd9Sstevel@tonic-gate if (stat(path, &sb) != -1) { 12407c478bd9Sstevel@tonic-gate mode = sb.st_mode; 12417c478bd9Sstevel@tonic-gate root_uid = sb.st_uid; 12427c478bd9Sstevel@tonic-gate sys_gid = sb.st_gid; 12437c478bd9Sstevel@tonic-gate } else { 12447c478bd9Sstevel@tonic-gate mode = DEFAULT_DEV_MODE; 12457c478bd9Sstevel@tonic-gate if ((pw = getpwnam(DEFAULT_DEV_USER)) != NULL) { 12467c478bd9Sstevel@tonic-gate root_uid = pw->pw_uid; 12477c478bd9Sstevel@tonic-gate } else { 12487c478bd9Sstevel@tonic-gate bam_error(CANT_FIND_USER, 12497c478bd9Sstevel@tonic-gate DEFAULT_DEV_USER, DEFAULT_DEV_UID); 12507c478bd9Sstevel@tonic-gate root_uid = (uid_t)DEFAULT_DEV_UID; 12517c478bd9Sstevel@tonic-gate } 12527c478bd9Sstevel@tonic-gate if ((gp = getgrnam(DEFAULT_DEV_GROUP)) != NULL) { 12537c478bd9Sstevel@tonic-gate sys_gid = gp->gr_gid; 12547c478bd9Sstevel@tonic-gate } else { 12557c478bd9Sstevel@tonic-gate bam_error(CANT_FIND_GROUP, 12567c478bd9Sstevel@tonic-gate DEFAULT_DEV_GROUP, DEFAULT_DEV_GID); 12577c478bd9Sstevel@tonic-gate sys_gid = (gid_t)DEFAULT_DEV_GID; 12587c478bd9Sstevel@tonic-gate } 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate (void) snprintf(tmpfile, sizeof (tmpfile), "%s%s", root, tmp); 12627c478bd9Sstevel@tonic-gate 12637c478bd9Sstevel@tonic-gate /* Truncate tmpfile first */ 12647c478bd9Sstevel@tonic-gate fp = fopen(tmpfile, "w"); 12657c478bd9Sstevel@tonic-gate if (fp == NULL) { 12667c478bd9Sstevel@tonic-gate bam_error(OPEN_FAIL, tmpfile, strerror(errno)); 12677c478bd9Sstevel@tonic-gate return (BAM_ERROR); 12687c478bd9Sstevel@tonic-gate } 1269963390b4Svikram ret = fclose(fp); 1270963390b4Svikram INJECT_ERROR1("LIST2FILE_TRUNC_FCLOSE", ret = EOF); 1271963390b4Svikram if (ret == EOF) { 12727c478bd9Sstevel@tonic-gate bam_error(CLOSE_FAIL, tmpfile, strerror(errno)); 12737c478bd9Sstevel@tonic-gate return (BAM_ERROR); 12747c478bd9Sstevel@tonic-gate } 12757c478bd9Sstevel@tonic-gate 12767c478bd9Sstevel@tonic-gate /* Now open it in append mode */ 12777c478bd9Sstevel@tonic-gate fp = fopen(tmpfile, "a"); 12787c478bd9Sstevel@tonic-gate if (fp == NULL) { 12797c478bd9Sstevel@tonic-gate bam_error(OPEN_FAIL, tmpfile, strerror(errno)); 12807c478bd9Sstevel@tonic-gate return (BAM_ERROR); 12817c478bd9Sstevel@tonic-gate } 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate for (; start; start = start->next) { 1284963390b4Svikram ret = s_fputs(start->line, fp); 1285963390b4Svikram INJECT_ERROR1("LIST2FILE_FPUTS", ret = EOF); 1286963390b4Svikram if (ret == EOF) { 12877c478bd9Sstevel@tonic-gate bam_error(WRITE_FAIL, tmpfile, strerror(errno)); 12887c478bd9Sstevel@tonic-gate (void) fclose(fp); 12897c478bd9Sstevel@tonic-gate return (BAM_ERROR); 12907c478bd9Sstevel@tonic-gate } 12917c478bd9Sstevel@tonic-gate } 12927c478bd9Sstevel@tonic-gate 1293963390b4Svikram ret = fclose(fp); 1294963390b4Svikram INJECT_ERROR1("LIST2FILE_APPEND_FCLOSE", ret = EOF); 1295963390b4Svikram if (ret == EOF) { 12967c478bd9Sstevel@tonic-gate bam_error(CLOSE_FAIL, tmpfile, strerror(errno)); 12977c478bd9Sstevel@tonic-gate return (BAM_ERROR); 12987c478bd9Sstevel@tonic-gate } 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate /* 1301de531be4Sjg * Set up desired attributes. Ignore failures on filesystems 1302de531be4Sjg * not supporting these operations - pcfs reports unsupported 1303de531be4Sjg * operations as EINVAL. 13047c478bd9Sstevel@tonic-gate */ 13057c478bd9Sstevel@tonic-gate ret = chmod(tmpfile, mode); 1306de531be4Sjg if (ret == -1 && 1307de531be4Sjg errno != EINVAL && errno != ENOTSUP) { 13087c478bd9Sstevel@tonic-gate bam_error(CHMOD_FAIL, tmpfile, strerror(errno)); 13097c478bd9Sstevel@tonic-gate return (BAM_ERROR); 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate 13127c478bd9Sstevel@tonic-gate ret = chown(tmpfile, root_uid, sys_gid); 1313de531be4Sjg if (ret == -1 && 1314de531be4Sjg errno != EINVAL && errno != ENOTSUP) { 13157c478bd9Sstevel@tonic-gate bam_error(CHOWN_FAIL, tmpfile, strerror(errno)); 13167c478bd9Sstevel@tonic-gate return (BAM_ERROR); 13177c478bd9Sstevel@tonic-gate } 13187c478bd9Sstevel@tonic-gate 13197c478bd9Sstevel@tonic-gate 13207c478bd9Sstevel@tonic-gate /* 13217c478bd9Sstevel@tonic-gate * Do an atomic rename 13227c478bd9Sstevel@tonic-gate */ 13237c478bd9Sstevel@tonic-gate ret = rename(tmpfile, path); 1324963390b4Svikram INJECT_ERROR1("LIST2FILE_RENAME", ret = -1); 13257c478bd9Sstevel@tonic-gate if (ret != 0) { 13267c478bd9Sstevel@tonic-gate bam_error(RENAME_FAIL, path, strerror(errno)); 13277c478bd9Sstevel@tonic-gate return (BAM_ERROR); 13287c478bd9Sstevel@tonic-gate } 13297c478bd9Sstevel@tonic-gate 1330eb2bd662Svikram BAM_DPRINTF((D_WROTE_FILE, fcn, path)); 13317c478bd9Sstevel@tonic-gate return (BAM_SUCCESS); 13327c478bd9Sstevel@tonic-gate } 13337c478bd9Sstevel@tonic-gate 13347c478bd9Sstevel@tonic-gate /* 1335*48847494SEnrico Perla - Sun Microsystems * Checks if the path specified (without the file name at the end) exists 1336*48847494SEnrico Perla - Sun Microsystems * and creates it if not. If the path exists and is not a directory, an attempt 1337*48847494SEnrico Perla - Sun Microsystems * to unlink is made. 13387c478bd9Sstevel@tonic-gate */ 1339*48847494SEnrico Perla - Sun Microsystems static int 1340*48847494SEnrico Perla - Sun Microsystems setup_path(char *path) 1341*48847494SEnrico Perla - Sun Microsystems { 1342*48847494SEnrico Perla - Sun Microsystems char *p; 1343*48847494SEnrico Perla - Sun Microsystems int ret; 1344*48847494SEnrico Perla - Sun Microsystems struct stat sb; 1345*48847494SEnrico Perla - Sun Microsystems 1346*48847494SEnrico Perla - Sun Microsystems p = strrchr(path, '/'); 1347*48847494SEnrico Perla - Sun Microsystems if (p != NULL) { 1348*48847494SEnrico Perla - Sun Microsystems *p = '\0'; 1349*48847494SEnrico Perla - Sun Microsystems if (stat(path, &sb) != 0 || !(S_ISDIR(sb.st_mode))) { 1350*48847494SEnrico Perla - Sun Microsystems /* best effort attempt, mkdirp will catch the error */ 1351*48847494SEnrico Perla - Sun Microsystems (void) unlink(path); 1352*48847494SEnrico Perla - Sun Microsystems if (bam_verbose) 1353*48847494SEnrico Perla - Sun Microsystems bam_print(NEED_DIRPATH, path); 1354*48847494SEnrico Perla - Sun Microsystems ret = mkdirp(path, DIR_PERMS); 1355*48847494SEnrico Perla - Sun Microsystems if (ret == -1) { 1356*48847494SEnrico Perla - Sun Microsystems bam_error(MKDIR_FAILED, path, strerror(errno)); 1357*48847494SEnrico Perla - Sun Microsystems *p = '/'; 1358*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1359*48847494SEnrico Perla - Sun Microsystems } 1360*48847494SEnrico Perla - Sun Microsystems } 1361*48847494SEnrico Perla - Sun Microsystems *p = '/'; 1362*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1363*48847494SEnrico Perla - Sun Microsystems } 1364*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1365*48847494SEnrico Perla - Sun Microsystems } 1366*48847494SEnrico Perla - Sun Microsystems 1367*48847494SEnrico Perla - Sun Microsystems typedef union { 1368*48847494SEnrico Perla - Sun Microsystems gzFile gzfile; 1369*48847494SEnrico Perla - Sun Microsystems int fdfile; 1370*48847494SEnrico Perla - Sun Microsystems } outfile; 1371*48847494SEnrico Perla - Sun Microsystems 1372*48847494SEnrico Perla - Sun Microsystems typedef struct { 1373*48847494SEnrico Perla - Sun Microsystems char path[PATH_MAX]; 1374*48847494SEnrico Perla - Sun Microsystems outfile out; 1375*48847494SEnrico Perla - Sun Microsystems } cachefile; 1376*48847494SEnrico Perla - Sun Microsystems 1377*48847494SEnrico Perla - Sun Microsystems static int 1378*48847494SEnrico Perla - Sun Microsystems setup_file(char *base, const char *path, cachefile *cf) 1379*48847494SEnrico Perla - Sun Microsystems { 1380*48847494SEnrico Perla - Sun Microsystems int ret; 1381*48847494SEnrico Perla - Sun Microsystems char *strip; 1382*48847494SEnrico Perla - Sun Microsystems 1383*48847494SEnrico Perla - Sun Microsystems /* init gzfile or fdfile in case we fail before opening */ 1384*48847494SEnrico Perla - Sun Microsystems if (bam_direct == BAM_DIRECT_DBOOT) 1385*48847494SEnrico Perla - Sun Microsystems cf->out.gzfile = NULL; 1386*48847494SEnrico Perla - Sun Microsystems else 1387*48847494SEnrico Perla - Sun Microsystems cf->out.fdfile = -1; 1388*48847494SEnrico Perla - Sun Microsystems 1389*48847494SEnrico Perla - Sun Microsystems /* strip the trailing altroot path */ 1390*48847494SEnrico Perla - Sun Microsystems strip = (char *)path + strlen(rootbuf); 1391*48847494SEnrico Perla - Sun Microsystems 1392*48847494SEnrico Perla - Sun Microsystems ret = snprintf(cf->path, sizeof (cf->path), "%s/%s", base, strip); 1393*48847494SEnrico Perla - Sun Microsystems if (ret >= sizeof (cf->path)) { 1394*48847494SEnrico Perla - Sun Microsystems bam_error(PATH_TOO_LONG, rootbuf); 1395*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1396*48847494SEnrico Perla - Sun Microsystems } 1397*48847494SEnrico Perla - Sun Microsystems 1398*48847494SEnrico Perla - Sun Microsystems /* Check if path is present in the archive cache directory */ 1399*48847494SEnrico Perla - Sun Microsystems if (setup_path(cf->path) == BAM_ERROR) 1400*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1401*48847494SEnrico Perla - Sun Microsystems 1402*48847494SEnrico Perla - Sun Microsystems if (bam_direct == BAM_DIRECT_DBOOT) { 1403*48847494SEnrico Perla - Sun Microsystems if ((cf->out.gzfile = gzopen(cf->path, "wb")) == NULL) { 1404*48847494SEnrico Perla - Sun Microsystems bam_error(GZ_OPEN_FAIL, gzerror(cf->out.gzfile, NULL)); 1405*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1406*48847494SEnrico Perla - Sun Microsystems } 1407*48847494SEnrico Perla - Sun Microsystems (void) gzsetparams(cf->out.gzfile, Z_BEST_SPEED, 1408*48847494SEnrico Perla - Sun Microsystems Z_DEFAULT_STRATEGY); 1409*48847494SEnrico Perla - Sun Microsystems } else { 1410*48847494SEnrico Perla - Sun Microsystems if ((cf->out.fdfile = open(cf->path, O_WRONLY | O_CREAT, 0644)) 1411*48847494SEnrico Perla - Sun Microsystems == -1) { 1412*48847494SEnrico Perla - Sun Microsystems bam_error(OPEN_FAIL, cf->path, strerror(errno)); 1413*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1414*48847494SEnrico Perla - Sun Microsystems } 1415*48847494SEnrico Perla - Sun Microsystems } 1416*48847494SEnrico Perla - Sun Microsystems 1417*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1418*48847494SEnrico Perla - Sun Microsystems } 1419*48847494SEnrico Perla - Sun Microsystems 1420*48847494SEnrico Perla - Sun Microsystems static int 1421*48847494SEnrico Perla - Sun Microsystems cache_write(cachefile cf, char *buf, int size) 1422*48847494SEnrico Perla - Sun Microsystems { 1423*48847494SEnrico Perla - Sun Microsystems int err; 1424*48847494SEnrico Perla - Sun Microsystems 1425*48847494SEnrico Perla - Sun Microsystems if (bam_direct == BAM_DIRECT_DBOOT) { 1426*48847494SEnrico Perla - Sun Microsystems if (gzwrite(cf.out.gzfile, buf, size) < 1) { 1427*48847494SEnrico Perla - Sun Microsystems bam_error(GZ_WRITE_FAIL, gzerror(cf.out.gzfile, &err)); 1428*48847494SEnrico Perla - Sun Microsystems if (err == Z_ERRNO) 1429*48847494SEnrico Perla - Sun Microsystems bam_error(WRITE_FAIL, cf.path, strerror(errno)); 1430*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1431*48847494SEnrico Perla - Sun Microsystems } 1432*48847494SEnrico Perla - Sun Microsystems } else { 1433*48847494SEnrico Perla - Sun Microsystems if (write(cf.out.fdfile, buf, size) < 1) { 1434*48847494SEnrico Perla - Sun Microsystems bam_error(WRITE_FAIL, cf.path, strerror(errno)); 1435*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1436*48847494SEnrico Perla - Sun Microsystems } 1437*48847494SEnrico Perla - Sun Microsystems } 1438*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1439*48847494SEnrico Perla - Sun Microsystems } 1440*48847494SEnrico Perla - Sun Microsystems 1441*48847494SEnrico Perla - Sun Microsystems static int 1442*48847494SEnrico Perla - Sun Microsystems cache_close(cachefile cf) 1443*48847494SEnrico Perla - Sun Microsystems { 1444*48847494SEnrico Perla - Sun Microsystems int ret; 1445*48847494SEnrico Perla - Sun Microsystems 1446*48847494SEnrico Perla - Sun Microsystems if (bam_direct == BAM_DIRECT_DBOOT) { 1447*48847494SEnrico Perla - Sun Microsystems if (cf.out.gzfile) { 1448*48847494SEnrico Perla - Sun Microsystems ret = gzclose(cf.out.gzfile); 1449*48847494SEnrico Perla - Sun Microsystems if (ret == Z_OK) 1450*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1451*48847494SEnrico Perla - Sun Microsystems else if (ret == Z_ERRNO) 1452*48847494SEnrico Perla - Sun Microsystems bam_error(CLOSE_FAIL, cf.path, strerror(errno)); 1453*48847494SEnrico Perla - Sun Microsystems else 1454*48847494SEnrico Perla - Sun Microsystems bam_error(GZCLOSE_FAIL, gzerror(cf.out.gzfile, 1455*48847494SEnrico Perla - Sun Microsystems NULL)); 1456*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1457*48847494SEnrico Perla - Sun Microsystems } 1458*48847494SEnrico Perla - Sun Microsystems } else { 1459*48847494SEnrico Perla - Sun Microsystems if (cf.out.fdfile != -1) { 1460*48847494SEnrico Perla - Sun Microsystems ret = close(cf.out.fdfile); 1461*48847494SEnrico Perla - Sun Microsystems if (ret != 0) { 1462*48847494SEnrico Perla - Sun Microsystems bam_error(CLOSE_FAIL, cf.path, strerror(errno)); 1463*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1464*48847494SEnrico Perla - Sun Microsystems } 1465*48847494SEnrico Perla - Sun Microsystems } 1466*48847494SEnrico Perla - Sun Microsystems } 1467*48847494SEnrico Perla - Sun Microsystems 1468*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1469*48847494SEnrico Perla - Sun Microsystems } 1470*48847494SEnrico Perla - Sun Microsystems 1471*48847494SEnrico Perla - Sun Microsystems static int 1472*48847494SEnrico Perla - Sun Microsystems dircache_updatefile(const char *path, int what) 1473*48847494SEnrico Perla - Sun Microsystems { 1474*48847494SEnrico Perla - Sun Microsystems int ret, exitcode; 1475*48847494SEnrico Perla - Sun Microsystems char buf[4096 * 4]; 1476*48847494SEnrico Perla - Sun Microsystems FILE *infile; 1477*48847494SEnrico Perla - Sun Microsystems cachefile outfile, outupdt; 1478*48847494SEnrico Perla - Sun Microsystems 1479*48847494SEnrico Perla - Sun Microsystems if (bam_nowrite()) 1480*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1481*48847494SEnrico Perla - Sun Microsystems 1482*48847494SEnrico Perla - Sun Microsystems if ((infile = fopen(path, "rb")) == NULL) { 1483*48847494SEnrico Perla - Sun Microsystems bam_error(OPEN_FAIL, path, strerror(errno)); 1484*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1485*48847494SEnrico Perla - Sun Microsystems } 1486*48847494SEnrico Perla - Sun Microsystems 1487*48847494SEnrico Perla - Sun Microsystems ret = setup_file(get_cachedir(what), path, &outfile); 1488*48847494SEnrico Perla - Sun Microsystems if (ret == BAM_ERROR) { 1489*48847494SEnrico Perla - Sun Microsystems exitcode = BAM_ERROR; 1490*48847494SEnrico Perla - Sun Microsystems goto out; 1491*48847494SEnrico Perla - Sun Microsystems } 1492*48847494SEnrico Perla - Sun Microsystems if (!is_dir_flag_on(what, NO_MULTI)) { 1493*48847494SEnrico Perla - Sun Microsystems ret = setup_file(get_updatedir(what), path, &outupdt); 1494*48847494SEnrico Perla - Sun Microsystems if (ret == BAM_ERROR) 1495*48847494SEnrico Perla - Sun Microsystems set_dir_flag(what, NO_MULTI); 1496*48847494SEnrico Perla - Sun Microsystems } 1497*48847494SEnrico Perla - Sun Microsystems 1498*48847494SEnrico Perla - Sun Microsystems while ((ret = fread(buf, 1, sizeof (buf), infile)) > 0) { 1499*48847494SEnrico Perla - Sun Microsystems if (cache_write(outfile, buf, ret) == BAM_ERROR) { 1500*48847494SEnrico Perla - Sun Microsystems exitcode = BAM_ERROR; 1501*48847494SEnrico Perla - Sun Microsystems goto out; 1502*48847494SEnrico Perla - Sun Microsystems } 1503*48847494SEnrico Perla - Sun Microsystems if (!is_dir_flag_on(what, NO_MULTI)) 1504*48847494SEnrico Perla - Sun Microsystems if (cache_write(outupdt, buf, ret) == BAM_ERROR) 1505*48847494SEnrico Perla - Sun Microsystems set_dir_flag(what, NO_MULTI); 1506*48847494SEnrico Perla - Sun Microsystems } 1507*48847494SEnrico Perla - Sun Microsystems 1508*48847494SEnrico Perla - Sun Microsystems set_dir_flag(what, NEED_UPDATE); 1509*48847494SEnrico Perla - Sun Microsystems get_count(what)++; 1510*48847494SEnrico Perla - Sun Microsystems exitcode = BAM_SUCCESS; 1511*48847494SEnrico Perla - Sun Microsystems out: 1512*48847494SEnrico Perla - Sun Microsystems (void) fclose(infile); 1513*48847494SEnrico Perla - Sun Microsystems if (cache_close(outfile) == BAM_ERROR) 1514*48847494SEnrico Perla - Sun Microsystems exitcode = BAM_ERROR; 1515*48847494SEnrico Perla - Sun Microsystems if (!is_dir_flag_on(what, NO_MULTI) && 1516*48847494SEnrico Perla - Sun Microsystems cache_close(outupdt) == BAM_ERROR) 1517*48847494SEnrico Perla - Sun Microsystems exitcode = BAM_ERROR; 1518*48847494SEnrico Perla - Sun Microsystems if (exitcode == BAM_ERROR) 1519*48847494SEnrico Perla - Sun Microsystems set_flag(UPDATE_ERROR); 1520*48847494SEnrico Perla - Sun Microsystems return (exitcode); 1521*48847494SEnrico Perla - Sun Microsystems } 1522*48847494SEnrico Perla - Sun Microsystems 1523*48847494SEnrico Perla - Sun Microsystems static int 1524*48847494SEnrico Perla - Sun Microsystems dircache_updatedir(const char *path, int what, int updt) 1525*48847494SEnrico Perla - Sun Microsystems { 1526*48847494SEnrico Perla - Sun Microsystems int ret; 1527*48847494SEnrico Perla - Sun Microsystems char dpath[PATH_MAX]; 1528*48847494SEnrico Perla - Sun Microsystems char *strip; 1529*48847494SEnrico Perla - Sun Microsystems struct stat sb; 1530*48847494SEnrico Perla - Sun Microsystems 1531*48847494SEnrico Perla - Sun Microsystems strip = (char *)path + strlen(rootbuf); 1532*48847494SEnrico Perla - Sun Microsystems 1533*48847494SEnrico Perla - Sun Microsystems ret = snprintf(dpath, sizeof (dpath), "%s/%s", updt ? 1534*48847494SEnrico Perla - Sun Microsystems get_updatedir(what) : get_cachedir(what), strip); 1535*48847494SEnrico Perla - Sun Microsystems 1536*48847494SEnrico Perla - Sun Microsystems if (ret >= sizeof (dpath)) { 1537*48847494SEnrico Perla - Sun Microsystems bam_error(PATH_TOO_LONG, rootbuf); 1538*48847494SEnrico Perla - Sun Microsystems set_flag(UPDATE_ERROR); 1539*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1540*48847494SEnrico Perla - Sun Microsystems } 1541*48847494SEnrico Perla - Sun Microsystems 1542*48847494SEnrico Perla - Sun Microsystems if (stat(dpath, &sb) == 0 && S_ISDIR(sb.st_mode)) 1543*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1544*48847494SEnrico Perla - Sun Microsystems 1545*48847494SEnrico Perla - Sun Microsystems if (updt) { 1546*48847494SEnrico Perla - Sun Microsystems if (!is_dir_flag_on(what, NO_MULTI)) 1547*48847494SEnrico Perla - Sun Microsystems if (!bam_nowrite() && mkdirp(dpath, DIR_PERMS) == -1) 1548*48847494SEnrico Perla - Sun Microsystems set_dir_flag(what, NO_MULTI); 1549*48847494SEnrico Perla - Sun Microsystems } else { 1550*48847494SEnrico Perla - Sun Microsystems if (!bam_nowrite() && mkdirp(dpath, DIR_PERMS) == -1) { 1551*48847494SEnrico Perla - Sun Microsystems set_flag(UPDATE_ERROR); 1552*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1553*48847494SEnrico Perla - Sun Microsystems } 1554*48847494SEnrico Perla - Sun Microsystems } 1555*48847494SEnrico Perla - Sun Microsystems 1556*48847494SEnrico Perla - Sun Microsystems set_dir_flag(what, NEED_UPDATE); 1557*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1558*48847494SEnrico Perla - Sun Microsystems } 1559*48847494SEnrico Perla - Sun Microsystems 1560*48847494SEnrico Perla - Sun Microsystems #define DO_CACHE_DIR 0 1561*48847494SEnrico Perla - Sun Microsystems #define DO_UPDATE_DIR 1 1562*48847494SEnrico Perla - Sun Microsystems 1563*48847494SEnrico Perla - Sun Microsystems #if defined(_LP64) || defined(_LONGLONG_TYPE) 1564*48847494SEnrico Perla - Sun Microsystems typedef Elf64_Ehdr _elfhdr; 1565*48847494SEnrico Perla - Sun Microsystems #else 1566*48847494SEnrico Perla - Sun Microsystems typedef Elf32_Ehdr _elfhdr; 1567*48847494SEnrico Perla - Sun Microsystems #endif 1568*48847494SEnrico Perla - Sun Microsystems 1569*48847494SEnrico Perla - Sun Microsystems /* 1570*48847494SEnrico Perla - Sun Microsystems * This routine updates the contents of the cache directory 1571*48847494SEnrico Perla - Sun Microsystems */ 1572*48847494SEnrico Perla - Sun Microsystems static int 1573*48847494SEnrico Perla - Sun Microsystems update_dircache(const char *path, int flags) 1574*48847494SEnrico Perla - Sun Microsystems { 1575*48847494SEnrico Perla - Sun Microsystems int rc = BAM_SUCCESS; 1576*48847494SEnrico Perla - Sun Microsystems 1577*48847494SEnrico Perla - Sun Microsystems switch (flags) { 1578*48847494SEnrico Perla - Sun Microsystems case FTW_F: 1579*48847494SEnrico Perla - Sun Microsystems { 1580*48847494SEnrico Perla - Sun Microsystems int fd; 1581*48847494SEnrico Perla - Sun Microsystems _elfhdr elf; 1582*48847494SEnrico Perla - Sun Microsystems 1583*48847494SEnrico Perla - Sun Microsystems if ((fd = open(path, O_RDONLY)) < 0) { 1584*48847494SEnrico Perla - Sun Microsystems bam_error(OPEN_FAIL, path, strerror(errno)); 1585*48847494SEnrico Perla - Sun Microsystems set_flag(UPDATE_ERROR); 1586*48847494SEnrico Perla - Sun Microsystems rc = BAM_ERROR; 1587*48847494SEnrico Perla - Sun Microsystems break; 1588*48847494SEnrico Perla - Sun Microsystems } 1589*48847494SEnrico Perla - Sun Microsystems 1590*48847494SEnrico Perla - Sun Microsystems /* 1591*48847494SEnrico Perla - Sun Microsystems * libelf and gelf would be a cleaner and easier way to handle 1592*48847494SEnrico Perla - Sun Microsystems * this, but libelf fails compilation if _ILP32 is defined && 1593*48847494SEnrico Perla - Sun Microsystems * _FILE_OFFSET_BITS is != 32 ... 1594*48847494SEnrico Perla - Sun Microsystems */ 1595*48847494SEnrico Perla - Sun Microsystems if (read(fd, (void *)&elf, sizeof (_elfhdr)) < 0) { 1596*48847494SEnrico Perla - Sun Microsystems bam_error(READ_FAIL, path, strerror(errno)); 1597*48847494SEnrico Perla - Sun Microsystems set_flag(UPDATE_ERROR); 1598*48847494SEnrico Perla - Sun Microsystems (void) close(fd); 1599*48847494SEnrico Perla - Sun Microsystems rc = BAM_ERROR; 1600*48847494SEnrico Perla - Sun Microsystems break; 1601*48847494SEnrico Perla - Sun Microsystems } 1602*48847494SEnrico Perla - Sun Microsystems (void) close(fd); 1603*48847494SEnrico Perla - Sun Microsystems 1604*48847494SEnrico Perla - Sun Microsystems /* 1605*48847494SEnrico Perla - Sun Microsystems * If the file is not an executable and is not inside an amd64 1606*48847494SEnrico Perla - Sun Microsystems * directory, we copy it in both the cache directories, 1607*48847494SEnrico Perla - Sun Microsystems * otherwise, we only copy it inside the 64-bit one. 1608*48847494SEnrico Perla - Sun Microsystems */ 1609*48847494SEnrico Perla - Sun Microsystems if (memcmp(elf.e_ident, ELFMAG, 4) != 0) { 1610*48847494SEnrico Perla - Sun Microsystems if (strstr(path, "/amd64")) { 1611*48847494SEnrico Perla - Sun Microsystems if (has_cachedir(FILE64)) 1612*48847494SEnrico Perla - Sun Microsystems rc = dircache_updatefile(path, FILE64); 1613*48847494SEnrico Perla - Sun Microsystems } else if (has_cachedir(FILE64)) { 1614*48847494SEnrico Perla - Sun Microsystems rc = dircache_updatefile(path, FILE32); 1615*48847494SEnrico Perla - Sun Microsystems if (rc == BAM_SUCCESS) 1616*48847494SEnrico Perla - Sun Microsystems rc = dircache_updatefile(path, FILE64); 1617*48847494SEnrico Perla - Sun Microsystems } else { 1618*48847494SEnrico Perla - Sun Microsystems rc = dircache_updatefile(path, FILE32); 1619*48847494SEnrico Perla - Sun Microsystems } 1620*48847494SEnrico Perla - Sun Microsystems } else { 1621*48847494SEnrico Perla - Sun Microsystems /* 1622*48847494SEnrico Perla - Sun Microsystems * Based on the ELF class we copy the file in the 32-bit 1623*48847494SEnrico Perla - Sun Microsystems * or the 64-bit cache directory. 1624*48847494SEnrico Perla - Sun Microsystems */ 1625*48847494SEnrico Perla - Sun Microsystems if (elf.e_ident[EI_CLASS] == ELFCLASS32) 1626*48847494SEnrico Perla - Sun Microsystems rc = dircache_updatefile(path, FILE32); 1627*48847494SEnrico Perla - Sun Microsystems else if (elf.e_ident[EI_CLASS] == ELFCLASS64) 1628*48847494SEnrico Perla - Sun Microsystems if (has_cachedir(FILE64)) 1629*48847494SEnrico Perla - Sun Microsystems rc = dircache_updatefile(path, FILE64); 1630*48847494SEnrico Perla - Sun Microsystems else { 1631*48847494SEnrico Perla - Sun Microsystems bam_print(NO3264ELF, path); 1632*48847494SEnrico Perla - Sun Microsystems /* paranoid */ 1633*48847494SEnrico Perla - Sun Microsystems rc = dircache_updatefile(path, FILE32); 1634*48847494SEnrico Perla - Sun Microsystems if (rc == BAM_SUCCESS) 1635*48847494SEnrico Perla - Sun Microsystems rc = dircache_updatefile(path, FILE64); 1636*48847494SEnrico Perla - Sun Microsystems } 1637*48847494SEnrico Perla - Sun Microsystems } 1638*48847494SEnrico Perla - Sun Microsystems break; 1639*48847494SEnrico Perla - Sun Microsystems } 1640*48847494SEnrico Perla - Sun Microsystems case FTW_D: 1641*48847494SEnrico Perla - Sun Microsystems if (strstr(path, "/amd64") == NULL) { 1642*48847494SEnrico Perla - Sun Microsystems rc = dircache_updatedir(path, FILE32, DO_UPDATE_DIR); 1643*48847494SEnrico Perla - Sun Microsystems if (rc == BAM_SUCCESS) 1644*48847494SEnrico Perla - Sun Microsystems rc = dircache_updatedir(path, FILE32, 1645*48847494SEnrico Perla - Sun Microsystems DO_CACHE_DIR); 1646*48847494SEnrico Perla - Sun Microsystems } else { 1647*48847494SEnrico Perla - Sun Microsystems if (has_cachedir(FILE64)) { 1648*48847494SEnrico Perla - Sun Microsystems rc = dircache_updatedir(path, FILE64, 1649*48847494SEnrico Perla - Sun Microsystems DO_UPDATE_DIR); 1650*48847494SEnrico Perla - Sun Microsystems if (rc == BAM_SUCCESS) 1651*48847494SEnrico Perla - Sun Microsystems rc = dircache_updatedir(path, FILE64, 1652*48847494SEnrico Perla - Sun Microsystems DO_CACHE_DIR); 1653*48847494SEnrico Perla - Sun Microsystems } 1654*48847494SEnrico Perla - Sun Microsystems } 1655*48847494SEnrico Perla - Sun Microsystems break; 1656*48847494SEnrico Perla - Sun Microsystems default: 1657*48847494SEnrico Perla - Sun Microsystems rc = BAM_ERROR; 1658*48847494SEnrico Perla - Sun Microsystems break; 1659*48847494SEnrico Perla - Sun Microsystems } 1660*48847494SEnrico Perla - Sun Microsystems 1661*48847494SEnrico Perla - Sun Microsystems return (rc); 1662*48847494SEnrico Perla - Sun Microsystems } 1663*48847494SEnrico Perla - Sun Microsystems 16647c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 16657c478bd9Sstevel@tonic-gate static int 16667c478bd9Sstevel@tonic-gate cmpstat( 16677c478bd9Sstevel@tonic-gate const char *file, 1668*48847494SEnrico Perla - Sun Microsystems const struct stat *st, 16697c478bd9Sstevel@tonic-gate int flags, 16707c478bd9Sstevel@tonic-gate struct FTW *ftw) 16717c478bd9Sstevel@tonic-gate { 16727c478bd9Sstevel@tonic-gate uint_t sz; 16737c478bd9Sstevel@tonic-gate uint64_t *value; 16747c478bd9Sstevel@tonic-gate uint64_t filestat[2]; 1675*48847494SEnrico Perla - Sun Microsystems int error, ret; 16767c478bd9Sstevel@tonic-gate 167758091fd8Ssetje struct safefile *safefilep; 167858091fd8Ssetje FILE *fp; 1679*48847494SEnrico Perla - Sun Microsystems struct stat sb; 168058091fd8Ssetje 16817c478bd9Sstevel@tonic-gate /* 1682*48847494SEnrico Perla - Sun Microsystems * On SPARC we create/update links too. 16837c478bd9Sstevel@tonic-gate */ 1684*48847494SEnrico Perla - Sun Microsystems if (flags != FTW_F && flags != FTW_D && (flags == FTW_SL && 1685*48847494SEnrico Perla - Sun Microsystems !is_flag_on(IS_SPARC_TARGET))) 1686*48847494SEnrico Perla - Sun Microsystems return (0); 1687*48847494SEnrico Perla - Sun Microsystems 1688*48847494SEnrico Perla - Sun Microsystems /* 1689*48847494SEnrico Perla - Sun Microsystems * Ignore broken links 1690*48847494SEnrico Perla - Sun Microsystems */ 1691*48847494SEnrico Perla - Sun Microsystems if (flags == FTW_SL && stat(file, &sb) < 0) 16927c478bd9Sstevel@tonic-gate return (0); 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate /* 16957c478bd9Sstevel@tonic-gate * new_nvlp may be NULL if there were errors earlier 16967c478bd9Sstevel@tonic-gate * but this is not fatal to update determination. 16977c478bd9Sstevel@tonic-gate */ 16987c478bd9Sstevel@tonic-gate if (walk_arg.new_nvlp) { 1699*48847494SEnrico Perla - Sun Microsystems filestat[0] = st->st_size; 1700*48847494SEnrico Perla - Sun Microsystems filestat[1] = st->st_mtime; 17017c478bd9Sstevel@tonic-gate error = nvlist_add_uint64_array(walk_arg.new_nvlp, 17027c478bd9Sstevel@tonic-gate file + bam_rootlen, filestat, 2); 17037c478bd9Sstevel@tonic-gate if (error) 17047c478bd9Sstevel@tonic-gate bam_error(NVADD_FAIL, file, strerror(error)); 17057c478bd9Sstevel@tonic-gate } 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate /* 1708d876c67dSjg * If we are invoked as part of system/filesystem/boot-archive, then 170958091fd8Ssetje * there are a number of things we should not worry about 17107c478bd9Sstevel@tonic-gate */ 171158091fd8Ssetje if (bam_smf_check) { 171258091fd8Ssetje /* ignore amd64 modules unless we are booted amd64. */ 171358091fd8Ssetje if (!is_amd64() && strstr(file, "/amd64/") != 0) 17147c478bd9Sstevel@tonic-gate return (0); 17157c478bd9Sstevel@tonic-gate 171658091fd8Ssetje /* read in list of safe files */ 171758091fd8Ssetje if (safefiles == NULL) 171858091fd8Ssetje if (fp = fopen("/boot/solaris/filelist.safe", "r")) { 171958091fd8Ssetje safefiles = s_calloc(1, 172058091fd8Ssetje sizeof (struct safefile)); 172158091fd8Ssetje safefilep = safefiles; 172258091fd8Ssetje safefilep->name = s_calloc(1, MAXPATHLEN + 172358091fd8Ssetje MAXNAMELEN); 172458091fd8Ssetje safefilep->next = NULL; 172558091fd8Ssetje while (s_fgets(safefilep->name, MAXPATHLEN + 172658091fd8Ssetje MAXNAMELEN, fp) != NULL) { 172758091fd8Ssetje safefilep->next = s_calloc(1, 172858091fd8Ssetje sizeof (struct safefile)); 172958091fd8Ssetje safefilep = safefilep->next; 173058091fd8Ssetje safefilep->name = s_calloc(1, 173158091fd8Ssetje MAXPATHLEN + MAXNAMELEN); 173258091fd8Ssetje safefilep->next = NULL; 173358091fd8Ssetje } 173458091fd8Ssetje (void) fclose(fp); 173558091fd8Ssetje } 173658091fd8Ssetje } 173758091fd8Ssetje 17387c478bd9Sstevel@tonic-gate /* 1739*48847494SEnrico Perla - Sun Microsystems * On SPARC we create a -path-list file for mkisofs 1740*48847494SEnrico Perla - Sun Microsystems */ 1741*48847494SEnrico Perla - Sun Microsystems if (is_flag_on(IS_SPARC_TARGET) && !bam_nowrite()) { 1742*48847494SEnrico Perla - Sun Microsystems if (flags != FTW_D) { 1743*48847494SEnrico Perla - Sun Microsystems char *strip; 1744*48847494SEnrico Perla - Sun Microsystems 1745*48847494SEnrico Perla - Sun Microsystems strip = (char *)file + strlen(rootbuf); 1746*48847494SEnrico Perla - Sun Microsystems (void) fprintf(walk_arg.sparcfile, "/%s=%s\n", strip, 1747*48847494SEnrico Perla - Sun Microsystems file); 1748*48847494SEnrico Perla - Sun Microsystems } 1749*48847494SEnrico Perla - Sun Microsystems } 1750*48847494SEnrico Perla - Sun Microsystems 1751*48847494SEnrico Perla - Sun Microsystems /* 1752*48847494SEnrico Perla - Sun Microsystems * We are transitioning from the old model to the dircache or the cache 1753*48847494SEnrico Perla - Sun Microsystems * directory was removed: create the entry without further checkings. 1754*48847494SEnrico Perla - Sun Microsystems */ 1755*48847494SEnrico Perla - Sun Microsystems if (is_flag_on(NEED_CACHE_DIR)) { 1756*48847494SEnrico Perla - Sun Microsystems if (bam_verbose) 1757*48847494SEnrico Perla - Sun Microsystems bam_print(PARSEABLE_NEW_FILE, file); 1758*48847494SEnrico Perla - Sun Microsystems 1759*48847494SEnrico Perla - Sun Microsystems if (is_flag_on(IS_SPARC_TARGET)) { 1760*48847494SEnrico Perla - Sun Microsystems set_dir_flag(FILE64, NEED_UPDATE); 1761*48847494SEnrico Perla - Sun Microsystems return (0); 1762*48847494SEnrico Perla - Sun Microsystems } 1763*48847494SEnrico Perla - Sun Microsystems 1764*48847494SEnrico Perla - Sun Microsystems ret = update_dircache(file, flags); 1765*48847494SEnrico Perla - Sun Microsystems if (ret == BAM_ERROR) { 1766*48847494SEnrico Perla - Sun Microsystems bam_error(UPDT_CACHE_FAIL, file); 1767*48847494SEnrico Perla - Sun Microsystems return (-1); 1768*48847494SEnrico Perla - Sun Microsystems } 1769*48847494SEnrico Perla - Sun Microsystems 1770*48847494SEnrico Perla - Sun Microsystems return (0); 1771*48847494SEnrico Perla - Sun Microsystems } 1772*48847494SEnrico Perla - Sun Microsystems 1773*48847494SEnrico Perla - Sun Microsystems /* 17747c478bd9Sstevel@tonic-gate * We need an update if file doesn't exist in old archive 17757c478bd9Sstevel@tonic-gate */ 17767c478bd9Sstevel@tonic-gate if (walk_arg.old_nvlp == NULL || 17777c478bd9Sstevel@tonic-gate nvlist_lookup_uint64_array(walk_arg.old_nvlp, 17787c478bd9Sstevel@tonic-gate file + bam_rootlen, &value, &sz) != 0) { 17797c478bd9Sstevel@tonic-gate if (bam_smf_check) /* ignore new during smf check */ 17807c478bd9Sstevel@tonic-gate return (0); 1781*48847494SEnrico Perla - Sun Microsystems 1782*48847494SEnrico Perla - Sun Microsystems if (is_flag_on(IS_SPARC_TARGET)) { 1783*48847494SEnrico Perla - Sun Microsystems set_dir_flag(FILE64, NEED_UPDATE); 1784*48847494SEnrico Perla - Sun Microsystems } else { 1785*48847494SEnrico Perla - Sun Microsystems ret = update_dircache(file, flags); 1786*48847494SEnrico Perla - Sun Microsystems if (ret == BAM_ERROR) { 1787*48847494SEnrico Perla - Sun Microsystems bam_error(UPDT_CACHE_FAIL, file); 1788*48847494SEnrico Perla - Sun Microsystems return (-1); 1789*48847494SEnrico Perla - Sun Microsystems } 1790*48847494SEnrico Perla - Sun Microsystems } 1791*48847494SEnrico Perla - Sun Microsystems 17927c478bd9Sstevel@tonic-gate if (bam_verbose) 17937c478bd9Sstevel@tonic-gate bam_print(PARSEABLE_NEW_FILE, file); 17947c478bd9Sstevel@tonic-gate return (0); 17957c478bd9Sstevel@tonic-gate } 17967c478bd9Sstevel@tonic-gate 17977c478bd9Sstevel@tonic-gate /* 1798*48847494SEnrico Perla - Sun Microsystems * If we got there, the file is already listed as to be included in the 1799*48847494SEnrico Perla - Sun Microsystems * iso image. We just need to know if we are going to rebuild it or not 1800*48847494SEnrico Perla - Sun Microsystems */ 1801*48847494SEnrico Perla - Sun Microsystems 1802*48847494SEnrico Perla - Sun Microsystems if (is_flag_on(IS_SPARC_TARGET) && 1803*48847494SEnrico Perla - Sun Microsystems is_dir_flag_on(FILE64, NEED_UPDATE) && !bam_smf_check) 1804*48847494SEnrico Perla - Sun Microsystems return (0); 1805*48847494SEnrico Perla - Sun Microsystems 1806*48847494SEnrico Perla - Sun Microsystems /* 18077c478bd9Sstevel@tonic-gate * File exists in old archive. Check if file has changed 18087c478bd9Sstevel@tonic-gate */ 18097c478bd9Sstevel@tonic-gate assert(sz == 2); 18107c478bd9Sstevel@tonic-gate bcopy(value, filestat, sizeof (filestat)); 18117c478bd9Sstevel@tonic-gate 1812*48847494SEnrico Perla - Sun Microsystems if (flags != FTW_D && (filestat[0] != st->st_size || 1813*48847494SEnrico Perla - Sun Microsystems filestat[1] != st->st_mtime)) { 18147c609327Ssetje if (bam_smf_check) { 18157c609327Ssetje safefilep = safefiles; 18167c609327Ssetje while (safefilep != NULL) { 18177c609327Ssetje if (strcmp(file + bam_rootlen, 18187c609327Ssetje safefilep->name) == 0) { 18197c609327Ssetje (void) creat(NEED_UPDATE_FILE, 0644); 18207c609327Ssetje return (0); 18217c609327Ssetje } 18227c609327Ssetje safefilep = safefilep->next; 18237c609327Ssetje } 18247c609327Ssetje } 1825*48847494SEnrico Perla - Sun Microsystems 1826*48847494SEnrico Perla - Sun Microsystems if (is_flag_on(IS_SPARC_TARGET)) { 1827*48847494SEnrico Perla - Sun Microsystems set_dir_flag(FILE64, NEED_UPDATE); 1828*48847494SEnrico Perla - Sun Microsystems } else { 1829*48847494SEnrico Perla - Sun Microsystems ret = update_dircache(file, flags); 1830*48847494SEnrico Perla - Sun Microsystems if (ret == BAM_ERROR) { 1831*48847494SEnrico Perla - Sun Microsystems bam_error(UPDT_CACHE_FAIL, file); 1832*48847494SEnrico Perla - Sun Microsystems return (-1); 1833*48847494SEnrico Perla - Sun Microsystems } 1834*48847494SEnrico Perla - Sun Microsystems } 1835*48847494SEnrico Perla - Sun Microsystems 18367c478bd9Sstevel@tonic-gate if (bam_verbose) 18377c478bd9Sstevel@tonic-gate if (bam_smf_check) 18387c478bd9Sstevel@tonic-gate bam_print(" %s\n", file); 18397c478bd9Sstevel@tonic-gate else 18407c478bd9Sstevel@tonic-gate bam_print(PARSEABLE_OUT_DATE, file); 18417c478bd9Sstevel@tonic-gate } 18427c478bd9Sstevel@tonic-gate 18437c478bd9Sstevel@tonic-gate return (0); 18447c478bd9Sstevel@tonic-gate } 18457c478bd9Sstevel@tonic-gate 18467c478bd9Sstevel@tonic-gate /* 1847*48847494SEnrico Perla - Sun Microsystems * Remove a directory path recursively 1848*48847494SEnrico Perla - Sun Microsystems */ 1849*48847494SEnrico Perla - Sun Microsystems static int 1850*48847494SEnrico Perla - Sun Microsystems rmdir_r(char *path) 1851*48847494SEnrico Perla - Sun Microsystems { 1852*48847494SEnrico Perla - Sun Microsystems struct dirent *d = NULL; 1853*48847494SEnrico Perla - Sun Microsystems DIR *dir = NULL; 1854*48847494SEnrico Perla - Sun Microsystems char tpath[PATH_MAX]; 1855*48847494SEnrico Perla - Sun Microsystems struct stat sb; 1856*48847494SEnrico Perla - Sun Microsystems 1857*48847494SEnrico Perla - Sun Microsystems if ((dir = opendir(path)) == NULL) 1858*48847494SEnrico Perla - Sun Microsystems return (-1); 1859*48847494SEnrico Perla - Sun Microsystems 1860*48847494SEnrico Perla - Sun Microsystems while (d = readdir(dir)) { 1861*48847494SEnrico Perla - Sun Microsystems if ((strcmp(d->d_name, ".") != 0) && 1862*48847494SEnrico Perla - Sun Microsystems (strcmp(d->d_name, "..") != 0)) { 1863*48847494SEnrico Perla - Sun Microsystems (void) snprintf(tpath, sizeof (tpath), "%s/%s", 1864*48847494SEnrico Perla - Sun Microsystems path, d->d_name); 1865*48847494SEnrico Perla - Sun Microsystems if (stat(tpath, &sb) == 0) { 1866*48847494SEnrico Perla - Sun Microsystems if (sb.st_mode & S_IFDIR) 1867*48847494SEnrico Perla - Sun Microsystems (void) rmdir_r(tpath); 1868*48847494SEnrico Perla - Sun Microsystems else 1869*48847494SEnrico Perla - Sun Microsystems (void) remove(tpath); 1870*48847494SEnrico Perla - Sun Microsystems } 1871*48847494SEnrico Perla - Sun Microsystems } 1872*48847494SEnrico Perla - Sun Microsystems } 1873*48847494SEnrico Perla - Sun Microsystems return (remove(path)); 1874*48847494SEnrico Perla - Sun Microsystems } 1875*48847494SEnrico Perla - Sun Microsystems 1876*48847494SEnrico Perla - Sun Microsystems /* 1877*48847494SEnrico Perla - Sun Microsystems * Check if cache directory exists and, if not, create it and update flags 1878*48847494SEnrico Perla - Sun Microsystems * accordingly. If the path exists, but it's not a directory, a best effort 1879*48847494SEnrico Perla - Sun Microsystems * attempt to remove and recreate it is made. 1880*48847494SEnrico Perla - Sun Microsystems * If the user requested a 'purge', always recreate the directory from scratch. 1881*48847494SEnrico Perla - Sun Microsystems */ 1882*48847494SEnrico Perla - Sun Microsystems static int 1883*48847494SEnrico Perla - Sun Microsystems set_cache_dir(char *root, int what) 1884*48847494SEnrico Perla - Sun Microsystems { 1885*48847494SEnrico Perla - Sun Microsystems struct stat sb; 1886*48847494SEnrico Perla - Sun Microsystems int ret = 0; 1887*48847494SEnrico Perla - Sun Microsystems 1888*48847494SEnrico Perla - Sun Microsystems ret = snprintf(get_cachedir(what), sizeof (get_cachedir(what)), 1889*48847494SEnrico Perla - Sun Microsystems "%s%s%s%s%s", root, ARCHIVE_PREFIX, get_machine(), what == FILE64 ? 1890*48847494SEnrico Perla - Sun Microsystems "/amd64" : "", CACHEDIR_SUFFIX); 1891*48847494SEnrico Perla - Sun Microsystems 1892*48847494SEnrico Perla - Sun Microsystems if (ret >= sizeof (get_cachedir(what))) { 1893*48847494SEnrico Perla - Sun Microsystems bam_error(PATH_TOO_LONG, rootbuf); 1894*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1895*48847494SEnrico Perla - Sun Microsystems } 1896*48847494SEnrico Perla - Sun Microsystems 1897*48847494SEnrico Perla - Sun Microsystems if (bam_purge) 1898*48847494SEnrico Perla - Sun Microsystems (void) rmdir_r(get_cachedir(what)); 1899*48847494SEnrico Perla - Sun Microsystems 1900*48847494SEnrico Perla - Sun Microsystems if (stat(get_cachedir(what), &sb) != 0 || !(S_ISDIR(sb.st_mode))) { 1901*48847494SEnrico Perla - Sun Microsystems /* best effort unlink attempt, mkdir will catch errors */ 1902*48847494SEnrico Perla - Sun Microsystems (void) unlink(get_cachedir(what)); 1903*48847494SEnrico Perla - Sun Microsystems 1904*48847494SEnrico Perla - Sun Microsystems if (bam_verbose) 1905*48847494SEnrico Perla - Sun Microsystems bam_print(UPDATE_CDIR_MISS, get_cachedir(what)); 1906*48847494SEnrico Perla - Sun Microsystems ret = mkdir(get_cachedir(what), DIR_PERMS); 1907*48847494SEnrico Perla - Sun Microsystems if (ret < 0) { 1908*48847494SEnrico Perla - Sun Microsystems bam_error(MKDIR_FAILED, get_cachedir(what), 1909*48847494SEnrico Perla - Sun Microsystems strerror(errno)); 1910*48847494SEnrico Perla - Sun Microsystems get_cachedir(what)[0] = '\0'; 1911*48847494SEnrico Perla - Sun Microsystems return (ret); 1912*48847494SEnrico Perla - Sun Microsystems } 1913*48847494SEnrico Perla - Sun Microsystems set_flag(NEED_CACHE_DIR); 1914*48847494SEnrico Perla - Sun Microsystems set_dir_flag(what, NO_MULTI); 1915*48847494SEnrico Perla - Sun Microsystems } 1916*48847494SEnrico Perla - Sun Microsystems 1917*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1918*48847494SEnrico Perla - Sun Microsystems } 1919*48847494SEnrico Perla - Sun Microsystems 1920*48847494SEnrico Perla - Sun Microsystems static int 1921*48847494SEnrico Perla - Sun Microsystems set_update_dir(char *root, int what) 1922*48847494SEnrico Perla - Sun Microsystems { 1923*48847494SEnrico Perla - Sun Microsystems struct stat sb; 1924*48847494SEnrico Perla - Sun Microsystems int ret; 1925*48847494SEnrico Perla - Sun Microsystems 1926*48847494SEnrico Perla - Sun Microsystems if (is_dir_flag_on(what, NO_MULTI)) 1927*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1928*48847494SEnrico Perla - Sun Microsystems 1929*48847494SEnrico Perla - Sun Microsystems if (!bam_extend) { 1930*48847494SEnrico Perla - Sun Microsystems set_dir_flag(what, NO_MULTI); 1931*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1932*48847494SEnrico Perla - Sun Microsystems } 1933*48847494SEnrico Perla - Sun Microsystems 1934*48847494SEnrico Perla - Sun Microsystems if (what == FILE64 && !is_flag_on(IS_SPARC_TARGET)) 1935*48847494SEnrico Perla - Sun Microsystems ret = snprintf(get_updatedir(what), 1936*48847494SEnrico Perla - Sun Microsystems sizeof (get_updatedir(what)), "%s%s%s/amd64%s", root, 1937*48847494SEnrico Perla - Sun Microsystems ARCHIVE_PREFIX, get_machine(), UPDATEDIR_SUFFIX); 1938*48847494SEnrico Perla - Sun Microsystems else 1939*48847494SEnrico Perla - Sun Microsystems ret = snprintf(get_updatedir(what), 1940*48847494SEnrico Perla - Sun Microsystems sizeof (get_updatedir(what)), "%s%s%s%s", root, 1941*48847494SEnrico Perla - Sun Microsystems ARCHIVE_PREFIX, get_machine(), UPDATEDIR_SUFFIX); 1942*48847494SEnrico Perla - Sun Microsystems 1943*48847494SEnrico Perla - Sun Microsystems if (ret >= sizeof (get_updatedir(what))) { 1944*48847494SEnrico Perla - Sun Microsystems bam_error(PATH_TOO_LONG, rootbuf); 1945*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1946*48847494SEnrico Perla - Sun Microsystems } 1947*48847494SEnrico Perla - Sun Microsystems 1948*48847494SEnrico Perla - Sun Microsystems if (stat(get_updatedir(what), &sb) == 0) { 1949*48847494SEnrico Perla - Sun Microsystems if (S_ISDIR(sb.st_mode)) 1950*48847494SEnrico Perla - Sun Microsystems ret = rmdir_r(get_updatedir(what)); 1951*48847494SEnrico Perla - Sun Microsystems else 1952*48847494SEnrico Perla - Sun Microsystems ret = unlink(get_updatedir(what)); 1953*48847494SEnrico Perla - Sun Microsystems 1954*48847494SEnrico Perla - Sun Microsystems if (ret != 0) 1955*48847494SEnrico Perla - Sun Microsystems set_dir_flag(what, NO_MULTI); 1956*48847494SEnrico Perla - Sun Microsystems } 1957*48847494SEnrico Perla - Sun Microsystems 1958*48847494SEnrico Perla - Sun Microsystems if (mkdir(get_updatedir(what), DIR_PERMS) < 0) 1959*48847494SEnrico Perla - Sun Microsystems set_dir_flag(what, NO_MULTI); 1960*48847494SEnrico Perla - Sun Microsystems 1961*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1962*48847494SEnrico Perla - Sun Microsystems } 1963*48847494SEnrico Perla - Sun Microsystems 1964*48847494SEnrico Perla - Sun Microsystems static int 1965*48847494SEnrico Perla - Sun Microsystems is_valid_archive(char *root, int what) 1966*48847494SEnrico Perla - Sun Microsystems { 1967*48847494SEnrico Perla - Sun Microsystems char archive_path[PATH_MAX]; 1968*48847494SEnrico Perla - Sun Microsystems struct stat sb; 1969*48847494SEnrico Perla - Sun Microsystems int ret; 1970*48847494SEnrico Perla - Sun Microsystems 1971*48847494SEnrico Perla - Sun Microsystems if (what == FILE64 && !is_flag_on(IS_SPARC_TARGET)) 1972*48847494SEnrico Perla - Sun Microsystems ret = snprintf(archive_path, sizeof (archive_path), 1973*48847494SEnrico Perla - Sun Microsystems "%s%s%s/amd64%s", root, ARCHIVE_PREFIX, get_machine(), 1974*48847494SEnrico Perla - Sun Microsystems ARCHIVE_SUFFIX); 1975*48847494SEnrico Perla - Sun Microsystems else 1976*48847494SEnrico Perla - Sun Microsystems ret = snprintf(archive_path, sizeof (archive_path), "%s%s%s%s", 1977*48847494SEnrico Perla - Sun Microsystems root, ARCHIVE_PREFIX, get_machine(), ARCHIVE_SUFFIX); 1978*48847494SEnrico Perla - Sun Microsystems 1979*48847494SEnrico Perla - Sun Microsystems if (ret >= sizeof (archive_path)) { 1980*48847494SEnrico Perla - Sun Microsystems bam_error(PATH_TOO_LONG, rootbuf); 1981*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 1982*48847494SEnrico Perla - Sun Microsystems } 1983*48847494SEnrico Perla - Sun Microsystems 1984*48847494SEnrico Perla - Sun Microsystems if (stat(archive_path, &sb) != 0) { 1985*48847494SEnrico Perla - Sun Microsystems if (bam_verbose && !bam_check) 1986*48847494SEnrico Perla - Sun Microsystems bam_print(UPDATE_ARCH_MISS, archive_path); 1987*48847494SEnrico Perla - Sun Microsystems set_dir_flag(what, NEED_UPDATE); 1988*48847494SEnrico Perla - Sun Microsystems set_dir_flag(what, NO_MULTI); 1989*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1990*48847494SEnrico Perla - Sun Microsystems } 1991*48847494SEnrico Perla - Sun Microsystems 1992*48847494SEnrico Perla - Sun Microsystems if (is_flag_on(IS_SPARC_TARGET)) 1993*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 1994*48847494SEnrico Perla - Sun Microsystems 1995*48847494SEnrico Perla - Sun Microsystems if (bam_extend && sb.st_size > BA_SIZE_MAX) { 1996*48847494SEnrico Perla - Sun Microsystems if (bam_verbose && !bam_check) 1997*48847494SEnrico Perla - Sun Microsystems bam_print(MULTI_SIZE, archive_path, BA_SIZE_MAX); 1998*48847494SEnrico Perla - Sun Microsystems set_dir_flag(what, NO_MULTI); 1999*48847494SEnrico Perla - Sun Microsystems } 2000*48847494SEnrico Perla - Sun Microsystems 2001*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 2002*48847494SEnrico Perla - Sun Microsystems } 2003*48847494SEnrico Perla - Sun Microsystems 2004*48847494SEnrico Perla - Sun Microsystems /* 2005*48847494SEnrico Perla - Sun Microsystems * Check flags and presence of required files and directories. 20067c478bd9Sstevel@tonic-gate * The force flag and/or absence of files should 20077c478bd9Sstevel@tonic-gate * trigger an update. 20087c478bd9Sstevel@tonic-gate * Suppress stdout output if check (-n) option is set 20097c478bd9Sstevel@tonic-gate * (as -n should only produce parseable output.) 20107c478bd9Sstevel@tonic-gate */ 2011*48847494SEnrico Perla - Sun Microsystems static int 20127c478bd9Sstevel@tonic-gate check_flags_and_files(char *root) 20137c478bd9Sstevel@tonic-gate { 2014*48847494SEnrico Perla - Sun Microsystems 20157c478bd9Sstevel@tonic-gate struct stat sb; 2016*48847494SEnrico Perla - Sun Microsystems int ret; 2017*48847494SEnrico Perla - Sun Microsystems 2018*48847494SEnrico Perla - Sun Microsystems /* 2019*48847494SEnrico Perla - Sun Microsystems * If archive is missing, create archive 2020*48847494SEnrico Perla - Sun Microsystems */ 2021*48847494SEnrico Perla - Sun Microsystems if (is_flag_on(IS_SPARC_TARGET)) { 2022*48847494SEnrico Perla - Sun Microsystems ret = is_valid_archive(root, FILE64); 2023*48847494SEnrico Perla - Sun Microsystems } else { 2024*48847494SEnrico Perla - Sun Microsystems int what = FILE32; 2025*48847494SEnrico Perla - Sun Microsystems do { 2026*48847494SEnrico Perla - Sun Microsystems ret = is_valid_archive(root, what); 2027*48847494SEnrico Perla - Sun Microsystems if (ret == BAM_ERROR) 2028*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2029*48847494SEnrico Perla - Sun Microsystems what++; 2030*48847494SEnrico Perla - Sun Microsystems } while (bam_direct == BAM_DIRECT_DBOOT && what < CACHEDIR_NUM); 2031*48847494SEnrico Perla - Sun Microsystems } 2032*48847494SEnrico Perla - Sun Microsystems 2033*48847494SEnrico Perla - Sun Microsystems if (bam_nowrite()) 2034*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 2035*48847494SEnrico Perla - Sun Microsystems 2036*48847494SEnrico Perla - Sun Microsystems 2037*48847494SEnrico Perla - Sun Microsystems /* 2038*48847494SEnrico Perla - Sun Microsystems * check if cache directories exist on x86. 2039*48847494SEnrico Perla - Sun Microsystems * check (and always open) the cache file on SPARC. 2040*48847494SEnrico Perla - Sun Microsystems */ 2041*48847494SEnrico Perla - Sun Microsystems if (is_sparc()) { 2042*48847494SEnrico Perla - Sun Microsystems ret = snprintf(get_cachedir(FILE64), 2043*48847494SEnrico Perla - Sun Microsystems sizeof (get_cachedir(FILE64)), "%s%s%s/%s", root, 2044*48847494SEnrico Perla - Sun Microsystems ARCHIVE_PREFIX, get_machine(), CACHEDIR_SUFFIX); 2045*48847494SEnrico Perla - Sun Microsystems 2046*48847494SEnrico Perla - Sun Microsystems if (ret >= sizeof (get_cachedir(FILE64))) { 2047*48847494SEnrico Perla - Sun Microsystems bam_error(PATH_TOO_LONG, rootbuf); 2048*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2049*48847494SEnrico Perla - Sun Microsystems } 2050*48847494SEnrico Perla - Sun Microsystems 2051*48847494SEnrico Perla - Sun Microsystems if (stat(get_cachedir(FILE64), &sb) != 0) { 2052*48847494SEnrico Perla - Sun Microsystems set_flag(NEED_CACHE_DIR); 2053*48847494SEnrico Perla - Sun Microsystems set_dir_flag(FILE64, NEED_UPDATE); 2054*48847494SEnrico Perla - Sun Microsystems } 2055*48847494SEnrico Perla - Sun Microsystems 2056*48847494SEnrico Perla - Sun Microsystems walk_arg.sparcfile = fopen(get_cachedir(FILE64), "w"); 2057*48847494SEnrico Perla - Sun Microsystems if (walk_arg.sparcfile == NULL) { 2058*48847494SEnrico Perla - Sun Microsystems bam_error(OPEN_FAIL, get_cachedir(FILE64), 2059*48847494SEnrico Perla - Sun Microsystems strerror(errno)); 2060*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2061*48847494SEnrico Perla - Sun Microsystems } 2062*48847494SEnrico Perla - Sun Microsystems 2063*48847494SEnrico Perla - Sun Microsystems set_dir_present(FILE64); 2064*48847494SEnrico Perla - Sun Microsystems } else { 2065*48847494SEnrico Perla - Sun Microsystems int what = FILE32; 2066*48847494SEnrico Perla - Sun Microsystems 2067*48847494SEnrico Perla - Sun Microsystems do { 2068*48847494SEnrico Perla - Sun Microsystems if (set_cache_dir(root, what) != 0) 2069*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2070*48847494SEnrico Perla - Sun Microsystems 2071*48847494SEnrico Perla - Sun Microsystems set_dir_present(what); 2072*48847494SEnrico Perla - Sun Microsystems 2073*48847494SEnrico Perla - Sun Microsystems if (set_update_dir(root, what) != 0) 2074*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2075*48847494SEnrico Perla - Sun Microsystems what++; 2076*48847494SEnrico Perla - Sun Microsystems } while (bam_direct == BAM_DIRECT_DBOOT && what < CACHEDIR_NUM); 2077*48847494SEnrico Perla - Sun Microsystems } 20787c478bd9Sstevel@tonic-gate 20797c478bd9Sstevel@tonic-gate /* 20807c478bd9Sstevel@tonic-gate * if force, create archive unconditionally 20817c478bd9Sstevel@tonic-gate */ 20827c478bd9Sstevel@tonic-gate if (bam_force) { 2083*48847494SEnrico Perla - Sun Microsystems if (!is_sparc()) 2084*48847494SEnrico Perla - Sun Microsystems set_dir_flag(FILE32, NEED_UPDATE); 2085*48847494SEnrico Perla - Sun Microsystems set_dir_flag(FILE64, NEED_UPDATE); 2086*48847494SEnrico Perla - Sun Microsystems if (bam_verbose) 20877c478bd9Sstevel@tonic-gate bam_print(UPDATE_FORCE); 2088*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 20897c478bd9Sstevel@tonic-gate } 20907c478bd9Sstevel@tonic-gate 2091*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 20927c478bd9Sstevel@tonic-gate } 20937c478bd9Sstevel@tonic-gate 20947c478bd9Sstevel@tonic-gate static error_t 20957c478bd9Sstevel@tonic-gate read_one_list(char *root, filelist_t *flistp, char *filelist) 20967c478bd9Sstevel@tonic-gate { 20977c478bd9Sstevel@tonic-gate char path[PATH_MAX]; 20987c478bd9Sstevel@tonic-gate FILE *fp; 20997c478bd9Sstevel@tonic-gate char buf[BAM_MAXLINE]; 2100eb2bd662Svikram const char *fcn = "read_one_list()"; 21017c478bd9Sstevel@tonic-gate 21027c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s%s", root, filelist); 21037c478bd9Sstevel@tonic-gate 21047c478bd9Sstevel@tonic-gate fp = fopen(path, "r"); 21057c478bd9Sstevel@tonic-gate if (fp == NULL) { 2106eb2bd662Svikram BAM_DPRINTF((D_FLIST_FAIL, fcn, path, strerror(errno))); 21077c478bd9Sstevel@tonic-gate return (BAM_ERROR); 21087c478bd9Sstevel@tonic-gate } 21097c478bd9Sstevel@tonic-gate while (s_fgets(buf, sizeof (buf), fp) != NULL) { 2110b610f78eSvikram /* skip blank lines */ 2111b610f78eSvikram if (strspn(buf, " \t") == strlen(buf)) 2112b610f78eSvikram continue; 21137c478bd9Sstevel@tonic-gate append_to_flist(flistp, buf); 21147c478bd9Sstevel@tonic-gate } 21157c478bd9Sstevel@tonic-gate if (fclose(fp) != 0) { 21167c478bd9Sstevel@tonic-gate bam_error(CLOSE_FAIL, path, strerror(errno)); 21177c478bd9Sstevel@tonic-gate return (BAM_ERROR); 21187c478bd9Sstevel@tonic-gate } 21197c478bd9Sstevel@tonic-gate return (BAM_SUCCESS); 21207c478bd9Sstevel@tonic-gate } 21217c478bd9Sstevel@tonic-gate 21227c478bd9Sstevel@tonic-gate static error_t 21237c478bd9Sstevel@tonic-gate read_list(char *root, filelist_t *flistp) 21247c478bd9Sstevel@tonic-gate { 2125986fd29aSsetje char path[PATH_MAX]; 2126986fd29aSsetje char cmd[PATH_MAX]; 2127986fd29aSsetje struct stat sb; 2128986fd29aSsetje int n, rval; 2129eb2bd662Svikram const char *fcn = "read_list()"; 21307c478bd9Sstevel@tonic-gate 21317c478bd9Sstevel@tonic-gate flistp->head = flistp->tail = NULL; 21327c478bd9Sstevel@tonic-gate 21337c478bd9Sstevel@tonic-gate /* 2134986fd29aSsetje * build and check path to extract_boot_filelist.ksh 2135986fd29aSsetje */ 2136986fd29aSsetje n = snprintf(path, sizeof (path), "%s%s", root, EXTRACT_BOOT_FILELIST); 2137986fd29aSsetje if (n >= sizeof (path)) { 2138986fd29aSsetje bam_error(NO_FLIST); 2139986fd29aSsetje return (BAM_ERROR); 2140986fd29aSsetje } 2141986fd29aSsetje 2142986fd29aSsetje /* 2143986fd29aSsetje * If extract_boot_filelist is present, exec it, otherwise read 2144986fd29aSsetje * the filelists directly, for compatibility with older images. 2145986fd29aSsetje */ 2146986fd29aSsetje if (stat(path, &sb) == 0) { 2147986fd29aSsetje /* 2148986fd29aSsetje * build arguments to exec extract_boot_filelist.ksh 2149986fd29aSsetje */ 2150d876c67dSjg char *rootarg, *platarg; 2151d876c67dSjg int platarglen = 1, rootarglen = 1; 2152d876c67dSjg if (strlen(root) > 1) 2153d876c67dSjg rootarglen += strlen(root) + strlen("-R "); 2154d876c67dSjg if (bam_alt_platform) 2155d876c67dSjg platarglen += strlen(bam_platform) + strlen("-p "); 2156d876c67dSjg platarg = s_calloc(1, platarglen); 2157d876c67dSjg rootarg = s_calloc(1, rootarglen); 2158d876c67dSjg *platarg = 0; 2159d876c67dSjg *rootarg = 0; 2160d876c67dSjg 2161986fd29aSsetje if (strlen(root) > 1) { 2162d876c67dSjg (void) snprintf(rootarg, rootarglen, 2163d876c67dSjg "-R %s", root); 2164986fd29aSsetje } 2165d876c67dSjg if (bam_alt_platform) { 2166d876c67dSjg (void) snprintf(platarg, platarglen, 2167d876c67dSjg "-p %s", bam_platform); 2168d876c67dSjg } 2169d876c67dSjg n = snprintf(cmd, sizeof (cmd), "%s %s %s /%s /%s", 2170d876c67dSjg path, rootarg, platarg, BOOT_FILE_LIST, ETC_FILE_LIST); 2171d876c67dSjg free(platarg); 2172d876c67dSjg free(rootarg); 2173986fd29aSsetje if (n >= sizeof (cmd)) { 2174986fd29aSsetje bam_error(NO_FLIST); 2175986fd29aSsetje return (BAM_ERROR); 2176986fd29aSsetje } 2177986fd29aSsetje if (exec_cmd(cmd, flistp) != 0) { 2178eb2bd662Svikram BAM_DPRINTF((D_FLIST_FAIL, fcn, path, strerror(errno))); 2179986fd29aSsetje return (BAM_ERROR); 2180986fd29aSsetje } 2181986fd29aSsetje } else { 2182986fd29aSsetje /* 21837c478bd9Sstevel@tonic-gate * Read current lists of files - only the first is mandatory 21847c478bd9Sstevel@tonic-gate */ 21857c478bd9Sstevel@tonic-gate rval = read_one_list(root, flistp, BOOT_FILE_LIST); 21867c478bd9Sstevel@tonic-gate if (rval != BAM_SUCCESS) 21877c478bd9Sstevel@tonic-gate return (rval); 21887c478bd9Sstevel@tonic-gate (void) read_one_list(root, flistp, ETC_FILE_LIST); 2189986fd29aSsetje } 21907c478bd9Sstevel@tonic-gate 21917c478bd9Sstevel@tonic-gate if (flistp->head == NULL) { 21927c478bd9Sstevel@tonic-gate bam_error(NO_FLIST); 21937c478bd9Sstevel@tonic-gate return (BAM_ERROR); 21947c478bd9Sstevel@tonic-gate } 21957c478bd9Sstevel@tonic-gate 21967c478bd9Sstevel@tonic-gate return (BAM_SUCCESS); 21977c478bd9Sstevel@tonic-gate } 21987c478bd9Sstevel@tonic-gate 21997c478bd9Sstevel@tonic-gate static void 22007c478bd9Sstevel@tonic-gate getoldstat(char *root) 22017c478bd9Sstevel@tonic-gate { 22027c478bd9Sstevel@tonic-gate char path[PATH_MAX]; 22037c478bd9Sstevel@tonic-gate int fd, error; 22047c478bd9Sstevel@tonic-gate struct stat sb; 22057c478bd9Sstevel@tonic-gate char *ostat; 22067c478bd9Sstevel@tonic-gate 22077c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s%s", root, FILE_STAT); 22087c478bd9Sstevel@tonic-gate fd = open(path, O_RDONLY); 22097c478bd9Sstevel@tonic-gate if (fd == -1) { 22107c478bd9Sstevel@tonic-gate if (bam_verbose) 22117c478bd9Sstevel@tonic-gate bam_print(OPEN_FAIL, path, strerror(errno)); 2212*48847494SEnrico Perla - Sun Microsystems goto out_err; 22137c478bd9Sstevel@tonic-gate } 22147c478bd9Sstevel@tonic-gate 22157c478bd9Sstevel@tonic-gate if (fstat(fd, &sb) != 0) { 22167c478bd9Sstevel@tonic-gate bam_error(STAT_FAIL, path, strerror(errno)); 2217*48847494SEnrico Perla - Sun Microsystems goto out_err; 22187c478bd9Sstevel@tonic-gate } 22197c478bd9Sstevel@tonic-gate 22207c478bd9Sstevel@tonic-gate ostat = s_calloc(1, sb.st_size); 22217c478bd9Sstevel@tonic-gate 22227c478bd9Sstevel@tonic-gate if (read(fd, ostat, sb.st_size) != sb.st_size) { 22237c478bd9Sstevel@tonic-gate bam_error(READ_FAIL, path, strerror(errno)); 22247c478bd9Sstevel@tonic-gate free(ostat); 2225*48847494SEnrico Perla - Sun Microsystems goto out_err; 22267c478bd9Sstevel@tonic-gate } 22277c478bd9Sstevel@tonic-gate 22287c478bd9Sstevel@tonic-gate (void) close(fd); 2229*48847494SEnrico Perla - Sun Microsystems fd = -1; 22307c478bd9Sstevel@tonic-gate 22317c478bd9Sstevel@tonic-gate walk_arg.old_nvlp = NULL; 22327c478bd9Sstevel@tonic-gate error = nvlist_unpack(ostat, sb.st_size, &walk_arg.old_nvlp, 0); 22337c478bd9Sstevel@tonic-gate 22347c478bd9Sstevel@tonic-gate free(ostat); 22357c478bd9Sstevel@tonic-gate 22367c478bd9Sstevel@tonic-gate if (error) { 22377c478bd9Sstevel@tonic-gate bam_error(UNPACK_FAIL, path, strerror(error)); 22387c478bd9Sstevel@tonic-gate walk_arg.old_nvlp = NULL; 2239*48847494SEnrico Perla - Sun Microsystems goto out_err; 2240*48847494SEnrico Perla - Sun Microsystems } else { 22417c478bd9Sstevel@tonic-gate return; 22427c478bd9Sstevel@tonic-gate } 2243*48847494SEnrico Perla - Sun Microsystems 2244*48847494SEnrico Perla - Sun Microsystems out_err: 2245*48847494SEnrico Perla - Sun Microsystems if (fd != -1) 2246*48847494SEnrico Perla - Sun Microsystems (void) close(fd); 2247*48847494SEnrico Perla - Sun Microsystems set_dir_flag(FILE32, NEED_UPDATE); 2248*48847494SEnrico Perla - Sun Microsystems set_dir_flag(FILE64, NEED_UPDATE); 2249*48847494SEnrico Perla - Sun Microsystems } 2250*48847494SEnrico Perla - Sun Microsystems 2251*48847494SEnrico Perla - Sun Microsystems /* Best effort stale entry removal */ 2252*48847494SEnrico Perla - Sun Microsystems static void 2253*48847494SEnrico Perla - Sun Microsystems delete_stale(char *file, int what) 2254*48847494SEnrico Perla - Sun Microsystems { 2255*48847494SEnrico Perla - Sun Microsystems char path[PATH_MAX]; 2256*48847494SEnrico Perla - Sun Microsystems struct stat sb; 2257*48847494SEnrico Perla - Sun Microsystems 2258*48847494SEnrico Perla - Sun Microsystems (void) snprintf(path, sizeof (path), "%s/%s", get_cachedir(what), file); 2259*48847494SEnrico Perla - Sun Microsystems if (!bam_check && stat(path, &sb) == 0) { 2260*48847494SEnrico Perla - Sun Microsystems if (sb.st_mode & S_IFDIR) 2261*48847494SEnrico Perla - Sun Microsystems (void) rmdir_r(path); 2262*48847494SEnrico Perla - Sun Microsystems else 2263*48847494SEnrico Perla - Sun Microsystems (void) unlink(path); 2264*48847494SEnrico Perla - Sun Microsystems 2265*48847494SEnrico Perla - Sun Microsystems set_dir_flag(what, (NEED_UPDATE | NO_MULTI)); 2266*48847494SEnrico Perla - Sun Microsystems } 2267*48847494SEnrico Perla - Sun Microsystems if (bam_verbose) 2268*48847494SEnrico Perla - Sun Microsystems bam_print(PARSEABLE_STALE_FILE, path); 22697c478bd9Sstevel@tonic-gate } 22707c478bd9Sstevel@tonic-gate 2271a28d77b8Svikram /* 2272a28d77b8Svikram * Checks if a file in the current (old) archive has 2273a28d77b8Svikram * been deleted from the root filesystem. This is needed for 2274a28d77b8Svikram * software like Trusted Extensions (TX) that switch early 2275a28d77b8Svikram * in boot based on presence/absence of a kernel module. 2276a28d77b8Svikram */ 2277a28d77b8Svikram static void 2278a28d77b8Svikram check4stale(char *root) 2279a28d77b8Svikram { 2280a28d77b8Svikram nvpair_t *nvp; 2281a28d77b8Svikram nvlist_t *nvlp; 2282a28d77b8Svikram char *file; 2283a28d77b8Svikram char path[PATH_MAX]; 2284a28d77b8Svikram 2285a28d77b8Svikram /* 2286a28d77b8Svikram * Skip stale file check during smf check 2287a28d77b8Svikram */ 2288a28d77b8Svikram if (bam_smf_check) 2289a28d77b8Svikram return; 2290a28d77b8Svikram 2291*48847494SEnrico Perla - Sun Microsystems /* 2292*48847494SEnrico Perla - Sun Microsystems * If we need to (re)create the cache, there's no need to check for 2293*48847494SEnrico Perla - Sun Microsystems * stale files 2294*48847494SEnrico Perla - Sun Microsystems */ 2295*48847494SEnrico Perla - Sun Microsystems if (is_flag_on(NEED_CACHE_DIR)) 2296*48847494SEnrico Perla - Sun Microsystems return; 2297*48847494SEnrico Perla - Sun Microsystems 2298a28d77b8Svikram /* Nothing to do if no old stats */ 2299a28d77b8Svikram if ((nvlp = walk_arg.old_nvlp) == NULL) 2300a28d77b8Svikram return; 2301a28d77b8Svikram 2302a28d77b8Svikram for (nvp = nvlist_next_nvpair(nvlp, NULL); nvp; 2303a28d77b8Svikram nvp = nvlist_next_nvpair(nvlp, nvp)) { 2304a28d77b8Svikram file = nvpair_name(nvp); 2305a28d77b8Svikram if (file == NULL) 2306a28d77b8Svikram continue; 2307a28d77b8Svikram (void) snprintf(path, sizeof (path), "%s/%s", 2308a28d77b8Svikram root, file); 2309*48847494SEnrico Perla - Sun Microsystems if (access(path, F_OK) < 0) { 2310*48847494SEnrico Perla - Sun Microsystems int what; 2311*48847494SEnrico Perla - Sun Microsystems 2312*48847494SEnrico Perla - Sun Microsystems if (is_flag_on(IS_SPARC_TARGET)) 2313*48847494SEnrico Perla - Sun Microsystems set_dir_flag(FILE64, NEED_UPDATE); 2314*48847494SEnrico Perla - Sun Microsystems 2315*48847494SEnrico Perla - Sun Microsystems for (what = FILE32; what < CACHEDIR_NUM; what++) 2316*48847494SEnrico Perla - Sun Microsystems if (has_cachedir(what)) 2317*48847494SEnrico Perla - Sun Microsystems delete_stale(file, what); 2318a28d77b8Svikram } 2319a28d77b8Svikram } 2320a28d77b8Svikram } 2321a28d77b8Svikram 23227c478bd9Sstevel@tonic-gate static void 23237c478bd9Sstevel@tonic-gate create_newstat(void) 23247c478bd9Sstevel@tonic-gate { 23257c478bd9Sstevel@tonic-gate int error; 23267c478bd9Sstevel@tonic-gate 23277c478bd9Sstevel@tonic-gate error = nvlist_alloc(&walk_arg.new_nvlp, NV_UNIQUE_NAME, 0); 23287c478bd9Sstevel@tonic-gate if (error) { 23297c478bd9Sstevel@tonic-gate /* 23307c478bd9Sstevel@tonic-gate * Not fatal - we can still create archive 23317c478bd9Sstevel@tonic-gate */ 23327c478bd9Sstevel@tonic-gate walk_arg.new_nvlp = NULL; 23337c478bd9Sstevel@tonic-gate bam_error(NVALLOC_FAIL, strerror(error)); 23347c478bd9Sstevel@tonic-gate } 23357c478bd9Sstevel@tonic-gate } 23367c478bd9Sstevel@tonic-gate 2337*48847494SEnrico Perla - Sun Microsystems static int 23387c478bd9Sstevel@tonic-gate walk_list(char *root, filelist_t *flistp) 23397c478bd9Sstevel@tonic-gate { 23407c478bd9Sstevel@tonic-gate char path[PATH_MAX]; 23417c478bd9Sstevel@tonic-gate line_t *lp; 23427c478bd9Sstevel@tonic-gate 23437c478bd9Sstevel@tonic-gate for (lp = flistp->head; lp; lp = lp->next) { 2344986fd29aSsetje /* 2345986fd29aSsetje * Don't follow symlinks. A symlink must refer to 2346986fd29aSsetje * a file that would appear in the archive through 2347986fd29aSsetje * a direct reference. This matches the archive 2348986fd29aSsetje * construction behavior. 2349986fd29aSsetje */ 23507c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s%s", root, lp->line); 2351986fd29aSsetje if (nftw(path, cmpstat, 20, FTW_PHYS) == -1) { 2352*48847494SEnrico Perla - Sun Microsystems if (is_flag_on(UPDATE_ERROR)) 2353*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 23547c478bd9Sstevel@tonic-gate /* 23557c478bd9Sstevel@tonic-gate * Some files may not exist. 23567c478bd9Sstevel@tonic-gate * For example: etc/rtc_config on a x86 diskless system 23577c478bd9Sstevel@tonic-gate * Emit verbose message only 23587c478bd9Sstevel@tonic-gate */ 23597c478bd9Sstevel@tonic-gate if (bam_verbose) 23607c478bd9Sstevel@tonic-gate bam_print(NFTW_FAIL, path, strerror(errno)); 23617c478bd9Sstevel@tonic-gate } 23627c478bd9Sstevel@tonic-gate } 2363*48847494SEnrico Perla - Sun Microsystems 2364*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 23657c478bd9Sstevel@tonic-gate } 23667c478bd9Sstevel@tonic-gate 23677c478bd9Sstevel@tonic-gate static void 23687c478bd9Sstevel@tonic-gate savenew(char *root) 23697c478bd9Sstevel@tonic-gate { 23707c478bd9Sstevel@tonic-gate char path[PATH_MAX]; 23717c478bd9Sstevel@tonic-gate char path2[PATH_MAX]; 23727c478bd9Sstevel@tonic-gate size_t sz; 23737c478bd9Sstevel@tonic-gate char *nstat; 23747c478bd9Sstevel@tonic-gate int fd, wrote, error; 23757c478bd9Sstevel@tonic-gate 23767c478bd9Sstevel@tonic-gate nstat = NULL; 23777c478bd9Sstevel@tonic-gate sz = 0; 23787c478bd9Sstevel@tonic-gate error = nvlist_pack(walk_arg.new_nvlp, &nstat, &sz, 23797c478bd9Sstevel@tonic-gate NV_ENCODE_XDR, 0); 23807c478bd9Sstevel@tonic-gate if (error) { 23817c478bd9Sstevel@tonic-gate bam_error(PACK_FAIL, strerror(error)); 23827c478bd9Sstevel@tonic-gate return; 23837c478bd9Sstevel@tonic-gate } 23847c478bd9Sstevel@tonic-gate 23857c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s%s", root, FILE_STAT_TMP); 23867c478bd9Sstevel@tonic-gate fd = open(path, O_RDWR|O_CREAT|O_TRUNC, FILE_STAT_MODE); 23877c478bd9Sstevel@tonic-gate if (fd == -1) { 23887c478bd9Sstevel@tonic-gate bam_error(OPEN_FAIL, path, strerror(errno)); 23897c478bd9Sstevel@tonic-gate free(nstat); 23907c478bd9Sstevel@tonic-gate return; 23917c478bd9Sstevel@tonic-gate } 23927c478bd9Sstevel@tonic-gate wrote = write(fd, nstat, sz); 23937c478bd9Sstevel@tonic-gate if (wrote != sz) { 23947c478bd9Sstevel@tonic-gate bam_error(WRITE_FAIL, path, strerror(errno)); 23957c478bd9Sstevel@tonic-gate (void) close(fd); 23967c478bd9Sstevel@tonic-gate free(nstat); 23977c478bd9Sstevel@tonic-gate return; 23987c478bd9Sstevel@tonic-gate } 23997c478bd9Sstevel@tonic-gate (void) close(fd); 24007c478bd9Sstevel@tonic-gate free(nstat); 24017c478bd9Sstevel@tonic-gate 24027c478bd9Sstevel@tonic-gate (void) snprintf(path2, sizeof (path2), "%s%s", root, FILE_STAT); 24037c478bd9Sstevel@tonic-gate if (rename(path, path2) != 0) { 24047c478bd9Sstevel@tonic-gate bam_error(RENAME_FAIL, path2, strerror(errno)); 24057c478bd9Sstevel@tonic-gate } 24067c478bd9Sstevel@tonic-gate } 24077c478bd9Sstevel@tonic-gate 2408*48847494SEnrico Perla - Sun Microsystems #define init_walk_args() bzero(&walk_arg, sizeof (walk_arg)) 2409*48847494SEnrico Perla - Sun Microsystems 24107c478bd9Sstevel@tonic-gate static void 24117c478bd9Sstevel@tonic-gate clear_walk_args(void) 24127c478bd9Sstevel@tonic-gate { 24137c478bd9Sstevel@tonic-gate if (walk_arg.old_nvlp) 24147c478bd9Sstevel@tonic-gate nvlist_free(walk_arg.old_nvlp); 24157c478bd9Sstevel@tonic-gate if (walk_arg.new_nvlp) 24167c478bd9Sstevel@tonic-gate nvlist_free(walk_arg.new_nvlp); 2417*48847494SEnrico Perla - Sun Microsystems if (walk_arg.sparcfile) 2418*48847494SEnrico Perla - Sun Microsystems (void) fclose(walk_arg.sparcfile); 24197c478bd9Sstevel@tonic-gate walk_arg.old_nvlp = NULL; 24207c478bd9Sstevel@tonic-gate walk_arg.new_nvlp = NULL; 2421*48847494SEnrico Perla - Sun Microsystems walk_arg.sparcfile = NULL; 24227c478bd9Sstevel@tonic-gate } 24237c478bd9Sstevel@tonic-gate 24247c478bd9Sstevel@tonic-gate /* 24257c478bd9Sstevel@tonic-gate * Returns: 24267c478bd9Sstevel@tonic-gate * 0 - no update necessary 24277c478bd9Sstevel@tonic-gate * 1 - update required. 24287c478bd9Sstevel@tonic-gate * BAM_ERROR (-1) - An error occurred 24297c478bd9Sstevel@tonic-gate * 24307c478bd9Sstevel@tonic-gate * Special handling for check (-n): 24317c478bd9Sstevel@tonic-gate * ================================ 24327c478bd9Sstevel@tonic-gate * The check (-n) option produces parseable output. 24337c478bd9Sstevel@tonic-gate * To do this, we suppress all stdout messages unrelated 24347c478bd9Sstevel@tonic-gate * to out of sync files. 24357c478bd9Sstevel@tonic-gate * All stderr messages are still printed though. 24367c478bd9Sstevel@tonic-gate * 24377c478bd9Sstevel@tonic-gate */ 24387c478bd9Sstevel@tonic-gate static int 24397c478bd9Sstevel@tonic-gate update_required(char *root) 24407c478bd9Sstevel@tonic-gate { 24417c478bd9Sstevel@tonic-gate struct stat sb; 24427c478bd9Sstevel@tonic-gate char path[PATH_MAX]; 24437c478bd9Sstevel@tonic-gate filelist_t flist; 24447c478bd9Sstevel@tonic-gate filelist_t *flistp = &flist; 2445*48847494SEnrico Perla - Sun Microsystems int ret; 24467c478bd9Sstevel@tonic-gate 24477c478bd9Sstevel@tonic-gate flistp->head = flistp->tail = NULL; 24487c478bd9Sstevel@tonic-gate 2449*48847494SEnrico Perla - Sun Microsystems if (is_sparc()) 2450*48847494SEnrico Perla - Sun Microsystems set_flag(IS_SPARC_TARGET); 24517c478bd9Sstevel@tonic-gate 24527c478bd9Sstevel@tonic-gate /* 2453*48847494SEnrico Perla - Sun Microsystems * Check if cache directories and archives are present 24547c478bd9Sstevel@tonic-gate */ 2455*48847494SEnrico Perla - Sun Microsystems 2456*48847494SEnrico Perla - Sun Microsystems ret = check_flags_and_files(root); 2457*48847494SEnrico Perla - Sun Microsystems if (ret < 0) 2458*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 24597c478bd9Sstevel@tonic-gate 24607c478bd9Sstevel@tonic-gate /* 24617c478bd9Sstevel@tonic-gate * In certain deployment scenarios, filestat may not 24627c478bd9Sstevel@tonic-gate * exist. Ignore it during boot-archive SMF check. 24637c478bd9Sstevel@tonic-gate */ 24647c478bd9Sstevel@tonic-gate if (bam_smf_check) { 24657c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), "%s%s", root, FILE_STAT); 24667c478bd9Sstevel@tonic-gate if (stat(path, &sb) != 0) 24677c478bd9Sstevel@tonic-gate return (0); 24687c478bd9Sstevel@tonic-gate } 24697c478bd9Sstevel@tonic-gate 24707c478bd9Sstevel@tonic-gate getoldstat(root); 24717c478bd9Sstevel@tonic-gate 24727c478bd9Sstevel@tonic-gate /* 2473a28d77b8Svikram * Check if the archive contains files that are no longer 2474a28d77b8Svikram * present on the root filesystem. 2475a28d77b8Svikram */ 2476a28d77b8Svikram check4stale(root); 2477a28d77b8Svikram 2478a28d77b8Svikram /* 24797c478bd9Sstevel@tonic-gate * read list of files 24807c478bd9Sstevel@tonic-gate */ 24817c478bd9Sstevel@tonic-gate if (read_list(root, flistp) != BAM_SUCCESS) { 24827c478bd9Sstevel@tonic-gate clear_walk_args(); 24837c478bd9Sstevel@tonic-gate return (BAM_ERROR); 24847c478bd9Sstevel@tonic-gate } 24857c478bd9Sstevel@tonic-gate 24867c478bd9Sstevel@tonic-gate assert(flistp->head && flistp->tail); 24877c478bd9Sstevel@tonic-gate 24887c478bd9Sstevel@tonic-gate /* 24897c478bd9Sstevel@tonic-gate * At this point either the update is required 24907c478bd9Sstevel@tonic-gate * or the decision is pending. In either case 24917c478bd9Sstevel@tonic-gate * we need to create new stat nvlist 24927c478bd9Sstevel@tonic-gate */ 24937c478bd9Sstevel@tonic-gate create_newstat(); 24947c478bd9Sstevel@tonic-gate /* 24957c478bd9Sstevel@tonic-gate * This walk does 2 things: 24967c478bd9Sstevel@tonic-gate * - gets new stat data for every file 24977c478bd9Sstevel@tonic-gate * - (optional) compare old and new stat data 24987c478bd9Sstevel@tonic-gate */ 2499*48847494SEnrico Perla - Sun Microsystems ret = walk_list(root, &flist); 25007c478bd9Sstevel@tonic-gate 25017c478bd9Sstevel@tonic-gate /* done with the file list */ 25027c478bd9Sstevel@tonic-gate filelist_free(flistp); 25037c478bd9Sstevel@tonic-gate 2504*48847494SEnrico Perla - Sun Microsystems /* something went wrong */ 2505*48847494SEnrico Perla - Sun Microsystems 2506*48847494SEnrico Perla - Sun Microsystems if (ret == BAM_ERROR) { 2507*48847494SEnrico Perla - Sun Microsystems bam_error(CACHE_FAIL); 2508*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 25097c478bd9Sstevel@tonic-gate } 25107c478bd9Sstevel@tonic-gate 2511*48847494SEnrico Perla - Sun Microsystems if (walk_arg.new_nvlp == NULL) { 2512*48847494SEnrico Perla - Sun Microsystems (void) fclose(walk_arg.sparcfile); 2513*48847494SEnrico Perla - Sun Microsystems bam_error(NO_NEW_STAT); 2514*48847494SEnrico Perla - Sun Microsystems } 25157c478bd9Sstevel@tonic-gate 2516*48847494SEnrico Perla - Sun Microsystems /* If nothing was updated, discard newstat. */ 2517*48847494SEnrico Perla - Sun Microsystems 2518*48847494SEnrico Perla - Sun Microsystems if (!is_dir_flag_on(FILE32, NEED_UPDATE) && 2519*48847494SEnrico Perla - Sun Microsystems !is_dir_flag_on(FILE64, NEED_UPDATE)) { 25207c478bd9Sstevel@tonic-gate clear_walk_args(); 25217c478bd9Sstevel@tonic-gate return (0); 25227c478bd9Sstevel@tonic-gate } 25237c478bd9Sstevel@tonic-gate 2524*48847494SEnrico Perla - Sun Microsystems (void) fclose(walk_arg.sparcfile); 2525*48847494SEnrico Perla - Sun Microsystems 25267c478bd9Sstevel@tonic-gate return (1); 25277c478bd9Sstevel@tonic-gate } 25287c478bd9Sstevel@tonic-gate 2529*48847494SEnrico Perla - Sun Microsystems /* 2530*48847494SEnrico Perla - Sun Microsystems * Returns 1 if we're dealing with a bfu archive update, 0 otherwise 2531*48847494SEnrico Perla - Sun Microsystems */ 2532*48847494SEnrico Perla - Sun Microsystems static int 2533*48847494SEnrico Perla - Sun Microsystems is_bfu() 2534*48847494SEnrico Perla - Sun Microsystems { 2535*48847494SEnrico Perla - Sun Microsystems char *path; 2536*48847494SEnrico Perla - Sun Microsystems 2537*48847494SEnrico Perla - Sun Microsystems path = getenv("PATH"); 2538*48847494SEnrico Perla - Sun Microsystems if (path != NULL && 2539*48847494SEnrico Perla - Sun Microsystems strncmp(path, "/tmp/bfubin", strlen("/tmp/bfubin")) == 0) { 2540*48847494SEnrico Perla - Sun Microsystems struct stat sb; 2541*48847494SEnrico Perla - Sun Microsystems if (stat("/tmp/bfubin", &sb) == 0) { 2542*48847494SEnrico Perla - Sun Microsystems if (!(sb.st_mode & S_IFDIR)) 2543*48847494SEnrico Perla - Sun Microsystems return (0); 2544*48847494SEnrico Perla - Sun Microsystems if (sb.st_uid != getuid()) 2545*48847494SEnrico Perla - Sun Microsystems return (0); 2546*48847494SEnrico Perla - Sun Microsystems return (1); 2547*48847494SEnrico Perla - Sun Microsystems } 2548*48847494SEnrico Perla - Sun Microsystems } 2549*48847494SEnrico Perla - Sun Microsystems return (0); 2550*48847494SEnrico Perla - Sun Microsystems } 2551*48847494SEnrico Perla - Sun Microsystems 2552*48847494SEnrico Perla - Sun Microsystems #define LOCKFS_PATH (is_bfu() ? LOCKFS_BFU : LOCKFS_BIN) 2553*48847494SEnrico Perla - Sun Microsystems 2554*48847494SEnrico Perla - Sun Microsystems static int 2555*48847494SEnrico Perla - Sun Microsystems flushfs(char *root) 2556*48847494SEnrico Perla - Sun Microsystems { 2557*48847494SEnrico Perla - Sun Microsystems char cmd[PATH_MAX + 30]; 2558*48847494SEnrico Perla - Sun Microsystems 2559*48847494SEnrico Perla - Sun Microsystems (void) snprintf(cmd, sizeof (cmd), "%s -f \"%s\" 2>/dev/null", 2560*48847494SEnrico Perla - Sun Microsystems LOCKFS_PATH, root); 2561*48847494SEnrico Perla - Sun Microsystems 2562*48847494SEnrico Perla - Sun Microsystems return (exec_cmd(cmd, NULL)); 2563*48847494SEnrico Perla - Sun Microsystems } 2564*48847494SEnrico Perla - Sun Microsystems 2565*48847494SEnrico Perla - Sun Microsystems static int 2566*48847494SEnrico Perla - Sun Microsystems do_archive_copy(char *source, char *dest) 2567*48847494SEnrico Perla - Sun Microsystems { 2568*48847494SEnrico Perla - Sun Microsystems 2569*48847494SEnrico Perla - Sun Microsystems (void) sync(); 2570*48847494SEnrico Perla - Sun Microsystems 2571*48847494SEnrico Perla - Sun Microsystems /* the equivalent of mv archive-new-$pid boot_archive */ 2572*48847494SEnrico Perla - Sun Microsystems if (rename(source, dest) != 0) 2573*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2574*48847494SEnrico Perla - Sun Microsystems 2575*48847494SEnrico Perla - Sun Microsystems if (flushfs(bam_root) != 0) 2576*48847494SEnrico Perla - Sun Microsystems (void) sync(); 2577*48847494SEnrico Perla - Sun Microsystems 2578*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 2579*48847494SEnrico Perla - Sun Microsystems } 2580*48847494SEnrico Perla - Sun Microsystems 2581*48847494SEnrico Perla - Sun Microsystems static int 2582*48847494SEnrico Perla - Sun Microsystems check_cmdline(filelist_t flist) 2583*48847494SEnrico Perla - Sun Microsystems { 2584*48847494SEnrico Perla - Sun Microsystems line_t *lp; 2585*48847494SEnrico Perla - Sun Microsystems 2586*48847494SEnrico Perla - Sun Microsystems for (lp = flist.head; lp; lp = lp->next) { 2587*48847494SEnrico Perla - Sun Microsystems if (strstr(lp->line, "Error:") != NULL || 2588*48847494SEnrico Perla - Sun Microsystems strstr(lp->line, "Inode number overflow") != NULL) { 2589*48847494SEnrico Perla - Sun Microsystems (void) fprintf(stderr, "%s", lp->line); 2590*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2591*48847494SEnrico Perla - Sun Microsystems } 2592*48847494SEnrico Perla - Sun Microsystems } 2593*48847494SEnrico Perla - Sun Microsystems 2594*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 2595*48847494SEnrico Perla - Sun Microsystems } 2596*48847494SEnrico Perla - Sun Microsystems 2597*48847494SEnrico Perla - Sun Microsystems static int 2598*48847494SEnrico Perla - Sun Microsystems check_archive(char *dest) 2599*48847494SEnrico Perla - Sun Microsystems { 2600*48847494SEnrico Perla - Sun Microsystems struct stat sb; 2601*48847494SEnrico Perla - Sun Microsystems 2602*48847494SEnrico Perla - Sun Microsystems if (stat(dest, &sb) != 0 || !S_ISREG(sb.st_mode) || 2603*48847494SEnrico Perla - Sun Microsystems sb.st_size < 10000) { 2604*48847494SEnrico Perla - Sun Microsystems bam_error(ARCHIVE_BAD, dest); 2605*48847494SEnrico Perla - Sun Microsystems (void) unlink(dest); 2606*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2607*48847494SEnrico Perla - Sun Microsystems } 2608*48847494SEnrico Perla - Sun Microsystems 2609*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 2610*48847494SEnrico Perla - Sun Microsystems } 2611*48847494SEnrico Perla - Sun Microsystems 2612*48847494SEnrico Perla - Sun Microsystems /* 2613*48847494SEnrico Perla - Sun Microsystems * Returns 1 if mkiso is in the expected PATH, 0 otherwise 2614*48847494SEnrico Perla - Sun Microsystems */ 2615*48847494SEnrico Perla - Sun Microsystems static int 2616*48847494SEnrico Perla - Sun Microsystems is_mkisofs() 2617*48847494SEnrico Perla - Sun Microsystems { 2618*48847494SEnrico Perla - Sun Microsystems if (is_bfu()) { 2619*48847494SEnrico Perla - Sun Microsystems if (access(MKISOFS_BFUBIN, X_OK) == 0) 2620*48847494SEnrico Perla - Sun Microsystems return (1); 2621*48847494SEnrico Perla - Sun Microsystems } else { 2622*48847494SEnrico Perla - Sun Microsystems if (access(MKISOFS_BIN, X_OK) == 0) 2623*48847494SEnrico Perla - Sun Microsystems return (1); 2624*48847494SEnrico Perla - Sun Microsystems } 2625*48847494SEnrico Perla - Sun Microsystems return (0); 2626*48847494SEnrico Perla - Sun Microsystems } 2627*48847494SEnrico Perla - Sun Microsystems 2628*48847494SEnrico Perla - Sun Microsystems #define MKISO_PARAMS " -quiet -graft-points -dlrDJN -relaxed-filenames " 2629*48847494SEnrico Perla - Sun Microsystems #define MKISO_PATH (is_bfu() ? MKISOFS_BFUBIN : MKISOFS_BIN) 2630*48847494SEnrico Perla - Sun Microsystems #define DD_PATH (is_bfu() ? DD_PATH_BFU : DD_PATH_USR) 2631*48847494SEnrico Perla - Sun Microsystems 2632*48847494SEnrico Perla - Sun Microsystems static int 2633*48847494SEnrico Perla - Sun Microsystems create_sparc_archive(char *archive, char *tempname, char *bootblk, char *list) 2634*48847494SEnrico Perla - Sun Microsystems { 2635*48847494SEnrico Perla - Sun Microsystems int ret; 2636*48847494SEnrico Perla - Sun Microsystems char cmdline[3 * PATH_MAX + 64]; 2637*48847494SEnrico Perla - Sun Microsystems filelist_t flist = {0}; 2638*48847494SEnrico Perla - Sun Microsystems const char *func = "create_sparc_archive()"; 2639*48847494SEnrico Perla - Sun Microsystems 2640*48847494SEnrico Perla - Sun Microsystems if (access(bootblk, R_OK) == 1) { 2641*48847494SEnrico Perla - Sun Microsystems bam_error(BOOTBLK_FAIL, bootblk); 2642*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2643*48847494SEnrico Perla - Sun Microsystems } 2644*48847494SEnrico Perla - Sun Microsystems 2645*48847494SEnrico Perla - Sun Microsystems /* 2646*48847494SEnrico Perla - Sun Microsystems * Prepare mkisofs command line and execute it 2647*48847494SEnrico Perla - Sun Microsystems */ 2648*48847494SEnrico Perla - Sun Microsystems (void) snprintf(cmdline, sizeof (cmdline), "%s %s -G %s -o \"%s\" " 2649*48847494SEnrico Perla - Sun Microsystems "-path-list \"%s\" 2>&1", MKISO_PATH, MKISO_PARAMS, bootblk, 2650*48847494SEnrico Perla - Sun Microsystems tempname, list); 2651*48847494SEnrico Perla - Sun Microsystems 2652*48847494SEnrico Perla - Sun Microsystems BAM_DPRINTF((D_CMDLINE, func, cmdline)); 2653*48847494SEnrico Perla - Sun Microsystems 2654*48847494SEnrico Perla - Sun Microsystems ret = exec_cmd(cmdline, &flist); 2655*48847494SEnrico Perla - Sun Microsystems if (ret != 0 || check_cmdline(flist) == BAM_ERROR) 2656*48847494SEnrico Perla - Sun Microsystems goto out_err; 2657*48847494SEnrico Perla - Sun Microsystems 2658*48847494SEnrico Perla - Sun Microsystems filelist_free(&flist); 2659*48847494SEnrico Perla - Sun Microsystems 2660*48847494SEnrico Perla - Sun Microsystems /* 2661*48847494SEnrico Perla - Sun Microsystems * Prepare dd command line to copy the bootblk on the new archive and 2662*48847494SEnrico Perla - Sun Microsystems * execute it 2663*48847494SEnrico Perla - Sun Microsystems */ 2664*48847494SEnrico Perla - Sun Microsystems (void) snprintf(cmdline, sizeof (cmdline), "%s if=\"%s\" of=\"%s\"" 2665*48847494SEnrico Perla - Sun Microsystems " bs=1b oseek=1 count=15 conv=notrunc conv=sync 2>&1", DD_PATH, 2666*48847494SEnrico Perla - Sun Microsystems bootblk, tempname); 2667*48847494SEnrico Perla - Sun Microsystems 2668*48847494SEnrico Perla - Sun Microsystems BAM_DPRINTF((D_CMDLINE, func, cmdline)); 2669*48847494SEnrico Perla - Sun Microsystems 2670*48847494SEnrico Perla - Sun Microsystems ret = exec_cmd(cmdline, &flist); 2671*48847494SEnrico Perla - Sun Microsystems if (ret != 0 || check_cmdline(flist) == BAM_ERROR) 2672*48847494SEnrico Perla - Sun Microsystems goto out_err; 2673*48847494SEnrico Perla - Sun Microsystems 2674*48847494SEnrico Perla - Sun Microsystems filelist_free(&flist); 2675*48847494SEnrico Perla - Sun Microsystems 2676*48847494SEnrico Perla - Sun Microsystems /* Did we get a valid archive ? */ 2677*48847494SEnrico Perla - Sun Microsystems if (check_archive(tempname) == BAM_ERROR) 2678*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2679*48847494SEnrico Perla - Sun Microsystems 2680*48847494SEnrico Perla - Sun Microsystems return (do_archive_copy(tempname, archive)); 2681*48847494SEnrico Perla - Sun Microsystems 2682*48847494SEnrico Perla - Sun Microsystems out_err: 2683*48847494SEnrico Perla - Sun Microsystems filelist_free(&flist); 2684*48847494SEnrico Perla - Sun Microsystems bam_error(ARCHIVE_FAIL, cmdline); 2685*48847494SEnrico Perla - Sun Microsystems (void) unlink(tempname); 2686*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2687*48847494SEnrico Perla - Sun Microsystems } 2688*48847494SEnrico Perla - Sun Microsystems 2689*48847494SEnrico Perla - Sun Microsystems static unsigned int 2690*48847494SEnrico Perla - Sun Microsystems from_733(unsigned char *s) 2691*48847494SEnrico Perla - Sun Microsystems { 2692*48847494SEnrico Perla - Sun Microsystems int i; 2693*48847494SEnrico Perla - Sun Microsystems unsigned int ret = 0; 2694*48847494SEnrico Perla - Sun Microsystems 2695*48847494SEnrico Perla - Sun Microsystems for (i = 0; i < 4; i++) 2696*48847494SEnrico Perla - Sun Microsystems ret |= s[i] << (8 * i); 2697*48847494SEnrico Perla - Sun Microsystems 2698*48847494SEnrico Perla - Sun Microsystems return (ret); 2699*48847494SEnrico Perla - Sun Microsystems } 2700*48847494SEnrico Perla - Sun Microsystems 2701*48847494SEnrico Perla - Sun Microsystems static void 2702*48847494SEnrico Perla - Sun Microsystems to_733(unsigned char *s, unsigned int val) 2703*48847494SEnrico Perla - Sun Microsystems { 2704*48847494SEnrico Perla - Sun Microsystems int i; 2705*48847494SEnrico Perla - Sun Microsystems 2706*48847494SEnrico Perla - Sun Microsystems for (i = 0; i < 4; i++) 2707*48847494SEnrico Perla - Sun Microsystems s[i] = s[7-i] = (val >> (8 * i)) & 0xFF; 2708*48847494SEnrico Perla - Sun Microsystems } 2709*48847494SEnrico Perla - Sun Microsystems 2710*48847494SEnrico Perla - Sun Microsystems /* 2711*48847494SEnrico Perla - Sun Microsystems * Extends the current boot archive without recreating it from scratch 2712*48847494SEnrico Perla - Sun Microsystems */ 2713*48847494SEnrico Perla - Sun Microsystems static int 2714*48847494SEnrico Perla - Sun Microsystems extend_iso_archive(char *archive, char *tempname, char *update_dir) 2715*48847494SEnrico Perla - Sun Microsystems { 2716*48847494SEnrico Perla - Sun Microsystems int fd = -1, newfd = -1, ret, i; 2717*48847494SEnrico Perla - Sun Microsystems int next_session = 0, new_size = 0; 2718*48847494SEnrico Perla - Sun Microsystems char cmdline[3 * PATH_MAX + 64]; 2719*48847494SEnrico Perla - Sun Microsystems const char *func = "extend_iso_archive()"; 2720*48847494SEnrico Perla - Sun Microsystems filelist_t flist = {0}; 2721*48847494SEnrico Perla - Sun Microsystems struct iso_pdesc saved_desc[MAX_IVDs]; 2722*48847494SEnrico Perla - Sun Microsystems 2723*48847494SEnrico Perla - Sun Microsystems fd = open(archive, O_RDWR); 2724*48847494SEnrico Perla - Sun Microsystems if (fd == -1) { 2725*48847494SEnrico Perla - Sun Microsystems bam_error(OPEN_FAIL, archive, strerror(errno)); 2726*48847494SEnrico Perla - Sun Microsystems goto out_err; 2727*48847494SEnrico Perla - Sun Microsystems } 2728*48847494SEnrico Perla - Sun Microsystems 2729*48847494SEnrico Perla - Sun Microsystems /* 2730*48847494SEnrico Perla - Sun Microsystems * A partial read is likely due to a corrupted file 2731*48847494SEnrico Perla - Sun Microsystems */ 2732*48847494SEnrico Perla - Sun Microsystems ret = pread64(fd, saved_desc, sizeof (saved_desc), 2733*48847494SEnrico Perla - Sun Microsystems VOLDESC_OFF * CD_BLOCK); 2734*48847494SEnrico Perla - Sun Microsystems if (ret != sizeof (saved_desc)) { 2735*48847494SEnrico Perla - Sun Microsystems bam_error(READ_FAIL, archive, strerror(errno)); 2736*48847494SEnrico Perla - Sun Microsystems goto out_err; 2737*48847494SEnrico Perla - Sun Microsystems } 2738*48847494SEnrico Perla - Sun Microsystems 2739*48847494SEnrico Perla - Sun Microsystems if (memcmp(saved_desc[0].type, "\1CD001", 6)) { 2740*48847494SEnrico Perla - Sun Microsystems bam_error(SIGN_FAIL, archive); 2741*48847494SEnrico Perla - Sun Microsystems goto out_err; 2742*48847494SEnrico Perla - Sun Microsystems } 2743*48847494SEnrico Perla - Sun Microsystems 2744*48847494SEnrico Perla - Sun Microsystems /* 2745*48847494SEnrico Perla - Sun Microsystems * Read primary descriptor and locate next_session offset (it should 2746*48847494SEnrico Perla - Sun Microsystems * point to the end of the archive) 2747*48847494SEnrico Perla - Sun Microsystems */ 2748*48847494SEnrico Perla - Sun Microsystems next_session = P2ROUNDUP(from_733(saved_desc[0].volume_space_size), 16); 2749*48847494SEnrico Perla - Sun Microsystems 2750*48847494SEnrico Perla - Sun Microsystems (void) snprintf(cmdline, sizeof (cmdline), "%s -C 16,%d -M %s %s -o \"" 2751*48847494SEnrico Perla - Sun Microsystems "%s\" \"%s\" 2>&1", MKISO_PATH, next_session, archive, MKISO_PARAMS, 2752*48847494SEnrico Perla - Sun Microsystems tempname, update_dir); 2753*48847494SEnrico Perla - Sun Microsystems 2754*48847494SEnrico Perla - Sun Microsystems BAM_DPRINTF((D_CMDLINE, func, cmdline)); 2755*48847494SEnrico Perla - Sun Microsystems 2756*48847494SEnrico Perla - Sun Microsystems ret = exec_cmd(cmdline, &flist); 2757*48847494SEnrico Perla - Sun Microsystems if (ret != 0 || check_cmdline(flist) == BAM_ERROR) { 2758*48847494SEnrico Perla - Sun Microsystems bam_error(MULTI_FAIL, cmdline); 2759*48847494SEnrico Perla - Sun Microsystems goto out_flist_err; 2760*48847494SEnrico Perla - Sun Microsystems } 2761*48847494SEnrico Perla - Sun Microsystems filelist_free(&flist); 2762*48847494SEnrico Perla - Sun Microsystems 2763*48847494SEnrico Perla - Sun Microsystems newfd = open(tempname, O_RDONLY); 2764*48847494SEnrico Perla - Sun Microsystems if (newfd == -1) { 2765*48847494SEnrico Perla - Sun Microsystems bam_error(OPEN_FAIL, archive, strerror(errno)); 2766*48847494SEnrico Perla - Sun Microsystems goto out_err; 2767*48847494SEnrico Perla - Sun Microsystems } 2768*48847494SEnrico Perla - Sun Microsystems 2769*48847494SEnrico Perla - Sun Microsystems ret = pread64(newfd, saved_desc, sizeof (saved_desc), 2770*48847494SEnrico Perla - Sun Microsystems VOLDESC_OFF * CD_BLOCK); 2771*48847494SEnrico Perla - Sun Microsystems if (ret != sizeof (saved_desc)) { 2772*48847494SEnrico Perla - Sun Microsystems bam_error(READ_FAIL, archive, strerror(errno)); 2773*48847494SEnrico Perla - Sun Microsystems goto out_err; 2774*48847494SEnrico Perla - Sun Microsystems } 2775*48847494SEnrico Perla - Sun Microsystems 2776*48847494SEnrico Perla - Sun Microsystems if (memcmp(saved_desc[0].type, "\1CD001", 6)) { 2777*48847494SEnrico Perla - Sun Microsystems bam_error(SIGN_FAIL, archive); 2778*48847494SEnrico Perla - Sun Microsystems goto out_err; 2779*48847494SEnrico Perla - Sun Microsystems } 2780*48847494SEnrico Perla - Sun Microsystems 2781*48847494SEnrico Perla - Sun Microsystems new_size = from_733(saved_desc[0].volume_space_size) + next_session; 2782*48847494SEnrico Perla - Sun Microsystems to_733(saved_desc[0].volume_space_size, new_size); 2783*48847494SEnrico Perla - Sun Microsystems 2784*48847494SEnrico Perla - Sun Microsystems for (i = 1; i < MAX_IVDs; i++) { 2785*48847494SEnrico Perla - Sun Microsystems if (saved_desc[i].type[0] == (unsigned char)255) 2786*48847494SEnrico Perla - Sun Microsystems break; 2787*48847494SEnrico Perla - Sun Microsystems if (memcmp(saved_desc[i].id, "CD001", 5)) 2788*48847494SEnrico Perla - Sun Microsystems break; 2789*48847494SEnrico Perla - Sun Microsystems 2790*48847494SEnrico Perla - Sun Microsystems if (bam_verbose) 2791*48847494SEnrico Perla - Sun Microsystems bam_print("%s: Updating descriptor entry [%d]\n", func, 2792*48847494SEnrico Perla - Sun Microsystems i); 2793*48847494SEnrico Perla - Sun Microsystems 2794*48847494SEnrico Perla - Sun Microsystems to_733(saved_desc[i].volume_space_size, new_size); 2795*48847494SEnrico Perla - Sun Microsystems } 2796*48847494SEnrico Perla - Sun Microsystems 2797*48847494SEnrico Perla - Sun Microsystems ret = pwrite64(fd, saved_desc, DVD_BLOCK, VOLDESC_OFF*CD_BLOCK); 2798*48847494SEnrico Perla - Sun Microsystems if (ret != DVD_BLOCK) { 2799*48847494SEnrico Perla - Sun Microsystems bam_error(WRITE_FAIL, archive, strerror(errno)); 2800*48847494SEnrico Perla - Sun Microsystems goto out_err; 2801*48847494SEnrico Perla - Sun Microsystems } 2802*48847494SEnrico Perla - Sun Microsystems (void) close(newfd); 2803*48847494SEnrico Perla - Sun Microsystems newfd = -1; 2804*48847494SEnrico Perla - Sun Microsystems 2805*48847494SEnrico Perla - Sun Microsystems ret = close(fd); 2806*48847494SEnrico Perla - Sun Microsystems if (ret != 0) { 2807*48847494SEnrico Perla - Sun Microsystems bam_error(CLOSE_FAIL, archive, strerror(errno)); 2808*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2809*48847494SEnrico Perla - Sun Microsystems } 2810*48847494SEnrico Perla - Sun Microsystems fd = -1; 2811*48847494SEnrico Perla - Sun Microsystems 2812*48847494SEnrico Perla - Sun Microsystems (void) snprintf(cmdline, sizeof (cmdline), "%s if=%s of=%s bs=32k " 2813*48847494SEnrico Perla - Sun Microsystems "seek=%d conv=sync 2>&1", DD_PATH, tempname, archive, 2814*48847494SEnrico Perla - Sun Microsystems (next_session/16)); 2815*48847494SEnrico Perla - Sun Microsystems 2816*48847494SEnrico Perla - Sun Microsystems BAM_DPRINTF((D_CMDLINE, func, cmdline)); 2817*48847494SEnrico Perla - Sun Microsystems 2818*48847494SEnrico Perla - Sun Microsystems ret = exec_cmd(cmdline, &flist); 2819*48847494SEnrico Perla - Sun Microsystems if (ret != 0 || check_cmdline(flist) == BAM_ERROR) { 2820*48847494SEnrico Perla - Sun Microsystems bam_error(MULTI_FAIL, cmdline); 2821*48847494SEnrico Perla - Sun Microsystems goto out_flist_err; 2822*48847494SEnrico Perla - Sun Microsystems } 2823*48847494SEnrico Perla - Sun Microsystems filelist_free(&flist); 2824*48847494SEnrico Perla - Sun Microsystems 2825*48847494SEnrico Perla - Sun Microsystems (void) unlink(tempname); 2826*48847494SEnrico Perla - Sun Microsystems 2827*48847494SEnrico Perla - Sun Microsystems if (bam_verbose) 2828*48847494SEnrico Perla - Sun Microsystems bam_print("boot archive updated successfully\n"); 2829*48847494SEnrico Perla - Sun Microsystems 2830*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 2831*48847494SEnrico Perla - Sun Microsystems 2832*48847494SEnrico Perla - Sun Microsystems out_flist_err: 2833*48847494SEnrico Perla - Sun Microsystems filelist_free(&flist); 2834*48847494SEnrico Perla - Sun Microsystems out_err: 2835*48847494SEnrico Perla - Sun Microsystems if (fd != -1) 2836*48847494SEnrico Perla - Sun Microsystems (void) close(fd); 2837*48847494SEnrico Perla - Sun Microsystems if (newfd != -1) 2838*48847494SEnrico Perla - Sun Microsystems (void) close(newfd); 2839*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2840*48847494SEnrico Perla - Sun Microsystems } 2841*48847494SEnrico Perla - Sun Microsystems 2842*48847494SEnrico Perla - Sun Microsystems static int 2843*48847494SEnrico Perla - Sun Microsystems create_x86_archive(char *archive, char *tempname, char *update_dir) 2844*48847494SEnrico Perla - Sun Microsystems { 2845*48847494SEnrico Perla - Sun Microsystems int ret; 2846*48847494SEnrico Perla - Sun Microsystems char cmdline[3 * PATH_MAX + 64]; 2847*48847494SEnrico Perla - Sun Microsystems filelist_t flist = {0}; 2848*48847494SEnrico Perla - Sun Microsystems const char *func = "create_x86_archive()"; 2849*48847494SEnrico Perla - Sun Microsystems 2850*48847494SEnrico Perla - Sun Microsystems (void) snprintf(cmdline, sizeof (cmdline), "%s %s -o \"%s\" \"%s\" " 2851*48847494SEnrico Perla - Sun Microsystems "2>&1", MKISO_PATH, MKISO_PARAMS, tempname, update_dir); 2852*48847494SEnrico Perla - Sun Microsystems 2853*48847494SEnrico Perla - Sun Microsystems BAM_DPRINTF((D_CMDLINE, func, cmdline)); 2854*48847494SEnrico Perla - Sun Microsystems 2855*48847494SEnrico Perla - Sun Microsystems ret = exec_cmd(cmdline, &flist); 2856*48847494SEnrico Perla - Sun Microsystems if (ret != 0 || check_cmdline(flist) == BAM_ERROR) { 2857*48847494SEnrico Perla - Sun Microsystems bam_error(ARCHIVE_FAIL, cmdline); 2858*48847494SEnrico Perla - Sun Microsystems filelist_free(&flist); 2859*48847494SEnrico Perla - Sun Microsystems (void) unlink(tempname); 2860*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2861*48847494SEnrico Perla - Sun Microsystems } 2862*48847494SEnrico Perla - Sun Microsystems 2863*48847494SEnrico Perla - Sun Microsystems filelist_free(&flist); 2864*48847494SEnrico Perla - Sun Microsystems 2865*48847494SEnrico Perla - Sun Microsystems if (check_archive(tempname) == BAM_ERROR) 2866*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2867*48847494SEnrico Perla - Sun Microsystems 2868*48847494SEnrico Perla - Sun Microsystems return (do_archive_copy(tempname, archive)); 2869*48847494SEnrico Perla - Sun Microsystems } 2870*48847494SEnrico Perla - Sun Microsystems 2871*48847494SEnrico Perla - Sun Microsystems static int 2872*48847494SEnrico Perla - Sun Microsystems mkisofs_archive(char *root, int what) 2873*48847494SEnrico Perla - Sun Microsystems { 2874*48847494SEnrico Perla - Sun Microsystems int ret; 2875*48847494SEnrico Perla - Sun Microsystems char temp[PATH_MAX]; 2876*48847494SEnrico Perla - Sun Microsystems char bootblk[PATH_MAX]; 2877*48847494SEnrico Perla - Sun Microsystems char boot_archive[PATH_MAX]; 2878*48847494SEnrico Perla - Sun Microsystems 2879*48847494SEnrico Perla - Sun Microsystems if (what == FILE64 && !is_flag_on(IS_SPARC_TARGET)) 2880*48847494SEnrico Perla - Sun Microsystems ret = snprintf(temp, sizeof (temp), 2881*48847494SEnrico Perla - Sun Microsystems "%s%s%s/amd64/archive-new-%d", root, ARCHIVE_PREFIX, 2882*48847494SEnrico Perla - Sun Microsystems get_machine(), getpid()); 2883*48847494SEnrico Perla - Sun Microsystems else 2884*48847494SEnrico Perla - Sun Microsystems ret = snprintf(temp, sizeof (temp), "%s%s%s/archive-new-%d", 2885*48847494SEnrico Perla - Sun Microsystems root, ARCHIVE_PREFIX, get_machine(), getpid()); 2886*48847494SEnrico Perla - Sun Microsystems 2887*48847494SEnrico Perla - Sun Microsystems if (ret >= sizeof (temp)) 2888*48847494SEnrico Perla - Sun Microsystems goto out_path_err; 2889*48847494SEnrico Perla - Sun Microsystems 2890*48847494SEnrico Perla - Sun Microsystems if (what == FILE64 && !is_flag_on(IS_SPARC_TARGET)) 2891*48847494SEnrico Perla - Sun Microsystems ret = snprintf(boot_archive, sizeof (boot_archive), 2892*48847494SEnrico Perla - Sun Microsystems "%s%s%s/amd64%s", root, ARCHIVE_PREFIX, get_machine(), 2893*48847494SEnrico Perla - Sun Microsystems ARCHIVE_SUFFIX); 2894*48847494SEnrico Perla - Sun Microsystems else 2895*48847494SEnrico Perla - Sun Microsystems ret = snprintf(boot_archive, sizeof (boot_archive), 2896*48847494SEnrico Perla - Sun Microsystems "%s%s%s%s", root, ARCHIVE_PREFIX, get_machine(), 2897*48847494SEnrico Perla - Sun Microsystems ARCHIVE_SUFFIX); 2898*48847494SEnrico Perla - Sun Microsystems 2899*48847494SEnrico Perla - Sun Microsystems if (ret >= sizeof (boot_archive)) 2900*48847494SEnrico Perla - Sun Microsystems goto out_path_err; 2901*48847494SEnrico Perla - Sun Microsystems 2902*48847494SEnrico Perla - Sun Microsystems bam_print("updating %s\n", boot_archive); 2903*48847494SEnrico Perla - Sun Microsystems 2904*48847494SEnrico Perla - Sun Microsystems if (is_flag_on(IS_SPARC_TARGET)) { 2905*48847494SEnrico Perla - Sun Microsystems ret = snprintf(bootblk, sizeof (bootblk), 2906*48847494SEnrico Perla - Sun Microsystems "%s/platform/%s/lib/fs/hsfs/bootblk", root, get_machine()); 2907*48847494SEnrico Perla - Sun Microsystems if (ret >= sizeof (bootblk)) 2908*48847494SEnrico Perla - Sun Microsystems goto out_path_err; 2909*48847494SEnrico Perla - Sun Microsystems 2910*48847494SEnrico Perla - Sun Microsystems ret = create_sparc_archive(boot_archive, temp, bootblk, 2911*48847494SEnrico Perla - Sun Microsystems get_cachedir(what)); 2912*48847494SEnrico Perla - Sun Microsystems } else { 2913*48847494SEnrico Perla - Sun Microsystems if (!is_dir_flag_on(what, NO_MULTI)) { 2914*48847494SEnrico Perla - Sun Microsystems if (bam_verbose) 2915*48847494SEnrico Perla - Sun Microsystems bam_print("Attempting to extend x86 archive: " 2916*48847494SEnrico Perla - Sun Microsystems "%s\n", boot_archive); 2917*48847494SEnrico Perla - Sun Microsystems 2918*48847494SEnrico Perla - Sun Microsystems ret = extend_iso_archive(boot_archive, temp, 2919*48847494SEnrico Perla - Sun Microsystems get_updatedir(what)); 2920*48847494SEnrico Perla - Sun Microsystems if (ret == BAM_SUCCESS) { 2921*48847494SEnrico Perla - Sun Microsystems if (bam_verbose) 2922*48847494SEnrico Perla - Sun Microsystems bam_print("Successfully extended %s\n", 2923*48847494SEnrico Perla - Sun Microsystems boot_archive); 2924*48847494SEnrico Perla - Sun Microsystems 2925*48847494SEnrico Perla - Sun Microsystems (void) rmdir_r(get_updatedir(what)); 2926*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 2927*48847494SEnrico Perla - Sun Microsystems } 2928*48847494SEnrico Perla - Sun Microsystems } 2929*48847494SEnrico Perla - Sun Microsystems /* 2930*48847494SEnrico Perla - Sun Microsystems * The boot archive will be recreated from scratch. We get here 2931*48847494SEnrico Perla - Sun Microsystems * if at least one of these conditions is true: 2932*48847494SEnrico Perla - Sun Microsystems * - bootadm was called without the -e switch 2933*48847494SEnrico Perla - Sun Microsystems * - the archive (or the archive cache) doesn't exist 2934*48847494SEnrico Perla - Sun Microsystems * - archive size is bigger than BA_SIZE_MAX 2935*48847494SEnrico Perla - Sun Microsystems * - more than COUNT_MAX files need to be updated 2936*48847494SEnrico Perla - Sun Microsystems * - an error occourred either populating the /updates directory 2937*48847494SEnrico Perla - Sun Microsystems * or extend_iso_archive() failed 2938*48847494SEnrico Perla - Sun Microsystems */ 2939*48847494SEnrico Perla - Sun Microsystems if (bam_verbose) 2940*48847494SEnrico Perla - Sun Microsystems bam_print("Unable to extend %s... rebuilding archive\n", 2941*48847494SEnrico Perla - Sun Microsystems boot_archive); 2942*48847494SEnrico Perla - Sun Microsystems 2943*48847494SEnrico Perla - Sun Microsystems if (get_updatedir(what)[0] != '\0') 2944*48847494SEnrico Perla - Sun Microsystems (void) rmdir_r(get_updatedir(what)); 2945*48847494SEnrico Perla - Sun Microsystems 2946*48847494SEnrico Perla - Sun Microsystems 2947*48847494SEnrico Perla - Sun Microsystems ret = create_x86_archive(boot_archive, temp, 2948*48847494SEnrico Perla - Sun Microsystems get_cachedir(what)); 2949*48847494SEnrico Perla - Sun Microsystems } 2950*48847494SEnrico Perla - Sun Microsystems 2951*48847494SEnrico Perla - Sun Microsystems if (ret == BAM_SUCCESS && bam_verbose) 2952*48847494SEnrico Perla - Sun Microsystems bam_print("Successfully created %s\n", boot_archive); 2953*48847494SEnrico Perla - Sun Microsystems 2954*48847494SEnrico Perla - Sun Microsystems return (ret); 2955*48847494SEnrico Perla - Sun Microsystems 2956*48847494SEnrico Perla - Sun Microsystems out_path_err: 2957*48847494SEnrico Perla - Sun Microsystems bam_error(PATH_TOO_LONG, root); 2958*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2959*48847494SEnrico Perla - Sun Microsystems } 2960*48847494SEnrico Perla - Sun Microsystems 29617c478bd9Sstevel@tonic-gate static error_t 29627c478bd9Sstevel@tonic-gate create_ramdisk(char *root) 29637c478bd9Sstevel@tonic-gate { 29647c478bd9Sstevel@tonic-gate char *cmdline, path[PATH_MAX]; 29657c478bd9Sstevel@tonic-gate size_t len; 29667c478bd9Sstevel@tonic-gate struct stat sb; 2967*48847494SEnrico Perla - Sun Microsystems int ret, what; 2968*48847494SEnrico Perla - Sun Microsystems 2969*48847494SEnrico Perla - Sun Microsystems /* If there is mkisofs, use it to create the required archives */ 2970*48847494SEnrico Perla - Sun Microsystems if (is_mkisofs()) { 2971*48847494SEnrico Perla - Sun Microsystems for (what = FILE32; what < CACHEDIR_NUM; what++) { 2972*48847494SEnrico Perla - Sun Microsystems if (is_dir_flag_on(what, NEED_UPDATE)) { 2973*48847494SEnrico Perla - Sun Microsystems ret = mkisofs_archive(root, what); 2974*48847494SEnrico Perla - Sun Microsystems if (ret != 0) 2975*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 2976*48847494SEnrico Perla - Sun Microsystems } 2977*48847494SEnrico Perla - Sun Microsystems } 2978*48847494SEnrico Perla - Sun Microsystems return (BAM_SUCCESS); 2979*48847494SEnrico Perla - Sun Microsystems } 29807c478bd9Sstevel@tonic-gate 29817c478bd9Sstevel@tonic-gate /* 2982*48847494SEnrico Perla - Sun Microsystems * Else setup command args for create_ramdisk.ksh for the UFS archives 29837c478bd9Sstevel@tonic-gate */ 2984*48847494SEnrico Perla - Sun Microsystems if (bam_verbose) 2985*48847494SEnrico Perla - Sun Microsystems bam_print("mkisofs not found, creating UFS archive\n"); 2986*48847494SEnrico Perla - Sun Microsystems 2987986fd29aSsetje (void) snprintf(path, sizeof (path), "%s/%s", root, CREATE_RAMDISK); 29887c478bd9Sstevel@tonic-gate if (stat(path, &sb) != 0) { 29897c478bd9Sstevel@tonic-gate bam_error(ARCH_EXEC_MISS, path, strerror(errno)); 29907c478bd9Sstevel@tonic-gate return (BAM_ERROR); 29917c478bd9Sstevel@tonic-gate } 29927c478bd9Sstevel@tonic-gate 29937c478bd9Sstevel@tonic-gate len = strlen(path) + strlen(root) + 10; /* room for space + -R */ 2994d876c67dSjg if (bam_alt_platform) 2995d876c67dSjg len += strlen(bam_platform) + strlen("-p "); 29967c478bd9Sstevel@tonic-gate cmdline = s_calloc(1, len); 29977c478bd9Sstevel@tonic-gate 2998d876c67dSjg if (bam_alt_platform) { 2999d876c67dSjg assert(strlen(root) > 1); 3000d876c67dSjg (void) snprintf(cmdline, len, "%s -p %s -R %s", 3001d876c67dSjg path, bam_platform, root); 3002d876c67dSjg /* chop off / at the end */ 3003d876c67dSjg cmdline[strlen(cmdline) - 1] = '\0'; 3004d876c67dSjg } else if (strlen(root) > 1) { 30057c478bd9Sstevel@tonic-gate (void) snprintf(cmdline, len, "%s -R %s", path, root); 30067c478bd9Sstevel@tonic-gate /* chop off / at the end */ 30077c478bd9Sstevel@tonic-gate cmdline[strlen(cmdline) - 1] = '\0'; 30087c478bd9Sstevel@tonic-gate } else 30097c478bd9Sstevel@tonic-gate (void) snprintf(cmdline, len, "%s", path); 30107c478bd9Sstevel@tonic-gate 3011986fd29aSsetje if (exec_cmd(cmdline, NULL) != 0) { 30127c478bd9Sstevel@tonic-gate bam_error(ARCHIVE_FAIL, cmdline); 30137c478bd9Sstevel@tonic-gate free(cmdline); 30147c478bd9Sstevel@tonic-gate return (BAM_ERROR); 30157c478bd9Sstevel@tonic-gate } 30167c478bd9Sstevel@tonic-gate free(cmdline); 30177c478bd9Sstevel@tonic-gate /* 3018986fd29aSsetje * The existence of the expected archives used to be 3019986fd29aSsetje * verified here. This check is done in create_ramdisk as 3020986fd29aSsetje * it needs to be in sync with the altroot operated upon. 30217c478bd9Sstevel@tonic-gate */ 30227c478bd9Sstevel@tonic-gate return (BAM_SUCCESS); 30237c478bd9Sstevel@tonic-gate } 30247c478bd9Sstevel@tonic-gate 30257c478bd9Sstevel@tonic-gate /* 30267c478bd9Sstevel@tonic-gate * Checks if target filesystem is on a ramdisk 30277c478bd9Sstevel@tonic-gate * 1 - is miniroot 30287c478bd9Sstevel@tonic-gate * 0 - is not 30297c478bd9Sstevel@tonic-gate * When in doubt assume it is not a ramdisk. 30307c478bd9Sstevel@tonic-gate */ 30317c478bd9Sstevel@tonic-gate static int 30327c478bd9Sstevel@tonic-gate is_ramdisk(char *root) 30337c478bd9Sstevel@tonic-gate { 30347c478bd9Sstevel@tonic-gate struct extmnttab mnt; 30357c478bd9Sstevel@tonic-gate FILE *fp; 30367c478bd9Sstevel@tonic-gate int found; 3037b610f78eSvikram char mntpt[PATH_MAX]; 3038b610f78eSvikram char *cp; 30397c478bd9Sstevel@tonic-gate 30407c478bd9Sstevel@tonic-gate /* 30417c478bd9Sstevel@tonic-gate * There are 3 situations where creating archive is 30427c478bd9Sstevel@tonic-gate * of dubious value: 3043b610f78eSvikram * - create boot_archive on a lofi-mounted boot_archive 30447c478bd9Sstevel@tonic-gate * - create it on a ramdisk which is the root filesystem 30457c478bd9Sstevel@tonic-gate * - create it on a ramdisk mounted somewhere else 30467c478bd9Sstevel@tonic-gate * The first is not easy to detect and checking for it is not 30477c478bd9Sstevel@tonic-gate * worth it. 30487c478bd9Sstevel@tonic-gate * The other two conditions are handled here 30497c478bd9Sstevel@tonic-gate */ 30507c478bd9Sstevel@tonic-gate fp = fopen(MNTTAB, "r"); 30517c478bd9Sstevel@tonic-gate if (fp == NULL) { 30527c478bd9Sstevel@tonic-gate bam_error(OPEN_FAIL, MNTTAB, strerror(errno)); 30537c478bd9Sstevel@tonic-gate return (0); 30547c478bd9Sstevel@tonic-gate } 30557c478bd9Sstevel@tonic-gate 30567c478bd9Sstevel@tonic-gate resetmnttab(fp); 30577c478bd9Sstevel@tonic-gate 3058b610f78eSvikram /* 3059b610f78eSvikram * Remove any trailing / from the mount point 3060b610f78eSvikram */ 3061b610f78eSvikram (void) strlcpy(mntpt, root, sizeof (mntpt)); 3062b610f78eSvikram if (strcmp(root, "/") != 0) { 3063b610f78eSvikram cp = mntpt + strlen(mntpt) - 1; 3064b610f78eSvikram if (*cp == '/') 3065b610f78eSvikram *cp = '\0'; 3066b610f78eSvikram } 30677c478bd9Sstevel@tonic-gate found = 0; 30687c478bd9Sstevel@tonic-gate while (getextmntent(fp, &mnt, sizeof (mnt)) == 0) { 3069b610f78eSvikram if (strcmp(mnt.mnt_mountp, mntpt) == 0) { 30707c478bd9Sstevel@tonic-gate found = 1; 30717c478bd9Sstevel@tonic-gate break; 30727c478bd9Sstevel@tonic-gate } 30737c478bd9Sstevel@tonic-gate } 30747c478bd9Sstevel@tonic-gate 30757c478bd9Sstevel@tonic-gate if (!found) { 30767c478bd9Sstevel@tonic-gate if (bam_verbose) 3077b610f78eSvikram bam_error(NOT_IN_MNTTAB, mntpt); 30787c478bd9Sstevel@tonic-gate (void) fclose(fp); 30797c478bd9Sstevel@tonic-gate return (0); 30807c478bd9Sstevel@tonic-gate } 30817c478bd9Sstevel@tonic-gate 30827c478bd9Sstevel@tonic-gate if (strstr(mnt.mnt_special, RAMDISK_SPECIAL) != NULL) { 30837c478bd9Sstevel@tonic-gate if (bam_verbose) 30847c478bd9Sstevel@tonic-gate bam_error(IS_RAMDISK, bam_root); 30857c478bd9Sstevel@tonic-gate (void) fclose(fp); 30867c478bd9Sstevel@tonic-gate return (1); 30877c478bd9Sstevel@tonic-gate } 30887c478bd9Sstevel@tonic-gate 30897c478bd9Sstevel@tonic-gate (void) fclose(fp); 30907c478bd9Sstevel@tonic-gate 30917c478bd9Sstevel@tonic-gate return (0); 30927c478bd9Sstevel@tonic-gate } 30937c478bd9Sstevel@tonic-gate 30947c478bd9Sstevel@tonic-gate static int 3095986fd29aSsetje is_boot_archive(char *root) 30967c478bd9Sstevel@tonic-gate { 30977c478bd9Sstevel@tonic-gate char path[PATH_MAX]; 30987c478bd9Sstevel@tonic-gate struct stat sb; 3099eb2bd662Svikram int error; 3100eb2bd662Svikram const char *fcn = "is_boot_archive()"; 31017c478bd9Sstevel@tonic-gate 31027c478bd9Sstevel@tonic-gate /* 3103986fd29aSsetje * We can't create an archive without the create_ramdisk script 31047c478bd9Sstevel@tonic-gate */ 3105986fd29aSsetje (void) snprintf(path, sizeof (path), "%s/%s", root, CREATE_RAMDISK); 3106eb2bd662Svikram error = stat(path, &sb); 3107eb2bd662Svikram INJECT_ERROR1("NOT_ARCHIVE_BASED", error = -1); 3108eb2bd662Svikram if (error == -1) { 31097c478bd9Sstevel@tonic-gate if (bam_verbose) 31107c478bd9Sstevel@tonic-gate bam_print(FILE_MISS, path); 3111eb2bd662Svikram BAM_DPRINTF((D_NOT_ARCHIVE_BOOT, fcn, root)); 31127c478bd9Sstevel@tonic-gate return (0); 31137c478bd9Sstevel@tonic-gate } 31147c478bd9Sstevel@tonic-gate 3115eb2bd662Svikram BAM_DPRINTF((D_IS_ARCHIVE_BOOT, fcn, root)); 3116986fd29aSsetje return (1); 3117986fd29aSsetje } 3118986fd29aSsetje 31197c478bd9Sstevel@tonic-gate /* 3120986fd29aSsetje * Need to call this for anything that operates on the GRUB menu 3121963390b4Svikram * In the x86 live upgrade case the directory /boot/grub may be present 3122963390b4Svikram * even on pre-newboot BEs. The authoritative way to check for a GRUB target 3123963390b4Svikram * is to check for the presence of the stage2 binary which is present 3124963390b4Svikram * only on GRUB targets (even on x86 boot partitions). Checking for the 3125963390b4Svikram * presence of the multiboot binary is not correct as it is not present 3126963390b4Svikram * on x86 boot partitions. 3127986fd29aSsetje */ 3128986fd29aSsetje int 3129986fd29aSsetje is_grub(const char *root) 3130986fd29aSsetje { 3131986fd29aSsetje char path[PATH_MAX]; 3132986fd29aSsetje struct stat sb; 3133eb2bd662Svikram const char *fcn = "is_grub()"; 3134986fd29aSsetje 3135963390b4Svikram (void) snprintf(path, sizeof (path), "%s%s", root, GRUB_STAGE2); 31367c478bd9Sstevel@tonic-gate if (stat(path, &sb) == -1) { 3137eb2bd662Svikram BAM_DPRINTF((D_NO_GRUB_DIR, fcn, path)); 31387c478bd9Sstevel@tonic-gate return (0); 31397c478bd9Sstevel@tonic-gate } 31407c478bd9Sstevel@tonic-gate 31417c478bd9Sstevel@tonic-gate return (1); 31427c478bd9Sstevel@tonic-gate } 31437c478bd9Sstevel@tonic-gate 31447c478bd9Sstevel@tonic-gate static int 3145eb2bd662Svikram is_zfs(char *root) 3146eb2bd662Svikram { 3147eb2bd662Svikram struct statvfs vfs; 3148eb2bd662Svikram int ret; 3149eb2bd662Svikram const char *fcn = "is_zfs()"; 3150eb2bd662Svikram 3151eb2bd662Svikram ret = statvfs(root, &vfs); 3152eb2bd662Svikram INJECT_ERROR1("STATVFS_ZFS", ret = 1); 3153eb2bd662Svikram if (ret != 0) { 3154eb2bd662Svikram bam_error(STATVFS_FAIL, root, strerror(errno)); 3155eb2bd662Svikram return (0); 3156eb2bd662Svikram } 3157eb2bd662Svikram 3158eb2bd662Svikram if (strncmp(vfs.f_basetype, "zfs", strlen("zfs")) == 0) { 3159eb2bd662Svikram BAM_DPRINTF((D_IS_ZFS, fcn, root)); 3160eb2bd662Svikram return (1); 3161eb2bd662Svikram } else { 3162eb2bd662Svikram BAM_DPRINTF((D_IS_NOT_ZFS, fcn, root)); 3163eb2bd662Svikram return (0); 3164eb2bd662Svikram } 3165eb2bd662Svikram } 3166eb2bd662Svikram 3167eb2bd662Svikram static int 3168eb2bd662Svikram is_ufs(char *root) 3169eb2bd662Svikram { 3170eb2bd662Svikram struct statvfs vfs; 3171eb2bd662Svikram int ret; 3172eb2bd662Svikram const char *fcn = "is_ufs()"; 3173eb2bd662Svikram 3174eb2bd662Svikram ret = statvfs(root, &vfs); 3175eb2bd662Svikram INJECT_ERROR1("STATVFS_UFS", ret = 1); 3176eb2bd662Svikram if (ret != 0) { 3177eb2bd662Svikram bam_error(STATVFS_FAIL, root, strerror(errno)); 3178eb2bd662Svikram return (0); 3179eb2bd662Svikram } 3180eb2bd662Svikram 3181eb2bd662Svikram if (strncmp(vfs.f_basetype, "ufs", strlen("ufs")) == 0) { 3182eb2bd662Svikram BAM_DPRINTF((D_IS_UFS, fcn, root)); 3183eb2bd662Svikram return (1); 3184eb2bd662Svikram } else { 3185eb2bd662Svikram BAM_DPRINTF((D_IS_NOT_UFS, fcn, root)); 3186eb2bd662Svikram return (0); 3187eb2bd662Svikram } 3188eb2bd662Svikram } 3189eb2bd662Svikram 3190eb2bd662Svikram static int 3191eb2bd662Svikram is_pcfs(char *root) 3192eb2bd662Svikram { 3193eb2bd662Svikram struct statvfs vfs; 3194eb2bd662Svikram int ret; 3195eb2bd662Svikram const char *fcn = "is_pcfs()"; 3196eb2bd662Svikram 3197eb2bd662Svikram ret = statvfs(root, &vfs); 3198eb2bd662Svikram INJECT_ERROR1("STATVFS_PCFS", ret = 1); 3199eb2bd662Svikram if (ret != 0) { 3200eb2bd662Svikram bam_error(STATVFS_FAIL, root, strerror(errno)); 3201eb2bd662Svikram return (0); 3202eb2bd662Svikram } 3203eb2bd662Svikram 3204eb2bd662Svikram if (strncmp(vfs.f_basetype, "pcfs", strlen("pcfs")) == 0) { 3205eb2bd662Svikram BAM_DPRINTF((D_IS_PCFS, fcn, root)); 3206eb2bd662Svikram return (1); 3207eb2bd662Svikram } else { 3208eb2bd662Svikram BAM_DPRINTF((D_IS_NOT_PCFS, fcn, root)); 3209eb2bd662Svikram return (0); 3210eb2bd662Svikram } 3211eb2bd662Svikram } 3212eb2bd662Svikram 3213eb2bd662Svikram static int 32147c478bd9Sstevel@tonic-gate is_readonly(char *root) 32157c478bd9Sstevel@tonic-gate { 3216eb2bd662Svikram int fd; 3217eb2bd662Svikram int error; 3218eb2bd662Svikram char testfile[PATH_MAX]; 3219eb2bd662Svikram const char *fcn = "is_readonly()"; 32207c478bd9Sstevel@tonic-gate 32217c478bd9Sstevel@tonic-gate /* 3222eb2bd662Svikram * Using statvfs() to check for a read-only filesystem is not 3223eb2bd662Svikram * reliable. The only way to reliably test is to attempt to 3224eb2bd662Svikram * create a file 32257c478bd9Sstevel@tonic-gate */ 3226eb2bd662Svikram (void) snprintf(testfile, sizeof (testfile), "%s/%s.%d", 3227eb2bd662Svikram root, BOOTADM_RDONLY_TEST, getpid()); 32287c478bd9Sstevel@tonic-gate 3229eb2bd662Svikram (void) unlink(testfile); 3230eb2bd662Svikram 3231eb2bd662Svikram errno = 0; 3232eb2bd662Svikram fd = open(testfile, O_RDWR|O_CREAT|O_EXCL, 0644); 3233eb2bd662Svikram error = errno; 3234eb2bd662Svikram INJECT_ERROR2("RDONLY_TEST_ERROR", fd = -1, error = EACCES); 3235eb2bd662Svikram if (fd == -1 && error == EROFS) { 3236eb2bd662Svikram BAM_DPRINTF((D_RDONLY_FS, fcn, root)); 32377c478bd9Sstevel@tonic-gate return (1); 3238eb2bd662Svikram } else if (fd == -1) { 3239eb2bd662Svikram bam_error(RDONLY_TEST_ERROR, root, strerror(error)); 32407c478bd9Sstevel@tonic-gate } 32417c478bd9Sstevel@tonic-gate 3242eb2bd662Svikram (void) close(fd); 3243eb2bd662Svikram (void) unlink(testfile); 32447c478bd9Sstevel@tonic-gate 3245eb2bd662Svikram BAM_DPRINTF((D_RDWR_FS, fcn, root)); 3246e7cbe64fSgw25295 return (0); 3247e7cbe64fSgw25295 } 3248e7cbe64fSgw25295 32497c478bd9Sstevel@tonic-gate static error_t 32507c478bd9Sstevel@tonic-gate update_archive(char *root, char *opt) 32517c478bd9Sstevel@tonic-gate { 32527c478bd9Sstevel@tonic-gate error_t ret; 32537c478bd9Sstevel@tonic-gate 32547c478bd9Sstevel@tonic-gate assert(root); 32557c478bd9Sstevel@tonic-gate assert(opt == NULL); 32567c478bd9Sstevel@tonic-gate 3257*48847494SEnrico Perla - Sun Microsystems init_walk_args(); 3258*48847494SEnrico Perla - Sun Microsystems (void) umask(022); 3259*48847494SEnrico Perla - Sun Microsystems 32607c478bd9Sstevel@tonic-gate /* 3261986fd29aSsetje * root must belong to a boot archive based OS, 32627c478bd9Sstevel@tonic-gate */ 3263986fd29aSsetje if (!is_boot_archive(root)) { 3264b610f78eSvikram /* 3265b610f78eSvikram * Emit message only if not in context of update_all. 3266b610f78eSvikram * If in update_all, emit only if verbose flag is set. 3267b610f78eSvikram */ 3268b610f78eSvikram if (!bam_update_all || bam_verbose) 3269eb2bd662Svikram bam_print(NOT_ARCHIVE_BOOT, root); 3270*48847494SEnrico Perla - Sun Microsystems return (BAM_ERROR); 32717c478bd9Sstevel@tonic-gate } 32727c478bd9Sstevel@tonic-gate 32737c478bd9Sstevel@tonic-gate /* 32748c1b6884Sszhou * If smf check is requested when / is writable (can happen 32758c1b6884Sszhou * on first reboot following an upgrade because service 32768c1b6884Sszhou * dependency is messed up), skip the check. 32778c1b6884Sszhou */ 3278*48847494SEnrico Perla - Sun Microsystems if (bam_smf_check && !bam_root_readonly && !is_zfs(root)) 32798c1b6884Sszhou return (BAM_SUCCESS); 32808c1b6884Sszhou 32818c1b6884Sszhou /* 32828c1b6884Sszhou * root must be writable. This check applies to alternate 32838c1b6884Sszhou * root (-R option); bam_root_readonly applies to '/' only. 3284*48847494SEnrico Perla - Sun Microsystems * The behaviour translates into being the one of a 'check'. 32857c478bd9Sstevel@tonic-gate */ 328661cb17bdSsetje if (!bam_smf_check && !bam_check && is_readonly(root)) { 3287*48847494SEnrico Perla - Sun Microsystems set_flag(RDONLY_FSCHK); 3288*48847494SEnrico Perla - Sun Microsystems bam_check = 1; 32897c478bd9Sstevel@tonic-gate } 32907c478bd9Sstevel@tonic-gate 32917c478bd9Sstevel@tonic-gate /* 3292*48847494SEnrico Perla - Sun Microsystems * Don't generate archive on ramdisk, but still check if the 3293*48847494SEnrico Perla - Sun Microsystems * archive is up-to-date 32947c478bd9Sstevel@tonic-gate */ 32957c478bd9Sstevel@tonic-gate if (is_ramdisk(root)) { 3296*48847494SEnrico Perla - Sun Microsystems set_flag(RAMDSK_FSCHK); 3297*48847494SEnrico Perla - Sun Microsystems bam_check = 1; 32987c478bd9Sstevel@tonic-gate } 32997c478bd9Sstevel@tonic-gate 33007c478bd9Sstevel@tonic-gate /* 33017c478bd9Sstevel@tonic-gate * Now check if updated is really needed 33027c478bd9Sstevel@tonic-gate */ 33037c478bd9Sstevel@tonic-gate ret = update_required(root); 33047c478bd9Sstevel@tonic-gate 33057c478bd9Sstevel@tonic-gate /* 33067c478bd9Sstevel@tonic-gate * The check command (-n) is *not* a dry run 33077c478bd9Sstevel@tonic-gate * It only checks if the archive is in sync. 3308*48847494SEnrico Perla - Sun Microsystems * A readonly filesystem or being on a ramdisk have to be considered 3309*48847494SEnrico Perla - Sun Microsystems * errors only if an update is required. 33107c478bd9Sstevel@tonic-gate */ 33117c478bd9Sstevel@tonic-gate if (bam_check) { 3312*48847494SEnrico Perla - Sun Microsystems if (is_flag_on(RDONLY_FSCHK)) { 3313*48847494SEnrico Perla - Sun Microsystems if (ret > 0) 3314*48847494SEnrico Perla - Sun Microsystems bam_error(RDONLY_FS, root); 3315*48847494SEnrico Perla - Sun Microsystems if (bam_update_all) 3316*48847494SEnrico Perla - Sun Microsystems return ((ret != 0) ? BAM_ERROR : BAM_SUCCESS); 3317*48847494SEnrico Perla - Sun Microsystems } 3318*48847494SEnrico Perla - Sun Microsystems 3319*48847494SEnrico Perla - Sun Microsystems if (is_flag_on(RAMDSK_FSCHK)) { 3320*48847494SEnrico Perla - Sun Microsystems if (ret > 0) 3321*48847494SEnrico Perla - Sun Microsystems bam_error(SKIP_RAMDISK, root); 3322*48847494SEnrico Perla - Sun Microsystems if (bam_update_all) 3323*48847494SEnrico Perla - Sun Microsystems return ((ret != 0) ? BAM_ERROR : BAM_SUCCESS); 3324*48847494SEnrico Perla - Sun Microsystems } 3325*48847494SEnrico Perla - Sun Microsystems 33267c478bd9Sstevel@tonic-gate bam_exit((ret != 0) ? 1 : 0); 33277c478bd9Sstevel@tonic-gate } 33287c478bd9Sstevel@tonic-gate 33297c478bd9Sstevel@tonic-gate if (ret == 1) { 33307c478bd9Sstevel@tonic-gate /* create the ramdisk */ 33317c478bd9Sstevel@tonic-gate ret = create_ramdisk(root); 33327c478bd9Sstevel@tonic-gate } 3333986fd29aSsetje 3334986fd29aSsetje /* if the archive is updated, save the new stat data */ 3335986fd29aSsetje if (ret == 0 && walk_arg.new_nvlp != NULL) { 3336986fd29aSsetje savenew(root); 3337986fd29aSsetje } 3338986fd29aSsetje 3339986fd29aSsetje clear_walk_args(); 3340986fd29aSsetje 33417c478bd9Sstevel@tonic-gate return (ret); 33427c478bd9Sstevel@tonic-gate } 33437c478bd9Sstevel@tonic-gate 3344963390b4Svikram static error_t 3345963390b4Svikram synchronize_BE_menu(void) 3346fbac2b2bSvikram { 3347fbac2b2bSvikram struct stat sb; 3348963390b4Svikram char cmdline[PATH_MAX]; 3349963390b4Svikram char cksum_line[PATH_MAX]; 3350963390b4Svikram filelist_t flist = {0}; 3351963390b4Svikram char *old_cksum_str; 3352963390b4Svikram char *old_size_str; 3353963390b4Svikram char *old_file; 3354963390b4Svikram char *curr_cksum_str; 3355963390b4Svikram char *curr_size_str; 3356963390b4Svikram char *curr_file; 3357963390b4Svikram FILE *cfp; 3358963390b4Svikram int found; 3359963390b4Svikram int ret; 3360963390b4Svikram const char *fcn = "synchronize_BE_menu()"; 3361fbac2b2bSvikram 3362963390b4Svikram BAM_DPRINTF((D_FUNC_ENTRY0, fcn)); 3363fbac2b2bSvikram 3364963390b4Svikram /* Check if findroot enabled LU BE */ 3365963390b4Svikram if (stat(FINDROOT_INSTALLGRUB, &sb) != 0) { 3366963390b4Svikram BAM_DPRINTF((D_NOT_LU_BE, fcn)); 3367963390b4Svikram return (BAM_SUCCESS); 3368fbac2b2bSvikram } 3369fbac2b2bSvikram 3370963390b4Svikram if (stat(LU_MENU_CKSUM, &sb) != 0) { 3371963390b4Svikram BAM_DPRINTF((D_NO_CKSUM_FILE, fcn, LU_MENU_CKSUM)); 3372963390b4Svikram goto menu_sync; 3373fbac2b2bSvikram } 3374963390b4Svikram 3375963390b4Svikram cfp = fopen(LU_MENU_CKSUM, "r"); 3376963390b4Svikram INJECT_ERROR1("CKSUM_FILE_MISSING", cfp = NULL); 3377963390b4Svikram if (cfp == NULL) { 3378963390b4Svikram bam_error(CANNOT_READ_LU_CKSUM, LU_MENU_CKSUM); 3379963390b4Svikram goto menu_sync; 3380963390b4Svikram } 3381963390b4Svikram BAM_DPRINTF((D_CKSUM_FILE_OPENED, fcn, LU_MENU_CKSUM)); 3382963390b4Svikram 3383963390b4Svikram found = 0; 3384963390b4Svikram while (s_fgets(cksum_line, sizeof (cksum_line), cfp) != NULL) { 3385963390b4Svikram INJECT_ERROR1("MULTIPLE_CKSUM", found = 1); 3386963390b4Svikram if (found) { 3387963390b4Svikram bam_error(MULTIPLE_LU_CKSUM, LU_MENU_CKSUM); 3388963390b4Svikram (void) fclose(cfp); 3389963390b4Svikram goto menu_sync; 3390963390b4Svikram } 3391963390b4Svikram found = 1; 3392963390b4Svikram } 3393963390b4Svikram BAM_DPRINTF((D_CKSUM_FILE_READ, fcn, LU_MENU_CKSUM)); 3394963390b4Svikram 3395963390b4Svikram 3396963390b4Svikram old_cksum_str = strtok(cksum_line, " \t"); 3397963390b4Svikram old_size_str = strtok(NULL, " \t"); 3398963390b4Svikram old_file = strtok(NULL, " \t"); 3399963390b4Svikram 3400963390b4Svikram INJECT_ERROR1("OLD_CKSUM_NULL", old_cksum_str = NULL); 3401963390b4Svikram INJECT_ERROR1("OLD_SIZE_NULL", old_size_str = NULL); 3402963390b4Svikram INJECT_ERROR1("OLD_FILE_NULL", old_file = NULL); 3403963390b4Svikram if (old_cksum_str == NULL || old_size_str == NULL || old_file == NULL) { 3404963390b4Svikram bam_error(CANNOT_PARSE_LU_CKSUM, LU_MENU_CKSUM); 3405963390b4Svikram goto menu_sync; 3406963390b4Svikram } 3407963390b4Svikram BAM_DPRINTF((D_CKSUM_FILE_PARSED, fcn, LU_MENU_CKSUM)); 3408963390b4Svikram 3409963390b4Svikram /* Get checksum of current menu */ 3410963390b4Svikram (void) snprintf(cmdline, sizeof (cmdline), "%s %s", 3411963390b4Svikram CKSUM, GRUB_MENU); 3412963390b4Svikram ret = exec_cmd(cmdline, &flist); 3413963390b4Svikram INJECT_ERROR1("GET_CURR_CKSUM", ret = 1); 3414963390b4Svikram if (ret != 0) { 3415963390b4Svikram bam_error(MENU_CKSUM_FAIL); 3416963390b4Svikram return (BAM_ERROR); 3417963390b4Svikram } 3418963390b4Svikram BAM_DPRINTF((D_CKSUM_GEN_SUCCESS, fcn)); 3419963390b4Svikram 3420963390b4Svikram INJECT_ERROR1("GET_CURR_CKSUM_OUTPUT", flist.head = NULL); 3421963390b4Svikram if ((flist.head == NULL) || (flist.head != flist.tail)) { 3422963390b4Svikram bam_error(BAD_CKSUM); 3423963390b4Svikram filelist_free(&flist); 3424963390b4Svikram return (BAM_ERROR); 3425963390b4Svikram } 3426963390b4Svikram BAM_DPRINTF((D_CKSUM_GEN_OUTPUT_VALID, fcn)); 3427963390b4Svikram 3428963390b4Svikram curr_cksum_str = strtok(flist.head->line, " \t"); 3429963390b4Svikram curr_size_str = strtok(NULL, " \t"); 3430963390b4Svikram curr_file = strtok(NULL, " \t"); 3431963390b4Svikram 3432963390b4Svikram INJECT_ERROR1("CURR_CKSUM_NULL", curr_cksum_str = NULL); 3433963390b4Svikram INJECT_ERROR1("CURR_SIZE_NULL", curr_size_str = NULL); 3434963390b4Svikram INJECT_ERROR1("CURR_FILE_NULL", curr_file = NULL); 3435963390b4Svikram if (curr_cksum_str == NULL || curr_size_str == NULL || 3436963390b4Svikram curr_file == NULL) { 3437963390b4Svikram bam_error(BAD_CKSUM_PARSE); 3438963390b4Svikram filelist_free(&flist); 3439963390b4Svikram return (BAM_ERROR); 3440963390b4Svikram } 3441963390b4Svikram BAM_DPRINTF((D_CKSUM_GEN_PARSED, fcn)); 3442963390b4Svikram 3443963390b4Svikram if (strcmp(old_cksum_str, curr_cksum_str) == 0 && 3444963390b4Svikram strcmp(old_size_str, curr_size_str) == 0 && 3445963390b4Svikram strcmp(old_file, curr_file) == 0) { 3446963390b4Svikram filelist_free(&flist); 3447963390b4Svikram BAM_DPRINTF((D_CKSUM_NO_CHANGE, fcn)); 3448963390b4Svikram return (BAM_SUCCESS); 3449963390b4Svikram } 3450963390b4Svikram 3451963390b4Svikram filelist_free(&flist); 3452963390b4Svikram 3453963390b4Svikram /* cksum doesn't match - the menu has changed */ 3454963390b4Svikram BAM_DPRINTF((D_CKSUM_HAS_CHANGED, fcn)); 3455963390b4Svikram 3456963390b4Svikram menu_sync: 3457963390b4Svikram bam_print(PROP_GRUB_MENU); 3458963390b4Svikram 3459963390b4Svikram (void) snprintf(cmdline, sizeof (cmdline), 3460a6968364Svikram "/bin/sh -c '. %s > /dev/null; %s %s yes > /dev/null'", 3461963390b4Svikram LULIB, LULIB_PROPAGATE_FILE, GRUB_MENU); 3462963390b4Svikram ret = exec_cmd(cmdline, NULL); 3463963390b4Svikram INJECT_ERROR1("PROPAGATE_MENU", ret = 1); 3464963390b4Svikram if (ret != 0) { 3465963390b4Svikram bam_error(MENU_PROP_FAIL); 3466963390b4Svikram return (BAM_ERROR); 3467963390b4Svikram } 3468963390b4Svikram BAM_DPRINTF((D_PROPAGATED_MENU, fcn)); 3469963390b4Svikram 3470a6968364Svikram (void) snprintf(cmdline, sizeof (cmdline), "/bin/cp %s %s > /dev/null", 3471963390b4Svikram GRUB_MENU, GRUB_BACKUP_MENU); 3472963390b4Svikram ret = exec_cmd(cmdline, NULL); 3473963390b4Svikram INJECT_ERROR1("CREATE_BACKUP", ret = 1); 3474963390b4Svikram if (ret != 0) { 3475963390b4Svikram bam_error(MENU_BACKUP_FAIL, GRUB_BACKUP_MENU); 3476963390b4Svikram return (BAM_ERROR); 3477963390b4Svikram } 3478963390b4Svikram BAM_DPRINTF((D_CREATED_BACKUP, fcn, GRUB_BACKUP_MENU)); 3479963390b4Svikram 3480963390b4Svikram (void) snprintf(cmdline, sizeof (cmdline), 3481a6968364Svikram "/bin/sh -c '. %s > /dev/null; %s %s no > /dev/null'", 3482963390b4Svikram LULIB, LULIB_PROPAGATE_FILE, GRUB_BACKUP_MENU); 3483963390b4Svikram ret = exec_cmd(cmdline, NULL); 3484963390b4Svikram INJECT_ERROR1("PROPAGATE_BACKUP", ret = 1); 3485963390b4Svikram if (ret != 0) { 3486963390b4Svikram bam_error(BACKUP_PROP_FAIL, GRUB_BACKUP_MENU); 3487963390b4Svikram return (BAM_ERROR); 3488963390b4Svikram } 3489963390b4Svikram BAM_DPRINTF((D_PROPAGATED_BACKUP, fcn, GRUB_BACKUP_MENU)); 3490963390b4Svikram 3491963390b4Svikram (void) snprintf(cmdline, sizeof (cmdline), "%s %s > %s", 3492963390b4Svikram CKSUM, GRUB_MENU, LU_MENU_CKSUM); 3493963390b4Svikram ret = exec_cmd(cmdline, NULL); 3494963390b4Svikram INJECT_ERROR1("CREATE_CKSUM_FILE", ret = 1); 3495963390b4Svikram if (ret != 0) { 3496963390b4Svikram bam_error(MENU_CKSUM_WRITE_FAIL, LU_MENU_CKSUM); 3497963390b4Svikram return (BAM_ERROR); 3498963390b4Svikram } 3499963390b4Svikram BAM_DPRINTF((D_CREATED_CKSUM_FILE, fcn, LU_MENU_CKSUM)); 3500963390b4Svikram 3501963390b4Svikram (void) snprintf(cmdline, sizeof (cmdline), 3502a6968364Svikram "/bin/sh -c '. %s > /dev/null; %s %s no > /dev/null'", 3503963390b4Svikram LULIB, LULIB_PROPAGATE_FILE, LU_MENU_CKSUM); 3504963390b4Svikram ret = exec_cmd(cmdline, NULL); 3505963390b4Svikram INJECT_ERROR1("PROPAGATE_MENU_CKSUM_FILE", ret = 1); 3506963390b4Svikram if (ret != 0) { 3507963390b4Svikram bam_error(MENU_CKSUM_PROP_FAIL, LU_MENU_CKSUM); 3508963390b4Svikram return (BAM_ERROR); 3509963390b4Svikram } 3510963390b4Svikram BAM_DPRINTF((D_PROPAGATED_CKSUM_FILE, fcn, LU_MENU_CKSUM)); 3511963390b4Svikram 3512963390b4Svikram (void) snprintf(cmdline, sizeof (cmdline), 3513a6968364Svikram "/bin/sh -c '. %s > /dev/null; %s %s no > /dev/null'", 3514963390b4Svikram LULIB, LULIB_PROPAGATE_FILE, BOOTADM); 3515963390b4Svikram ret = exec_cmd(cmdline, NULL); 3516963390b4Svikram INJECT_ERROR1("PROPAGATE_BOOTADM_FILE", ret = 1); 3517963390b4Svikram if (ret != 0) { 3518963390b4Svikram bam_error(BOOTADM_PROP_FAIL, BOOTADM); 3519963390b4Svikram return (BAM_ERROR); 3520963390b4Svikram } 3521963390b4Svikram BAM_DPRINTF((D_PROPAGATED_BOOTADM, fcn, BOOTADM)); 3522963390b4Svikram 3523963390b4Svikram return (BAM_SUCCESS); 3524fbac2b2bSvikram } 3525fbac2b2bSvikram 35267c478bd9Sstevel@tonic-gate static error_t 35277c478bd9Sstevel@tonic-gate update_all(char *root, char *opt) 35287c478bd9Sstevel@tonic-gate { 35297c478bd9Sstevel@tonic-gate struct extmnttab mnt; 35307c478bd9Sstevel@tonic-gate struct stat sb; 35317c478bd9Sstevel@tonic-gate FILE *fp; 35327c478bd9Sstevel@tonic-gate char multibt[PATH_MAX]; 3533986fd29aSsetje char creatram[PATH_MAX]; 35347c478bd9Sstevel@tonic-gate error_t ret = BAM_SUCCESS; 35357c478bd9Sstevel@tonic-gate 353640541d5dSvikram assert(root); 35377c478bd9Sstevel@tonic-gate assert(opt == NULL); 35387c478bd9Sstevel@tonic-gate 353940541d5dSvikram if (bam_rootlen != 1 || *root != '/') { 354040541d5dSvikram elide_trailing_slash(root, multibt, sizeof (multibt)); 354140541d5dSvikram bam_error(ALT_ROOT_INVALID, multibt); 354240541d5dSvikram return (BAM_ERROR); 354340541d5dSvikram } 354440541d5dSvikram 35457c478bd9Sstevel@tonic-gate /* 354698892a30Snadkarni * Check to see if we are in the midst of safemode patching 354798892a30Snadkarni * If so skip building the archive for /. Instead build it 354898892a30Snadkarni * against the latest bits obtained by creating a fresh lofs 354998892a30Snadkarni * mount of root. 355098892a30Snadkarni */ 355198892a30Snadkarni if (stat(LOFS_PATCH_FILE, &sb) == 0) { 3552*48847494SEnrico Perla - Sun Microsystems if (mkdir(LOFS_PATCH_MNT, DIR_PERMS) == -1 && 355398892a30Snadkarni errno != EEXIST) { 355498892a30Snadkarni bam_error(MKDIR_FAILED, "%s", LOFS_PATCH_MNT, 355598892a30Snadkarni strerror(errno)); 355698892a30Snadkarni ret = BAM_ERROR; 355798892a30Snadkarni goto out; 355898892a30Snadkarni } 355998892a30Snadkarni (void) snprintf(multibt, sizeof (multibt), 356098892a30Snadkarni "/sbin/mount -F lofs -o nosub / %s", LOFS_PATCH_MNT); 3561986fd29aSsetje if (exec_cmd(multibt, NULL) != 0) { 356298892a30Snadkarni bam_error(MOUNT_FAILED, LOFS_PATCH_MNT, "lofs"); 356398892a30Snadkarni ret = BAM_ERROR; 356498892a30Snadkarni } 356598892a30Snadkarni if (ret != BAM_ERROR) { 356698892a30Snadkarni (void) snprintf(rootbuf, sizeof (rootbuf), "%s/", 356798892a30Snadkarni LOFS_PATCH_MNT); 356898892a30Snadkarni bam_rootlen = strlen(rootbuf); 356998892a30Snadkarni if (update_archive(rootbuf, opt) != BAM_SUCCESS) 357098892a30Snadkarni ret = BAM_ERROR; 357195b1e0e9Snadkarni /* 357295b1e0e9Snadkarni * unmount the lofs mount since there could be 357395b1e0e9Snadkarni * multiple invocations of bootadm -a update_all 357495b1e0e9Snadkarni */ 357595b1e0e9Snadkarni (void) snprintf(multibt, sizeof (multibt), 357695b1e0e9Snadkarni "/sbin/umount %s", LOFS_PATCH_MNT); 3577986fd29aSsetje if (exec_cmd(multibt, NULL) != 0) { 357895b1e0e9Snadkarni bam_error(UMOUNT_FAILED, LOFS_PATCH_MNT); 357995b1e0e9Snadkarni ret = BAM_ERROR; 358095b1e0e9Snadkarni } 358198892a30Snadkarni } 358298892a30Snadkarni } else { 358398892a30Snadkarni /* 35847c478bd9Sstevel@tonic-gate * First update archive for current root 35857c478bd9Sstevel@tonic-gate */ 35867c478bd9Sstevel@tonic-gate if (update_archive(root, opt) != BAM_SUCCESS) 35877c478bd9Sstevel@tonic-gate ret = BAM_ERROR; 358898892a30Snadkarni } 358998892a30Snadkarni 359098892a30Snadkarni if (ret == BAM_ERROR) 359198892a30Snadkarni goto out; 35927c478bd9Sstevel@tonic-gate 35937c478bd9Sstevel@tonic-gate /* 35947c478bd9Sstevel@tonic-gate * Now walk the mount table, performing archive update 35957c478bd9Sstevel@tonic-gate * for all mounted Newboot root filesystems 35967c478bd9Sstevel@tonic-gate */ 35977c478bd9Sstevel@tonic-gate fp = fopen(MNTTAB, "r"); 35987c478bd9Sstevel@tonic-gate if (fp == NULL) { 35997c478bd9Sstevel@tonic-gate bam_error(OPEN_FAIL, MNTTAB, strerror(errno)); 3600b610f78eSvikram ret = BAM_ERROR; 3601b610f78eSvikram goto out; 36027c478bd9Sstevel@tonic-gate } 36037c478bd9Sstevel@tonic-gate 36047c478bd9Sstevel@tonic-gate resetmnttab(fp); 36057c478bd9Sstevel@tonic-gate 36067c478bd9Sstevel@tonic-gate while (getextmntent(fp, &mnt, sizeof (mnt)) == 0) { 36077c478bd9Sstevel@tonic-gate if (mnt.mnt_special == NULL) 36087c478bd9Sstevel@tonic-gate continue; 3609f904d32dSJerry Gilliam if ((strcmp(mnt.mnt_fstype, MNTTYPE_ZFS) != 0) && 3610f904d32dSJerry Gilliam (strncmp(mnt.mnt_special, "/dev/", strlen("/dev/")) != 0)) 36117c478bd9Sstevel@tonic-gate continue; 36127c478bd9Sstevel@tonic-gate if (strcmp(mnt.mnt_mountp, "/") == 0) 36137c478bd9Sstevel@tonic-gate continue; 36147c478bd9Sstevel@tonic-gate 3615986fd29aSsetje (void) snprintf(creatram, sizeof (creatram), "%s/%s", 3616986fd29aSsetje mnt.mnt_mountp, CREATE_RAMDISK); 36177c478bd9Sstevel@tonic-gate 3618986fd29aSsetje if (stat(creatram, &sb) == -1) 36197c478bd9Sstevel@tonic-gate continue; 36207c478bd9Sstevel@tonic-gate 36217c478bd9Sstevel@tonic-gate /* 36227c478bd9Sstevel@tonic-gate * We put a trailing slash to be consistent with root = "/" 36237c478bd9Sstevel@tonic-gate * case, such that we don't have to print // in some cases. 36247c478bd9Sstevel@tonic-gate */ 36257c478bd9Sstevel@tonic-gate (void) snprintf(rootbuf, sizeof (rootbuf), "%s/", 36267c478bd9Sstevel@tonic-gate mnt.mnt_mountp); 36277c478bd9Sstevel@tonic-gate bam_rootlen = strlen(rootbuf); 3628ae115bc7Smrj 3629ae115bc7Smrj /* 3630ae115bc7Smrj * It's possible that other mounts may be an alternate boot 3631ae115bc7Smrj * architecture, so check it again. 3632ae115bc7Smrj */ 3633eb2bd662Svikram if ((get_boot_cap(rootbuf) != BAM_SUCCESS) || 3634ae115bc7Smrj (update_archive(rootbuf, opt) != BAM_SUCCESS)) 36357c478bd9Sstevel@tonic-gate ret = BAM_ERROR; 36367c478bd9Sstevel@tonic-gate } 36377c478bd9Sstevel@tonic-gate 36387c478bd9Sstevel@tonic-gate (void) fclose(fp); 36397c478bd9Sstevel@tonic-gate 3640b610f78eSvikram out: 3641fbac2b2bSvikram /* 3642963390b4Svikram * We no longer use biosdev for Live Upgrade. Hence 3643963390b4Svikram * there is no need to defer (to shutdown time) any fdisk 3644963390b4Svikram * updates 3645fbac2b2bSvikram */ 3646963390b4Svikram if (stat(GRUB_fdisk, &sb) == 0 || stat(GRUB_fdisk_target, &sb) == 0) { 3647963390b4Svikram bam_error(FDISK_FILES_FOUND, GRUB_fdisk, GRUB_fdisk_target); 3648fbac2b2bSvikram } 3649fbac2b2bSvikram 3650963390b4Svikram /* 3651963390b4Svikram * If user has updated menu in current BE, propagate the 3652963390b4Svikram * updates to all BEs. 3653963390b4Svikram */ 365419397407SSherry Moore if (sync_menu && synchronize_BE_menu() != BAM_SUCCESS) 3655963390b4Svikram ret = BAM_ERROR; 3656963390b4Svikram 36577c478bd9Sstevel@tonic-gate return (ret); 36587c478bd9Sstevel@tonic-gate } 36597c478bd9Sstevel@tonic-gate 36607c478bd9Sstevel@tonic-gate static void 36617c478bd9Sstevel@tonic-gate append_line(menu_t *mp, line_t *lp) 36627c478bd9Sstevel@tonic-gate { 36637c478bd9Sstevel@tonic-gate if (mp->start == NULL) { 36647c478bd9Sstevel@tonic-gate mp->start = lp; 36657c478bd9Sstevel@tonic-gate } else { 36667c478bd9Sstevel@tonic-gate mp->end->next = lp; 36678c1b6884Sszhou lp->prev = mp->end; 36687c478bd9Sstevel@tonic-gate } 36697c478bd9Sstevel@tonic-gate mp->end = lp; 36707c478bd9Sstevel@tonic-gate } 36717c478bd9Sstevel@tonic-gate 3672eb2bd662Svikram void 36738c1b6884Sszhou unlink_line(menu_t *mp, line_t *lp) 36748c1b6884Sszhou { 36758c1b6884Sszhou /* unlink from list */ 36768c1b6884Sszhou if (lp->prev) 36778c1b6884Sszhou lp->prev->next = lp->next; 36788c1b6884Sszhou else 36798c1b6884Sszhou mp->start = lp->next; 36808c1b6884Sszhou if (lp->next) 36818c1b6884Sszhou lp->next->prev = lp->prev; 36828c1b6884Sszhou else 36838c1b6884Sszhou mp->end = lp->prev; 36848c1b6884Sszhou } 36858c1b6884Sszhou 36868c1b6884Sszhou static entry_t * 36878c1b6884Sszhou boot_entry_new(menu_t *mp, line_t *start, line_t *end) 36888c1b6884Sszhou { 36898c1b6884Sszhou entry_t *ent, *prev; 3690eb2bd662Svikram const char *fcn = "boot_entry_new()"; 3691eb2bd662Svikram 3692eb2bd662Svikram assert(mp); 3693eb2bd662Svikram assert(start); 3694eb2bd662Svikram assert(end); 36958c1b6884Sszhou 36968c1b6884Sszhou ent = s_calloc(1, sizeof (entry_t)); 3697eb2bd662Svikram BAM_DPRINTF((D_ENTRY_NEW, fcn)); 36988c1b6884Sszhou ent->start = start; 36998c1b6884Sszhou ent->end = end; 37008c1b6884Sszhou 37018c1b6884Sszhou if (mp->entries == NULL) { 37028c1b6884Sszhou mp->entries = ent; 3703eb2bd662Svikram BAM_DPRINTF((D_ENTRY_NEW_FIRST, fcn)); 37048c1b6884Sszhou return (ent); 37058c1b6884Sszhou } 37068c1b6884Sszhou 37078c1b6884Sszhou prev = mp->entries; 37088c1b6884Sszhou while (prev->next) 37098c1b6884Sszhou prev = prev->next; 37108c1b6884Sszhou prev->next = ent; 37118c1b6884Sszhou ent->prev = prev; 3712eb2bd662Svikram BAM_DPRINTF((D_ENTRY_NEW_LINKED, fcn)); 37138c1b6884Sszhou return (ent); 37148c1b6884Sszhou } 37158c1b6884Sszhou 37168c1b6884Sszhou static void 37178c1b6884Sszhou boot_entry_addline(entry_t *ent, line_t *lp) 37188c1b6884Sszhou { 37198c1b6884Sszhou if (ent) 37208c1b6884Sszhou ent->end = lp; 37218c1b6884Sszhou } 37228c1b6884Sszhou 37237c478bd9Sstevel@tonic-gate /* 3724843e1988Sjohnlev * Check whether cmd matches the one indexed by which, and whether arg matches 3725843e1988Sjohnlev * str. which must be either KERNEL_CMD or MODULE_CMD, and a match to the 3726843e1988Sjohnlev * respective *_DOLLAR_CMD is also acceptable. The arg is searched using 3727843e1988Sjohnlev * strstr(), so it can be a partial match. 3728843e1988Sjohnlev */ 3729843e1988Sjohnlev static int 3730843e1988Sjohnlev check_cmd(const char *cmd, const int which, const char *arg, const char *str) 3731843e1988Sjohnlev { 3732eb2bd662Svikram int ret; 3733eb2bd662Svikram const char *fcn = "check_cmd()"; 3734eb2bd662Svikram 3735eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY2, fcn, arg, str)); 3736eb2bd662Svikram 3737843e1988Sjohnlev if ((strcmp(cmd, menu_cmds[which]) != 0) && 3738843e1988Sjohnlev (strcmp(cmd, menu_cmds[which + 1]) != 0)) { 3739eb2bd662Svikram BAM_DPRINTF((D_CHECK_CMD_CMD_NOMATCH, 3740eb2bd662Svikram fcn, cmd, menu_cmds[which])); 3741843e1988Sjohnlev return (0); 3742843e1988Sjohnlev } 3743eb2bd662Svikram ret = (strstr(arg, str) != NULL); 3744eb2bd662Svikram 3745eb2bd662Svikram if (ret) { 3746eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 3747eb2bd662Svikram } else { 3748eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 3749eb2bd662Svikram } 3750eb2bd662Svikram 3751eb2bd662Svikram return (ret); 3752eb2bd662Svikram } 3753eb2bd662Svikram 3754eb2bd662Svikram static error_t 3755eb2bd662Svikram kernel_parser(entry_t *entry, char *cmd, char *arg, int linenum) 3756eb2bd662Svikram { 3757eb2bd662Svikram const char *fcn = "kernel_parser()"; 3758eb2bd662Svikram 3759eb2bd662Svikram assert(entry); 3760eb2bd662Svikram assert(cmd); 3761eb2bd662Svikram assert(arg); 3762eb2bd662Svikram 3763eb2bd662Svikram if (strcmp(cmd, menu_cmds[KERNEL_CMD]) != 0 && 3764eb2bd662Svikram strcmp(cmd, menu_cmds[KERNEL_DOLLAR_CMD]) != 0) { 3765eb2bd662Svikram BAM_DPRINTF((D_NOT_KERNEL_CMD, fcn, cmd)); 3766eb2bd662Svikram return (BAM_ERROR); 3767eb2bd662Svikram } 3768eb2bd662Svikram 3769eb2bd662Svikram if (strncmp(arg, DIRECT_BOOT_32, sizeof (DIRECT_BOOT_32) - 1) == 0) { 3770eb2bd662Svikram BAM_DPRINTF((D_SET_DBOOT_32, fcn, arg)); 3771eb2bd662Svikram entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_32BIT; 3772eb2bd662Svikram } else if (strncmp(arg, DIRECT_BOOT_KERNEL, 3773eb2bd662Svikram sizeof (DIRECT_BOOT_KERNEL) - 1) == 0) { 3774eb2bd662Svikram BAM_DPRINTF((D_SET_DBOOT, fcn, arg)); 3775eb2bd662Svikram entry->flags |= BAM_ENTRY_DBOOT; 3776eb2bd662Svikram } else if (strncmp(arg, DIRECT_BOOT_64, 3777eb2bd662Svikram sizeof (DIRECT_BOOT_64) - 1) == 0) { 3778eb2bd662Svikram BAM_DPRINTF((D_SET_DBOOT_64, fcn, arg)); 3779eb2bd662Svikram entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_64BIT; 3780eb2bd662Svikram } else if (strncmp(arg, DIRECT_BOOT_FAILSAFE_KERNEL, 3781eb2bd662Svikram sizeof (DIRECT_BOOT_FAILSAFE_KERNEL) - 1) == 0) { 3782eb2bd662Svikram BAM_DPRINTF((D_SET_DBOOT_FAILSAFE, fcn, arg)); 3783eb2bd662Svikram entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_FAILSAFE; 3784bbcc54bdSEnrico Perla - Sun Microsystems } else if (strncmp(arg, DIRECT_BOOT_FAILSAFE_32, 3785bbcc54bdSEnrico Perla - Sun Microsystems sizeof (DIRECT_BOOT_FAILSAFE_32) - 1) == 0) { 3786bbcc54bdSEnrico Perla - Sun Microsystems BAM_DPRINTF((D_SET_DBOOT_FAILSAFE_32, fcn, arg)); 3787bbcc54bdSEnrico Perla - Sun Microsystems entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_FAILSAFE 3788bbcc54bdSEnrico Perla - Sun Microsystems | BAM_ENTRY_32BIT; 3789bbcc54bdSEnrico Perla - Sun Microsystems } else if (strncmp(arg, DIRECT_BOOT_FAILSAFE_64, 3790bbcc54bdSEnrico Perla - Sun Microsystems sizeof (DIRECT_BOOT_FAILSAFE_64) - 1) == 0) { 3791bbcc54bdSEnrico Perla - Sun Microsystems BAM_DPRINTF((D_SET_DBOOT_FAILSAFE_64, fcn, arg)); 3792bbcc54bdSEnrico Perla - Sun Microsystems entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_FAILSAFE 3793bbcc54bdSEnrico Perla - Sun Microsystems | BAM_ENTRY_64BIT; 3794eb2bd662Svikram } else if (strncmp(arg, MULTI_BOOT, sizeof (MULTI_BOOT) - 1) == 0) { 3795eb2bd662Svikram BAM_DPRINTF((D_SET_MULTIBOOT, fcn, arg)); 3796eb2bd662Svikram entry->flags |= BAM_ENTRY_MULTIBOOT; 3797eb2bd662Svikram } else if (strncmp(arg, MULTI_BOOT_FAILSAFE, 3798eb2bd662Svikram sizeof (MULTI_BOOT_FAILSAFE) - 1) == 0) { 3799eb2bd662Svikram BAM_DPRINTF((D_SET_MULTIBOOT_FAILSAFE, fcn, arg)); 3800eb2bd662Svikram entry->flags |= BAM_ENTRY_MULTIBOOT | BAM_ENTRY_FAILSAFE; 3801eb2bd662Svikram } else if (strstr(arg, XEN_KERNEL_SUBSTR)) { 3802eb2bd662Svikram BAM_DPRINTF((D_SET_HV, fcn, arg)); 3803eb2bd662Svikram entry->flags |= BAM_ENTRY_HV; 3804eb2bd662Svikram } else if (!(entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU))) { 3805eb2bd662Svikram BAM_DPRINTF((D_SET_HAND_KERNEL, fcn, arg)); 3806eb2bd662Svikram return (BAM_ERROR); 380737eb779cSVikram Hegde } else if (strncmp(arg, KERNEL_PREFIX, strlen(KERNEL_PREFIX)) == 0 && 380837eb779cSVikram Hegde strstr(arg, UNIX_SPACE)) { 380937eb779cSVikram Hegde entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_32BIT; 381037eb779cSVikram Hegde } else if (strncmp(arg, KERNEL_PREFIX, strlen(KERNEL_PREFIX)) == 0 && 381137eb779cSVikram Hegde strstr(arg, AMD_UNIX_SPACE)) { 381237eb779cSVikram Hegde entry->flags |= BAM_ENTRY_DBOOT | BAM_ENTRY_64BIT; 3813eb2bd662Svikram } else { 3814eb2bd662Svikram BAM_DPRINTF((D_IS_UNKNOWN_KERNEL, fcn, arg)); 3815eb2bd662Svikram bam_error(UNKNOWN_KERNEL_LINE, linenum); 3816eb2bd662Svikram return (BAM_ERROR); 3817eb2bd662Svikram } 3818eb2bd662Svikram 3819eb2bd662Svikram return (BAM_SUCCESS); 3820eb2bd662Svikram } 3821eb2bd662Svikram 3822eb2bd662Svikram static error_t 3823eb2bd662Svikram module_parser(entry_t *entry, char *cmd, char *arg, int linenum) 3824eb2bd662Svikram { 3825eb2bd662Svikram const char *fcn = "module_parser()"; 3826eb2bd662Svikram 3827eb2bd662Svikram assert(entry); 3828eb2bd662Svikram assert(cmd); 3829eb2bd662Svikram assert(arg); 3830eb2bd662Svikram 3831eb2bd662Svikram if (strcmp(cmd, menu_cmds[MODULE_CMD]) != 0 && 3832eb2bd662Svikram strcmp(cmd, menu_cmds[MODULE_DOLLAR_CMD]) != 0) { 3833eb2bd662Svikram BAM_DPRINTF((D_NOT_MODULE_CMD, fcn, cmd)); 3834eb2bd662Svikram return (BAM_ERROR); 3835eb2bd662Svikram } 3836eb2bd662Svikram 3837eb2bd662Svikram if (strcmp(arg, DIRECT_BOOT_ARCHIVE) == 0 || 3838eb2bd662Svikram strcmp(arg, DIRECT_BOOT_ARCHIVE_32) == 0 || 3839eb2bd662Svikram strcmp(arg, DIRECT_BOOT_ARCHIVE_64) == 0 || 3840eb2bd662Svikram strcmp(arg, MULTIBOOT_ARCHIVE) == 0 || 3841eb2bd662Svikram strcmp(arg, FAILSAFE_ARCHIVE) == 0 || 3842bbcc54bdSEnrico Perla - Sun Microsystems strcmp(arg, FAILSAFE_ARCHIVE_32) == 0 || 3843bbcc54bdSEnrico Perla - Sun Microsystems strcmp(arg, FAILSAFE_ARCHIVE_64) == 0 || 3844eb2bd662Svikram strcmp(arg, XEN_KERNEL_MODULE_LINE) == 0 || 3845eb2bd662Svikram strcmp(arg, XEN_KERNEL_MODULE_LINE_ZFS) == 0) { 3846eb2bd662Svikram BAM_DPRINTF((D_BOOTADM_LU_MODULE, fcn, arg)); 3847eb2bd662Svikram return (BAM_SUCCESS); 3848eb2bd662Svikram } else if (!(entry->flags & BAM_ENTRY_BOOTADM) && 3849eb2bd662Svikram !(entry->flags & BAM_ENTRY_LU)) { 3850eb2bd662Svikram /* don't emit warning for hand entries */ 3851eb2bd662Svikram BAM_DPRINTF((D_IS_HAND_MODULE, fcn, arg)); 3852eb2bd662Svikram return (BAM_ERROR); 3853eb2bd662Svikram } else { 3854eb2bd662Svikram BAM_DPRINTF((D_IS_UNKNOWN_MODULE, fcn, arg)); 3855eb2bd662Svikram bam_error(UNKNOWN_MODULE_LINE, linenum); 3856eb2bd662Svikram return (BAM_ERROR); 3857eb2bd662Svikram } 3858843e1988Sjohnlev } 3859843e1988Sjohnlev 3860843e1988Sjohnlev /* 38617c478bd9Sstevel@tonic-gate * A line in menu.lst looks like 38627c478bd9Sstevel@tonic-gate * [ ]*<cmd>[ \t=]*<arg>* 38637c478bd9Sstevel@tonic-gate */ 38647c478bd9Sstevel@tonic-gate static void 38657c478bd9Sstevel@tonic-gate line_parser(menu_t *mp, char *str, int *lineNum, int *entryNum) 38667c478bd9Sstevel@tonic-gate { 38677c478bd9Sstevel@tonic-gate /* 38687c478bd9Sstevel@tonic-gate * save state across calls. This is so that 38697c478bd9Sstevel@tonic-gate * header gets the right entry# after title has 38707c478bd9Sstevel@tonic-gate * been processed 38717c478bd9Sstevel@tonic-gate */ 38728c1b6884Sszhou static line_t *prev = NULL; 38738c1b6884Sszhou static entry_t *curr_ent = NULL; 3874ae115bc7Smrj static int in_liveupgrade = 0; 38757c478bd9Sstevel@tonic-gate 38767c478bd9Sstevel@tonic-gate line_t *lp; 38777c478bd9Sstevel@tonic-gate char *cmd, *sep, *arg; 38787c478bd9Sstevel@tonic-gate char save, *cp, *line; 38797c478bd9Sstevel@tonic-gate menu_flag_t flag = BAM_INVALID; 3880eb2bd662Svikram const char *fcn = "line_parser()"; 38817c478bd9Sstevel@tonic-gate 38827c478bd9Sstevel@tonic-gate if (str == NULL) { 38837c478bd9Sstevel@tonic-gate return; 38847c478bd9Sstevel@tonic-gate } 38857c478bd9Sstevel@tonic-gate 38867c478bd9Sstevel@tonic-gate /* 38877c478bd9Sstevel@tonic-gate * First save a copy of the entire line. 38887c478bd9Sstevel@tonic-gate * We use this later to set the line field. 38897c478bd9Sstevel@tonic-gate */ 38907c478bd9Sstevel@tonic-gate line = s_strdup(str); 38917c478bd9Sstevel@tonic-gate 38927c478bd9Sstevel@tonic-gate /* Eat up leading whitespace */ 38937c478bd9Sstevel@tonic-gate while (*str == ' ' || *str == '\t') 38947c478bd9Sstevel@tonic-gate str++; 38957c478bd9Sstevel@tonic-gate 38967c478bd9Sstevel@tonic-gate if (*str == '#') { /* comment */ 38977c478bd9Sstevel@tonic-gate cmd = s_strdup("#"); 38987c478bd9Sstevel@tonic-gate sep = NULL; 38997c478bd9Sstevel@tonic-gate arg = s_strdup(str + 1); 39007c478bd9Sstevel@tonic-gate flag = BAM_COMMENT; 3901ae115bc7Smrj if (strstr(arg, BAM_LU_HDR) != NULL) { 3902ae115bc7Smrj in_liveupgrade = 1; 3903ae115bc7Smrj } else if (strstr(arg, BAM_LU_FTR) != NULL) { 3904ae115bc7Smrj in_liveupgrade = 0; 3905ae115bc7Smrj } 39067c478bd9Sstevel@tonic-gate } else if (*str == '\0') { /* blank line */ 39077c478bd9Sstevel@tonic-gate cmd = sep = arg = NULL; 39087c478bd9Sstevel@tonic-gate flag = BAM_EMPTY; 39097c478bd9Sstevel@tonic-gate } else { 39107c478bd9Sstevel@tonic-gate /* 39117c478bd9Sstevel@tonic-gate * '=' is not a documented separator in grub syntax. 39127c478bd9Sstevel@tonic-gate * However various development bits use '=' as a 39137c478bd9Sstevel@tonic-gate * separator. In addition, external users also 39147c478bd9Sstevel@tonic-gate * use = as a separator. So we will allow that usage. 39157c478bd9Sstevel@tonic-gate */ 39167c478bd9Sstevel@tonic-gate cp = str; 39177c478bd9Sstevel@tonic-gate while (*str != ' ' && *str != '\t' && *str != '=') { 39187c478bd9Sstevel@tonic-gate if (*str == '\0') { 39197c478bd9Sstevel@tonic-gate cmd = s_strdup(cp); 39207c478bd9Sstevel@tonic-gate sep = arg = NULL; 39217c478bd9Sstevel@tonic-gate break; 39227c478bd9Sstevel@tonic-gate } 39237c478bd9Sstevel@tonic-gate str++; 39247c478bd9Sstevel@tonic-gate } 39257c478bd9Sstevel@tonic-gate 39267c478bd9Sstevel@tonic-gate if (*str != '\0') { 39277c478bd9Sstevel@tonic-gate save = *str; 39287c478bd9Sstevel@tonic-gate *str = '\0'; 39297c478bd9Sstevel@tonic-gate cmd = s_strdup(cp); 39307c478bd9Sstevel@tonic-gate *str = save; 39317c478bd9Sstevel@tonic-gate 39327c478bd9Sstevel@tonic-gate str++; 39337c478bd9Sstevel@tonic-gate save = *str; 39347c478bd9Sstevel@tonic-gate *str = '\0'; 39357c478bd9Sstevel@tonic-gate sep = s_strdup(str - 1); 39367c478bd9Sstevel@tonic-gate *str = save; 39377c478bd9Sstevel@tonic-gate 39387c478bd9Sstevel@tonic-gate while (*str == ' ' || *str == '\t') 39397c478bd9Sstevel@tonic-gate str++; 39407c478bd9Sstevel@tonic-gate if (*str == '\0') 39417c478bd9Sstevel@tonic-gate arg = NULL; 39427c478bd9Sstevel@tonic-gate else 39437c478bd9Sstevel@tonic-gate arg = s_strdup(str); 39447c478bd9Sstevel@tonic-gate } 39457c478bd9Sstevel@tonic-gate } 39467c478bd9Sstevel@tonic-gate 39477c478bd9Sstevel@tonic-gate lp = s_calloc(1, sizeof (line_t)); 39487c478bd9Sstevel@tonic-gate 39497c478bd9Sstevel@tonic-gate lp->cmd = cmd; 39507c478bd9Sstevel@tonic-gate lp->sep = sep; 39517c478bd9Sstevel@tonic-gate lp->arg = arg; 39527c478bd9Sstevel@tonic-gate lp->line = line; 39537c478bd9Sstevel@tonic-gate lp->lineNum = ++(*lineNum); 39547c478bd9Sstevel@tonic-gate if (cmd && strcmp(cmd, menu_cmds[TITLE_CMD]) == 0) { 39557c478bd9Sstevel@tonic-gate lp->entryNum = ++(*entryNum); 39567c478bd9Sstevel@tonic-gate lp->flags = BAM_TITLE; 39577c478bd9Sstevel@tonic-gate if (prev && prev->flags == BAM_COMMENT && 3958ae115bc7Smrj prev->arg && strcmp(prev->arg, BAM_BOOTADM_HDR) == 0) { 39597c478bd9Sstevel@tonic-gate prev->entryNum = lp->entryNum; 39608c1b6884Sszhou curr_ent = boot_entry_new(mp, prev, lp); 3961eb2bd662Svikram curr_ent->flags |= BAM_ENTRY_BOOTADM; 3962eb2bd662Svikram BAM_DPRINTF((D_IS_BOOTADM_ENTRY, fcn, arg)); 39638c1b6884Sszhou } else { 39648c1b6884Sszhou curr_ent = boot_entry_new(mp, lp, lp); 3965ae115bc7Smrj if (in_liveupgrade) { 3966eb2bd662Svikram curr_ent->flags |= BAM_ENTRY_LU; 3967eb2bd662Svikram BAM_DPRINTF((D_IS_LU_ENTRY, fcn, arg)); 39688c1b6884Sszhou } 3969ae115bc7Smrj } 3970ae115bc7Smrj curr_ent->entryNum = *entryNum; 39717c478bd9Sstevel@tonic-gate } else if (flag != BAM_INVALID) { 39727c478bd9Sstevel@tonic-gate /* 39737c478bd9Sstevel@tonic-gate * For header comments, the entry# is "fixed up" 39747c478bd9Sstevel@tonic-gate * by the subsequent title 39757c478bd9Sstevel@tonic-gate */ 39767c478bd9Sstevel@tonic-gate lp->entryNum = *entryNum; 39777c478bd9Sstevel@tonic-gate lp->flags = flag; 39787c478bd9Sstevel@tonic-gate } else { 39797c478bd9Sstevel@tonic-gate lp->entryNum = *entryNum; 3980ae115bc7Smrj 3981ae115bc7Smrj if (*entryNum == ENTRY_INIT) { 3982ae115bc7Smrj lp->flags = BAM_GLOBAL; 3983ae115bc7Smrj } else { 3984ae115bc7Smrj lp->flags = BAM_ENTRY; 3985ae115bc7Smrj 3986ae115bc7Smrj if (cmd && arg) { 3987eb2bd662Svikram if (strcmp(cmd, menu_cmds[ROOT_CMD]) == 0) { 3988eb2bd662Svikram BAM_DPRINTF((D_IS_ROOT_CMD, fcn, arg)); 3989ae115bc7Smrj curr_ent->flags |= BAM_ENTRY_ROOT; 3990eb2bd662Svikram } else if (strcmp(cmd, menu_cmds[FINDROOT_CMD]) 3991eb2bd662Svikram == 0) { 3992eb2bd662Svikram BAM_DPRINTF((D_IS_FINDROOT_CMD, fcn, 3993eb2bd662Svikram arg)); 3994eb2bd662Svikram curr_ent->flags |= BAM_ENTRY_FINDROOT; 3995eb2bd662Svikram } else if (strcmp(cmd, 3996eb2bd662Svikram menu_cmds[CHAINLOADER_CMD]) == 0) { 3997eb2bd662Svikram BAM_DPRINTF((D_IS_CHAINLOADER_CMD, fcn, 3998eb2bd662Svikram arg)); 3999ae115bc7Smrj curr_ent->flags |= 4000ae115bc7Smrj BAM_ENTRY_CHAINLOADER; 4001eb2bd662Svikram } else if (kernel_parser(curr_ent, cmd, arg, 4002eb2bd662Svikram lp->lineNum) != BAM_SUCCESS) { 4003eb2bd662Svikram (void) module_parser(curr_ent, cmd, 4004eb2bd662Svikram arg, lp->lineNum); 4005eb2bd662Svikram } 4006ae115bc7Smrj } 4007ae115bc7Smrj } 40087c478bd9Sstevel@tonic-gate } 40097c478bd9Sstevel@tonic-gate 40108c1b6884Sszhou /* record default, old default, and entry line ranges */ 40118c1b6884Sszhou if (lp->flags == BAM_GLOBAL && 40128c1b6884Sszhou strcmp(lp->cmd, menu_cmds[DEFAULT_CMD]) == 0) { 40138c1b6884Sszhou mp->curdefault = lp; 40148c1b6884Sszhou } else if (lp->flags == BAM_COMMENT && 40158c1b6884Sszhou strncmp(lp->arg, BAM_OLDDEF, strlen(BAM_OLDDEF)) == 0) { 40168c1b6884Sszhou mp->olddefault = lp; 4017ae115bc7Smrj } else if (lp->flags == BAM_COMMENT && 4018ae115bc7Smrj strncmp(lp->arg, BAM_OLD_RC_DEF, strlen(BAM_OLD_RC_DEF)) == 0) { 4019ae115bc7Smrj mp->old_rc_default = lp; 40208c1b6884Sszhou } else if (lp->flags == BAM_ENTRY || 4021ae115bc7Smrj (lp->flags == BAM_COMMENT && 4022ae115bc7Smrj strcmp(lp->arg, BAM_BOOTADM_FTR) == 0)) { 40238c1b6884Sszhou boot_entry_addline(curr_ent, lp); 40248c1b6884Sszhou } 40257c478bd9Sstevel@tonic-gate append_line(mp, lp); 40267c478bd9Sstevel@tonic-gate 40277c478bd9Sstevel@tonic-gate prev = lp; 40287c478bd9Sstevel@tonic-gate } 40297c478bd9Sstevel@tonic-gate 4030eb2bd662Svikram void 403140541d5dSvikram update_numbering(menu_t *mp) 403240541d5dSvikram { 403340541d5dSvikram int lineNum; 403440541d5dSvikram int entryNum; 403540541d5dSvikram int old_default_value; 403640541d5dSvikram line_t *lp, *prev, *default_lp, *default_entry; 403740541d5dSvikram char buf[PATH_MAX]; 403840541d5dSvikram 403940541d5dSvikram if (mp->start == NULL) { 404040541d5dSvikram return; 404140541d5dSvikram } 404240541d5dSvikram 404340541d5dSvikram lineNum = LINE_INIT; 404440541d5dSvikram entryNum = ENTRY_INIT; 404540541d5dSvikram old_default_value = ENTRY_INIT; 404640541d5dSvikram lp = default_lp = default_entry = NULL; 404740541d5dSvikram 404840541d5dSvikram prev = NULL; 404940541d5dSvikram for (lp = mp->start; lp; prev = lp, lp = lp->next) { 405040541d5dSvikram lp->lineNum = ++lineNum; 405140541d5dSvikram 405240541d5dSvikram /* 405340541d5dSvikram * Get the value of the default command 405440541d5dSvikram */ 405540541d5dSvikram if (lp->entryNum == ENTRY_INIT && lp->cmd && 405640541d5dSvikram strcmp(lp->cmd, menu_cmds[DEFAULT_CMD]) == 0 && 405740541d5dSvikram lp->arg) { 405840541d5dSvikram old_default_value = atoi(lp->arg); 405940541d5dSvikram default_lp = lp; 406040541d5dSvikram } 406140541d5dSvikram 406240541d5dSvikram /* 4063eb2bd662Svikram * If not a booting entry, nothing else to fix for this 406440541d5dSvikram * entry 406540541d5dSvikram */ 406640541d5dSvikram if (lp->entryNum == ENTRY_INIT) 406740541d5dSvikram continue; 406840541d5dSvikram 406940541d5dSvikram /* 407040541d5dSvikram * Record the position of the default entry. 407140541d5dSvikram * The following works because global 407240541d5dSvikram * commands like default and timeout should precede 407340541d5dSvikram * actual boot entries, so old_default_value 407440541d5dSvikram * is already known (or default cmd is missing). 407540541d5dSvikram */ 407640541d5dSvikram if (default_entry == NULL && 407740541d5dSvikram old_default_value != ENTRY_INIT && 407840541d5dSvikram lp->entryNum == old_default_value) { 407940541d5dSvikram default_entry = lp; 408040541d5dSvikram } 408140541d5dSvikram 408240541d5dSvikram /* 408340541d5dSvikram * Now fixup the entry number 408440541d5dSvikram */ 408540541d5dSvikram if (lp->cmd && strcmp(lp->cmd, menu_cmds[TITLE_CMD]) == 0) { 408640541d5dSvikram lp->entryNum = ++entryNum; 408740541d5dSvikram /* fixup the bootadm header */ 408840541d5dSvikram if (prev && prev->flags == BAM_COMMENT && 4089ae115bc7Smrj prev->arg && 4090ae115bc7Smrj strcmp(prev->arg, BAM_BOOTADM_HDR) == 0) { 409140541d5dSvikram prev->entryNum = lp->entryNum; 409240541d5dSvikram } 409340541d5dSvikram } else { 409440541d5dSvikram lp->entryNum = entryNum; 409540541d5dSvikram } 409640541d5dSvikram } 409740541d5dSvikram 409840541d5dSvikram /* 409940541d5dSvikram * No default command in menu, simply return 410040541d5dSvikram */ 410140541d5dSvikram if (default_lp == NULL) { 410240541d5dSvikram return; 410340541d5dSvikram } 410440541d5dSvikram 410540541d5dSvikram free(default_lp->arg); 410640541d5dSvikram free(default_lp->line); 410740541d5dSvikram 410840541d5dSvikram if (default_entry == NULL) { 410940541d5dSvikram default_lp->arg = s_strdup("0"); 411040541d5dSvikram } else { 411140541d5dSvikram (void) snprintf(buf, sizeof (buf), "%d", 411240541d5dSvikram default_entry->entryNum); 411340541d5dSvikram default_lp->arg = s_strdup(buf); 411440541d5dSvikram } 411540541d5dSvikram 411640541d5dSvikram /* 411740541d5dSvikram * The following is required since only the line field gets 411840541d5dSvikram * written back to menu.lst 411940541d5dSvikram */ 412040541d5dSvikram (void) snprintf(buf, sizeof (buf), "%s%s%s", 412140541d5dSvikram menu_cmds[DEFAULT_CMD], menu_cmds[SEP_CMD], default_lp->arg); 412240541d5dSvikram default_lp->line = s_strdup(buf); 412340541d5dSvikram } 412440541d5dSvikram 412540541d5dSvikram 41267c478bd9Sstevel@tonic-gate static menu_t * 41277c478bd9Sstevel@tonic-gate menu_read(char *menu_path) 41287c478bd9Sstevel@tonic-gate { 41297c478bd9Sstevel@tonic-gate FILE *fp; 41307c478bd9Sstevel@tonic-gate char buf[BAM_MAXLINE], *cp; 41317c478bd9Sstevel@tonic-gate menu_t *mp; 41327c478bd9Sstevel@tonic-gate int line, entry, len, n; 41337c478bd9Sstevel@tonic-gate 41347c478bd9Sstevel@tonic-gate mp = s_calloc(1, sizeof (menu_t)); 41357c478bd9Sstevel@tonic-gate 41367c478bd9Sstevel@tonic-gate fp = fopen(menu_path, "r"); 41377c478bd9Sstevel@tonic-gate if (fp == NULL) { /* Let the caller handle this error */ 41387c478bd9Sstevel@tonic-gate return (mp); 41397c478bd9Sstevel@tonic-gate } 41407c478bd9Sstevel@tonic-gate 41417c478bd9Sstevel@tonic-gate 41427c478bd9Sstevel@tonic-gate /* Note: GRUB boot entry number starts with 0 */ 41437c478bd9Sstevel@tonic-gate line = LINE_INIT; 41447c478bd9Sstevel@tonic-gate entry = ENTRY_INIT; 41457c478bd9Sstevel@tonic-gate cp = buf; 41467c478bd9Sstevel@tonic-gate len = sizeof (buf); 41477c478bd9Sstevel@tonic-gate while (s_fgets(cp, len, fp) != NULL) { 41487c478bd9Sstevel@tonic-gate n = strlen(cp); 41497c478bd9Sstevel@tonic-gate if (cp[n - 1] == '\\') { 41507c478bd9Sstevel@tonic-gate len -= n - 1; 41517c478bd9Sstevel@tonic-gate assert(len >= 2); 41527c478bd9Sstevel@tonic-gate cp += n - 1; 41537c478bd9Sstevel@tonic-gate continue; 41547c478bd9Sstevel@tonic-gate } 41557c478bd9Sstevel@tonic-gate line_parser(mp, buf, &line, &entry); 41567c478bd9Sstevel@tonic-gate cp = buf; 41577c478bd9Sstevel@tonic-gate len = sizeof (buf); 41587c478bd9Sstevel@tonic-gate } 41597c478bd9Sstevel@tonic-gate 41607c478bd9Sstevel@tonic-gate if (fclose(fp) == EOF) { 41617c478bd9Sstevel@tonic-gate bam_error(CLOSE_FAIL, menu_path, strerror(errno)); 41627c478bd9Sstevel@tonic-gate } 41637c478bd9Sstevel@tonic-gate 41647c478bd9Sstevel@tonic-gate return (mp); 41657c478bd9Sstevel@tonic-gate } 41667c478bd9Sstevel@tonic-gate 41677c478bd9Sstevel@tonic-gate static error_t 41687c478bd9Sstevel@tonic-gate selector(menu_t *mp, char *opt, int *entry, char **title) 41697c478bd9Sstevel@tonic-gate { 41707c478bd9Sstevel@tonic-gate char *eq; 41717c478bd9Sstevel@tonic-gate char *opt_dup; 41727c478bd9Sstevel@tonic-gate int entryNum; 41737c478bd9Sstevel@tonic-gate 41747c478bd9Sstevel@tonic-gate assert(mp); 41757c478bd9Sstevel@tonic-gate assert(mp->start); 41767c478bd9Sstevel@tonic-gate assert(opt); 41777c478bd9Sstevel@tonic-gate 41787c478bd9Sstevel@tonic-gate opt_dup = s_strdup(opt); 41797c478bd9Sstevel@tonic-gate 41807c478bd9Sstevel@tonic-gate if (entry) 41817c478bd9Sstevel@tonic-gate *entry = ENTRY_INIT; 41827c478bd9Sstevel@tonic-gate if (title) 41837c478bd9Sstevel@tonic-gate *title = NULL; 41847c478bd9Sstevel@tonic-gate 41857c478bd9Sstevel@tonic-gate eq = strchr(opt_dup, '='); 41867c478bd9Sstevel@tonic-gate if (eq == NULL) { 41877c478bd9Sstevel@tonic-gate bam_error(INVALID_OPT, opt); 41887c478bd9Sstevel@tonic-gate free(opt_dup); 41897c478bd9Sstevel@tonic-gate return (BAM_ERROR); 41907c478bd9Sstevel@tonic-gate } 41917c478bd9Sstevel@tonic-gate 41927c478bd9Sstevel@tonic-gate *eq = '\0'; 41937c478bd9Sstevel@tonic-gate if (entry && strcmp(opt_dup, OPT_ENTRY_NUM) == 0) { 41947c478bd9Sstevel@tonic-gate assert(mp->end); 41957c478bd9Sstevel@tonic-gate entryNum = s_strtol(eq + 1); 41967c478bd9Sstevel@tonic-gate if (entryNum < 0 || entryNum > mp->end->entryNum) { 41977c478bd9Sstevel@tonic-gate bam_error(INVALID_ENTRY, eq + 1); 41987c478bd9Sstevel@tonic-gate free(opt_dup); 41997c478bd9Sstevel@tonic-gate return (BAM_ERROR); 42007c478bd9Sstevel@tonic-gate } 42017c478bd9Sstevel@tonic-gate *entry = entryNum; 42027c478bd9Sstevel@tonic-gate } else if (title && strcmp(opt_dup, menu_cmds[TITLE_CMD]) == 0) { 42037c478bd9Sstevel@tonic-gate *title = opt + (eq - opt_dup) + 1; 42047c478bd9Sstevel@tonic-gate } else { 42057c478bd9Sstevel@tonic-gate bam_error(INVALID_OPT, opt); 42067c478bd9Sstevel@tonic-gate free(opt_dup); 42077c478bd9Sstevel@tonic-gate return (BAM_ERROR); 42087c478bd9Sstevel@tonic-gate } 42097c478bd9Sstevel@tonic-gate 42107c478bd9Sstevel@tonic-gate free(opt_dup); 42117c478bd9Sstevel@tonic-gate return (BAM_SUCCESS); 42127c478bd9Sstevel@tonic-gate } 42137c478bd9Sstevel@tonic-gate 42147c478bd9Sstevel@tonic-gate /* 42157c478bd9Sstevel@tonic-gate * If invoked with no titles/entries (opt == NULL) 42167c478bd9Sstevel@tonic-gate * only title lines in file are printed. 42177c478bd9Sstevel@tonic-gate * 42187c478bd9Sstevel@tonic-gate * If invoked with a title or entry #, all 42197c478bd9Sstevel@tonic-gate * lines in *every* matching entry are listed 42207c478bd9Sstevel@tonic-gate */ 42217c478bd9Sstevel@tonic-gate static error_t 42227c478bd9Sstevel@tonic-gate list_entry(menu_t *mp, char *menu_path, char *opt) 42237c478bd9Sstevel@tonic-gate { 42247c478bd9Sstevel@tonic-gate line_t *lp; 42257c478bd9Sstevel@tonic-gate int entry = ENTRY_INIT; 42267c478bd9Sstevel@tonic-gate int found; 42277c478bd9Sstevel@tonic-gate char *title = NULL; 42287c478bd9Sstevel@tonic-gate 42297c478bd9Sstevel@tonic-gate assert(mp); 42307c478bd9Sstevel@tonic-gate assert(menu_path); 42317c478bd9Sstevel@tonic-gate 4232eb2bd662Svikram /* opt is optional */ 4233eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY2, "list_entry", menu_path, 4234eb2bd662Svikram opt ? opt : "<NULL>")); 4235eb2bd662Svikram 42367c478bd9Sstevel@tonic-gate if (mp->start == NULL) { 42377c478bd9Sstevel@tonic-gate bam_error(NO_MENU, menu_path); 42387c478bd9Sstevel@tonic-gate return (BAM_ERROR); 42397c478bd9Sstevel@tonic-gate } 42407c478bd9Sstevel@tonic-gate 42417c478bd9Sstevel@tonic-gate if (opt != NULL) { 42427c478bd9Sstevel@tonic-gate if (selector(mp, opt, &entry, &title) != BAM_SUCCESS) { 42437c478bd9Sstevel@tonic-gate return (BAM_ERROR); 42447c478bd9Sstevel@tonic-gate } 42457c478bd9Sstevel@tonic-gate assert((entry != ENTRY_INIT) ^ (title != NULL)); 42467c478bd9Sstevel@tonic-gate } else { 42477c478bd9Sstevel@tonic-gate (void) read_globals(mp, menu_path, menu_cmds[DEFAULT_CMD], 0); 42487c478bd9Sstevel@tonic-gate (void) read_globals(mp, menu_path, menu_cmds[TIMEOUT_CMD], 0); 42497c478bd9Sstevel@tonic-gate } 42507c478bd9Sstevel@tonic-gate 42517c478bd9Sstevel@tonic-gate found = 0; 42527c478bd9Sstevel@tonic-gate for (lp = mp->start; lp; lp = lp->next) { 42537c478bd9Sstevel@tonic-gate if (lp->flags == BAM_COMMENT || lp->flags == BAM_EMPTY) 42547c478bd9Sstevel@tonic-gate continue; 42557c478bd9Sstevel@tonic-gate if (opt == NULL && lp->flags == BAM_TITLE) { 42567c478bd9Sstevel@tonic-gate bam_print(PRINT_TITLE, lp->entryNum, 42577c478bd9Sstevel@tonic-gate lp->arg); 42587c478bd9Sstevel@tonic-gate found = 1; 42597c478bd9Sstevel@tonic-gate continue; 42607c478bd9Sstevel@tonic-gate } 42617c478bd9Sstevel@tonic-gate if (entry != ENTRY_INIT && lp->entryNum == entry) { 42627c478bd9Sstevel@tonic-gate bam_print(PRINT, lp->line); 42637c478bd9Sstevel@tonic-gate found = 1; 42647c478bd9Sstevel@tonic-gate continue; 42657c478bd9Sstevel@tonic-gate } 42667c478bd9Sstevel@tonic-gate 42677c478bd9Sstevel@tonic-gate /* 42687c478bd9Sstevel@tonic-gate * We set the entry value here so that all lines 42697c478bd9Sstevel@tonic-gate * in entry get printed. If we subsequently match 42707c478bd9Sstevel@tonic-gate * title in other entries, all lines in those 42717c478bd9Sstevel@tonic-gate * entries get printed as well. 42727c478bd9Sstevel@tonic-gate */ 42737c478bd9Sstevel@tonic-gate if (title && lp->flags == BAM_TITLE && lp->arg && 42747c478bd9Sstevel@tonic-gate strncmp(title, lp->arg, strlen(title)) == 0) { 42757c478bd9Sstevel@tonic-gate bam_print(PRINT, lp->line); 42767c478bd9Sstevel@tonic-gate entry = lp->entryNum; 42777c478bd9Sstevel@tonic-gate found = 1; 42787c478bd9Sstevel@tonic-gate continue; 42797c478bd9Sstevel@tonic-gate } 42807c478bd9Sstevel@tonic-gate } 42817c478bd9Sstevel@tonic-gate 42827c478bd9Sstevel@tonic-gate if (!found) { 42837c478bd9Sstevel@tonic-gate bam_error(NO_MATCH_ENTRY); 42847c478bd9Sstevel@tonic-gate return (BAM_ERROR); 42857c478bd9Sstevel@tonic-gate } 42867c478bd9Sstevel@tonic-gate 42877c478bd9Sstevel@tonic-gate return (BAM_SUCCESS); 42887c478bd9Sstevel@tonic-gate } 42897c478bd9Sstevel@tonic-gate 4290843e1988Sjohnlev int 42917c478bd9Sstevel@tonic-gate add_boot_entry(menu_t *mp, 42927c478bd9Sstevel@tonic-gate char *title, 4293eb2bd662Svikram char *findroot, 42947c478bd9Sstevel@tonic-gate char *kernel, 4295843e1988Sjohnlev char *mod_kernel, 42967c478bd9Sstevel@tonic-gate char *module) 42977c478bd9Sstevel@tonic-gate { 4298eb2bd662Svikram int lineNum; 4299eb2bd662Svikram int entryNum; 43007c478bd9Sstevel@tonic-gate char linebuf[BAM_MAXLINE]; 4301eb2bd662Svikram menu_cmd_t k_cmd; 4302eb2bd662Svikram menu_cmd_t m_cmd; 4303eb2bd662Svikram const char *fcn = "add_boot_entry()"; 43047c478bd9Sstevel@tonic-gate 43057c478bd9Sstevel@tonic-gate assert(mp); 43067c478bd9Sstevel@tonic-gate 4307eb2bd662Svikram INJECT_ERROR1("ADD_BOOT_ENTRY_FINDROOT_NULL", findroot = NULL); 4308eb2bd662Svikram if (findroot == NULL) { 4309eb2bd662Svikram bam_error(NULL_FINDROOT); 4310eb2bd662Svikram return (BAM_ERROR); 4311eb2bd662Svikram } 4312eb2bd662Svikram 43137c478bd9Sstevel@tonic-gate if (title == NULL) { 4314ee3b8144Sszhou title = "Solaris"; /* default to Solaris */ 43157c478bd9Sstevel@tonic-gate } 43167c478bd9Sstevel@tonic-gate if (kernel == NULL) { 43177c478bd9Sstevel@tonic-gate bam_error(SUBOPT_MISS, menu_cmds[KERNEL_CMD]); 43187c478bd9Sstevel@tonic-gate return (BAM_ERROR); 43197c478bd9Sstevel@tonic-gate } 43207c478bd9Sstevel@tonic-gate if (module == NULL) { 4321ae115bc7Smrj if (bam_direct != BAM_DIRECT_DBOOT) { 43227c478bd9Sstevel@tonic-gate bam_error(SUBOPT_MISS, menu_cmds[MODULE_CMD]); 43237c478bd9Sstevel@tonic-gate return (BAM_ERROR); 43247c478bd9Sstevel@tonic-gate } 43257c478bd9Sstevel@tonic-gate 4326ae115bc7Smrj /* Figure the commands out from the kernel line */ 4327ae115bc7Smrj if (strstr(kernel, "$ISADIR") != NULL) { 4328ae115bc7Smrj module = DIRECT_BOOT_ARCHIVE; 4329ae115bc7Smrj k_cmd = KERNEL_DOLLAR_CMD; 4330ae115bc7Smrj m_cmd = MODULE_DOLLAR_CMD; 4331ae115bc7Smrj } else if (strstr(kernel, "amd64") != NULL) { 4332ae115bc7Smrj module = DIRECT_BOOT_ARCHIVE_64; 4333ae115bc7Smrj k_cmd = KERNEL_CMD; 4334ae115bc7Smrj m_cmd = MODULE_CMD; 4335ae115bc7Smrj } else { 4336ae115bc7Smrj module = DIRECT_BOOT_ARCHIVE_32; 4337ae115bc7Smrj k_cmd = KERNEL_CMD; 4338ae115bc7Smrj m_cmd = MODULE_CMD; 4339ae115bc7Smrj } 4340ae115bc7Smrj } else if ((bam_direct == BAM_DIRECT_DBOOT) && 4341ae115bc7Smrj (strstr(kernel, "$ISADIR") != NULL)) { 4342ae115bc7Smrj /* 4343ae115bc7Smrj * If it's a non-failsafe dboot kernel, use the "kernel$" 4344ae115bc7Smrj * command. Otherwise, use "kernel". 4345ae115bc7Smrj */ 4346ae115bc7Smrj k_cmd = KERNEL_DOLLAR_CMD; 4347ae115bc7Smrj m_cmd = MODULE_DOLLAR_CMD; 4348ae115bc7Smrj } else { 4349ae115bc7Smrj k_cmd = KERNEL_CMD; 4350ae115bc7Smrj m_cmd = MODULE_CMD; 4351ae115bc7Smrj } 4352ae115bc7Smrj 43537c478bd9Sstevel@tonic-gate if (mp->start) { 43547c478bd9Sstevel@tonic-gate lineNum = mp->end->lineNum; 43557c478bd9Sstevel@tonic-gate entryNum = mp->end->entryNum; 43567c478bd9Sstevel@tonic-gate } else { 43577c478bd9Sstevel@tonic-gate lineNum = LINE_INIT; 43587c478bd9Sstevel@tonic-gate entryNum = ENTRY_INIT; 43597c478bd9Sstevel@tonic-gate } 43607c478bd9Sstevel@tonic-gate 43617c478bd9Sstevel@tonic-gate /* 43627c478bd9Sstevel@tonic-gate * No separator for comment (HDR/FTR) commands 43637c478bd9Sstevel@tonic-gate * The syntax for comments is #<comment> 43647c478bd9Sstevel@tonic-gate */ 43657c478bd9Sstevel@tonic-gate (void) snprintf(linebuf, sizeof (linebuf), "%s%s", 4366ae115bc7Smrj menu_cmds[COMMENT_CMD], BAM_BOOTADM_HDR); 43678c1b6884Sszhou line_parser(mp, linebuf, &lineNum, &entryNum); 43687c478bd9Sstevel@tonic-gate 43697c478bd9Sstevel@tonic-gate (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", 43707c478bd9Sstevel@tonic-gate menu_cmds[TITLE_CMD], menu_cmds[SEP_CMD], title); 43718c1b6884Sszhou line_parser(mp, linebuf, &lineNum, &entryNum); 43727c478bd9Sstevel@tonic-gate 43737c478bd9Sstevel@tonic-gate (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", 4374eb2bd662Svikram menu_cmds[FINDROOT_CMD], menu_cmds[SEP_CMD], findroot); 43758c1b6884Sszhou line_parser(mp, linebuf, &lineNum, &entryNum); 4376eb2bd662Svikram BAM_DPRINTF((D_ADD_FINDROOT_NUM, fcn, lineNum, entryNum)); 43777c478bd9Sstevel@tonic-gate 43787c478bd9Sstevel@tonic-gate (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", 4379ae115bc7Smrj menu_cmds[k_cmd], menu_cmds[SEP_CMD], kernel); 43808c1b6884Sszhou line_parser(mp, linebuf, &lineNum, &entryNum); 43817c478bd9Sstevel@tonic-gate 4382843e1988Sjohnlev if (mod_kernel != NULL) { 4383843e1988Sjohnlev (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", 4384843e1988Sjohnlev menu_cmds[m_cmd], menu_cmds[SEP_CMD], mod_kernel); 4385843e1988Sjohnlev line_parser(mp, linebuf, &lineNum, &entryNum); 4386843e1988Sjohnlev } 4387843e1988Sjohnlev 43887c478bd9Sstevel@tonic-gate (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", 4389ae115bc7Smrj menu_cmds[m_cmd], menu_cmds[SEP_CMD], module); 43908c1b6884Sszhou line_parser(mp, linebuf, &lineNum, &entryNum); 43917c478bd9Sstevel@tonic-gate 43927c478bd9Sstevel@tonic-gate (void) snprintf(linebuf, sizeof (linebuf), "%s%s", 4393ae115bc7Smrj menu_cmds[COMMENT_CMD], BAM_BOOTADM_FTR); 43948c1b6884Sszhou line_parser(mp, linebuf, &lineNum, &entryNum); 43957c478bd9Sstevel@tonic-gate 43967c478bd9Sstevel@tonic-gate return (entryNum); 43977c478bd9Sstevel@tonic-gate } 43987c478bd9Sstevel@tonic-gate 43997c478bd9Sstevel@tonic-gate static error_t 44007c478bd9Sstevel@tonic-gate do_delete(menu_t *mp, int entryNum) 44017c478bd9Sstevel@tonic-gate { 4402eb2bd662Svikram line_t *lp; 4403eb2bd662Svikram line_t *freed; 4404eb2bd662Svikram entry_t *ent; 4405eb2bd662Svikram entry_t *tmp; 44067c478bd9Sstevel@tonic-gate int deleted; 4407eb2bd662Svikram const char *fcn = "do_delete()"; 44087c478bd9Sstevel@tonic-gate 44097c478bd9Sstevel@tonic-gate assert(entryNum != ENTRY_INIT); 44107c478bd9Sstevel@tonic-gate 4411eb2bd662Svikram tmp = NULL; 4412eb2bd662Svikram 44138c1b6884Sszhou ent = mp->entries; 44148c1b6884Sszhou while (ent) { 44158c1b6884Sszhou lp = ent->start; 44168c1b6884Sszhou /* check entry number and make sure it's a bootadm entry */ 44178c1b6884Sszhou if (lp->flags != BAM_COMMENT || 4418ae115bc7Smrj strcmp(lp->arg, BAM_BOOTADM_HDR) != 0 || 44198c1b6884Sszhou (entryNum != ALL_ENTRIES && lp->entryNum != entryNum)) { 44208c1b6884Sszhou ent = ent->next; 44217c478bd9Sstevel@tonic-gate continue; 44227c478bd9Sstevel@tonic-gate } 44237c478bd9Sstevel@tonic-gate 44248c1b6884Sszhou /* free the entry content */ 44258c1b6884Sszhou do { 44268c1b6884Sszhou freed = lp; 44278c1b6884Sszhou lp = lp->next; /* prev stays the same */ 4428eb2bd662Svikram BAM_DPRINTF((D_FREEING_LINE, fcn, freed->lineNum)); 44298c1b6884Sszhou unlink_line(mp, freed); 44308c1b6884Sszhou line_free(freed); 44318c1b6884Sszhou } while (freed != ent->end); 44327c478bd9Sstevel@tonic-gate 44338c1b6884Sszhou /* free the entry_t structure */ 4434eb2bd662Svikram assert(tmp == NULL); 44358c1b6884Sszhou tmp = ent; 44368c1b6884Sszhou ent = ent->next; 44378c1b6884Sszhou if (tmp->prev) 44388c1b6884Sszhou tmp->prev->next = ent; 44397c478bd9Sstevel@tonic-gate else 44408c1b6884Sszhou mp->entries = ent; 44418c1b6884Sszhou if (ent) 44428c1b6884Sszhou ent->prev = tmp->prev; 4443eb2bd662Svikram BAM_DPRINTF((D_FREEING_ENTRY, fcn, tmp->entryNum)); 4444eb2bd662Svikram free(tmp); 4445eb2bd662Svikram tmp = NULL; 44467c478bd9Sstevel@tonic-gate deleted = 1; 44477c478bd9Sstevel@tonic-gate } 44487c478bd9Sstevel@tonic-gate 4449eb2bd662Svikram assert(tmp == NULL); 4450eb2bd662Svikram 44517c478bd9Sstevel@tonic-gate if (!deleted && entryNum != ALL_ENTRIES) { 44527c478bd9Sstevel@tonic-gate bam_error(NO_BOOTADM_MATCH); 44537c478bd9Sstevel@tonic-gate return (BAM_ERROR); 44547c478bd9Sstevel@tonic-gate } 44557c478bd9Sstevel@tonic-gate 445640541d5dSvikram /* 445740541d5dSvikram * Now that we have deleted an entry, update 445840541d5dSvikram * the entry numbering and the default cmd. 445940541d5dSvikram */ 446040541d5dSvikram update_numbering(mp); 446140541d5dSvikram 44627c478bd9Sstevel@tonic-gate return (BAM_SUCCESS); 44637c478bd9Sstevel@tonic-gate } 44647c478bd9Sstevel@tonic-gate 44657c478bd9Sstevel@tonic-gate static error_t 4466eb2bd662Svikram delete_all_entries(menu_t *mp, char *dummy, char *opt) 44677c478bd9Sstevel@tonic-gate { 44687c478bd9Sstevel@tonic-gate assert(mp); 4469eb2bd662Svikram assert(dummy == NULL); 44707c478bd9Sstevel@tonic-gate assert(opt == NULL); 44717c478bd9Sstevel@tonic-gate 4472eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY0, "delete_all_entries")); 4473eb2bd662Svikram 44747c478bd9Sstevel@tonic-gate if (mp->start == NULL) { 4475eb2bd662Svikram bam_print(EMPTY_MENU); 44767c478bd9Sstevel@tonic-gate return (BAM_SUCCESS); 44777c478bd9Sstevel@tonic-gate } 44787c478bd9Sstevel@tonic-gate 44797c478bd9Sstevel@tonic-gate if (do_delete(mp, ALL_ENTRIES) != BAM_SUCCESS) { 44807c478bd9Sstevel@tonic-gate return (BAM_ERROR); 44817c478bd9Sstevel@tonic-gate } 44827c478bd9Sstevel@tonic-gate 44837c478bd9Sstevel@tonic-gate return (BAM_WRITE); 44847c478bd9Sstevel@tonic-gate } 44857c478bd9Sstevel@tonic-gate 44867c478bd9Sstevel@tonic-gate static FILE * 4487eb2bd662Svikram create_diskmap(char *osroot) 44887c478bd9Sstevel@tonic-gate { 44897c478bd9Sstevel@tonic-gate FILE *fp; 44907c478bd9Sstevel@tonic-gate char cmd[PATH_MAX]; 4491eb2bd662Svikram const char *fcn = "create_diskmap()"; 44927c478bd9Sstevel@tonic-gate 44937c478bd9Sstevel@tonic-gate /* make sure we have a map file */ 44947c478bd9Sstevel@tonic-gate fp = fopen(GRUBDISK_MAP, "r"); 44957c478bd9Sstevel@tonic-gate if (fp == NULL) { 44967c478bd9Sstevel@tonic-gate (void) snprintf(cmd, sizeof (cmd), 4497eb2bd662Svikram "%s/%s > /dev/null", osroot, CREATE_DISKMAP); 4498eb2bd662Svikram if (exec_cmd(cmd, NULL) != 0) 4499eb2bd662Svikram return (NULL); 45007c478bd9Sstevel@tonic-gate fp = fopen(GRUBDISK_MAP, "r"); 4501eb2bd662Svikram INJECT_ERROR1("DISKMAP_CREATE_FAIL", fp = NULL); 4502eb2bd662Svikram if (fp) { 4503eb2bd662Svikram BAM_DPRINTF((D_CREATED_DISKMAP, fcn, GRUBDISK_MAP)); 4504eb2bd662Svikram } else { 4505eb2bd662Svikram BAM_DPRINTF((D_CREATE_DISKMAP_FAIL, fcn, GRUBDISK_MAP)); 4506eb2bd662Svikram } 45077c478bd9Sstevel@tonic-gate } 45087c478bd9Sstevel@tonic-gate return (fp); 45097c478bd9Sstevel@tonic-gate } 45107c478bd9Sstevel@tonic-gate 45117c478bd9Sstevel@tonic-gate #define SECTOR_SIZE 512 45127c478bd9Sstevel@tonic-gate 45137c478bd9Sstevel@tonic-gate static int 45147c478bd9Sstevel@tonic-gate get_partition(char *device) 45157c478bd9Sstevel@tonic-gate { 45167c478bd9Sstevel@tonic-gate int i, fd, is_pcfs, partno = -1; 45177c478bd9Sstevel@tonic-gate struct mboot *mboot; 45187c478bd9Sstevel@tonic-gate char boot_sect[SECTOR_SIZE]; 45197c478bd9Sstevel@tonic-gate char *wholedisk, *slice; 45207c478bd9Sstevel@tonic-gate 45217c478bd9Sstevel@tonic-gate /* form whole disk (p0) */ 45227c478bd9Sstevel@tonic-gate slice = device + strlen(device) - 2; 45237c478bd9Sstevel@tonic-gate is_pcfs = (*slice != 's'); 45247c478bd9Sstevel@tonic-gate if (!is_pcfs) 45257c478bd9Sstevel@tonic-gate *slice = '\0'; 45267c478bd9Sstevel@tonic-gate wholedisk = s_calloc(1, strlen(device) + 3); 45277c478bd9Sstevel@tonic-gate (void) snprintf(wholedisk, strlen(device) + 3, "%sp0", device); 45287c478bd9Sstevel@tonic-gate if (!is_pcfs) 45297c478bd9Sstevel@tonic-gate *slice = 's'; 45307c478bd9Sstevel@tonic-gate 45317c478bd9Sstevel@tonic-gate /* read boot sector */ 45327c478bd9Sstevel@tonic-gate fd = open(wholedisk, O_RDONLY); 45337c478bd9Sstevel@tonic-gate free(wholedisk); 45347c478bd9Sstevel@tonic-gate if (fd == -1 || read(fd, boot_sect, SECTOR_SIZE) != SECTOR_SIZE) { 45357c478bd9Sstevel@tonic-gate return (partno); 45367c478bd9Sstevel@tonic-gate } 45377c478bd9Sstevel@tonic-gate (void) close(fd); 45387c478bd9Sstevel@tonic-gate 45397c478bd9Sstevel@tonic-gate /* parse fdisk table */ 45407c478bd9Sstevel@tonic-gate mboot = (struct mboot *)((void *)boot_sect); 45417c478bd9Sstevel@tonic-gate for (i = 0; i < FD_NUMPART; i++) { 45427c478bd9Sstevel@tonic-gate struct ipart *part = 45437c478bd9Sstevel@tonic-gate (struct ipart *)(uintptr_t)mboot->parts + i; 45447c478bd9Sstevel@tonic-gate if (is_pcfs) { /* looking for solaris boot part */ 45457c478bd9Sstevel@tonic-gate if (part->systid == 0xbe) { 45467c478bd9Sstevel@tonic-gate partno = i; 45477c478bd9Sstevel@tonic-gate break; 45487c478bd9Sstevel@tonic-gate } 45497c478bd9Sstevel@tonic-gate } else { /* look for solaris partition, old and new */ 45507c478bd9Sstevel@tonic-gate if (part->systid == SUNIXOS || 45517c478bd9Sstevel@tonic-gate part->systid == SUNIXOS2) { 45527c478bd9Sstevel@tonic-gate partno = i; 45537c478bd9Sstevel@tonic-gate break; 45547c478bd9Sstevel@tonic-gate } 45557c478bd9Sstevel@tonic-gate } 45567c478bd9Sstevel@tonic-gate } 45577c478bd9Sstevel@tonic-gate return (partno); 45587c478bd9Sstevel@tonic-gate } 45597c478bd9Sstevel@tonic-gate 4560eb2bd662Svikram char * 4561eb2bd662Svikram get_grubroot(char *osroot, char *osdev, char *menu_root) 45627c478bd9Sstevel@tonic-gate { 4563eb2bd662Svikram char *grubroot; /* (hd#,#,#) */ 45647c478bd9Sstevel@tonic-gate char *slice; 45657c478bd9Sstevel@tonic-gate char *grubhd; 45667c478bd9Sstevel@tonic-gate int fdiskpart; 45677c478bd9Sstevel@tonic-gate int found = 0; 4568eb2bd662Svikram char *devname; 4569eb2bd662Svikram char *ctdname = strstr(osdev, "dsk/"); 45707c478bd9Sstevel@tonic-gate char linebuf[PATH_MAX]; 4571eb2bd662Svikram FILE *fp; 45727c478bd9Sstevel@tonic-gate 4573eb2bd662Svikram INJECT_ERROR1("GRUBROOT_INVALID_OSDEV", ctdname = NULL); 4574eb2bd662Svikram if (ctdname == NULL) { 4575eb2bd662Svikram bam_error(INVALID_DEV_DSK, osdev); 45767c478bd9Sstevel@tonic-gate return (NULL); 4577eb2bd662Svikram } 4578eb2bd662Svikram 4579eb2bd662Svikram if (menu_root && !menu_on_bootdisk(osroot, menu_root)) { 4580eb2bd662Svikram /* menu bears no resemblance to our reality */ 458137eb779cSVikram Hegde bam_error(CANNOT_GRUBROOT_BOOTDISK, osdev); 4582eb2bd662Svikram return (NULL); 4583eb2bd662Svikram } 45847c478bd9Sstevel@tonic-gate 45857c478bd9Sstevel@tonic-gate ctdname += strlen("dsk/"); 45867c478bd9Sstevel@tonic-gate slice = strrchr(ctdname, 's'); 45877c478bd9Sstevel@tonic-gate if (slice) 45887c478bd9Sstevel@tonic-gate *slice = '\0'; 45897c478bd9Sstevel@tonic-gate 4590eb2bd662Svikram fp = create_diskmap(osroot); 4591eb2bd662Svikram if (fp == NULL) { 4592eb2bd662Svikram bam_error(DISKMAP_FAIL, osroot); 4593eb2bd662Svikram return (NULL); 4594eb2bd662Svikram } 4595eb2bd662Svikram 45967c478bd9Sstevel@tonic-gate rewind(fp); 45977c478bd9Sstevel@tonic-gate while (s_fgets(linebuf, sizeof (linebuf), fp) != NULL) { 45987c478bd9Sstevel@tonic-gate grubhd = strtok(linebuf, " \t\n"); 45997c478bd9Sstevel@tonic-gate if (grubhd) 46007c478bd9Sstevel@tonic-gate devname = strtok(NULL, " \t\n"); 46017c478bd9Sstevel@tonic-gate else 46027c478bd9Sstevel@tonic-gate devname = NULL; 46037c478bd9Sstevel@tonic-gate if (devname && strcmp(devname, ctdname) == 0) { 46047c478bd9Sstevel@tonic-gate found = 1; 46057c478bd9Sstevel@tonic-gate break; 46067c478bd9Sstevel@tonic-gate } 46077c478bd9Sstevel@tonic-gate } 46087c478bd9Sstevel@tonic-gate 46097c478bd9Sstevel@tonic-gate if (slice) 46107c478bd9Sstevel@tonic-gate *slice = 's'; 46117c478bd9Sstevel@tonic-gate 4612eb2bd662Svikram (void) fclose(fp); 4613eb2bd662Svikram fp = NULL; 4614eb2bd662Svikram 4615eb2bd662Svikram INJECT_ERROR1("GRUBROOT_BIOSDEV_FAIL", found = 0); 46167c478bd9Sstevel@tonic-gate if (found == 0) { 461737eb779cSVikram Hegde bam_error(BIOSDEV_SKIP, osdev); 4618eb2bd662Svikram return (NULL); 46197c478bd9Sstevel@tonic-gate } 46207c478bd9Sstevel@tonic-gate 4621eb2bd662Svikram fdiskpart = get_partition(osdev); 4622eb2bd662Svikram INJECT_ERROR1("GRUBROOT_FDISK_FAIL", fdiskpart = -1); 4623eb2bd662Svikram if (fdiskpart == -1) { 4624eb2bd662Svikram bam_error(FDISKPART_FAIL, osdev); 46257c478bd9Sstevel@tonic-gate return (NULL); 4626eb2bd662Svikram } 46277c478bd9Sstevel@tonic-gate 4628eb2bd662Svikram grubroot = s_calloc(1, 10); 46297c478bd9Sstevel@tonic-gate if (slice) { 4630eb2bd662Svikram (void) snprintf(grubroot, 10, "(hd%s,%d,%c)", 46317c478bd9Sstevel@tonic-gate grubhd, fdiskpart, slice[1] + 'a' - '0'); 46327c478bd9Sstevel@tonic-gate } else 4633eb2bd662Svikram (void) snprintf(grubroot, 10, "(hd%s,%d)", 46347c478bd9Sstevel@tonic-gate grubhd, fdiskpart); 46357c478bd9Sstevel@tonic-gate 4636eb2bd662Svikram assert(fp == NULL); 4637eb2bd662Svikram assert(strncmp(grubroot, "(hd", strlen("(hd")) == 0); 4638eb2bd662Svikram return (grubroot); 4639eb2bd662Svikram } 4640eb2bd662Svikram 4641eb2bd662Svikram static char * 4642eb2bd662Svikram find_primary_common(char *mntpt, char *fstype) 4643eb2bd662Svikram { 4644eb2bd662Svikram char signdir[PATH_MAX]; 4645eb2bd662Svikram char tmpsign[MAXNAMELEN + 1]; 4646eb2bd662Svikram char *lu; 4647eb2bd662Svikram char *ufs; 4648eb2bd662Svikram char *zfs; 4649eb2bd662Svikram DIR *dirp = NULL; 4650eb2bd662Svikram struct dirent *entp; 4651eb2bd662Svikram struct stat sb; 4652eb2bd662Svikram const char *fcn = "find_primary_common()"; 4653eb2bd662Svikram 4654eb2bd662Svikram (void) snprintf(signdir, sizeof (signdir), "%s/%s", 4655eb2bd662Svikram mntpt, GRUBSIGN_DIR); 4656eb2bd662Svikram 4657eb2bd662Svikram if (stat(signdir, &sb) == -1) { 4658eb2bd662Svikram BAM_DPRINTF((D_NO_SIGNDIR, fcn, signdir)); 4659eb2bd662Svikram return (NULL); 4660eb2bd662Svikram } 4661eb2bd662Svikram 4662eb2bd662Svikram dirp = opendir(signdir); 4663eb2bd662Svikram INJECT_ERROR1("SIGNDIR_OPENDIR_FAIL", dirp = NULL); 4664eb2bd662Svikram if (dirp == NULL) { 4665eb2bd662Svikram bam_error(OPENDIR_FAILED, signdir, strerror(errno)); 4666eb2bd662Svikram return (NULL); 4667eb2bd662Svikram } 4668eb2bd662Svikram 4669eb2bd662Svikram ufs = zfs = lu = NULL; 4670eb2bd662Svikram 4671eb2bd662Svikram while (entp = readdir(dirp)) { 4672eb2bd662Svikram if (strcmp(entp->d_name, ".") == 0 || 4673eb2bd662Svikram strcmp(entp->d_name, "..") == 0) 4674eb2bd662Svikram continue; 4675eb2bd662Svikram 4676eb2bd662Svikram (void) snprintf(tmpsign, sizeof (tmpsign), "%s", entp->d_name); 4677eb2bd662Svikram 4678eb2bd662Svikram if (lu == NULL && 4679eb2bd662Svikram strncmp(tmpsign, GRUBSIGN_LU_PREFIX, 4680eb2bd662Svikram strlen(GRUBSIGN_LU_PREFIX)) == 0) { 4681eb2bd662Svikram lu = s_strdup(tmpsign); 4682eb2bd662Svikram } 4683eb2bd662Svikram 4684eb2bd662Svikram if (ufs == NULL && 4685eb2bd662Svikram strncmp(tmpsign, GRUBSIGN_UFS_PREFIX, 4686eb2bd662Svikram strlen(GRUBSIGN_UFS_PREFIX)) == 0) { 4687eb2bd662Svikram ufs = s_strdup(tmpsign); 4688eb2bd662Svikram } 4689eb2bd662Svikram 4690eb2bd662Svikram if (zfs == NULL && 4691eb2bd662Svikram strncmp(tmpsign, GRUBSIGN_ZFS_PREFIX, 4692eb2bd662Svikram strlen(GRUBSIGN_ZFS_PREFIX)) == 0) { 4693eb2bd662Svikram zfs = s_strdup(tmpsign); 4694eb2bd662Svikram } 4695eb2bd662Svikram } 4696eb2bd662Svikram 4697eb2bd662Svikram BAM_DPRINTF((D_EXIST_PRIMARY_SIGNS, fcn, 4698eb2bd662Svikram zfs ? zfs : "NULL", 4699eb2bd662Svikram ufs ? ufs : "NULL", 4700eb2bd662Svikram lu ? lu : "NULL")); 4701eb2bd662Svikram 4702eb2bd662Svikram if (dirp) { 4703eb2bd662Svikram (void) closedir(dirp); 4704eb2bd662Svikram dirp = NULL; 4705eb2bd662Svikram } 4706eb2bd662Svikram 4707eb2bd662Svikram if (strcmp(fstype, "ufs") == 0 && zfs) { 4708eb2bd662Svikram bam_error(SIGN_FSTYPE_MISMATCH, zfs, "ufs"); 4709eb2bd662Svikram free(zfs); 4710eb2bd662Svikram zfs = NULL; 4711eb2bd662Svikram } else if (strcmp(fstype, "zfs") == 0 && ufs) { 4712eb2bd662Svikram bam_error(SIGN_FSTYPE_MISMATCH, ufs, "zfs"); 4713eb2bd662Svikram free(ufs); 4714eb2bd662Svikram ufs = NULL; 4715eb2bd662Svikram } 4716eb2bd662Svikram 4717eb2bd662Svikram assert(dirp == NULL); 4718eb2bd662Svikram 4719eb2bd662Svikram /* For now, we let Live Upgrade take care of its signature itself */ 4720eb2bd662Svikram if (lu) { 4721eb2bd662Svikram BAM_DPRINTF((D_FREEING_LU_SIGNS, fcn, lu)); 4722eb2bd662Svikram free(lu); 4723eb2bd662Svikram lu = NULL; 4724eb2bd662Svikram } 4725eb2bd662Svikram 4726eb2bd662Svikram return (zfs ? zfs : ufs); 4727eb2bd662Svikram } 4728eb2bd662Svikram 4729eb2bd662Svikram static char * 4730eb2bd662Svikram find_backup_common(char *mntpt, char *fstype) 4731eb2bd662Svikram { 4732eb2bd662Svikram FILE *bfp = NULL; 4733eb2bd662Svikram char tmpsign[MAXNAMELEN + 1]; 4734eb2bd662Svikram char backup[PATH_MAX]; 4735eb2bd662Svikram char *ufs; 4736eb2bd662Svikram char *zfs; 4737eb2bd662Svikram char *lu; 4738eb2bd662Svikram int error; 4739eb2bd662Svikram const char *fcn = "find_backup_common()"; 4740eb2bd662Svikram 4741eb2bd662Svikram /* 4742eb2bd662Svikram * We didn't find it in the primary directory. 4743eb2bd662Svikram * Look at the backup 4744eb2bd662Svikram */ 4745eb2bd662Svikram (void) snprintf(backup, sizeof (backup), "%s%s", 4746eb2bd662Svikram mntpt, GRUBSIGN_BACKUP); 4747eb2bd662Svikram 4748eb2bd662Svikram bfp = fopen(backup, "r"); 4749eb2bd662Svikram if (bfp == NULL) { 4750eb2bd662Svikram error = errno; 4751eb2bd662Svikram if (bam_verbose) { 4752eb2bd662Svikram bam_error(OPEN_FAIL, backup, strerror(error)); 4753eb2bd662Svikram } 4754eb2bd662Svikram BAM_DPRINTF((D_OPEN_FAIL, fcn, backup, strerror(error))); 4755eb2bd662Svikram return (NULL); 4756eb2bd662Svikram } 4757eb2bd662Svikram 4758eb2bd662Svikram ufs = zfs = lu = NULL; 4759eb2bd662Svikram 4760eb2bd662Svikram while (s_fgets(tmpsign, sizeof (tmpsign), bfp) != NULL) { 4761eb2bd662Svikram 4762eb2bd662Svikram if (lu == NULL && 4763eb2bd662Svikram strncmp(tmpsign, GRUBSIGN_LU_PREFIX, 4764eb2bd662Svikram strlen(GRUBSIGN_LU_PREFIX)) == 0) { 4765eb2bd662Svikram lu = s_strdup(tmpsign); 4766eb2bd662Svikram } 4767eb2bd662Svikram 4768eb2bd662Svikram if (ufs == NULL && 4769eb2bd662Svikram strncmp(tmpsign, GRUBSIGN_UFS_PREFIX, 4770eb2bd662Svikram strlen(GRUBSIGN_UFS_PREFIX)) == 0) { 4771eb2bd662Svikram ufs = s_strdup(tmpsign); 4772eb2bd662Svikram } 4773eb2bd662Svikram 4774eb2bd662Svikram if (zfs == NULL && 4775eb2bd662Svikram strncmp(tmpsign, GRUBSIGN_ZFS_PREFIX, 4776eb2bd662Svikram strlen(GRUBSIGN_ZFS_PREFIX)) == 0) { 4777eb2bd662Svikram zfs = s_strdup(tmpsign); 4778eb2bd662Svikram } 4779eb2bd662Svikram } 4780eb2bd662Svikram 4781eb2bd662Svikram BAM_DPRINTF((D_EXIST_BACKUP_SIGNS, fcn, 4782eb2bd662Svikram zfs ? zfs : "NULL", 4783eb2bd662Svikram ufs ? ufs : "NULL", 4784eb2bd662Svikram lu ? lu : "NULL")); 4785eb2bd662Svikram 4786eb2bd662Svikram if (bfp) { 4787eb2bd662Svikram (void) fclose(bfp); 4788eb2bd662Svikram bfp = NULL; 4789eb2bd662Svikram } 4790eb2bd662Svikram 4791eb2bd662Svikram if (strcmp(fstype, "ufs") == 0 && zfs) { 4792eb2bd662Svikram bam_error(SIGN_FSTYPE_MISMATCH, zfs, "ufs"); 4793eb2bd662Svikram free(zfs); 4794eb2bd662Svikram zfs = NULL; 4795eb2bd662Svikram } else if (strcmp(fstype, "zfs") == 0 && ufs) { 4796eb2bd662Svikram bam_error(SIGN_FSTYPE_MISMATCH, ufs, "zfs"); 4797eb2bd662Svikram free(ufs); 4798eb2bd662Svikram ufs = NULL; 4799eb2bd662Svikram } 4800eb2bd662Svikram 4801eb2bd662Svikram assert(bfp == NULL); 4802eb2bd662Svikram 4803eb2bd662Svikram /* For now, we let Live Upgrade take care of its signature itself */ 4804eb2bd662Svikram if (lu) { 4805eb2bd662Svikram BAM_DPRINTF((D_FREEING_LU_SIGNS, fcn, lu)); 4806eb2bd662Svikram free(lu); 4807eb2bd662Svikram lu = NULL; 4808eb2bd662Svikram } 4809eb2bd662Svikram 4810eb2bd662Svikram return (zfs ? zfs : ufs); 4811eb2bd662Svikram } 4812eb2bd662Svikram 4813eb2bd662Svikram static char * 4814eb2bd662Svikram find_ufs_existing(char *osroot) 4815eb2bd662Svikram { 4816eb2bd662Svikram char *sign; 4817eb2bd662Svikram const char *fcn = "find_ufs_existing()"; 4818eb2bd662Svikram 4819eb2bd662Svikram sign = find_primary_common(osroot, "ufs"); 4820eb2bd662Svikram if (sign == NULL) { 4821eb2bd662Svikram sign = find_backup_common(osroot, "ufs"); 4822eb2bd662Svikram BAM_DPRINTF((D_EXIST_BACKUP_SIGN, fcn, sign ? sign : "NULL")); 4823eb2bd662Svikram } else { 4824eb2bd662Svikram BAM_DPRINTF((D_EXIST_PRIMARY_SIGN, fcn, sign)); 4825eb2bd662Svikram } 4826eb2bd662Svikram 4827eb2bd662Svikram return (sign); 4828eb2bd662Svikram } 4829eb2bd662Svikram 4830eb2bd662Svikram char * 4831eb2bd662Svikram get_mountpoint(char *special, char *fstype) 4832eb2bd662Svikram { 4833eb2bd662Svikram FILE *mntfp; 4834eb2bd662Svikram struct mnttab mp = {0}; 4835eb2bd662Svikram struct mnttab mpref = {0}; 4836eb2bd662Svikram int error; 4837eb2bd662Svikram int ret; 4838eb2bd662Svikram const char *fcn = "get_mountpoint()"; 4839eb2bd662Svikram 4840eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY2, fcn, special, fstype)); 4841eb2bd662Svikram 4842eb2bd662Svikram mntfp = fopen(MNTTAB, "r"); 4843eb2bd662Svikram error = errno; 4844eb2bd662Svikram INJECT_ERROR1("MNTTAB_ERR_GET_MNTPT", mntfp = NULL); 4845eb2bd662Svikram if (mntfp == NULL) { 4846eb2bd662Svikram bam_error(OPEN_FAIL, MNTTAB, strerror(error)); 4847eb2bd662Svikram return (NULL); 4848eb2bd662Svikram } 4849eb2bd662Svikram 4850eb2bd662Svikram mpref.mnt_special = special; 4851eb2bd662Svikram mpref.mnt_fstype = fstype; 4852eb2bd662Svikram 4853eb2bd662Svikram ret = getmntany(mntfp, &mp, &mpref); 4854eb2bd662Svikram INJECT_ERROR1("GET_MOUNTPOINT_MNTANY", ret = 1); 4855eb2bd662Svikram if (ret != 0) { 4856eb2bd662Svikram (void) fclose(mntfp); 4857eb2bd662Svikram BAM_DPRINTF((D_NO_MNTPT, fcn, special, fstype)); 4858eb2bd662Svikram return (NULL); 4859eb2bd662Svikram } 4860eb2bd662Svikram (void) fclose(mntfp); 4861eb2bd662Svikram 4862eb2bd662Svikram assert(mp.mnt_mountp); 4863eb2bd662Svikram 4864eb2bd662Svikram BAM_DPRINTF((D_GET_MOUNTPOINT_RET, fcn, special, mp.mnt_mountp)); 4865eb2bd662Svikram 4866eb2bd662Svikram return (s_strdup(mp.mnt_mountp)); 4867eb2bd662Svikram } 4868eb2bd662Svikram 4869eb2bd662Svikram /* 4870eb2bd662Svikram * Mounts a "legacy" top dataset (if needed) 4871eb2bd662Svikram * Returns: The mountpoint of the legacy top dataset or NULL on error 4872eb2bd662Svikram * mnted returns one of the above values defined for zfs_mnted_t 4873eb2bd662Svikram */ 4874eb2bd662Svikram static char * 4875eb2bd662Svikram mount_legacy_dataset(char *pool, zfs_mnted_t *mnted) 4876eb2bd662Svikram { 4877eb2bd662Svikram char cmd[PATH_MAX]; 4878eb2bd662Svikram char tmpmnt[PATH_MAX]; 4879eb2bd662Svikram filelist_t flist = {0}; 4880eb2bd662Svikram char *is_mounted; 4881eb2bd662Svikram struct stat sb; 4882eb2bd662Svikram int ret; 4883eb2bd662Svikram const char *fcn = "mount_legacy_dataset()"; 4884eb2bd662Svikram 4885eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY1, fcn, pool)); 4886eb2bd662Svikram 4887eb2bd662Svikram *mnted = ZFS_MNT_ERROR; 4888eb2bd662Svikram 4889eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), 4890eb2bd662Svikram "/sbin/zfs get -Ho value mounted %s", 4891eb2bd662Svikram pool); 4892eb2bd662Svikram 4893eb2bd662Svikram ret = exec_cmd(cmd, &flist); 4894eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_LEG_GET_MOUNTED_CMD", ret = 1); 4895eb2bd662Svikram if (ret != 0) { 4896eb2bd662Svikram bam_error(ZFS_MNTED_FAILED, pool); 4897eb2bd662Svikram return (NULL); 4898eb2bd662Svikram } 4899eb2bd662Svikram 4900eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_LEG_GET_MOUNTED_OUT", flist.head = NULL); 4901eb2bd662Svikram if ((flist.head == NULL) || (flist.head != flist.tail)) { 4902eb2bd662Svikram bam_error(BAD_ZFS_MNTED, pool); 4903eb2bd662Svikram filelist_free(&flist); 4904eb2bd662Svikram return (NULL); 4905eb2bd662Svikram } 4906eb2bd662Svikram 4907eb2bd662Svikram is_mounted = strtok(flist.head->line, " \t\n"); 4908eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_LEG_GET_MOUNTED_STRTOK_YES", is_mounted = "yes"); 4909eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_LEG_GET_MOUNTED_STRTOK_NO", is_mounted = "no"); 4910eb2bd662Svikram if (strcmp(is_mounted, "no") != 0) { 4911eb2bd662Svikram filelist_free(&flist); 4912eb2bd662Svikram *mnted = LEGACY_ALREADY; 4913eb2bd662Svikram /* get_mountpoint returns a strdup'ed string */ 4914eb2bd662Svikram BAM_DPRINTF((D_Z_MOUNT_TOP_LEG_ALREADY, fcn, pool)); 4915eb2bd662Svikram return (get_mountpoint(pool, "zfs")); 4916eb2bd662Svikram } 4917eb2bd662Svikram 4918eb2bd662Svikram filelist_free(&flist); 4919eb2bd662Svikram 4920eb2bd662Svikram /* 4921eb2bd662Svikram * legacy top dataset is not mounted. Mount it now 4922eb2bd662Svikram * First create a mountpoint. 4923eb2bd662Svikram */ 4924eb2bd662Svikram (void) snprintf(tmpmnt, sizeof (tmpmnt), "%s.%d", 4925eb2bd662Svikram ZFS_LEGACY_MNTPT, getpid()); 4926eb2bd662Svikram 4927eb2bd662Svikram ret = stat(tmpmnt, &sb); 4928eb2bd662Svikram if (ret == -1) { 4929eb2bd662Svikram BAM_DPRINTF((D_Z_MOUNT_TOP_LEG_MNTPT_ABS, fcn, pool, tmpmnt)); 4930*48847494SEnrico Perla - Sun Microsystems ret = mkdirp(tmpmnt, DIR_PERMS); 4931eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_TOP_LEG_MNTPT_MKDIRP", ret = -1); 4932eb2bd662Svikram if (ret == -1) { 4933eb2bd662Svikram bam_error(MKDIR_FAILED, tmpmnt, strerror(errno)); 4934eb2bd662Svikram return (NULL); 4935eb2bd662Svikram } 4936eb2bd662Svikram } else { 4937eb2bd662Svikram BAM_DPRINTF((D_Z_MOUNT_TOP_LEG_MNTPT_PRES, fcn, pool, tmpmnt)); 4938eb2bd662Svikram } 4939eb2bd662Svikram 4940eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), 4941eb2bd662Svikram "/sbin/mount -F zfs %s %s", 4942eb2bd662Svikram pool, tmpmnt); 4943eb2bd662Svikram 4944eb2bd662Svikram ret = exec_cmd(cmd, NULL); 4945eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_TOP_LEG_MOUNT_CMD", ret = 1); 4946eb2bd662Svikram if (ret != 0) { 4947eb2bd662Svikram bam_error(ZFS_MOUNT_FAILED, pool); 4948eb2bd662Svikram (void) rmdir(tmpmnt); 4949eb2bd662Svikram return (NULL); 4950eb2bd662Svikram } 4951eb2bd662Svikram 4952eb2bd662Svikram *mnted = LEGACY_MOUNTED; 4953eb2bd662Svikram BAM_DPRINTF((D_Z_MOUNT_TOP_LEG_MOUNTED, fcn, pool, tmpmnt)); 4954eb2bd662Svikram return (s_strdup(tmpmnt)); 4955eb2bd662Svikram } 4956eb2bd662Svikram 4957eb2bd662Svikram /* 4958eb2bd662Svikram * Mounts the top dataset (if needed) 4959eb2bd662Svikram * Returns: The mountpoint of the top dataset or NULL on error 4960eb2bd662Svikram * mnted returns one of the above values defined for zfs_mnted_t 4961eb2bd662Svikram */ 4962eb2bd662Svikram static char * 4963eb2bd662Svikram mount_top_dataset(char *pool, zfs_mnted_t *mnted) 4964eb2bd662Svikram { 4965eb2bd662Svikram char cmd[PATH_MAX]; 4966eb2bd662Svikram filelist_t flist = {0}; 4967eb2bd662Svikram char *is_mounted; 4968eb2bd662Svikram char *mntpt; 4969eb2bd662Svikram char *zmntpt; 4970eb2bd662Svikram int ret; 4971eb2bd662Svikram const char *fcn = "mount_top_dataset()"; 4972eb2bd662Svikram 4973eb2bd662Svikram *mnted = ZFS_MNT_ERROR; 4974eb2bd662Svikram 4975eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY1, fcn, pool)); 4976eb2bd662Svikram 4977eb2bd662Svikram /* 4978eb2bd662Svikram * First check if the top dataset is a "legacy" dataset 4979eb2bd662Svikram */ 4980eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), 4981eb2bd662Svikram "/sbin/zfs get -Ho value mountpoint %s", 4982eb2bd662Svikram pool); 4983eb2bd662Svikram ret = exec_cmd(cmd, &flist); 4984eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_TOP_GET_MNTPT", ret = 1); 4985eb2bd662Svikram if (ret != 0) { 4986eb2bd662Svikram bam_error(ZFS_MNTPT_FAILED, pool); 4987eb2bd662Svikram return (NULL); 4988eb2bd662Svikram } 4989eb2bd662Svikram 4990eb2bd662Svikram if (flist.head && (flist.head == flist.tail)) { 4991eb2bd662Svikram char *legacy = strtok(flist.head->line, " \t\n"); 4992eb2bd662Svikram if (legacy && strcmp(legacy, "legacy") == 0) { 4993eb2bd662Svikram filelist_free(&flist); 4994eb2bd662Svikram BAM_DPRINTF((D_Z_IS_LEGACY, fcn, pool)); 4995eb2bd662Svikram return (mount_legacy_dataset(pool, mnted)); 4996eb2bd662Svikram } 4997eb2bd662Svikram } 4998eb2bd662Svikram 4999eb2bd662Svikram filelist_free(&flist); 5000eb2bd662Svikram 5001eb2bd662Svikram BAM_DPRINTF((D_Z_IS_NOT_LEGACY, fcn, pool)); 5002eb2bd662Svikram 5003eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), 5004eb2bd662Svikram "/sbin/zfs get -Ho value mounted %s", 5005eb2bd662Svikram pool); 5006eb2bd662Svikram 5007eb2bd662Svikram ret = exec_cmd(cmd, &flist); 5008eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_TOP_NONLEG_GET_MOUNTED", ret = 1); 5009eb2bd662Svikram if (ret != 0) { 5010eb2bd662Svikram bam_error(ZFS_MNTED_FAILED, pool); 5011eb2bd662Svikram return (NULL); 5012eb2bd662Svikram } 5013eb2bd662Svikram 5014eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_TOP_NONLEG_GET_MOUNTED_VAL", flist.head = NULL); 5015eb2bd662Svikram if ((flist.head == NULL) || (flist.head != flist.tail)) { 5016eb2bd662Svikram bam_error(BAD_ZFS_MNTED, pool); 5017eb2bd662Svikram filelist_free(&flist); 5018eb2bd662Svikram return (NULL); 5019eb2bd662Svikram } 5020eb2bd662Svikram 5021eb2bd662Svikram is_mounted = strtok(flist.head->line, " \t\n"); 5022eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_TOP_NONLEG_GET_MOUNTED_YES", is_mounted = "yes"); 5023eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_TOP_NONLEG_GET_MOUNTED_NO", is_mounted = "no"); 5024eb2bd662Svikram if (strcmp(is_mounted, "no") != 0) { 5025eb2bd662Svikram filelist_free(&flist); 5026eb2bd662Svikram *mnted = ZFS_ALREADY; 5027eb2bd662Svikram BAM_DPRINTF((D_Z_MOUNT_TOP_NONLEG_MOUNTED_ALREADY, fcn, pool)); 5028eb2bd662Svikram goto mounted; 5029eb2bd662Svikram } 5030eb2bd662Svikram 5031eb2bd662Svikram filelist_free(&flist); 5032eb2bd662Svikram BAM_DPRINTF((D_Z_MOUNT_TOP_NONLEG_MOUNTED_NOT_ALREADY, fcn, pool)); 5033eb2bd662Svikram 5034eb2bd662Svikram /* top dataset is not mounted. Mount it now */ 5035eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), 5036eb2bd662Svikram "/sbin/zfs mount %s", pool); 5037eb2bd662Svikram ret = exec_cmd(cmd, NULL); 5038eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_TOP_NONLEG_MOUNT_CMD", ret = 1); 5039eb2bd662Svikram if (ret != 0) { 5040eb2bd662Svikram bam_error(ZFS_MOUNT_FAILED, pool); 5041eb2bd662Svikram return (NULL); 5042eb2bd662Svikram } 5043eb2bd662Svikram *mnted = ZFS_MOUNTED; 5044eb2bd662Svikram BAM_DPRINTF((D_Z_MOUNT_TOP_NONLEG_MOUNTED_NOW, fcn, pool)); 5045eb2bd662Svikram /*FALLTHRU*/ 5046eb2bd662Svikram mounted: 5047eb2bd662Svikram /* 5048eb2bd662Svikram * Now get the mountpoint 5049eb2bd662Svikram */ 5050eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), 5051eb2bd662Svikram "/sbin/zfs get -Ho value mountpoint %s", 5052eb2bd662Svikram pool); 5053eb2bd662Svikram 5054eb2bd662Svikram ret = exec_cmd(cmd, &flist); 5055eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_TOP_NONLEG_GET_MNTPT_CMD", ret = 1); 5056eb2bd662Svikram if (ret != 0) { 5057eb2bd662Svikram bam_error(ZFS_MNTPT_FAILED, pool); 5058eb2bd662Svikram goto error; 5059eb2bd662Svikram } 5060eb2bd662Svikram 5061eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_TOP_NONLEG_GET_MNTPT_OUT", flist.head = NULL); 5062eb2bd662Svikram if ((flist.head == NULL) || (flist.head != flist.tail)) { 5063eb2bd662Svikram bam_error(NULL_ZFS_MNTPT, pool); 5064eb2bd662Svikram goto error; 5065eb2bd662Svikram } 5066eb2bd662Svikram 5067eb2bd662Svikram mntpt = strtok(flist.head->line, " \t\n"); 5068eb2bd662Svikram INJECT_ERROR1("Z_MOUNT_TOP_NONLEG_GET_MNTPT_STRTOK", mntpt = "foo"); 5069eb2bd662Svikram if (*mntpt != '/') { 5070eb2bd662Svikram bam_error(BAD_ZFS_MNTPT, pool, mntpt); 5071eb2bd662Svikram goto error; 5072eb2bd662Svikram } 5073eb2bd662Svikram zmntpt = s_strdup(mntpt); 5074eb2bd662Svikram 5075eb2bd662Svikram filelist_free(&flist); 5076eb2bd662Svikram 5077eb2bd662Svikram BAM_DPRINTF((D_Z_MOUNT_TOP_NONLEG_MNTPT, fcn, pool, zmntpt)); 5078eb2bd662Svikram 5079eb2bd662Svikram return (zmntpt); 5080eb2bd662Svikram 5081eb2bd662Svikram error: 5082eb2bd662Svikram filelist_free(&flist); 5083eb2bd662Svikram (void) umount_top_dataset(pool, *mnted, NULL); 5084eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 5085eb2bd662Svikram return (NULL); 5086eb2bd662Svikram } 5087eb2bd662Svikram 5088eb2bd662Svikram static int 5089eb2bd662Svikram umount_top_dataset(char *pool, zfs_mnted_t mnted, char *mntpt) 5090eb2bd662Svikram { 5091eb2bd662Svikram char cmd[PATH_MAX]; 5092eb2bd662Svikram int ret; 5093eb2bd662Svikram const char *fcn = "umount_top_dataset()"; 5094eb2bd662Svikram 5095eb2bd662Svikram INJECT_ERROR1("Z_UMOUNT_TOP_INVALID_STATE", mnted = ZFS_MNT_ERROR); 5096eb2bd662Svikram switch (mnted) { 5097eb2bd662Svikram case LEGACY_ALREADY: 5098eb2bd662Svikram case ZFS_ALREADY: 5099eb2bd662Svikram /* nothing to do */ 5100eb2bd662Svikram BAM_DPRINTF((D_Z_UMOUNT_TOP_ALREADY_NOP, fcn, pool, 5101eb2bd662Svikram mntpt ? mntpt : "NULL")); 5102eb2bd662Svikram free(mntpt); 5103eb2bd662Svikram return (BAM_SUCCESS); 5104eb2bd662Svikram case LEGACY_MOUNTED: 5105eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), 5106eb2bd662Svikram "/sbin/umount %s", pool); 5107eb2bd662Svikram ret = exec_cmd(cmd, NULL); 5108eb2bd662Svikram INJECT_ERROR1("Z_UMOUNT_TOP_LEGACY_UMOUNT_FAIL", ret = 1); 5109eb2bd662Svikram if (ret != 0) { 5110eb2bd662Svikram bam_error(UMOUNT_FAILED, pool); 5111eb2bd662Svikram free(mntpt); 5112eb2bd662Svikram return (BAM_ERROR); 5113eb2bd662Svikram } 5114eb2bd662Svikram if (mntpt) 5115eb2bd662Svikram (void) rmdir(mntpt); 5116eb2bd662Svikram free(mntpt); 5117eb2bd662Svikram BAM_DPRINTF((D_Z_UMOUNT_TOP_LEGACY, fcn, pool)); 5118eb2bd662Svikram return (BAM_SUCCESS); 5119eb2bd662Svikram case ZFS_MOUNTED: 5120eb2bd662Svikram free(mntpt); 5121eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), 5122eb2bd662Svikram "/sbin/zfs unmount %s", pool); 5123eb2bd662Svikram ret = exec_cmd(cmd, NULL); 5124eb2bd662Svikram INJECT_ERROR1("Z_UMOUNT_TOP_NONLEG_UMOUNT_FAIL", ret = 1); 5125eb2bd662Svikram if (ret != 0) { 5126eb2bd662Svikram bam_error(UMOUNT_FAILED, pool); 5127eb2bd662Svikram return (BAM_ERROR); 5128eb2bd662Svikram } 5129eb2bd662Svikram BAM_DPRINTF((D_Z_UMOUNT_TOP_NONLEG, fcn, pool)); 5130eb2bd662Svikram return (BAM_SUCCESS); 5131eb2bd662Svikram default: 5132eb2bd662Svikram bam_error(INT_BAD_MNTSTATE, pool); 5133eb2bd662Svikram return (BAM_ERROR); 5134eb2bd662Svikram } 5135eb2bd662Svikram /*NOTREACHED*/ 5136eb2bd662Svikram } 5137eb2bd662Svikram 5138eb2bd662Svikram /* 5139eb2bd662Svikram * For ZFS, osdev can be one of two forms 5140eb2bd662Svikram * It can be a "special" file as seen in mnttab: rpool/ROOT/szboot_0402 5141eb2bd662Svikram * It can be a /dev/[r]dsk special file. We handle both instances 5142eb2bd662Svikram */ 5143eb2bd662Svikram static char * 5144eb2bd662Svikram get_pool(char *osdev) 5145eb2bd662Svikram { 5146eb2bd662Svikram char cmd[PATH_MAX]; 5147eb2bd662Svikram char buf[PATH_MAX]; 5148eb2bd662Svikram filelist_t flist = {0}; 5149eb2bd662Svikram char *pool; 5150eb2bd662Svikram char *cp; 5151eb2bd662Svikram char *slash; 5152eb2bd662Svikram int ret; 5153eb2bd662Svikram const char *fcn = "get_pool()"; 5154eb2bd662Svikram 5155eb2bd662Svikram INJECT_ERROR1("GET_POOL_OSDEV", osdev = NULL); 5156eb2bd662Svikram if (osdev == NULL) { 5157eb2bd662Svikram bam_error(GET_POOL_OSDEV_NULL); 5158eb2bd662Svikram return (NULL); 5159eb2bd662Svikram } 5160eb2bd662Svikram 5161eb2bd662Svikram BAM_DPRINTF((D_GET_POOL_OSDEV, fcn, osdev)); 5162eb2bd662Svikram 5163eb2bd662Svikram if (osdev[0] != '/') { 5164eb2bd662Svikram (void) strlcpy(buf, osdev, sizeof (buf)); 5165eb2bd662Svikram slash = strchr(buf, '/'); 5166eb2bd662Svikram if (slash) 5167eb2bd662Svikram *slash = '\0'; 5168eb2bd662Svikram pool = s_strdup(buf); 5169eb2bd662Svikram BAM_DPRINTF((D_GET_POOL_RET, fcn, pool)); 5170eb2bd662Svikram return (pool); 5171eb2bd662Svikram } else if (strncmp(osdev, "/dev/dsk/", strlen("/dev/dsk/")) != 0 && 5172eb2bd662Svikram strncmp(osdev, "/dev/rdsk/", strlen("/dev/rdsk/")) != 0) { 5173eb2bd662Svikram bam_error(GET_POOL_BAD_OSDEV, osdev); 5174eb2bd662Svikram return (NULL); 5175eb2bd662Svikram } 5176eb2bd662Svikram 5177eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), 5178eb2bd662Svikram "/usr/sbin/fstyp -a %s 2>/dev/null | /bin/grep '^name:'", 5179eb2bd662Svikram osdev); 5180eb2bd662Svikram 5181eb2bd662Svikram ret = exec_cmd(cmd, &flist); 5182eb2bd662Svikram INJECT_ERROR1("GET_POOL_FSTYP", ret = 1); 5183eb2bd662Svikram if (ret != 0) { 5184eb2bd662Svikram bam_error(FSTYP_A_FAILED, osdev); 5185eb2bd662Svikram return (NULL); 5186eb2bd662Svikram } 5187eb2bd662Svikram 5188eb2bd662Svikram INJECT_ERROR1("GET_POOL_FSTYP_OUT", flist.head = NULL); 5189eb2bd662Svikram if ((flist.head == NULL) || (flist.head != flist.tail)) { 5190eb2bd662Svikram bam_error(NULL_FSTYP_A, osdev); 5191eb2bd662Svikram filelist_free(&flist); 5192eb2bd662Svikram return (NULL); 5193eb2bd662Svikram } 5194eb2bd662Svikram 5195eb2bd662Svikram (void) strtok(flist.head->line, "'"); 5196eb2bd662Svikram cp = strtok(NULL, "'"); 5197eb2bd662Svikram INJECT_ERROR1("GET_POOL_FSTYP_STRTOK", cp = NULL); 5198eb2bd662Svikram if (cp == NULL) { 5199eb2bd662Svikram bam_error(BAD_FSTYP_A, osdev); 5200eb2bd662Svikram filelist_free(&flist); 5201eb2bd662Svikram return (NULL); 5202eb2bd662Svikram } 5203eb2bd662Svikram 5204eb2bd662Svikram pool = s_strdup(cp); 5205eb2bd662Svikram 5206eb2bd662Svikram filelist_free(&flist); 5207eb2bd662Svikram 5208eb2bd662Svikram BAM_DPRINTF((D_GET_POOL_RET, fcn, pool)); 5209eb2bd662Svikram 5210eb2bd662Svikram return (pool); 5211eb2bd662Svikram } 5212eb2bd662Svikram 5213eb2bd662Svikram static char * 5214eb2bd662Svikram find_zfs_existing(char *osdev) 5215eb2bd662Svikram { 5216eb2bd662Svikram char *pool; 5217eb2bd662Svikram zfs_mnted_t mnted; 5218eb2bd662Svikram char *mntpt; 5219eb2bd662Svikram char *sign; 5220eb2bd662Svikram const char *fcn = "find_zfs_existing()"; 5221eb2bd662Svikram 5222eb2bd662Svikram pool = get_pool(osdev); 5223eb2bd662Svikram INJECT_ERROR1("ZFS_FIND_EXIST_POOL", pool = NULL); 5224eb2bd662Svikram if (pool == NULL) { 5225eb2bd662Svikram bam_error(ZFS_GET_POOL_FAILED, osdev); 5226eb2bd662Svikram return (NULL); 5227eb2bd662Svikram } 5228eb2bd662Svikram 5229eb2bd662Svikram mntpt = mount_top_dataset(pool, &mnted); 5230eb2bd662Svikram INJECT_ERROR1("ZFS_FIND_EXIST_MOUNT_TOP", mntpt = NULL); 5231eb2bd662Svikram if (mntpt == NULL) { 5232eb2bd662Svikram bam_error(ZFS_MOUNT_TOP_DATASET_FAILED, pool); 5233eb2bd662Svikram free(pool); 5234eb2bd662Svikram return (NULL); 5235eb2bd662Svikram } 5236eb2bd662Svikram 5237eb2bd662Svikram sign = find_primary_common(mntpt, "zfs"); 5238eb2bd662Svikram if (sign == NULL) { 5239eb2bd662Svikram sign = find_backup_common(mntpt, "zfs"); 5240eb2bd662Svikram BAM_DPRINTF((D_EXIST_BACKUP_SIGN, fcn, sign ? sign : "NULL")); 5241eb2bd662Svikram } else { 5242eb2bd662Svikram BAM_DPRINTF((D_EXIST_PRIMARY_SIGN, fcn, sign)); 5243eb2bd662Svikram } 5244eb2bd662Svikram 5245eb2bd662Svikram (void) umount_top_dataset(pool, mnted, mntpt); 5246eb2bd662Svikram 5247eb2bd662Svikram free(pool); 5248eb2bd662Svikram 5249eb2bd662Svikram return (sign); 5250eb2bd662Svikram } 5251eb2bd662Svikram 5252eb2bd662Svikram static char * 5253eb2bd662Svikram find_existing_sign(char *osroot, char *osdev, char *fstype) 5254eb2bd662Svikram { 5255eb2bd662Svikram const char *fcn = "find_existing_sign()"; 5256eb2bd662Svikram 5257eb2bd662Svikram INJECT_ERROR1("FIND_EXIST_NOTSUP_FS", fstype = "foofs"); 5258eb2bd662Svikram if (strcmp(fstype, "ufs") == 0) { 5259eb2bd662Svikram BAM_DPRINTF((D_CHECK_UFS_EXIST_SIGN, fcn)); 5260eb2bd662Svikram return (find_ufs_existing(osroot)); 5261eb2bd662Svikram } else if (strcmp(fstype, "zfs") == 0) { 5262eb2bd662Svikram BAM_DPRINTF((D_CHECK_ZFS_EXIST_SIGN, fcn)); 5263eb2bd662Svikram return (find_zfs_existing(osdev)); 5264eb2bd662Svikram } else { 5265eb2bd662Svikram bam_error(GRUBSIGN_NOTSUP, fstype); 5266eb2bd662Svikram return (NULL); 5267eb2bd662Svikram } 5268eb2bd662Svikram } 5269eb2bd662Svikram 5270eb2bd662Svikram #define MH_HASH_SZ 16 5271eb2bd662Svikram 5272eb2bd662Svikram typedef enum { 5273eb2bd662Svikram MH_ERROR = -1, 5274eb2bd662Svikram MH_NOMATCH, 5275eb2bd662Svikram MH_MATCH 5276eb2bd662Svikram } mh_search_t; 5277eb2bd662Svikram 5278eb2bd662Svikram typedef struct mcache { 5279eb2bd662Svikram char *mc_special; 5280eb2bd662Svikram char *mc_mntpt; 5281eb2bd662Svikram char *mc_fstype; 5282eb2bd662Svikram struct mcache *mc_next; 5283eb2bd662Svikram } mcache_t; 5284eb2bd662Svikram 5285eb2bd662Svikram typedef struct mhash { 5286eb2bd662Svikram mcache_t *mh_hash[MH_HASH_SZ]; 5287eb2bd662Svikram } mhash_t; 5288eb2bd662Svikram 5289eb2bd662Svikram static int 5290eb2bd662Svikram mhash_fcn(char *key) 5291eb2bd662Svikram { 5292eb2bd662Svikram int i; 5293eb2bd662Svikram uint64_t sum = 0; 5294eb2bd662Svikram 5295eb2bd662Svikram for (i = 0; key[i] != '\0'; i++) { 5296eb2bd662Svikram sum += (uchar_t)key[i]; 5297eb2bd662Svikram } 5298eb2bd662Svikram 5299eb2bd662Svikram sum %= MH_HASH_SZ; 5300eb2bd662Svikram 5301eb2bd662Svikram assert(sum < MH_HASH_SZ); 5302eb2bd662Svikram 5303eb2bd662Svikram return (sum); 5304eb2bd662Svikram } 5305eb2bd662Svikram 5306eb2bd662Svikram static mhash_t * 5307eb2bd662Svikram cache_mnttab(void) 5308eb2bd662Svikram { 5309eb2bd662Svikram FILE *mfp; 5310eb2bd662Svikram struct extmnttab mnt; 5311eb2bd662Svikram mcache_t *mcp; 5312eb2bd662Svikram mhash_t *mhp; 5313eb2bd662Svikram char *ctds; 5314eb2bd662Svikram int idx; 5315eb2bd662Svikram int error; 5316eb2bd662Svikram char *special_dup; 5317eb2bd662Svikram const char *fcn = "cache_mnttab()"; 5318eb2bd662Svikram 5319eb2bd662Svikram mfp = fopen(MNTTAB, "r"); 5320eb2bd662Svikram error = errno; 5321eb2bd662Svikram INJECT_ERROR1("CACHE_MNTTAB_MNTTAB_ERR", mfp = NULL); 5322eb2bd662Svikram if (mfp == NULL) { 5323eb2bd662Svikram bam_error(OPEN_FAIL, MNTTAB, strerror(error)); 5324eb2bd662Svikram return (NULL); 5325eb2bd662Svikram } 5326eb2bd662Svikram 5327eb2bd662Svikram mhp = s_calloc(1, sizeof (mhash_t)); 5328eb2bd662Svikram 5329eb2bd662Svikram resetmnttab(mfp); 5330eb2bd662Svikram 5331eb2bd662Svikram while (getextmntent(mfp, &mnt, sizeof (mnt)) == 0) { 5332eb2bd662Svikram /* only cache ufs */ 5333eb2bd662Svikram if (strcmp(mnt.mnt_fstype, "ufs") != 0) 5334eb2bd662Svikram continue; 5335eb2bd662Svikram 5336eb2bd662Svikram /* basename() modifies its arg, so dup it */ 5337eb2bd662Svikram special_dup = s_strdup(mnt.mnt_special); 5338eb2bd662Svikram ctds = basename(special_dup); 5339eb2bd662Svikram 5340eb2bd662Svikram mcp = s_calloc(1, sizeof (mcache_t)); 5341eb2bd662Svikram mcp->mc_special = s_strdup(ctds); 5342eb2bd662Svikram mcp->mc_mntpt = s_strdup(mnt.mnt_mountp); 5343eb2bd662Svikram mcp->mc_fstype = s_strdup(mnt.mnt_fstype); 5344eb2bd662Svikram BAM_DPRINTF((D_CACHE_MNTS, fcn, ctds, 5345eb2bd662Svikram mnt.mnt_mountp, mnt.mnt_fstype)); 5346eb2bd662Svikram idx = mhash_fcn(ctds); 5347eb2bd662Svikram mcp->mc_next = mhp->mh_hash[idx]; 5348eb2bd662Svikram mhp->mh_hash[idx] = mcp; 5349eb2bd662Svikram free(special_dup); 5350eb2bd662Svikram } 5351eb2bd662Svikram 5352eb2bd662Svikram (void) fclose(mfp); 5353eb2bd662Svikram 5354eb2bd662Svikram return (mhp); 5355eb2bd662Svikram } 5356eb2bd662Svikram 5357eb2bd662Svikram static void 5358eb2bd662Svikram free_mnttab(mhash_t *mhp) 5359eb2bd662Svikram { 5360eb2bd662Svikram mcache_t *mcp; 5361eb2bd662Svikram int i; 5362eb2bd662Svikram 5363eb2bd662Svikram for (i = 0; i < MH_HASH_SZ; i++) { 5364eb2bd662Svikram /*LINTED*/ 5365eb2bd662Svikram while (mcp = mhp->mh_hash[i]) { 5366eb2bd662Svikram mhp->mh_hash[i] = mcp->mc_next; 5367eb2bd662Svikram free(mcp->mc_special); 5368eb2bd662Svikram free(mcp->mc_mntpt); 5369eb2bd662Svikram free(mcp->mc_fstype); 5370eb2bd662Svikram free(mcp); 5371eb2bd662Svikram } 5372eb2bd662Svikram } 5373eb2bd662Svikram 5374eb2bd662Svikram for (i = 0; i < MH_HASH_SZ; i++) { 5375eb2bd662Svikram assert(mhp->mh_hash[i] == NULL); 5376eb2bd662Svikram } 5377eb2bd662Svikram free(mhp); 5378eb2bd662Svikram } 5379eb2bd662Svikram 5380eb2bd662Svikram static mh_search_t 5381eb2bd662Svikram search_hash(mhash_t *mhp, char *special, char **mntpt) 5382eb2bd662Svikram { 5383eb2bd662Svikram int idx; 5384eb2bd662Svikram mcache_t *mcp; 5385eb2bd662Svikram const char *fcn = "search_hash()"; 5386eb2bd662Svikram 5387eb2bd662Svikram assert(mntpt); 5388eb2bd662Svikram 5389eb2bd662Svikram *mntpt = NULL; 5390eb2bd662Svikram 5391eb2bd662Svikram INJECT_ERROR1("SEARCH_HASH_FULL_PATH", special = "/foo"); 5392eb2bd662Svikram if (strchr(special, '/')) { 5393eb2bd662Svikram bam_error(INVALID_MHASH_KEY, special); 5394eb2bd662Svikram return (MH_ERROR); 5395eb2bd662Svikram } 5396eb2bd662Svikram 5397eb2bd662Svikram idx = mhash_fcn(special); 5398eb2bd662Svikram 5399eb2bd662Svikram for (mcp = mhp->mh_hash[idx]; mcp; mcp = mcp->mc_next) { 5400eb2bd662Svikram if (strcmp(mcp->mc_special, special) == 0) 5401eb2bd662Svikram break; 5402eb2bd662Svikram } 5403eb2bd662Svikram 5404eb2bd662Svikram if (mcp == NULL) { 5405eb2bd662Svikram BAM_DPRINTF((D_MNTTAB_HASH_NOMATCH, fcn, special)); 5406eb2bd662Svikram return (MH_NOMATCH); 5407eb2bd662Svikram } 5408eb2bd662Svikram 5409eb2bd662Svikram assert(strcmp(mcp->mc_fstype, "ufs") == 0); 5410eb2bd662Svikram *mntpt = mcp->mc_mntpt; 5411eb2bd662Svikram BAM_DPRINTF((D_MNTTAB_HASH_MATCH, fcn, special)); 5412eb2bd662Svikram return (MH_MATCH); 5413eb2bd662Svikram } 5414eb2bd662Svikram 5415eb2bd662Svikram static int 5416eb2bd662Svikram check_add_ufs_sign_to_list(FILE *tfp, char *mntpt) 5417eb2bd662Svikram { 5418eb2bd662Svikram char *sign; 5419eb2bd662Svikram char *signline; 5420eb2bd662Svikram char signbuf[MAXNAMELEN]; 5421eb2bd662Svikram int len; 5422eb2bd662Svikram int error; 5423eb2bd662Svikram const char *fcn = "check_add_ufs_sign_to_list()"; 5424eb2bd662Svikram 5425eb2bd662Svikram /* safe to specify NULL as "osdev" arg for UFS */ 5426eb2bd662Svikram sign = find_existing_sign(mntpt, NULL, "ufs"); 5427eb2bd662Svikram if (sign == NULL) { 5428eb2bd662Svikram /* No existing signature, nothing to add to list */ 5429eb2bd662Svikram BAM_DPRINTF((D_NO_SIGN_TO_LIST, fcn, mntpt)); 5430eb2bd662Svikram return (0); 5431eb2bd662Svikram } 5432eb2bd662Svikram 5433eb2bd662Svikram (void) snprintf(signbuf, sizeof (signbuf), "%s\n", sign); 5434eb2bd662Svikram signline = signbuf; 5435eb2bd662Svikram 5436eb2bd662Svikram INJECT_ERROR1("UFS_MNTPT_SIGN_NOTUFS", signline = "pool_rpool10\n"); 5437eb2bd662Svikram if (strncmp(signline, GRUBSIGN_UFS_PREFIX, 5438eb2bd662Svikram strlen(GRUBSIGN_UFS_PREFIX))) { 5439eb2bd662Svikram bam_error(INVALID_UFS_SIGNATURE, sign); 5440eb2bd662Svikram free(sign); 5441eb2bd662Svikram /* ignore invalid signatures */ 5442eb2bd662Svikram return (0); 5443eb2bd662Svikram } 5444eb2bd662Svikram 5445eb2bd662Svikram len = fputs(signline, tfp); 5446eb2bd662Svikram error = errno; 5447eb2bd662Svikram INJECT_ERROR1("SIGN_LIST_PUTS_ERROR", len = 0); 5448eb2bd662Svikram if (len != strlen(signline)) { 5449eb2bd662Svikram bam_error(SIGN_LIST_FPUTS_ERR, sign, strerror(error)); 5450eb2bd662Svikram free(sign); 5451eb2bd662Svikram return (-1); 5452eb2bd662Svikram } 5453eb2bd662Svikram 5454eb2bd662Svikram free(sign); 5455eb2bd662Svikram 5456eb2bd662Svikram BAM_DPRINTF((D_SIGN_LIST_PUTS_DONE, fcn, mntpt)); 5457eb2bd662Svikram return (0); 5458eb2bd662Svikram } 5459eb2bd662Svikram 5460eb2bd662Svikram /* 5461eb2bd662Svikram * slice is a basename not a full pathname 5462eb2bd662Svikram */ 5463eb2bd662Svikram static int 5464eb2bd662Svikram process_slice_common(char *slice, FILE *tfp, mhash_t *mhp, char *tmpmnt) 5465eb2bd662Svikram { 5466eb2bd662Svikram int ret; 5467eb2bd662Svikram char cmd[PATH_MAX]; 5468eb2bd662Svikram char path[PATH_MAX]; 5469eb2bd662Svikram struct stat sbuf; 5470eb2bd662Svikram char *mntpt; 5471eb2bd662Svikram filelist_t flist = {0}; 5472eb2bd662Svikram char *fstype; 5473eb2bd662Svikram char blkslice[PATH_MAX]; 5474eb2bd662Svikram const char *fcn = "process_slice_common()"; 5475eb2bd662Svikram 5476eb2bd662Svikram 5477eb2bd662Svikram ret = search_hash(mhp, slice, &mntpt); 5478eb2bd662Svikram switch (ret) { 5479eb2bd662Svikram case MH_MATCH: 5480eb2bd662Svikram if (check_add_ufs_sign_to_list(tfp, mntpt) == -1) 5481eb2bd662Svikram return (-1); 5482eb2bd662Svikram else 5483eb2bd662Svikram return (0); 5484eb2bd662Svikram case MH_NOMATCH: 5485eb2bd662Svikram break; 5486eb2bd662Svikram case MH_ERROR: 5487eb2bd662Svikram default: 5488eb2bd662Svikram return (-1); 5489eb2bd662Svikram } 5490eb2bd662Svikram 5491eb2bd662Svikram (void) snprintf(path, sizeof (path), "/dev/rdsk/%s", slice); 5492eb2bd662Svikram if (stat(path, &sbuf) == -1) { 5493eb2bd662Svikram BAM_DPRINTF((D_SLICE_ENOENT, fcn, path)); 5494eb2bd662Svikram return (0); 5495eb2bd662Svikram } 5496eb2bd662Svikram 5497eb2bd662Svikram /* Check if ufs */ 5498eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), 5499eb2bd662Svikram "/usr/sbin/fstyp /dev/rdsk/%s 2>/dev/null", 5500eb2bd662Svikram slice); 5501eb2bd662Svikram 5502eb2bd662Svikram if (exec_cmd(cmd, &flist) != 0) { 5503eb2bd662Svikram if (bam_verbose) 5504eb2bd662Svikram bam_print(FSTYP_FAILED, slice); 5505eb2bd662Svikram return (0); 5506eb2bd662Svikram } 5507eb2bd662Svikram 5508eb2bd662Svikram if ((flist.head == NULL) || (flist.head != flist.tail)) { 5509eb2bd662Svikram if (bam_verbose) 5510eb2bd662Svikram bam_print(FSTYP_BAD, slice); 5511eb2bd662Svikram filelist_free(&flist); 5512eb2bd662Svikram return (0); 5513eb2bd662Svikram } 5514eb2bd662Svikram 5515eb2bd662Svikram fstype = strtok(flist.head->line, " \t\n"); 5516eb2bd662Svikram if (fstype == NULL || strcmp(fstype, "ufs") != 0) { 5517eb2bd662Svikram if (bam_verbose) 5518eb2bd662Svikram bam_print(NOT_UFS_SLICE, slice, fstype); 5519eb2bd662Svikram filelist_free(&flist); 5520eb2bd662Svikram return (0); 5521eb2bd662Svikram } 5522eb2bd662Svikram 5523eb2bd662Svikram filelist_free(&flist); 5524eb2bd662Svikram 5525eb2bd662Svikram /* 5526eb2bd662Svikram * Since we are mounting the filesystem read-only, the 5527eb2bd662Svikram * the last mount field of the superblock is unchanged 5528eb2bd662Svikram * and does not need to be fixed up post-mount; 5529eb2bd662Svikram */ 5530eb2bd662Svikram 5531eb2bd662Svikram (void) snprintf(blkslice, sizeof (blkslice), "/dev/dsk/%s", 5532eb2bd662Svikram slice); 5533eb2bd662Svikram 5534eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), 5535eb2bd662Svikram "/usr/sbin/mount -F ufs -o ro %s %s " 5536eb2bd662Svikram "> /dev/null 2>&1", blkslice, tmpmnt); 5537eb2bd662Svikram 5538eb2bd662Svikram if (exec_cmd(cmd, NULL) != 0) { 5539eb2bd662Svikram if (bam_verbose) 5540eb2bd662Svikram bam_print(MOUNT_FAILED, blkslice, "ufs"); 5541eb2bd662Svikram return (0); 5542eb2bd662Svikram } 5543eb2bd662Svikram 5544eb2bd662Svikram ret = check_add_ufs_sign_to_list(tfp, tmpmnt); 5545eb2bd662Svikram 5546eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), 5547eb2bd662Svikram "/usr/sbin/umount -f %s > /dev/null 2>&1", 5548eb2bd662Svikram tmpmnt); 5549eb2bd662Svikram 5550eb2bd662Svikram if (exec_cmd(cmd, NULL) != 0) { 5551eb2bd662Svikram bam_print(UMOUNT_FAILED, slice); 5552eb2bd662Svikram return (0); 5553eb2bd662Svikram } 5554eb2bd662Svikram 5555eb2bd662Svikram return (ret); 5556eb2bd662Svikram } 5557eb2bd662Svikram 5558eb2bd662Svikram static int 5559eb2bd662Svikram process_vtoc_slices( 5560eb2bd662Svikram char *s0, 5561eb2bd662Svikram struct vtoc *vtoc, 5562eb2bd662Svikram FILE *tfp, 5563eb2bd662Svikram mhash_t *mhp, 5564eb2bd662Svikram char *tmpmnt) 5565eb2bd662Svikram { 5566eb2bd662Svikram int idx; 5567eb2bd662Svikram char slice[PATH_MAX]; 5568eb2bd662Svikram size_t len; 5569eb2bd662Svikram char *cp; 5570eb2bd662Svikram const char *fcn = "process_vtoc_slices()"; 5571eb2bd662Svikram 5572eb2bd662Svikram len = strlen(s0); 5573eb2bd662Svikram 5574eb2bd662Svikram assert(s0[len - 2] == 's' && s0[len - 1] == '0'); 5575eb2bd662Svikram 5576eb2bd662Svikram s0[len - 1] = '\0'; 5577eb2bd662Svikram 5578eb2bd662Svikram (void) strlcpy(slice, s0, sizeof (slice)); 5579eb2bd662Svikram 5580eb2bd662Svikram s0[len - 1] = '0'; 5581eb2bd662Svikram 5582eb2bd662Svikram cp = slice + len - 1; 5583eb2bd662Svikram 5584eb2bd662Svikram for (idx = 0; idx < vtoc->v_nparts; idx++) { 5585eb2bd662Svikram 5586eb2bd662Svikram (void) snprintf(cp, sizeof (slice) - (len - 1), "%u", idx); 5587eb2bd662Svikram 5588eb2bd662Svikram if (vtoc->v_part[idx].p_size == 0) { 5589eb2bd662Svikram BAM_DPRINTF((D_VTOC_SIZE_ZERO, fcn, slice)); 5590eb2bd662Svikram continue; 5591eb2bd662Svikram } 5592eb2bd662Svikram 5593eb2bd662Svikram /* Skip "SWAP", "USR", "BACKUP", "VAR", "HOME", "ALTSCTR" */ 5594eb2bd662Svikram switch (vtoc->v_part[idx].p_tag) { 5595eb2bd662Svikram case V_SWAP: 5596eb2bd662Svikram case V_USR: 5597eb2bd662Svikram case V_BACKUP: 5598eb2bd662Svikram case V_VAR: 5599eb2bd662Svikram case V_HOME: 5600eb2bd662Svikram case V_ALTSCTR: 5601eb2bd662Svikram BAM_DPRINTF((D_VTOC_NOT_ROOT_TAG, fcn, slice)); 5602eb2bd662Svikram continue; 5603eb2bd662Svikram default: 5604eb2bd662Svikram BAM_DPRINTF((D_VTOC_ROOT_TAG, fcn, slice)); 5605eb2bd662Svikram break; 5606eb2bd662Svikram } 5607eb2bd662Svikram 5608eb2bd662Svikram /* skip unmountable and readonly slices */ 5609eb2bd662Svikram switch (vtoc->v_part[idx].p_flag) { 5610eb2bd662Svikram case V_UNMNT: 5611eb2bd662Svikram case V_RONLY: 5612eb2bd662Svikram BAM_DPRINTF((D_VTOC_NOT_RDWR_FLAG, fcn, slice)); 5613eb2bd662Svikram continue; 5614eb2bd662Svikram default: 5615eb2bd662Svikram BAM_DPRINTF((D_VTOC_RDWR_FLAG, fcn, slice)); 5616eb2bd662Svikram break; 5617eb2bd662Svikram } 5618eb2bd662Svikram 5619eb2bd662Svikram if (process_slice_common(slice, tfp, mhp, tmpmnt) == -1) { 5620eb2bd662Svikram return (-1); 5621eb2bd662Svikram } 5622eb2bd662Svikram } 5623eb2bd662Svikram 5624eb2bd662Svikram return (0); 5625eb2bd662Svikram } 5626eb2bd662Svikram 5627eb2bd662Svikram static int 5628eb2bd662Svikram process_efi_slices( 5629eb2bd662Svikram char *s0, 5630eb2bd662Svikram struct dk_gpt *efi, 5631eb2bd662Svikram FILE *tfp, 5632eb2bd662Svikram mhash_t *mhp, 5633eb2bd662Svikram char *tmpmnt) 5634eb2bd662Svikram { 5635eb2bd662Svikram int idx; 5636eb2bd662Svikram char slice[PATH_MAX]; 5637eb2bd662Svikram size_t len; 5638eb2bd662Svikram char *cp; 5639eb2bd662Svikram const char *fcn = "process_efi_slices()"; 5640eb2bd662Svikram 5641eb2bd662Svikram len = strlen(s0); 5642eb2bd662Svikram 5643eb2bd662Svikram assert(s0[len - 2] == 's' && s0[len - 1] == '0'); 5644eb2bd662Svikram 5645eb2bd662Svikram s0[len - 1] = '\0'; 5646eb2bd662Svikram 5647eb2bd662Svikram (void) strlcpy(slice, s0, sizeof (slice)); 5648eb2bd662Svikram 5649eb2bd662Svikram s0[len - 1] = '0'; 5650eb2bd662Svikram 5651eb2bd662Svikram cp = slice + len - 1; 5652eb2bd662Svikram 5653eb2bd662Svikram for (idx = 0; idx < efi->efi_nparts; idx++) { 5654eb2bd662Svikram 5655eb2bd662Svikram (void) snprintf(cp, sizeof (slice) - (len - 1), "%u", idx); 5656eb2bd662Svikram 5657eb2bd662Svikram if (efi->efi_parts[idx].p_size == 0) { 5658eb2bd662Svikram BAM_DPRINTF((D_EFI_SIZE_ZERO, fcn, slice)); 5659eb2bd662Svikram continue; 5660eb2bd662Svikram } 5661eb2bd662Svikram 5662eb2bd662Svikram /* Skip "SWAP", "USR", "BACKUP", "VAR", "HOME", "ALTSCTR" */ 5663eb2bd662Svikram switch (efi->efi_parts[idx].p_tag) { 5664eb2bd662Svikram case V_SWAP: 5665eb2bd662Svikram case V_USR: 5666eb2bd662Svikram case V_BACKUP: 5667eb2bd662Svikram case V_VAR: 5668eb2bd662Svikram case V_HOME: 5669eb2bd662Svikram case V_ALTSCTR: 5670eb2bd662Svikram BAM_DPRINTF((D_EFI_NOT_ROOT_TAG, fcn, slice)); 5671eb2bd662Svikram continue; 5672eb2bd662Svikram default: 5673eb2bd662Svikram BAM_DPRINTF((D_EFI_ROOT_TAG, fcn, slice)); 5674eb2bd662Svikram break; 5675eb2bd662Svikram } 5676eb2bd662Svikram 5677eb2bd662Svikram /* skip unmountable and readonly slices */ 5678eb2bd662Svikram switch (efi->efi_parts[idx].p_flag) { 5679eb2bd662Svikram case V_UNMNT: 5680eb2bd662Svikram case V_RONLY: 5681eb2bd662Svikram BAM_DPRINTF((D_EFI_NOT_RDWR_FLAG, fcn, slice)); 5682eb2bd662Svikram continue; 5683eb2bd662Svikram default: 5684eb2bd662Svikram BAM_DPRINTF((D_EFI_RDWR_FLAG, fcn, slice)); 5685eb2bd662Svikram break; 5686eb2bd662Svikram } 5687eb2bd662Svikram 5688eb2bd662Svikram if (process_slice_common(slice, tfp, mhp, tmpmnt) == -1) { 5689eb2bd662Svikram return (-1); 5690eb2bd662Svikram } 5691eb2bd662Svikram } 5692eb2bd662Svikram 5693eb2bd662Svikram return (0); 5694eb2bd662Svikram } 5695eb2bd662Svikram 5696eb2bd662Svikram /* 5697eb2bd662Svikram * s0 is a basename not a full path 5698eb2bd662Svikram */ 5699eb2bd662Svikram static int 5700eb2bd662Svikram process_slice0(char *s0, FILE *tfp, mhash_t *mhp, char *tmpmnt) 5701eb2bd662Svikram { 5702eb2bd662Svikram struct vtoc vtoc; 5703eb2bd662Svikram struct dk_gpt *efi; 5704eb2bd662Svikram char s0path[PATH_MAX]; 5705eb2bd662Svikram struct stat sbuf; 5706eb2bd662Svikram int e_flag; 5707eb2bd662Svikram int v_flag; 5708eb2bd662Svikram int retval; 5709eb2bd662Svikram int err; 5710eb2bd662Svikram int fd; 5711eb2bd662Svikram const char *fcn = "process_slice0()"; 5712eb2bd662Svikram 5713eb2bd662Svikram (void) snprintf(s0path, sizeof (s0path), "/dev/rdsk/%s", s0); 5714eb2bd662Svikram 5715eb2bd662Svikram if (stat(s0path, &sbuf) == -1) { 5716eb2bd662Svikram BAM_DPRINTF((D_SLICE0_ENOENT, fcn, s0path)); 5717eb2bd662Svikram return (0); 5718eb2bd662Svikram } 5719eb2bd662Svikram 5720eb2bd662Svikram fd = open(s0path, O_NONBLOCK|O_RDONLY); 5721eb2bd662Svikram if (fd == -1) { 5722eb2bd662Svikram bam_error(OPEN_FAIL, s0path, strerror(errno)); 5723eb2bd662Svikram return (0); 5724eb2bd662Svikram } 5725eb2bd662Svikram 5726eb2bd662Svikram e_flag = v_flag = 0; 5727eb2bd662Svikram retval = ((err = read_vtoc(fd, &vtoc)) >= 0) ? 0 : err; 5728eb2bd662Svikram switch (retval) { 5729eb2bd662Svikram case VT_EIO: 5730eb2bd662Svikram BAM_DPRINTF((D_VTOC_READ_FAIL, fcn, s0path)); 5731eb2bd662Svikram break; 5732eb2bd662Svikram case VT_EINVAL: 5733eb2bd662Svikram BAM_DPRINTF((D_VTOC_INVALID, fcn, s0path)); 5734eb2bd662Svikram break; 5735eb2bd662Svikram case VT_ERROR: 5736eb2bd662Svikram BAM_DPRINTF((D_VTOC_UNKNOWN_ERR, fcn, s0path)); 5737eb2bd662Svikram break; 5738eb2bd662Svikram case VT_ENOTSUP: 5739eb2bd662Svikram e_flag = 1; 5740eb2bd662Svikram BAM_DPRINTF((D_VTOC_NOTSUP, fcn, s0path)); 5741eb2bd662Svikram break; 5742eb2bd662Svikram case 0: 5743eb2bd662Svikram v_flag = 1; 5744eb2bd662Svikram BAM_DPRINTF((D_VTOC_READ_SUCCESS, fcn, s0path)); 5745eb2bd662Svikram break; 5746eb2bd662Svikram default: 5747eb2bd662Svikram BAM_DPRINTF((D_VTOC_UNKNOWN_RETCODE, fcn, s0path)); 5748eb2bd662Svikram break; 5749eb2bd662Svikram } 5750eb2bd662Svikram 5751eb2bd662Svikram 5752eb2bd662Svikram if (e_flag) { 5753eb2bd662Svikram e_flag = 0; 5754eb2bd662Svikram retval = ((err = efi_alloc_and_read(fd, &efi)) >= 0) ? 0 : err; 5755eb2bd662Svikram switch (retval) { 5756eb2bd662Svikram case VT_EIO: 5757eb2bd662Svikram BAM_DPRINTF((D_EFI_READ_FAIL, fcn, s0path)); 5758eb2bd662Svikram break; 5759eb2bd662Svikram case VT_EINVAL: 5760eb2bd662Svikram BAM_DPRINTF((D_EFI_INVALID, fcn, s0path)); 5761eb2bd662Svikram break; 5762eb2bd662Svikram case VT_ERROR: 5763eb2bd662Svikram BAM_DPRINTF((D_EFI_UNKNOWN_ERR, fcn, s0path)); 5764eb2bd662Svikram break; 5765eb2bd662Svikram case VT_ENOTSUP: 5766eb2bd662Svikram BAM_DPRINTF((D_EFI_NOTSUP, fcn, s0path)); 5767eb2bd662Svikram break; 5768eb2bd662Svikram case 0: 5769eb2bd662Svikram e_flag = 1; 5770eb2bd662Svikram BAM_DPRINTF((D_EFI_READ_SUCCESS, fcn, s0path)); 5771eb2bd662Svikram break; 5772eb2bd662Svikram default: 5773eb2bd662Svikram BAM_DPRINTF((D_EFI_UNKNOWN_RETCODE, fcn, s0path)); 5774eb2bd662Svikram break; 5775eb2bd662Svikram } 5776eb2bd662Svikram } 5777eb2bd662Svikram 5778eb2bd662Svikram (void) close(fd); 5779eb2bd662Svikram 5780eb2bd662Svikram if (v_flag) { 5781eb2bd662Svikram retval = process_vtoc_slices(s0, 5782eb2bd662Svikram &vtoc, tfp, mhp, tmpmnt); 5783eb2bd662Svikram } else if (e_flag) { 5784eb2bd662Svikram retval = process_efi_slices(s0, 5785eb2bd662Svikram efi, tfp, mhp, tmpmnt); 5786eb2bd662Svikram } else { 5787eb2bd662Svikram BAM_DPRINTF((D_NOT_VTOC_OR_EFI, fcn, s0path)); 5788eb2bd662Svikram return (0); 5789eb2bd662Svikram } 5790eb2bd662Svikram 5791eb2bd662Svikram return (retval); 5792eb2bd662Svikram } 5793eb2bd662Svikram 5794eb2bd662Svikram /* 5795eb2bd662Svikram * Find and create a list of all existing UFS boot signatures 5796eb2bd662Svikram */ 5797eb2bd662Svikram static int 5798eb2bd662Svikram FindAllUfsSignatures(void) 5799eb2bd662Svikram { 5800eb2bd662Svikram mhash_t *mnttab_hash; 5801eb2bd662Svikram DIR *dirp = NULL; 5802eb2bd662Svikram struct dirent *dp; 5803eb2bd662Svikram char tmpmnt[PATH_MAX]; 5804eb2bd662Svikram char cmd[PATH_MAX]; 5805eb2bd662Svikram struct stat sb; 5806eb2bd662Svikram int fd; 5807eb2bd662Svikram FILE *tfp; 5808eb2bd662Svikram size_t len; 5809eb2bd662Svikram int ret; 5810eb2bd662Svikram int error; 5811eb2bd662Svikram const char *fcn = "FindAllUfsSignatures()"; 5812eb2bd662Svikram 5813eb2bd662Svikram if (stat(UFS_SIGNATURE_LIST, &sb) != -1) { 5814eb2bd662Svikram bam_print(SIGNATURE_LIST_EXISTS, UFS_SIGNATURE_LIST); 5815eb2bd662Svikram return (0); 5816eb2bd662Svikram } 5817eb2bd662Svikram 5818eb2bd662Svikram fd = open(UFS_SIGNATURE_LIST".tmp", 5819eb2bd662Svikram O_RDWR|O_CREAT|O_TRUNC, 0644); 5820eb2bd662Svikram error = errno; 5821eb2bd662Svikram INJECT_ERROR1("SIGN_LIST_TMP_TRUNC", fd = -1); 5822eb2bd662Svikram if (fd == -1) { 5823eb2bd662Svikram bam_error(OPEN_FAIL, UFS_SIGNATURE_LIST".tmp", strerror(error)); 5824eb2bd662Svikram return (-1); 5825eb2bd662Svikram } 5826eb2bd662Svikram 5827eb2bd662Svikram ret = close(fd); 5828eb2bd662Svikram error = errno; 5829eb2bd662Svikram INJECT_ERROR1("SIGN_LIST_TMP_CLOSE", ret = -1); 5830eb2bd662Svikram if (ret == -1) { 5831eb2bd662Svikram bam_error(CLOSE_FAIL, UFS_SIGNATURE_LIST".tmp", 5832eb2bd662Svikram strerror(error)); 5833eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".tmp"); 5834eb2bd662Svikram return (-1); 5835eb2bd662Svikram } 5836eb2bd662Svikram 5837eb2bd662Svikram tfp = fopen(UFS_SIGNATURE_LIST".tmp", "a"); 5838eb2bd662Svikram error = errno; 5839eb2bd662Svikram INJECT_ERROR1("SIGN_LIST_APPEND_FOPEN", tfp = NULL); 5840eb2bd662Svikram if (tfp == NULL) { 5841eb2bd662Svikram bam_error(OPEN_FAIL, UFS_SIGNATURE_LIST".tmp", strerror(error)); 5842eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".tmp"); 5843eb2bd662Svikram return (-1); 5844eb2bd662Svikram } 5845eb2bd662Svikram 5846eb2bd662Svikram mnttab_hash = cache_mnttab(); 5847eb2bd662Svikram INJECT_ERROR1("CACHE_MNTTAB_ERROR", mnttab_hash = NULL); 5848eb2bd662Svikram if (mnttab_hash == NULL) { 5849eb2bd662Svikram (void) fclose(tfp); 5850eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".tmp"); 5851eb2bd662Svikram bam_error(CACHE_MNTTAB_FAIL, fcn); 5852eb2bd662Svikram return (-1); 5853eb2bd662Svikram } 5854eb2bd662Svikram 5855eb2bd662Svikram (void) snprintf(tmpmnt, sizeof (tmpmnt), 5856eb2bd662Svikram "/tmp/bootadm_ufs_sign_mnt.%d", getpid()); 5857eb2bd662Svikram (void) unlink(tmpmnt); 5858eb2bd662Svikram 5859*48847494SEnrico Perla - Sun Microsystems ret = mkdirp(tmpmnt, DIR_PERMS); 5860eb2bd662Svikram error = errno; 5861eb2bd662Svikram INJECT_ERROR1("MKDIRP_SIGN_MNT", ret = -1); 5862eb2bd662Svikram if (ret == -1) { 5863eb2bd662Svikram bam_error(MKDIR_FAILED, tmpmnt, strerror(error)); 5864eb2bd662Svikram free_mnttab(mnttab_hash); 5865eb2bd662Svikram (void) fclose(tfp); 5866eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".tmp"); 5867eb2bd662Svikram return (-1); 5868eb2bd662Svikram } 5869eb2bd662Svikram 5870eb2bd662Svikram dirp = opendir("/dev/rdsk"); 5871eb2bd662Svikram error = errno; 5872eb2bd662Svikram INJECT_ERROR1("OPENDIR_DEV_RDSK", dirp = NULL); 5873eb2bd662Svikram if (dirp == NULL) { 5874eb2bd662Svikram bam_error(OPENDIR_FAILED, "/dev/rdsk", strerror(error)); 5875eb2bd662Svikram goto fail; 5876eb2bd662Svikram } 5877eb2bd662Svikram 5878eb2bd662Svikram while (dp = readdir(dirp)) { 5879eb2bd662Svikram if (strcmp(dp->d_name, ".") == 0 || 5880eb2bd662Svikram strcmp(dp->d_name, "..") == 0) 5881eb2bd662Svikram continue; 5882eb2bd662Svikram 5883eb2bd662Svikram /* 5884eb2bd662Svikram * we only look for the s0 slice. This is guranteed to 5885eb2bd662Svikram * have 's' at len - 2. 5886eb2bd662Svikram */ 5887eb2bd662Svikram len = strlen(dp->d_name); 5888eb2bd662Svikram if (dp->d_name[len - 2 ] != 's' || dp->d_name[len - 1] != '0') { 5889eb2bd662Svikram BAM_DPRINTF((D_SKIP_SLICE_NOTZERO, fcn, dp->d_name)); 5890eb2bd662Svikram continue; 5891eb2bd662Svikram } 5892eb2bd662Svikram 5893eb2bd662Svikram ret = process_slice0(dp->d_name, tfp, mnttab_hash, tmpmnt); 5894eb2bd662Svikram INJECT_ERROR1("PROCESS_S0_FAIL", ret = -1); 5895eb2bd662Svikram if (ret == -1) 5896eb2bd662Svikram goto fail; 5897eb2bd662Svikram } 5898eb2bd662Svikram 5899eb2bd662Svikram (void) closedir(dirp); 5900eb2bd662Svikram free_mnttab(mnttab_hash); 5901eb2bd662Svikram (void) rmdir(tmpmnt); 5902eb2bd662Svikram 5903eb2bd662Svikram ret = fclose(tfp); 5904eb2bd662Svikram error = errno; 5905eb2bd662Svikram INJECT_ERROR1("FCLOSE_SIGNLIST_TMP", ret = EOF); 5906eb2bd662Svikram if (ret == EOF) { 5907eb2bd662Svikram bam_error(CLOSE_FAIL, UFS_SIGNATURE_LIST".tmp", 5908eb2bd662Svikram strerror(error)); 5909eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".tmp"); 5910eb2bd662Svikram return (-1); 5911eb2bd662Svikram } 5912eb2bd662Svikram 5913eb2bd662Svikram /* We have a list of existing GRUB signatures. Sort it first */ 5914eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), 5915eb2bd662Svikram "/usr/bin/sort -u %s.tmp > %s.sorted", 5916eb2bd662Svikram UFS_SIGNATURE_LIST, UFS_SIGNATURE_LIST); 5917eb2bd662Svikram 5918eb2bd662Svikram ret = exec_cmd(cmd, NULL); 5919eb2bd662Svikram INJECT_ERROR1("SORT_SIGN_LIST", ret = 1); 5920eb2bd662Svikram if (ret != 0) { 5921eb2bd662Svikram bam_error(GRUBSIGN_SORT_FAILED); 5922eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".sorted"); 5923eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".tmp"); 5924eb2bd662Svikram return (-1); 5925eb2bd662Svikram } 5926eb2bd662Svikram 5927eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".tmp"); 5928eb2bd662Svikram 5929eb2bd662Svikram ret = rename(UFS_SIGNATURE_LIST".sorted", UFS_SIGNATURE_LIST); 5930eb2bd662Svikram error = errno; 5931eb2bd662Svikram INJECT_ERROR1("RENAME_TMP_SIGNLIST", ret = -1); 5932eb2bd662Svikram if (ret == -1) { 5933eb2bd662Svikram bam_error(RENAME_FAIL, UFS_SIGNATURE_LIST, strerror(error)); 5934eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".sorted"); 5935eb2bd662Svikram return (-1); 5936eb2bd662Svikram } 5937eb2bd662Svikram 5938eb2bd662Svikram if (stat(UFS_SIGNATURE_LIST, &sb) == 0 && sb.st_size == 0) { 5939eb2bd662Svikram BAM_DPRINTF((D_ZERO_LEN_SIGNLIST, fcn, UFS_SIGNATURE_LIST)); 5940eb2bd662Svikram } 5941eb2bd662Svikram 5942eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 5943eb2bd662Svikram return (0); 5944eb2bd662Svikram 5945eb2bd662Svikram fail: 5946eb2bd662Svikram if (dirp) 5947eb2bd662Svikram (void) closedir(dirp); 5948eb2bd662Svikram free_mnttab(mnttab_hash); 5949eb2bd662Svikram (void) rmdir(tmpmnt); 5950eb2bd662Svikram (void) fclose(tfp); 5951eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".tmp"); 5952eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 5953eb2bd662Svikram return (-1); 5954eb2bd662Svikram } 5955eb2bd662Svikram 5956eb2bd662Svikram static char * 5957eb2bd662Svikram create_ufs_sign(void) 5958eb2bd662Svikram { 5959eb2bd662Svikram struct stat sb; 5960eb2bd662Svikram int signnum = -1; 5961eb2bd662Svikram char tmpsign[MAXNAMELEN + 1]; 5962eb2bd662Svikram char *numstr; 5963eb2bd662Svikram int i; 5964eb2bd662Svikram FILE *tfp; 5965eb2bd662Svikram int ret; 5966eb2bd662Svikram int error; 5967eb2bd662Svikram const char *fcn = "create_ufs_sign()"; 5968eb2bd662Svikram 5969eb2bd662Svikram bam_print(SEARCHING_UFS_SIGN); 5970eb2bd662Svikram 5971eb2bd662Svikram ret = FindAllUfsSignatures(); 5972eb2bd662Svikram INJECT_ERROR1("FIND_ALL_UFS", ret = -1); 5973eb2bd662Svikram if (ret == -1) { 5974eb2bd662Svikram bam_error(ERR_FIND_UFS_SIGN); 5975eb2bd662Svikram return (NULL); 5976eb2bd662Svikram } 5977eb2bd662Svikram 5978eb2bd662Svikram /* Make sure the list exists and is owned by root */ 5979eb2bd662Svikram INJECT_ERROR1("SIGNLIST_NOT_CREATED", 5980eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST)); 5981eb2bd662Svikram if (stat(UFS_SIGNATURE_LIST, &sb) == -1 || sb.st_uid != 0) { 5982eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST); 5983eb2bd662Svikram bam_error(UFS_SIGNATURE_LIST_MISS, UFS_SIGNATURE_LIST); 5984eb2bd662Svikram return (NULL); 5985eb2bd662Svikram } 5986eb2bd662Svikram 5987eb2bd662Svikram if (sb.st_size == 0) { 5988eb2bd662Svikram bam_print(GRUBSIGN_UFS_NONE); 5989eb2bd662Svikram i = 0; 5990eb2bd662Svikram goto found; 5991eb2bd662Svikram } 5992eb2bd662Svikram 5993eb2bd662Svikram /* The signature list was sorted when it was created */ 5994eb2bd662Svikram tfp = fopen(UFS_SIGNATURE_LIST, "r"); 5995eb2bd662Svikram error = errno; 5996eb2bd662Svikram INJECT_ERROR1("FOPEN_SIGN_LIST", tfp = NULL); 5997eb2bd662Svikram if (tfp == NULL) { 5998eb2bd662Svikram bam_error(UFS_SIGNATURE_LIST_OPENERR, 5999eb2bd662Svikram UFS_SIGNATURE_LIST, strerror(error)); 6000eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST); 6001eb2bd662Svikram return (NULL); 6002eb2bd662Svikram } 6003eb2bd662Svikram 6004eb2bd662Svikram for (i = 0; s_fgets(tmpsign, sizeof (tmpsign), tfp); i++) { 6005eb2bd662Svikram 6006eb2bd662Svikram if (strncmp(tmpsign, GRUBSIGN_UFS_PREFIX, 6007eb2bd662Svikram strlen(GRUBSIGN_UFS_PREFIX)) != 0) { 6008eb2bd662Svikram (void) fclose(tfp); 6009eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST); 6010eb2bd662Svikram bam_error(UFS_BADSIGN, tmpsign); 6011eb2bd662Svikram return (NULL); 6012eb2bd662Svikram } 6013eb2bd662Svikram numstr = tmpsign + strlen(GRUBSIGN_UFS_PREFIX); 6014eb2bd662Svikram 6015eb2bd662Svikram if (numstr[0] == '\0' || !isdigit(numstr[0])) { 6016eb2bd662Svikram (void) fclose(tfp); 6017eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST); 6018eb2bd662Svikram bam_error(UFS_BADSIGN, tmpsign); 6019eb2bd662Svikram return (NULL); 6020eb2bd662Svikram } 6021eb2bd662Svikram 6022eb2bd662Svikram signnum = atoi(numstr); 6023eb2bd662Svikram INJECT_ERROR1("NEGATIVE_SIGN", signnum = -1); 6024eb2bd662Svikram if (signnum < 0) { 6025eb2bd662Svikram (void) fclose(tfp); 6026eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST); 6027eb2bd662Svikram bam_error(UFS_BADSIGN, tmpsign); 6028eb2bd662Svikram return (NULL); 6029eb2bd662Svikram } 6030eb2bd662Svikram 6031eb2bd662Svikram if (i != signnum) { 6032eb2bd662Svikram BAM_DPRINTF((D_FOUND_HOLE_SIGNLIST, fcn, i)); 6033eb2bd662Svikram break; 6034eb2bd662Svikram } 6035eb2bd662Svikram } 6036eb2bd662Svikram 6037eb2bd662Svikram (void) fclose(tfp); 6038eb2bd662Svikram 6039eb2bd662Svikram found: 6040eb2bd662Svikram (void) snprintf(tmpsign, sizeof (tmpsign), "rootfs%d", i); 6041eb2bd662Svikram 6042eb2bd662Svikram /* add the ufs signature to the /var/run list of signatures */ 6043eb2bd662Svikram ret = ufs_add_to_sign_list(tmpsign); 6044eb2bd662Svikram INJECT_ERROR1("UFS_ADD_TO_SIGN_LIST", ret = -1); 6045eb2bd662Svikram if (ret == -1) { 6046eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST); 6047eb2bd662Svikram bam_error(FAILED_ADD_SIGNLIST, tmpsign); 6048eb2bd662Svikram return (NULL); 6049eb2bd662Svikram } 6050eb2bd662Svikram 6051eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 6052eb2bd662Svikram 6053eb2bd662Svikram return (s_strdup(tmpsign)); 6054eb2bd662Svikram } 6055eb2bd662Svikram 6056eb2bd662Svikram static char * 6057eb2bd662Svikram get_fstype(char *osroot) 6058eb2bd662Svikram { 6059eb2bd662Svikram FILE *mntfp; 6060eb2bd662Svikram struct mnttab mp = {0}; 6061eb2bd662Svikram struct mnttab mpref = {0}; 6062eb2bd662Svikram int error; 6063eb2bd662Svikram int ret; 6064eb2bd662Svikram const char *fcn = "get_fstype()"; 6065eb2bd662Svikram 6066eb2bd662Svikram INJECT_ERROR1("GET_FSTYPE_OSROOT", osroot = NULL); 6067eb2bd662Svikram if (osroot == NULL) { 6068eb2bd662Svikram bam_error(GET_FSTYPE_ARGS); 6069eb2bd662Svikram return (NULL); 6070eb2bd662Svikram } 6071eb2bd662Svikram 6072eb2bd662Svikram mntfp = fopen(MNTTAB, "r"); 6073eb2bd662Svikram error = errno; 6074eb2bd662Svikram INJECT_ERROR1("GET_FSTYPE_FOPEN", mntfp = NULL); 6075eb2bd662Svikram if (mntfp == NULL) { 6076eb2bd662Svikram bam_error(OPEN_FAIL, MNTTAB, strerror(error)); 6077eb2bd662Svikram return (NULL); 6078eb2bd662Svikram } 6079eb2bd662Svikram 6080eb2bd662Svikram if (*osroot == '\0') 6081eb2bd662Svikram mpref.mnt_mountp = "/"; 6082eb2bd662Svikram else 6083eb2bd662Svikram mpref.mnt_mountp = osroot; 6084eb2bd662Svikram 6085eb2bd662Svikram ret = getmntany(mntfp, &mp, &mpref); 6086eb2bd662Svikram INJECT_ERROR1("GET_FSTYPE_GETMNTANY", ret = 1); 6087eb2bd662Svikram if (ret != 0) { 6088eb2bd662Svikram bam_error(MNTTAB_MNTPT_NOT_FOUND, osroot, MNTTAB); 6089eb2bd662Svikram (void) fclose(mntfp); 6090eb2bd662Svikram return (NULL); 6091eb2bd662Svikram } 6092eb2bd662Svikram (void) fclose(mntfp); 6093eb2bd662Svikram 6094eb2bd662Svikram INJECT_ERROR1("GET_FSTYPE_NULL", mp.mnt_fstype = NULL); 6095eb2bd662Svikram if (mp.mnt_fstype == NULL) { 6096eb2bd662Svikram bam_error(MNTTAB_FSTYPE_NULL, osroot); 6097eb2bd662Svikram return (NULL); 6098eb2bd662Svikram } 6099eb2bd662Svikram 6100eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 6101eb2bd662Svikram 6102eb2bd662Svikram return (s_strdup(mp.mnt_fstype)); 6103eb2bd662Svikram } 6104eb2bd662Svikram 6105eb2bd662Svikram static char * 6106eb2bd662Svikram create_zfs_sign(char *osdev) 6107eb2bd662Svikram { 6108eb2bd662Svikram char tmpsign[PATH_MAX]; 6109eb2bd662Svikram char *pool; 6110eb2bd662Svikram const char *fcn = "create_zfs_sign()"; 6111eb2bd662Svikram 6112eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY1, fcn, osdev)); 6113eb2bd662Svikram 6114eb2bd662Svikram /* 6115eb2bd662Svikram * First find the pool name 6116eb2bd662Svikram */ 6117eb2bd662Svikram pool = get_pool(osdev); 6118eb2bd662Svikram INJECT_ERROR1("CREATE_ZFS_SIGN_GET_POOL", pool = NULL); 6119eb2bd662Svikram if (pool == NULL) { 6120eb2bd662Svikram bam_error(GET_POOL_FAILED, osdev); 6121eb2bd662Svikram return (NULL); 6122eb2bd662Svikram } 6123eb2bd662Svikram 6124eb2bd662Svikram (void) snprintf(tmpsign, sizeof (tmpsign), "pool_%s", pool); 6125eb2bd662Svikram 6126eb2bd662Svikram BAM_DPRINTF((D_CREATED_ZFS_SIGN, fcn, tmpsign)); 6127eb2bd662Svikram 6128eb2bd662Svikram free(pool); 6129eb2bd662Svikram 6130eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 6131eb2bd662Svikram 6132eb2bd662Svikram return (s_strdup(tmpsign)); 6133eb2bd662Svikram } 6134eb2bd662Svikram 6135eb2bd662Svikram static char * 6136eb2bd662Svikram create_new_sign(char *osdev, char *fstype) 6137eb2bd662Svikram { 6138eb2bd662Svikram char *sign; 6139eb2bd662Svikram const char *fcn = "create_new_sign()"; 6140eb2bd662Svikram 6141eb2bd662Svikram INJECT_ERROR1("NEW_SIGN_FSTYPE", fstype = "foofs"); 6142eb2bd662Svikram 6143eb2bd662Svikram if (strcmp(fstype, "zfs") == 0) { 6144eb2bd662Svikram BAM_DPRINTF((D_CREATE_NEW_ZFS, fcn)); 6145eb2bd662Svikram sign = create_zfs_sign(osdev); 6146eb2bd662Svikram } else if (strcmp(fstype, "ufs") == 0) { 6147eb2bd662Svikram BAM_DPRINTF((D_CREATE_NEW_UFS, fcn)); 6148eb2bd662Svikram sign = create_ufs_sign(); 6149eb2bd662Svikram } else { 6150eb2bd662Svikram bam_error(GRUBSIGN_NOTSUP, fstype); 6151eb2bd662Svikram sign = NULL; 6152eb2bd662Svikram } 6153eb2bd662Svikram 6154eb2bd662Svikram BAM_DPRINTF((D_CREATED_NEW_SIGN, fcn, sign ? sign : "<NULL>")); 6155eb2bd662Svikram return (sign); 6156eb2bd662Svikram } 6157eb2bd662Svikram 6158eb2bd662Svikram static int 6159eb2bd662Svikram set_backup_common(char *mntpt, char *sign) 6160eb2bd662Svikram { 6161eb2bd662Svikram FILE *bfp; 6162eb2bd662Svikram char backup[PATH_MAX]; 6163eb2bd662Svikram char tmpsign[PATH_MAX]; 6164eb2bd662Svikram int error; 6165eb2bd662Svikram char *bdir; 6166eb2bd662Svikram char *backup_dup; 6167eb2bd662Svikram struct stat sb; 6168eb2bd662Svikram int ret; 6169eb2bd662Svikram const char *fcn = "set_backup_common()"; 6170eb2bd662Svikram 6171eb2bd662Svikram (void) snprintf(backup, sizeof (backup), "%s%s", 6172eb2bd662Svikram mntpt, GRUBSIGN_BACKUP); 6173eb2bd662Svikram 6174eb2bd662Svikram /* First read the backup */ 6175eb2bd662Svikram bfp = fopen(backup, "r"); 6176eb2bd662Svikram if (bfp != NULL) { 6177eb2bd662Svikram while (s_fgets(tmpsign, sizeof (tmpsign), bfp)) { 6178eb2bd662Svikram if (strcmp(tmpsign, sign) == 0) { 6179eb2bd662Svikram BAM_DPRINTF((D_FOUND_IN_BACKUP, fcn, sign)); 6180eb2bd662Svikram (void) fclose(bfp); 6181eb2bd662Svikram return (0); 6182eb2bd662Svikram } 6183eb2bd662Svikram } 6184eb2bd662Svikram (void) fclose(bfp); 6185eb2bd662Svikram BAM_DPRINTF((D_NOT_FOUND_IN_EXIST_BACKUP, fcn, sign)); 6186eb2bd662Svikram } else { 6187eb2bd662Svikram BAM_DPRINTF((D_BACKUP_NOT_EXIST, fcn, backup)); 6188eb2bd662Svikram } 6189eb2bd662Svikram 6190eb2bd662Svikram /* 6191eb2bd662Svikram * Didn't find the correct signature. First create 6192eb2bd662Svikram * the directory if necessary. 6193eb2bd662Svikram */ 6194eb2bd662Svikram 6195eb2bd662Svikram /* dirname() modifies its argument so dup it */ 6196eb2bd662Svikram backup_dup = s_strdup(backup); 6197eb2bd662Svikram bdir = dirname(backup_dup); 6198eb2bd662Svikram assert(bdir); 6199eb2bd662Svikram 6200eb2bd662Svikram ret = stat(bdir, &sb); 6201eb2bd662Svikram INJECT_ERROR1("SET_BACKUP_STAT", ret = -1); 6202eb2bd662Svikram if (ret == -1) { 6203eb2bd662Svikram BAM_DPRINTF((D_BACKUP_DIR_NOEXIST, fcn, bdir)); 6204*48847494SEnrico Perla - Sun Microsystems ret = mkdirp(bdir, DIR_PERMS); 6205eb2bd662Svikram error = errno; 6206eb2bd662Svikram INJECT_ERROR1("SET_BACKUP_MKDIRP", ret = -1); 6207eb2bd662Svikram if (ret == -1) { 6208eb2bd662Svikram bam_error(GRUBSIGN_BACKUP_MKDIRERR, 6209eb2bd662Svikram GRUBSIGN_BACKUP, strerror(error)); 6210eb2bd662Svikram free(backup_dup); 6211eb2bd662Svikram return (-1); 6212eb2bd662Svikram } 6213eb2bd662Svikram } 6214eb2bd662Svikram free(backup_dup); 6215eb2bd662Svikram 6216eb2bd662Svikram /* 6217eb2bd662Svikram * Open the backup in append mode to add the correct 6218eb2bd662Svikram * signature; 6219eb2bd662Svikram */ 6220eb2bd662Svikram bfp = fopen(backup, "a"); 6221eb2bd662Svikram error = errno; 6222eb2bd662Svikram INJECT_ERROR1("SET_BACKUP_FOPEN_A", bfp = NULL); 6223eb2bd662Svikram if (bfp == NULL) { 6224eb2bd662Svikram bam_error(GRUBSIGN_BACKUP_OPENERR, 6225eb2bd662Svikram GRUBSIGN_BACKUP, strerror(error)); 6226eb2bd662Svikram return (-1); 6227eb2bd662Svikram } 6228eb2bd662Svikram 6229eb2bd662Svikram (void) snprintf(tmpsign, sizeof (tmpsign), "%s\n", sign); 6230eb2bd662Svikram 6231eb2bd662Svikram ret = fputs(tmpsign, bfp); 6232eb2bd662Svikram error = errno; 6233eb2bd662Svikram INJECT_ERROR1("SET_BACKUP_FPUTS", ret = 0); 6234eb2bd662Svikram if (ret != strlen(tmpsign)) { 6235eb2bd662Svikram bam_error(GRUBSIGN_BACKUP_WRITEERR, 6236eb2bd662Svikram GRUBSIGN_BACKUP, strerror(error)); 6237eb2bd662Svikram (void) fclose(bfp); 6238eb2bd662Svikram return (-1); 6239eb2bd662Svikram } 6240eb2bd662Svikram 6241eb2bd662Svikram (void) fclose(bfp); 6242eb2bd662Svikram 6243eb2bd662Svikram if (bam_verbose) 6244eb2bd662Svikram bam_print(GRUBSIGN_BACKUP_UPDATED, GRUBSIGN_BACKUP); 6245eb2bd662Svikram 6246eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 6247eb2bd662Svikram 6248eb2bd662Svikram return (0); 6249eb2bd662Svikram } 6250eb2bd662Svikram 6251eb2bd662Svikram static int 6252eb2bd662Svikram set_backup_ufs(char *osroot, char *sign) 6253eb2bd662Svikram { 6254eb2bd662Svikram const char *fcn = "set_backup_ufs()"; 6255eb2bd662Svikram 6256eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY2, fcn, osroot, sign)); 6257eb2bd662Svikram return (set_backup_common(osroot, sign)); 6258eb2bd662Svikram } 6259eb2bd662Svikram 6260eb2bd662Svikram static int 6261eb2bd662Svikram set_backup_zfs(char *osdev, char *sign) 6262eb2bd662Svikram { 6263eb2bd662Svikram char *pool; 6264eb2bd662Svikram char *mntpt; 6265eb2bd662Svikram zfs_mnted_t mnted; 6266eb2bd662Svikram int ret; 6267eb2bd662Svikram const char *fcn = "set_backup_zfs()"; 6268eb2bd662Svikram 6269eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY2, fcn, osdev, sign)); 6270eb2bd662Svikram 6271eb2bd662Svikram pool = get_pool(osdev); 6272eb2bd662Svikram INJECT_ERROR1("SET_BACKUP_GET_POOL", pool = NULL); 6273eb2bd662Svikram if (pool == NULL) { 6274eb2bd662Svikram bam_error(GET_POOL_FAILED, osdev); 6275eb2bd662Svikram return (-1); 6276eb2bd662Svikram } 6277eb2bd662Svikram 6278eb2bd662Svikram mntpt = mount_top_dataset(pool, &mnted); 6279eb2bd662Svikram INJECT_ERROR1("SET_BACKUP_MOUNT_DATASET", mntpt = NULL); 6280eb2bd662Svikram if (mntpt == NULL) { 6281eb2bd662Svikram bam_error(FAIL_MNT_TOP_DATASET, pool); 6282eb2bd662Svikram free(pool); 6283eb2bd662Svikram return (-1); 6284eb2bd662Svikram } 6285eb2bd662Svikram 6286eb2bd662Svikram ret = set_backup_common(mntpt, sign); 6287eb2bd662Svikram 6288eb2bd662Svikram (void) umount_top_dataset(pool, mnted, mntpt); 6289eb2bd662Svikram 6290eb2bd662Svikram free(pool); 6291eb2bd662Svikram 6292eb2bd662Svikram INJECT_ERROR1("SET_BACKUP_ZFS_FAIL", ret = 1); 6293eb2bd662Svikram if (ret == 0) { 6294eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 6295eb2bd662Svikram } else { 6296eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 6297eb2bd662Svikram } 6298eb2bd662Svikram 6299eb2bd662Svikram return (ret); 6300eb2bd662Svikram } 6301eb2bd662Svikram 6302eb2bd662Svikram static int 6303eb2bd662Svikram set_backup(char *osroot, char *osdev, char *sign, char *fstype) 6304eb2bd662Svikram { 6305eb2bd662Svikram const char *fcn = "set_backup()"; 6306eb2bd662Svikram int ret; 6307eb2bd662Svikram 6308eb2bd662Svikram INJECT_ERROR1("SET_BACKUP_FSTYPE", fstype = "foofs"); 6309eb2bd662Svikram 6310eb2bd662Svikram if (strcmp(fstype, "ufs") == 0) { 6311eb2bd662Svikram BAM_DPRINTF((D_SET_BACKUP_UFS, fcn)); 6312eb2bd662Svikram ret = set_backup_ufs(osroot, sign); 6313eb2bd662Svikram } else if (strcmp(fstype, "zfs") == 0) { 6314eb2bd662Svikram BAM_DPRINTF((D_SET_BACKUP_ZFS, fcn)); 6315eb2bd662Svikram ret = set_backup_zfs(osdev, sign); 6316eb2bd662Svikram } else { 6317eb2bd662Svikram bam_error(GRUBSIGN_NOTSUP, fstype); 6318eb2bd662Svikram ret = -1; 6319eb2bd662Svikram } 6320eb2bd662Svikram 6321eb2bd662Svikram if (ret == 0) { 6322eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 6323eb2bd662Svikram } else { 6324eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 6325eb2bd662Svikram } 6326eb2bd662Svikram 6327eb2bd662Svikram return (ret); 6328eb2bd662Svikram } 6329eb2bd662Svikram 6330eb2bd662Svikram static int 6331eb2bd662Svikram set_primary_common(char *mntpt, char *sign) 6332eb2bd662Svikram { 6333eb2bd662Svikram char signfile[PATH_MAX]; 6334eb2bd662Svikram char signdir[PATH_MAX]; 6335eb2bd662Svikram struct stat sb; 6336eb2bd662Svikram int fd; 6337eb2bd662Svikram int error; 6338eb2bd662Svikram int ret; 6339eb2bd662Svikram const char *fcn = "set_primary_common()"; 6340eb2bd662Svikram 6341eb2bd662Svikram (void) snprintf(signfile, sizeof (signfile), "%s/%s/%s", 6342eb2bd662Svikram mntpt, GRUBSIGN_DIR, sign); 6343eb2bd662Svikram 6344eb2bd662Svikram if (stat(signfile, &sb) != -1) { 6345eb2bd662Svikram if (bam_verbose) 6346eb2bd662Svikram bam_print(PRIMARY_SIGN_EXISTS, sign); 6347eb2bd662Svikram return (0); 6348eb2bd662Svikram } else { 6349eb2bd662Svikram BAM_DPRINTF((D_PRIMARY_NOT_EXIST, fcn, signfile)); 6350eb2bd662Svikram } 6351eb2bd662Svikram 6352eb2bd662Svikram (void) snprintf(signdir, sizeof (signdir), "%s/%s", 6353eb2bd662Svikram mntpt, GRUBSIGN_DIR); 6354eb2bd662Svikram 6355eb2bd662Svikram if (stat(signdir, &sb) == -1) { 6356eb2bd662Svikram BAM_DPRINTF((D_PRIMARY_DIR_NOEXIST, fcn, signdir)); 6357*48847494SEnrico Perla - Sun Microsystems ret = mkdirp(signdir, DIR_PERMS); 6358eb2bd662Svikram error = errno; 6359eb2bd662Svikram INJECT_ERROR1("SET_PRIMARY_MKDIRP", ret = -1); 6360eb2bd662Svikram if (ret == -1) { 6361eb2bd662Svikram bam_error(GRUBSIGN_MKDIR_ERR, signdir, strerror(errno)); 6362eb2bd662Svikram return (-1); 6363eb2bd662Svikram } 6364eb2bd662Svikram } 6365eb2bd662Svikram 6366eb2bd662Svikram fd = open(signfile, O_RDWR|O_CREAT|O_TRUNC, 0444); 6367eb2bd662Svikram error = errno; 6368eb2bd662Svikram INJECT_ERROR1("PRIMARY_SIGN_CREAT", fd = -1); 6369eb2bd662Svikram if (fd == -1) { 6370eb2bd662Svikram bam_error(GRUBSIGN_PRIMARY_CREATERR, signfile, strerror(error)); 6371eb2bd662Svikram return (-1); 6372eb2bd662Svikram } 6373eb2bd662Svikram 6374eb2bd662Svikram ret = fsync(fd); 6375eb2bd662Svikram error = errno; 6376eb2bd662Svikram INJECT_ERROR1("PRIMARY_FSYNC", ret = -1); 6377eb2bd662Svikram if (ret != 0) { 6378eb2bd662Svikram bam_error(GRUBSIGN_PRIMARY_SYNCERR, signfile, strerror(error)); 6379eb2bd662Svikram } 6380eb2bd662Svikram 6381eb2bd662Svikram (void) close(fd); 6382eb2bd662Svikram 6383eb2bd662Svikram if (bam_verbose) 6384eb2bd662Svikram bam_print(GRUBSIGN_CREATED_PRIMARY, signfile); 6385eb2bd662Svikram 6386eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 6387eb2bd662Svikram 6388eb2bd662Svikram return (0); 6389eb2bd662Svikram } 6390eb2bd662Svikram 6391eb2bd662Svikram static int 6392eb2bd662Svikram set_primary_ufs(char *osroot, char *sign) 6393eb2bd662Svikram { 6394eb2bd662Svikram const char *fcn = "set_primary_ufs()"; 6395eb2bd662Svikram 6396eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY2, fcn, osroot, sign)); 6397eb2bd662Svikram return (set_primary_common(osroot, sign)); 6398eb2bd662Svikram } 6399eb2bd662Svikram 6400eb2bd662Svikram static int 6401eb2bd662Svikram set_primary_zfs(char *osdev, char *sign) 6402eb2bd662Svikram { 6403eb2bd662Svikram char *pool; 6404eb2bd662Svikram char *mntpt; 6405eb2bd662Svikram zfs_mnted_t mnted; 6406eb2bd662Svikram int ret; 6407eb2bd662Svikram const char *fcn = "set_primary_zfs()"; 6408eb2bd662Svikram 6409eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY2, fcn, osdev, sign)); 6410eb2bd662Svikram 6411eb2bd662Svikram pool = get_pool(osdev); 6412eb2bd662Svikram INJECT_ERROR1("SET_PRIMARY_ZFS_GET_POOL", pool = NULL); 6413eb2bd662Svikram if (pool == NULL) { 6414eb2bd662Svikram bam_error(GET_POOL_FAILED, osdev); 6415eb2bd662Svikram return (-1); 6416eb2bd662Svikram } 6417eb2bd662Svikram 6418eb2bd662Svikram /* Pool name must exist in the sign */ 6419eb2bd662Svikram ret = (strstr(sign, pool) != NULL); 6420eb2bd662Svikram INJECT_ERROR1("SET_PRIMARY_ZFS_POOL_SIGN_INCOMPAT", ret = 0); 6421eb2bd662Svikram if (ret == 0) { 6422eb2bd662Svikram bam_error(POOL_SIGN_INCOMPAT, pool, sign); 6423eb2bd662Svikram free(pool); 6424eb2bd662Svikram return (-1); 6425eb2bd662Svikram } 6426eb2bd662Svikram 6427eb2bd662Svikram mntpt = mount_top_dataset(pool, &mnted); 6428eb2bd662Svikram INJECT_ERROR1("SET_PRIMARY_ZFS_MOUNT_DATASET", mntpt = NULL); 6429eb2bd662Svikram if (mntpt == NULL) { 6430eb2bd662Svikram bam_error(FAIL_MNT_TOP_DATASET, pool); 6431eb2bd662Svikram free(pool); 6432eb2bd662Svikram return (-1); 6433eb2bd662Svikram } 6434eb2bd662Svikram 6435eb2bd662Svikram ret = set_primary_common(mntpt, sign); 6436eb2bd662Svikram 6437eb2bd662Svikram (void) umount_top_dataset(pool, mnted, mntpt); 6438eb2bd662Svikram 6439eb2bd662Svikram free(pool); 6440eb2bd662Svikram 6441eb2bd662Svikram INJECT_ERROR1("SET_PRIMARY_ZFS_FAIL", ret = 1); 6442eb2bd662Svikram if (ret == 0) { 6443eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 6444eb2bd662Svikram } else { 6445eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 6446eb2bd662Svikram } 6447eb2bd662Svikram 6448eb2bd662Svikram return (ret); 6449eb2bd662Svikram } 6450eb2bd662Svikram 6451eb2bd662Svikram static int 6452eb2bd662Svikram set_primary(char *osroot, char *osdev, char *sign, char *fstype) 6453eb2bd662Svikram { 6454eb2bd662Svikram const char *fcn = "set_primary()"; 6455eb2bd662Svikram int ret; 6456eb2bd662Svikram 6457eb2bd662Svikram INJECT_ERROR1("SET_PRIMARY_FSTYPE", fstype = "foofs"); 6458eb2bd662Svikram if (strcmp(fstype, "ufs") == 0) { 6459eb2bd662Svikram BAM_DPRINTF((D_SET_PRIMARY_UFS, fcn)); 6460eb2bd662Svikram ret = set_primary_ufs(osroot, sign); 6461eb2bd662Svikram } else if (strcmp(fstype, "zfs") == 0) { 6462eb2bd662Svikram BAM_DPRINTF((D_SET_PRIMARY_ZFS, fcn)); 6463eb2bd662Svikram ret = set_primary_zfs(osdev, sign); 6464eb2bd662Svikram } else { 6465eb2bd662Svikram bam_error(GRUBSIGN_NOTSUP, fstype); 6466eb2bd662Svikram ret = -1; 6467eb2bd662Svikram } 6468eb2bd662Svikram 6469eb2bd662Svikram if (ret == 0) { 6470eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 6471eb2bd662Svikram } else { 6472eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 6473eb2bd662Svikram } 6474eb2bd662Svikram 6475eb2bd662Svikram return (ret); 6476eb2bd662Svikram } 6477eb2bd662Svikram 6478eb2bd662Svikram static int 6479eb2bd662Svikram ufs_add_to_sign_list(char *sign) 6480eb2bd662Svikram { 6481eb2bd662Svikram FILE *tfp; 6482eb2bd662Svikram char signline[MAXNAMELEN]; 6483eb2bd662Svikram char cmd[PATH_MAX]; 6484eb2bd662Svikram int ret; 6485eb2bd662Svikram int error; 6486eb2bd662Svikram const char *fcn = "ufs_add_to_sign_list()"; 6487eb2bd662Svikram 6488eb2bd662Svikram INJECT_ERROR1("ADD_TO_SIGN_LIST_NOT_UFS", sign = "pool_rpool5"); 6489eb2bd662Svikram if (strncmp(sign, GRUBSIGN_UFS_PREFIX, 6490eb2bd662Svikram strlen(GRUBSIGN_UFS_PREFIX)) != 0) { 6491eb2bd662Svikram bam_error(INVALID_UFS_SIGN, sign); 6492eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST); 6493eb2bd662Svikram return (-1); 6494eb2bd662Svikram } 6495eb2bd662Svikram 6496eb2bd662Svikram /* 6497eb2bd662Svikram * most failures in this routine are not a fatal error 6498eb2bd662Svikram * We simply unlink the /var/run file and continue 6499eb2bd662Svikram */ 6500eb2bd662Svikram 6501eb2bd662Svikram ret = rename(UFS_SIGNATURE_LIST, UFS_SIGNATURE_LIST".tmp"); 6502eb2bd662Svikram error = errno; 6503eb2bd662Svikram INJECT_ERROR1("ADD_TO_SIGN_LIST_RENAME", ret = -1); 6504eb2bd662Svikram if (ret == -1) { 6505eb2bd662Svikram bam_error(RENAME_FAIL, UFS_SIGNATURE_LIST".tmp", 6506eb2bd662Svikram strerror(error)); 6507eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST); 6508eb2bd662Svikram return (0); 6509eb2bd662Svikram } 6510eb2bd662Svikram 6511eb2bd662Svikram tfp = fopen(UFS_SIGNATURE_LIST".tmp", "a"); 6512eb2bd662Svikram error = errno; 6513eb2bd662Svikram INJECT_ERROR1("ADD_TO_SIGN_LIST_FOPEN", tfp = NULL); 6514eb2bd662Svikram if (tfp == NULL) { 6515eb2bd662Svikram bam_error(OPEN_FAIL, UFS_SIGNATURE_LIST".tmp", strerror(error)); 6516eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".tmp"); 6517eb2bd662Svikram return (0); 6518eb2bd662Svikram } 6519eb2bd662Svikram 6520eb2bd662Svikram (void) snprintf(signline, sizeof (signline), "%s\n", sign); 6521eb2bd662Svikram 6522eb2bd662Svikram ret = fputs(signline, tfp); 6523eb2bd662Svikram error = errno; 6524eb2bd662Svikram INJECT_ERROR1("ADD_TO_SIGN_LIST_FPUTS", ret = 0); 6525eb2bd662Svikram if (ret != strlen(signline)) { 6526eb2bd662Svikram bam_error(SIGN_LIST_FPUTS_ERR, sign, strerror(error)); 6527eb2bd662Svikram (void) fclose(tfp); 6528eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".tmp"); 6529eb2bd662Svikram return (0); 6530eb2bd662Svikram } 6531eb2bd662Svikram 6532eb2bd662Svikram ret = fclose(tfp); 6533eb2bd662Svikram error = errno; 6534eb2bd662Svikram INJECT_ERROR1("ADD_TO_SIGN_LIST_FCLOSE", ret = EOF); 6535eb2bd662Svikram if (ret == EOF) { 6536eb2bd662Svikram bam_error(CLOSE_FAIL, UFS_SIGNATURE_LIST".tmp", 6537eb2bd662Svikram strerror(error)); 6538eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".tmp"); 6539eb2bd662Svikram return (0); 6540eb2bd662Svikram } 6541eb2bd662Svikram 6542eb2bd662Svikram /* Sort the list again */ 6543eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), 6544eb2bd662Svikram "/usr/bin/sort -u %s.tmp > %s.sorted", 6545eb2bd662Svikram UFS_SIGNATURE_LIST, UFS_SIGNATURE_LIST); 6546eb2bd662Svikram 6547eb2bd662Svikram ret = exec_cmd(cmd, NULL); 6548eb2bd662Svikram INJECT_ERROR1("ADD_TO_SIGN_LIST_SORT", ret = 1); 6549eb2bd662Svikram if (ret != 0) { 6550eb2bd662Svikram bam_error(GRUBSIGN_SORT_FAILED); 6551eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".sorted"); 6552eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".tmp"); 6553eb2bd662Svikram return (0); 6554eb2bd662Svikram } 6555eb2bd662Svikram 6556eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".tmp"); 6557eb2bd662Svikram 6558eb2bd662Svikram ret = rename(UFS_SIGNATURE_LIST".sorted", UFS_SIGNATURE_LIST); 6559eb2bd662Svikram error = errno; 6560eb2bd662Svikram INJECT_ERROR1("ADD_TO_SIGN_LIST_RENAME2", ret = -1); 6561eb2bd662Svikram if (ret == -1) { 6562eb2bd662Svikram bam_error(RENAME_FAIL, UFS_SIGNATURE_LIST, strerror(error)); 6563eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST".sorted"); 6564eb2bd662Svikram return (0); 6565eb2bd662Svikram } 6566eb2bd662Svikram 6567eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 6568eb2bd662Svikram 6569eb2bd662Svikram return (0); 6570eb2bd662Svikram } 6571eb2bd662Svikram 6572eb2bd662Svikram static int 6573eb2bd662Svikram set_signature(char *osroot, char *osdev, char *sign, char *fstype) 6574eb2bd662Svikram { 6575eb2bd662Svikram int ret; 6576eb2bd662Svikram const char *fcn = "set_signature()"; 6577eb2bd662Svikram 6578eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY4, fcn, osroot, osdev, sign, fstype)); 6579eb2bd662Svikram 6580eb2bd662Svikram ret = set_backup(osroot, osdev, sign, fstype); 6581eb2bd662Svikram INJECT_ERROR1("SET_SIGNATURE_BACKUP", ret = -1); 6582eb2bd662Svikram if (ret == -1) { 6583eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 6584eb2bd662Svikram bam_error(SET_BACKUP_FAILED, sign, osroot, osdev); 6585eb2bd662Svikram return (-1); 6586eb2bd662Svikram } 6587eb2bd662Svikram 6588eb2bd662Svikram ret = set_primary(osroot, osdev, sign, fstype); 6589eb2bd662Svikram INJECT_ERROR1("SET_SIGNATURE_PRIMARY", ret = -1); 6590eb2bd662Svikram 6591eb2bd662Svikram if (ret == 0) { 6592eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 6593eb2bd662Svikram } else { 6594eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 6595eb2bd662Svikram bam_error(SET_PRIMARY_FAILED, sign, osroot, osdev); 6596eb2bd662Svikram 6597eb2bd662Svikram } 6598eb2bd662Svikram return (ret); 6599eb2bd662Svikram } 6600eb2bd662Svikram 6601eb2bd662Svikram char * 6602eb2bd662Svikram get_grubsign(char *osroot, char *osdev) 6603eb2bd662Svikram { 6604eb2bd662Svikram char *grubsign; /* (<sign>,#,#) */ 6605eb2bd662Svikram char *slice; 6606eb2bd662Svikram int fdiskpart; 6607eb2bd662Svikram char *sign; 6608eb2bd662Svikram char *fstype; 6609eb2bd662Svikram int ret; 6610eb2bd662Svikram const char *fcn = "get_grubsign()"; 6611eb2bd662Svikram 6612eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY2, fcn, osroot, osdev)); 6613eb2bd662Svikram 6614eb2bd662Svikram fstype = get_fstype(osroot); 6615eb2bd662Svikram INJECT_ERROR1("GET_GRUBSIGN_FSTYPE", fstype = NULL); 6616eb2bd662Svikram if (fstype == NULL) { 6617eb2bd662Svikram bam_error(GET_FSTYPE_FAILED, osroot); 6618eb2bd662Svikram return (NULL); 6619eb2bd662Svikram } 6620eb2bd662Svikram 6621eb2bd662Svikram sign = find_existing_sign(osroot, osdev, fstype); 6622eb2bd662Svikram INJECT_ERROR1("FIND_EXISTING_SIGN", sign = NULL); 6623eb2bd662Svikram if (sign == NULL) { 6624eb2bd662Svikram BAM_DPRINTF((D_GET_GRUBSIGN_NO_EXISTING, fcn, osroot, osdev)); 6625eb2bd662Svikram sign = create_new_sign(osdev, fstype); 6626eb2bd662Svikram INJECT_ERROR1("CREATE_NEW_SIGN", sign = NULL); 6627eb2bd662Svikram if (sign == NULL) { 6628eb2bd662Svikram bam_error(GRUBSIGN_CREATE_FAIL, osdev); 6629eb2bd662Svikram free(fstype); 6630eb2bd662Svikram return (NULL); 6631eb2bd662Svikram } 6632eb2bd662Svikram } 6633eb2bd662Svikram 6634eb2bd662Svikram ret = set_signature(osroot, osdev, sign, fstype); 6635eb2bd662Svikram INJECT_ERROR1("SET_SIGNATURE_FAIL", ret = -1); 6636eb2bd662Svikram if (ret == -1) { 6637eb2bd662Svikram bam_error(GRUBSIGN_WRITE_FAIL, osdev); 6638eb2bd662Svikram free(sign); 6639eb2bd662Svikram free(fstype); 6640eb2bd662Svikram (void) unlink(UFS_SIGNATURE_LIST); 6641eb2bd662Svikram return (NULL); 6642eb2bd662Svikram } 6643eb2bd662Svikram 6644eb2bd662Svikram free(fstype); 6645eb2bd662Svikram 6646eb2bd662Svikram if (bam_verbose) 6647eb2bd662Svikram bam_print(GRUBSIGN_FOUND_OR_CREATED, sign, osdev); 6648eb2bd662Svikram 6649eb2bd662Svikram fdiskpart = get_partition(osdev); 6650eb2bd662Svikram INJECT_ERROR1("GET_GRUBSIGN_FDISK", fdiskpart = -1); 6651eb2bd662Svikram if (fdiskpart == -1) { 6652eb2bd662Svikram bam_error(FDISKPART_FAIL, osdev); 6653eb2bd662Svikram free(sign); 6654eb2bd662Svikram return (NULL); 6655eb2bd662Svikram } 6656eb2bd662Svikram 6657eb2bd662Svikram slice = strrchr(osdev, 's'); 6658eb2bd662Svikram 6659eb2bd662Svikram grubsign = s_calloc(1, MAXNAMELEN + 10); 6660eb2bd662Svikram if (slice) { 6661eb2bd662Svikram (void) snprintf(grubsign, MAXNAMELEN + 10, "(%s,%d,%c)", 6662eb2bd662Svikram sign, fdiskpart, slice[1] + 'a' - '0'); 6663eb2bd662Svikram } else 6664eb2bd662Svikram (void) snprintf(grubsign, MAXNAMELEN + 10, "(%s,%d)", 6665eb2bd662Svikram sign, fdiskpart); 6666eb2bd662Svikram 6667eb2bd662Svikram free(sign); 6668eb2bd662Svikram 6669eb2bd662Svikram BAM_DPRINTF((D_GET_GRUBSIGN_SUCCESS, fcn, grubsign)); 6670eb2bd662Svikram 6671eb2bd662Svikram return (grubsign); 66727c478bd9Sstevel@tonic-gate } 66737c478bd9Sstevel@tonic-gate 6674ee3b8144Sszhou static char * 6675ee3b8144Sszhou get_title(char *rootdir) 66767c478bd9Sstevel@tonic-gate { 6677eb2bd662Svikram static char title[80]; 6678eb2bd662Svikram char *cp = NULL; 6679eb2bd662Svikram char release[PATH_MAX]; 66807c478bd9Sstevel@tonic-gate FILE *fp; 6681eb2bd662Svikram const char *fcn = "get_title()"; 66827c478bd9Sstevel@tonic-gate 66837c478bd9Sstevel@tonic-gate /* open the /etc/release file */ 66847c478bd9Sstevel@tonic-gate (void) snprintf(release, sizeof (release), "%s/etc/release", rootdir); 66857c478bd9Sstevel@tonic-gate 66867c478bd9Sstevel@tonic-gate fp = fopen(release, "r"); 6687eb2bd662Svikram if (fp == NULL) { 6688eb2bd662Svikram bam_error(OPEN_FAIL, release, strerror(errno)); 6689eb2bd662Svikram cp = NULL; 6690eb2bd662Svikram goto out; 6691eb2bd662Svikram } 66927c478bd9Sstevel@tonic-gate 66937c478bd9Sstevel@tonic-gate while (s_fgets(title, sizeof (title), fp) != NULL) { 66947c478bd9Sstevel@tonic-gate cp = strstr(title, "Solaris"); 66957c478bd9Sstevel@tonic-gate if (cp) 66967c478bd9Sstevel@tonic-gate break; 66977c478bd9Sstevel@tonic-gate } 66987c478bd9Sstevel@tonic-gate (void) fclose(fp); 6699eb2bd662Svikram 6700eb2bd662Svikram out: 6701eb2bd662Svikram cp = cp ? cp : "Solaris"; 6702eb2bd662Svikram 6703eb2bd662Svikram BAM_DPRINTF((D_GET_TITLE, fcn, cp)); 6704eb2bd662Svikram 6705eb2bd662Svikram return (cp); 67067c478bd9Sstevel@tonic-gate } 67077c478bd9Sstevel@tonic-gate 6708ae115bc7Smrj char * 67097c478bd9Sstevel@tonic-gate get_special(char *mountp) 67107c478bd9Sstevel@tonic-gate { 67117c478bd9Sstevel@tonic-gate FILE *mntfp; 6712eb2bd662Svikram struct mnttab mp = {0}; 6713eb2bd662Svikram struct mnttab mpref = {0}; 6714eb2bd662Svikram int error; 6715eb2bd662Svikram int ret; 6716eb2bd662Svikram const char *fcn = "get_special()"; 6717eb2bd662Svikram 6718eb2bd662Svikram INJECT_ERROR1("GET_SPECIAL_MNTPT", mountp = NULL); 6719eb2bd662Svikram if (mountp == NULL) { 6720eb2bd662Svikram bam_error(GET_SPECIAL_NULL_MNTPT); 6721eb2bd662Svikram return (NULL); 6722eb2bd662Svikram } 67237c478bd9Sstevel@tonic-gate 67247c478bd9Sstevel@tonic-gate mntfp = fopen(MNTTAB, "r"); 6725eb2bd662Svikram error = errno; 6726eb2bd662Svikram INJECT_ERROR1("GET_SPECIAL_MNTTAB_OPEN", mntfp = NULL); 67277c478bd9Sstevel@tonic-gate if (mntfp == NULL) { 6728eb2bd662Svikram bam_error(OPEN_FAIL, MNTTAB, strerror(error)); 6729eb2bd662Svikram return (NULL); 67307c478bd9Sstevel@tonic-gate } 67317c478bd9Sstevel@tonic-gate 67327c478bd9Sstevel@tonic-gate if (*mountp == '\0') 67337c478bd9Sstevel@tonic-gate mpref.mnt_mountp = "/"; 67347c478bd9Sstevel@tonic-gate else 67357c478bd9Sstevel@tonic-gate mpref.mnt_mountp = mountp; 6736eb2bd662Svikram 6737eb2bd662Svikram ret = getmntany(mntfp, &mp, &mpref); 6738eb2bd662Svikram INJECT_ERROR1("GET_SPECIAL_MNTTAB_SEARCH", ret = 1); 6739eb2bd662Svikram if (ret != 0) { 67407c478bd9Sstevel@tonic-gate (void) fclose(mntfp); 6741eb2bd662Svikram BAM_DPRINTF((D_GET_SPECIAL_NOT_IN_MNTTAB, fcn, mountp)); 67427c478bd9Sstevel@tonic-gate return (NULL); 67437c478bd9Sstevel@tonic-gate } 67447c478bd9Sstevel@tonic-gate (void) fclose(mntfp); 67457c478bd9Sstevel@tonic-gate 6746eb2bd662Svikram BAM_DPRINTF((D_GET_SPECIAL, fcn, mp.mnt_special)); 6747eb2bd662Svikram 67487c478bd9Sstevel@tonic-gate return (s_strdup(mp.mnt_special)); 67497c478bd9Sstevel@tonic-gate } 67507c478bd9Sstevel@tonic-gate 6751eb2bd662Svikram static void 6752eb2bd662Svikram free_physarray(char **physarray, int n) 67537c478bd9Sstevel@tonic-gate { 6754eb2bd662Svikram int i; 6755eb2bd662Svikram const char *fcn = "free_physarray()"; 67567c478bd9Sstevel@tonic-gate 6757eb2bd662Svikram assert(physarray); 6758eb2bd662Svikram assert(n); 6759eb2bd662Svikram 6760eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY_N1, fcn, n)); 6761eb2bd662Svikram 6762eb2bd662Svikram for (i = 0; i < n; i++) { 6763eb2bd662Svikram free(physarray[i]); 67647c478bd9Sstevel@tonic-gate } 6765eb2bd662Svikram free(physarray); 6766eb2bd662Svikram 6767eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 6768eb2bd662Svikram } 6769eb2bd662Svikram 6770eb2bd662Svikram static int 6771eb2bd662Svikram zfs_get_physical(char *special, char ***physarray, int *n) 6772eb2bd662Svikram { 6773eb2bd662Svikram char sdup[PATH_MAX]; 6774eb2bd662Svikram char cmd[PATH_MAX]; 6775eb2bd662Svikram char dsk[PATH_MAX]; 6776eb2bd662Svikram char *pool; 6777eb2bd662Svikram filelist_t flist = {0}; 6778eb2bd662Svikram line_t *lp; 6779eb2bd662Svikram line_t *startlp; 6780eb2bd662Svikram char *comp1; 6781eb2bd662Svikram int i; 6782eb2bd662Svikram int ret; 6783eb2bd662Svikram const char *fcn = "zfs_get_physical()"; 6784eb2bd662Svikram 6785eb2bd662Svikram assert(special); 6786eb2bd662Svikram 6787eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY1, fcn, special)); 6788eb2bd662Svikram 6789eb2bd662Svikram INJECT_ERROR1("INVALID_ZFS_SPECIAL", special = "/foo"); 6790eb2bd662Svikram if (special[0] == '/') { 6791eb2bd662Svikram bam_error(INVALID_ZFS_SPECIAL, special); 6792eb2bd662Svikram return (-1); 6793eb2bd662Svikram } 6794eb2bd662Svikram 6795eb2bd662Svikram (void) strlcpy(sdup, special, sizeof (sdup)); 6796eb2bd662Svikram 6797eb2bd662Svikram pool = strtok(sdup, "/"); 6798eb2bd662Svikram INJECT_ERROR1("ZFS_GET_PHYS_POOL", pool = NULL); 6799eb2bd662Svikram if (pool == NULL) { 6800eb2bd662Svikram bam_error(CANT_FIND_POOL_FROM_SPECIAL, special); 6801eb2bd662Svikram return (-1); 6802eb2bd662Svikram } 6803eb2bd662Svikram 6804eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), "/sbin/zpool status %s", pool); 6805eb2bd662Svikram 6806eb2bd662Svikram ret = exec_cmd(cmd, &flist); 6807eb2bd662Svikram INJECT_ERROR1("ZFS_GET_PHYS_STATUS", ret = 1); 6808eb2bd662Svikram if (ret != 0) { 6809eb2bd662Svikram bam_error(ZFS_GET_POOL_STATUS, pool); 6810eb2bd662Svikram return (-1); 6811eb2bd662Svikram } 6812eb2bd662Svikram 6813eb2bd662Svikram INJECT_ERROR1("ZFS_GET_PHYS_STATUS_OUT", flist.head = NULL); 6814eb2bd662Svikram if (flist.head == NULL) { 6815eb2bd662Svikram bam_error(BAD_ZPOOL_STATUS, pool); 6816eb2bd662Svikram filelist_free(&flist); 6817eb2bd662Svikram return (-1); 6818eb2bd662Svikram } 6819eb2bd662Svikram 6820eb2bd662Svikram for (lp = flist.head; lp; lp = lp->next) { 6821eb2bd662Svikram BAM_DPRINTF((D_STRTOK_ZPOOL_STATUS, fcn, lp->line)); 6822eb2bd662Svikram comp1 = strtok(lp->line, " \t"); 6823eb2bd662Svikram if (comp1 == NULL) { 6824eb2bd662Svikram free(lp->line); 6825eb2bd662Svikram lp->line = NULL; 6826eb2bd662Svikram } else { 6827eb2bd662Svikram comp1 = s_strdup(comp1); 6828eb2bd662Svikram free(lp->line); 6829eb2bd662Svikram lp->line = comp1; 6830eb2bd662Svikram } 6831eb2bd662Svikram } 6832eb2bd662Svikram 6833eb2bd662Svikram for (lp = flist.head; lp; lp = lp->next) { 6834eb2bd662Svikram if (lp->line == NULL) 6835eb2bd662Svikram continue; 6836eb2bd662Svikram if (strcmp(lp->line, pool) == 0) { 6837eb2bd662Svikram BAM_DPRINTF((D_FOUND_POOL_IN_ZPOOL_STATUS, fcn, pool)); 6838eb2bd662Svikram break; 6839eb2bd662Svikram } 6840eb2bd662Svikram } 6841eb2bd662Svikram 6842eb2bd662Svikram if (lp == NULL) { 6843eb2bd662Svikram bam_error(NO_POOL_IN_ZPOOL_STATUS, pool); 6844eb2bd662Svikram filelist_free(&flist); 6845eb2bd662Svikram return (-1); 6846eb2bd662Svikram } 6847eb2bd662Svikram 6848eb2bd662Svikram startlp = lp->next; 6849eb2bd662Svikram for (i = 0, lp = startlp; lp; lp = lp->next) { 6850eb2bd662Svikram if (lp->line == NULL) 6851eb2bd662Svikram continue; 6852eb2bd662Svikram if (strcmp(lp->line, "mirror") == 0) 6853eb2bd662Svikram continue; 6854eb2bd662Svikram if (lp->line[0] == '\0' || strcmp(lp->line, "errors:") == 0) 6855eb2bd662Svikram break; 6856eb2bd662Svikram i++; 6857eb2bd662Svikram BAM_DPRINTF((D_COUNTING_ZFS_PHYS, fcn, i)); 6858eb2bd662Svikram } 6859eb2bd662Svikram 6860eb2bd662Svikram if (i == 0) { 6861eb2bd662Svikram bam_error(NO_PHYS_IN_ZPOOL_STATUS, pool); 6862eb2bd662Svikram filelist_free(&flist); 6863eb2bd662Svikram return (-1); 6864eb2bd662Svikram } 6865eb2bd662Svikram 6866eb2bd662Svikram *n = i; 6867eb2bd662Svikram *physarray = s_calloc(*n, sizeof (char *)); 6868eb2bd662Svikram for (i = 0, lp = startlp; lp; lp = lp->next) { 6869eb2bd662Svikram if (lp->line == NULL) 6870eb2bd662Svikram continue; 6871eb2bd662Svikram if (strcmp(lp->line, "mirror") == 0) 6872eb2bd662Svikram continue; 6873eb2bd662Svikram if (strcmp(lp->line, "errors:") == 0) 6874eb2bd662Svikram break; 6875eb2bd662Svikram if (strncmp(lp->line, "/dev/dsk/", strlen("/dev/dsk/")) != 0 && 6876eb2bd662Svikram strncmp(lp->line, "/dev/rdsk/", 6877eb2bd662Svikram strlen("/dev/rdsk/")) != 0) { 6878eb2bd662Svikram (void) snprintf(dsk, sizeof (dsk), "/dev/dsk/%s", 6879eb2bd662Svikram lp->line); 6880eb2bd662Svikram } else { 6881eb2bd662Svikram (void) strlcpy(dsk, lp->line, sizeof (dsk)); 6882eb2bd662Svikram } 6883eb2bd662Svikram BAM_DPRINTF((D_ADDING_ZFS_PHYS, fcn, dsk, pool)); 6884eb2bd662Svikram (*physarray)[i++] = s_strdup(dsk); 6885eb2bd662Svikram } 6886eb2bd662Svikram 6887eb2bd662Svikram assert(i == *n); 6888eb2bd662Svikram 6889eb2bd662Svikram filelist_free(&flist); 6890eb2bd662Svikram 6891eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 6892eb2bd662Svikram return (0); 6893eb2bd662Svikram } 6894eb2bd662Svikram 6895963390b4Svikram /* 6896963390b4Svikram * Certain services needed to run metastat successfully may not 6897963390b4Svikram * be enabled. Enable them now. 6898963390b4Svikram */ 6899963390b4Svikram /* 6900963390b4Svikram * Checks if the specified service is online 6901963390b4Svikram * Returns: 1 if the service is online 6902963390b4Svikram * 0 if the service is not online 6903963390b4Svikram * -1 on error 6904963390b4Svikram */ 6905963390b4Svikram static int 6906963390b4Svikram is_svc_online(char *svc) 6907963390b4Svikram { 6908963390b4Svikram char *state; 6909963390b4Svikram const char *fcn = "is_svc_online()"; 6910963390b4Svikram 6911963390b4Svikram BAM_DPRINTF((D_FUNC_ENTRY1, fcn, svc)); 6912963390b4Svikram 6913963390b4Svikram state = smf_get_state(svc); 6914963390b4Svikram INJECT_ERROR2("GET_SVC_STATE", free(state), state = NULL); 6915963390b4Svikram if (state == NULL) { 6916963390b4Svikram bam_error(GET_SVC_STATE_ERR, svc); 6917963390b4Svikram return (-1); 6918963390b4Svikram } 6919963390b4Svikram BAM_DPRINTF((D_GOT_SVC_STATUS, fcn, svc)); 6920963390b4Svikram 6921963390b4Svikram if (strcmp(state, SCF_STATE_STRING_ONLINE) == 0) { 6922963390b4Svikram BAM_DPRINTF((D_SVC_ONLINE, fcn, svc)); 6923963390b4Svikram free(state); 6924963390b4Svikram return (1); 6925963390b4Svikram } 6926963390b4Svikram 6927963390b4Svikram BAM_DPRINTF((D_SVC_NOT_ONLINE, fcn, state, svc)); 6928963390b4Svikram 6929963390b4Svikram free(state); 6930963390b4Svikram 6931963390b4Svikram return (0); 6932963390b4Svikram } 6933963390b4Svikram 6934963390b4Svikram static int 6935963390b4Svikram enable_svc(char *svc) 6936963390b4Svikram { 6937963390b4Svikram int ret; 6938963390b4Svikram int sleeptime; 6939963390b4Svikram const char *fcn = "enable_svc()"; 6940963390b4Svikram 6941963390b4Svikram ret = is_svc_online(svc); 6942963390b4Svikram if (ret == -1) { 6943963390b4Svikram bam_error(SVC_IS_ONLINE_FAILED, svc); 6944963390b4Svikram return (-1); 6945963390b4Svikram } else if (ret == 1) { 6946963390b4Svikram BAM_DPRINTF((D_SVC_ALREADY_ONLINE, fcn, svc)); 6947963390b4Svikram return (0); 6948963390b4Svikram } 6949963390b4Svikram 6950963390b4Svikram /* Service is not enabled. Enable it now. */ 6951963390b4Svikram ret = smf_enable_instance(svc, 0); 6952963390b4Svikram INJECT_ERROR1("ENABLE_SVC_FAILED", ret = -1); 6953963390b4Svikram if (ret != 0) { 6954963390b4Svikram bam_error(ENABLE_SVC_FAILED, svc); 6955963390b4Svikram return (-1); 6956963390b4Svikram } 6957963390b4Svikram 6958963390b4Svikram BAM_DPRINTF((D_SVC_ONLINE_INITIATED, fcn, svc)); 6959963390b4Svikram 6960963390b4Svikram sleeptime = 0; 6961963390b4Svikram do { 6962963390b4Svikram ret = is_svc_online(svc); 6963963390b4Svikram INJECT_ERROR1("SVC_ONLINE_SUCCESS", ret = 1); 6964963390b4Svikram INJECT_ERROR1("SVC_ONLINE_FAILURE", ret = -1); 6965963390b4Svikram INJECT_ERROR1("SVC_ONLINE_NOTYET", ret = 0); 6966963390b4Svikram if (ret == -1) { 6967963390b4Svikram bam_error(ERR_SVC_GET_ONLINE, svc); 6968963390b4Svikram return (-1); 6969963390b4Svikram } else if (ret == 1) { 6970963390b4Svikram BAM_DPRINTF((D_SVC_NOW_ONLINE, fcn, svc)); 6971963390b4Svikram return (1); 6972963390b4Svikram } 6973963390b4Svikram (void) sleep(1); 6974963390b4Svikram } while (sleeptime < 60); 6975963390b4Svikram 6976963390b4Svikram bam_error(TIMEOUT_ENABLE_SVC, svc); 6977963390b4Svikram 6978963390b4Svikram return (-1); 6979963390b4Svikram } 6980963390b4Svikram 6981eb2bd662Svikram static int 6982eb2bd662Svikram ufs_get_physical(char *special, char ***physarray, int *n) 6983eb2bd662Svikram { 6984eb2bd662Svikram char cmd[PATH_MAX]; 6985eb2bd662Svikram char *shortname; 6986eb2bd662Svikram filelist_t flist = {0}; 6987eb2bd662Svikram char *meta; 6988eb2bd662Svikram char *type; 6989eb2bd662Svikram char *comp1; 6990eb2bd662Svikram char *comp2; 6991eb2bd662Svikram char *comp3; 6992eb2bd662Svikram char *comp4; 6993eb2bd662Svikram int i; 6994eb2bd662Svikram line_t *lp; 6995eb2bd662Svikram int ret; 6996963390b4Svikram char *svc; 6997eb2bd662Svikram const char *fcn = "ufs_get_physical()"; 6998eb2bd662Svikram 6999eb2bd662Svikram assert(special); 7000eb2bd662Svikram 7001eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY1, fcn, special)); 7002eb2bd662Svikram 7003eb2bd662Svikram if (strncmp(special, "/dev/md/", strlen("/dev/md/")) != 0) { 7004eb2bd662Svikram bam_error(UFS_GET_PHYS_NOT_SVM, special); 7005eb2bd662Svikram return (-1); 7006eb2bd662Svikram } 7007eb2bd662Svikram 7008eb2bd662Svikram if (strncmp(special, "/dev/md/dsk/", strlen("/dev/md/dsk/")) == 0) { 7009eb2bd662Svikram shortname = special + strlen("/dev/md/dsk/"); 7010eb2bd662Svikram } else if (strncmp(special, "/dev/md/rdsk/", 7011eb2bd662Svikram strlen("/dev/md/rdsk/")) == 0) { 7012eb2bd662Svikram shortname = special + strlen("/dev/md/rdsk"); 7013eb2bd662Svikram } else { 7014eb2bd662Svikram bam_error(UFS_GET_PHYS_INVALID_SVM, special); 7015eb2bd662Svikram return (-1); 7016eb2bd662Svikram } 7017eb2bd662Svikram 7018eb2bd662Svikram BAM_DPRINTF((D_UFS_SVM_SHORT, fcn, special, shortname)); 7019eb2bd662Svikram 7020963390b4Svikram svc = "network/rpc/meta:default"; 7021963390b4Svikram if (enable_svc(svc) == -1) { 7022963390b4Svikram bam_error(UFS_SVM_METASTAT_SVC_ERR, svc); 7023963390b4Svikram } 7024963390b4Svikram 7025eb2bd662Svikram (void) snprintf(cmd, sizeof (cmd), "/sbin/metastat -p %s", shortname); 7026eb2bd662Svikram 7027eb2bd662Svikram ret = exec_cmd(cmd, &flist); 7028eb2bd662Svikram INJECT_ERROR1("UFS_SVM_METASTAT", ret = 1); 7029eb2bd662Svikram if (ret != 0) { 7030eb2bd662Svikram bam_error(UFS_SVM_METASTAT_ERR, shortname); 7031eb2bd662Svikram return (-1); 7032eb2bd662Svikram } 7033eb2bd662Svikram 7034eb2bd662Svikram INJECT_ERROR1("UFS_SVM_METASTAT_OUT", flist.head = NULL); 7035eb2bd662Svikram if (flist.head == NULL) { 7036eb2bd662Svikram bam_error(BAD_UFS_SVM_METASTAT, shortname); 7037eb2bd662Svikram filelist_free(&flist); 7038eb2bd662Svikram return (-1); 70397c478bd9Sstevel@tonic-gate } 70407c478bd9Sstevel@tonic-gate 70417c478bd9Sstevel@tonic-gate /* 7042eb2bd662Svikram * Check if not a mirror. We only parse a single metadevice 7043eb2bd662Svikram * if not a mirror 7044eb2bd662Svikram */ 7045eb2bd662Svikram meta = strtok(flist.head->line, " \t"); 7046eb2bd662Svikram type = strtok(NULL, " \t"); 7047eb2bd662Svikram if (meta == NULL || type == NULL) { 7048eb2bd662Svikram bam_error(ERROR_PARSE_UFS_SVM_METASTAT, shortname); 7049eb2bd662Svikram filelist_free(&flist); 7050eb2bd662Svikram return (-1); 7051eb2bd662Svikram } 7052eb2bd662Svikram if (strcmp(type, "-m") != 0) { 7053eb2bd662Svikram comp1 = strtok(NULL, " \t"); 7054eb2bd662Svikram comp2 = strtok(NULL, " \t"); 7055eb2bd662Svikram if (comp1 == NULL || comp2 != NULL) { 7056eb2bd662Svikram bam_error(INVALID_UFS_SVM_METASTAT, shortname); 7057eb2bd662Svikram filelist_free(&flist); 7058eb2bd662Svikram return (-1); 7059eb2bd662Svikram } 7060eb2bd662Svikram BAM_DPRINTF((D_UFS_SVM_ONE_COMP, fcn, comp1, shortname)); 7061eb2bd662Svikram *physarray = s_calloc(1, sizeof (char *)); 7062eb2bd662Svikram (*physarray)[0] = s_strdup(comp1); 7063eb2bd662Svikram *n = 1; 7064eb2bd662Svikram filelist_free(&flist); 7065eb2bd662Svikram return (0); 7066eb2bd662Svikram } 7067eb2bd662Svikram 7068eb2bd662Svikram /* 7069eb2bd662Svikram * Okay we have a mirror. Everything after the first line 7070eb2bd662Svikram * is a submirror 7071eb2bd662Svikram */ 7072eb2bd662Svikram for (i = 0, lp = flist.head->next; lp; lp = lp->next) { 7073eb2bd662Svikram if (strstr(lp->line, "/dev/dsk/") == NULL && 7074eb2bd662Svikram strstr(lp->line, "/dev/rdsk/") == NULL) { 7075eb2bd662Svikram bam_error(CANNOT_PARSE_UFS_SVM_METASTAT, shortname); 7076eb2bd662Svikram filelist_free(&flist); 7077eb2bd662Svikram return (-1); 7078eb2bd662Svikram } 7079eb2bd662Svikram i++; 7080eb2bd662Svikram } 7081eb2bd662Svikram 7082eb2bd662Svikram *physarray = s_calloc(i, sizeof (char *)); 7083eb2bd662Svikram *n = i; 7084eb2bd662Svikram 7085eb2bd662Svikram for (i = 0, lp = flist.head->next; lp; lp = lp->next) { 7086eb2bd662Svikram comp1 = strtok(lp->line, " \t"); 7087eb2bd662Svikram comp2 = strtok(NULL, " \t"); 7088eb2bd662Svikram comp3 = strtok(NULL, " \t"); 7089eb2bd662Svikram comp4 = strtok(NULL, " \t"); 7090eb2bd662Svikram 7091eb2bd662Svikram if (comp3 == NULL || comp4 == NULL || 7092eb2bd662Svikram (strncmp(comp4, "/dev/dsk/", strlen("/dev/dsk/")) != 0 && 7093eb2bd662Svikram strncmp(comp4, "/dev/rdsk/", strlen("/dev/rdsk/")) != 0)) { 7094eb2bd662Svikram bam_error(CANNOT_PARSE_UFS_SVM_SUBMIRROR, shortname); 7095eb2bd662Svikram filelist_free(&flist); 7096eb2bd662Svikram free_physarray(*physarray, *n); 7097eb2bd662Svikram return (-1); 7098eb2bd662Svikram } 7099eb2bd662Svikram 7100eb2bd662Svikram (*physarray)[i++] = s_strdup(comp4); 7101eb2bd662Svikram } 7102eb2bd662Svikram 7103eb2bd662Svikram assert(i == *n); 7104eb2bd662Svikram 7105eb2bd662Svikram filelist_free(&flist); 7106eb2bd662Svikram 7107eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 7108eb2bd662Svikram return (0); 7109eb2bd662Svikram } 7110eb2bd662Svikram 7111eb2bd662Svikram static int 7112eb2bd662Svikram get_physical(char *menu_root, char ***physarray, int *n) 7113eb2bd662Svikram { 7114eb2bd662Svikram char *special; 7115eb2bd662Svikram int ret; 7116eb2bd662Svikram const char *fcn = "get_physical()"; 7117eb2bd662Svikram 7118eb2bd662Svikram assert(menu_root); 7119eb2bd662Svikram assert(physarray); 7120eb2bd662Svikram assert(n); 7121eb2bd662Svikram 7122eb2bd662Svikram *physarray = NULL; 7123eb2bd662Svikram *n = 0; 7124eb2bd662Svikram 7125eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY1, fcn, menu_root)); 7126eb2bd662Svikram 7127eb2bd662Svikram /* First get the device special file from /etc/mnttab */ 7128eb2bd662Svikram special = get_special(menu_root); 7129eb2bd662Svikram INJECT_ERROR1("GET_PHYSICAL_SPECIAL", special = NULL); 7130eb2bd662Svikram if (special == NULL) { 7131eb2bd662Svikram bam_error(GET_SPECIAL_NULL, menu_root); 7132eb2bd662Svikram return (-1); 7133eb2bd662Svikram } 7134eb2bd662Svikram 7135eb2bd662Svikram /* If already a physical device nothing to do */ 7136eb2bd662Svikram if (strncmp(special, "/dev/dsk/", strlen("/dev/dsk/")) == 0 || 7137eb2bd662Svikram strncmp(special, "/dev/rdsk/", strlen("/dev/rdsk/")) == 0) { 7138eb2bd662Svikram BAM_DPRINTF((D_GET_PHYSICAL_ALREADY, fcn, menu_root, special)); 7139eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 7140eb2bd662Svikram *physarray = s_calloc(1, sizeof (char *)); 7141eb2bd662Svikram (*physarray)[0] = special; 7142eb2bd662Svikram *n = 1; 7143eb2bd662Svikram return (0); 7144eb2bd662Svikram } 7145eb2bd662Svikram 7146eb2bd662Svikram if (is_zfs(menu_root)) { 7147eb2bd662Svikram ret = zfs_get_physical(special, physarray, n); 7148eb2bd662Svikram } else if (is_ufs(menu_root)) { 7149eb2bd662Svikram ret = ufs_get_physical(special, physarray, n); 7150eb2bd662Svikram } else { 7151eb2bd662Svikram bam_error(GET_PHYSICAL_NOTSUP_FSTYPE, menu_root, special); 7152eb2bd662Svikram ret = -1; 7153eb2bd662Svikram } 7154eb2bd662Svikram 7155eb2bd662Svikram free(special); 7156eb2bd662Svikram 7157eb2bd662Svikram INJECT_ERROR1("GET_PHYSICAL_RET", ret = -1); 7158eb2bd662Svikram if (ret == -1) { 7159eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 7160eb2bd662Svikram } else { 7161eb2bd662Svikram int i; 7162eb2bd662Svikram assert (*n > 0); 7163eb2bd662Svikram for (i = 0; i < *n; i++) { 7164eb2bd662Svikram BAM_DPRINTF((D_GET_PHYSICAL_RET, fcn, (*physarray)[i])); 7165eb2bd662Svikram } 7166eb2bd662Svikram } 7167eb2bd662Svikram 7168eb2bd662Svikram return (ret); 7169eb2bd662Svikram } 7170eb2bd662Svikram 7171eb2bd662Svikram static int 7172eb2bd662Svikram is_bootdisk(char *osroot, char *physical) 7173eb2bd662Svikram { 7174eb2bd662Svikram int ret; 7175eb2bd662Svikram char *grubroot; 7176eb2bd662Svikram char *bootp; 7177eb2bd662Svikram const char *fcn = "is_bootdisk()"; 7178eb2bd662Svikram 7179eb2bd662Svikram assert(osroot); 7180eb2bd662Svikram assert(physical); 7181eb2bd662Svikram 7182eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY2, fcn, osroot, physical)); 7183eb2bd662Svikram 7184eb2bd662Svikram bootp = strstr(physical, "p0:boot"); 7185eb2bd662Svikram if (bootp) 7186eb2bd662Svikram *bootp = '\0'; 7187eb2bd662Svikram /* 7188eb2bd662Svikram * We just want the BIOS mapping for menu disk. 7189eb2bd662Svikram * Don't pass menu_root to get_grubroot() as the 7190eb2bd662Svikram * check that it is used for is not relevant here. 7191eb2bd662Svikram * The osroot is immaterial as well - it is only used to 7192eb2bd662Svikram * to find create_diskmap script. Everything hinges on 7193eb2bd662Svikram * "physical" 7194eb2bd662Svikram */ 7195eb2bd662Svikram grubroot = get_grubroot(osroot, physical, NULL); 7196eb2bd662Svikram 7197eb2bd662Svikram INJECT_ERROR1("IS_BOOTDISK_GRUBROOT", grubroot = NULL); 7198eb2bd662Svikram if (grubroot == NULL) { 719937eb779cSVikram Hegde if (bam_verbose) 720037eb779cSVikram Hegde bam_error(NO_GRUBROOT_FOR_DISK, physical); 7201eb2bd662Svikram return (0); 7202eb2bd662Svikram } 7203eb2bd662Svikram ret = grubroot[3] == '0'; 7204eb2bd662Svikram free(grubroot); 7205eb2bd662Svikram 7206eb2bd662Svikram BAM_DPRINTF((D_RETURN_RET, fcn, ret)); 7207eb2bd662Svikram 7208eb2bd662Svikram return (ret); 7209eb2bd662Svikram } 7210eb2bd662Svikram 7211eb2bd662Svikram /* 7212eb2bd662Svikram * Check if menu is on the boot device 72137c478bd9Sstevel@tonic-gate * Return 0 (false) on error 72147c478bd9Sstevel@tonic-gate */ 72157c478bd9Sstevel@tonic-gate static int 7216eb2bd662Svikram menu_on_bootdisk(char *osroot, char *menu_root) 72177c478bd9Sstevel@tonic-gate { 7218eb2bd662Svikram char **physarray; 72197c478bd9Sstevel@tonic-gate int ret; 7220eb2bd662Svikram int n; 7221eb2bd662Svikram int i; 7222eb2bd662Svikram int on_bootdisk; 7223eb2bd662Svikram const char *fcn = "menu_on_bootdisk()"; 72247c478bd9Sstevel@tonic-gate 7225eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY2, fcn, osroot, menu_root)); 72267c478bd9Sstevel@tonic-gate 7227eb2bd662Svikram ret = get_physical(menu_root, &physarray, &n); 7228eb2bd662Svikram INJECT_ERROR1("MENU_ON_BOOTDISK_PHYSICAL", ret = -1); 7229eb2bd662Svikram if (ret != 0) { 7230eb2bd662Svikram bam_error(GET_PHYSICAL_MENU_NULL, menu_root); 72317c478bd9Sstevel@tonic-gate return (0); 7232eb2bd662Svikram } 7233eb2bd662Svikram 7234eb2bd662Svikram assert(physarray); 7235eb2bd662Svikram assert(n > 0); 7236eb2bd662Svikram 7237eb2bd662Svikram on_bootdisk = 0; 7238eb2bd662Svikram for (i = 0; i < n; i++) { 7239eb2bd662Svikram assert(strncmp(physarray[i], "/dev/dsk/", 7240eb2bd662Svikram strlen("/dev/dsk/")) == 0 || 7241eb2bd662Svikram strncmp(physarray[i], "/dev/rdsk/", 7242eb2bd662Svikram strlen("/dev/rdsk/")) == 0); 7243eb2bd662Svikram 7244eb2bd662Svikram BAM_DPRINTF((D_CHECK_ON_BOOTDISK, fcn, physarray[i])); 7245eb2bd662Svikram if (is_bootdisk(osroot, physarray[i])) { 7246eb2bd662Svikram on_bootdisk = 1; 7247eb2bd662Svikram BAM_DPRINTF((D_IS_ON_BOOTDISK, fcn, physarray[i])); 7248eb2bd662Svikram } 7249eb2bd662Svikram } 7250eb2bd662Svikram 7251eb2bd662Svikram free_physarray(physarray, n); 7252eb2bd662Svikram 7253eb2bd662Svikram INJECT_ERROR1("ON_BOOTDISK_YES", on_bootdisk = 1); 7254eb2bd662Svikram INJECT_ERROR1("ON_BOOTDISK_NO", on_bootdisk = 0); 7255eb2bd662Svikram if (on_bootdisk) { 7256eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 7257eb2bd662Svikram } else { 7258eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 7259eb2bd662Svikram } 7260eb2bd662Svikram 7261eb2bd662Svikram return (on_bootdisk); 7262eb2bd662Svikram } 7263eb2bd662Svikram 7264eb2bd662Svikram void 7265eb2bd662Svikram bam_add_line(menu_t *mp, entry_t *entry, line_t *prev, line_t *lp) 7266eb2bd662Svikram { 7267eb2bd662Svikram const char *fcn = "bam_add_line()"; 7268eb2bd662Svikram 7269eb2bd662Svikram assert(mp); 7270eb2bd662Svikram assert(entry); 7271eb2bd662Svikram assert(prev); 7272eb2bd662Svikram assert(lp); 7273eb2bd662Svikram 7274eb2bd662Svikram lp->next = prev->next; 7275eb2bd662Svikram if (prev->next) { 7276eb2bd662Svikram BAM_DPRINTF((D_ADD_LINE_PREV_NEXT, fcn)); 7277eb2bd662Svikram prev->next->prev = lp; 7278eb2bd662Svikram } else { 7279eb2bd662Svikram BAM_DPRINTF((D_ADD_LINE_NOT_PREV_NEXT, fcn)); 7280eb2bd662Svikram } 7281eb2bd662Svikram prev->next = lp; 7282eb2bd662Svikram lp->prev = prev; 7283eb2bd662Svikram 7284eb2bd662Svikram if (entry->end == prev) { 7285eb2bd662Svikram BAM_DPRINTF((D_ADD_LINE_LAST_LINE_IN_ENTRY, fcn)); 7286eb2bd662Svikram entry->end = lp; 7287eb2bd662Svikram } 7288eb2bd662Svikram if (mp->end == prev) { 7289eb2bd662Svikram assert(lp->next == NULL); 7290eb2bd662Svikram mp->end = lp; 7291eb2bd662Svikram BAM_DPRINTF((D_ADD_LINE_LAST_LINE_IN_MENU, fcn)); 7292eb2bd662Svikram } 72937c478bd9Sstevel@tonic-gate } 72947c478bd9Sstevel@tonic-gate 72958c1b6884Sszhou /* 72968c1b6884Sszhou * look for matching bootadm entry with specified parameters 72978c1b6884Sszhou * Here are the rules (based on existing usage): 72988c1b6884Sszhou * - If title is specified, match on title only 7299eb2bd662Svikram * - Else, match on root/findroot, kernel, and module. 7300eb2bd662Svikram * Note that, if root_opt is non-zero, the absence of 7301eb2bd662Svikram * root line is considered a match. 73028c1b6884Sszhou */ 73038c1b6884Sszhou static entry_t * 7304eb2bd662Svikram find_boot_entry( 7305eb2bd662Svikram menu_t *mp, 7306eb2bd662Svikram char *title, 7307eb2bd662Svikram char *kernel, 7308eb2bd662Svikram char *findroot, 7309eb2bd662Svikram char *root, 7310eb2bd662Svikram char *module, 7311eb2bd662Svikram int root_opt, 7312eb2bd662Svikram int *entry_num) 73138c1b6884Sszhou { 73148c1b6884Sszhou int i; 73158c1b6884Sszhou line_t *lp; 73168c1b6884Sszhou entry_t *ent; 7317eb2bd662Svikram const char *fcn = "find_boot_entry()"; 7318eb2bd662Svikram 7319eb2bd662Svikram if (entry_num) 7320eb2bd662Svikram *entry_num = BAM_ERROR; 73218c1b6884Sszhou 73228c1b6884Sszhou /* find matching entry */ 73238c1b6884Sszhou for (i = 0, ent = mp->entries; ent; i++, ent = ent->next) { 73248c1b6884Sszhou lp = ent->start; 73258c1b6884Sszhou 73268c1b6884Sszhou /* first line of entry must be bootadm comment */ 73278c1b6884Sszhou lp = ent->start; 7328ae115bc7Smrj if (lp->flags != BAM_COMMENT || 7329ae115bc7Smrj strcmp(lp->arg, BAM_BOOTADM_HDR) != 0) { 73308c1b6884Sszhou continue; 73318c1b6884Sszhou } 73328c1b6884Sszhou 73338c1b6884Sszhou /* advance to title line */ 73348c1b6884Sszhou lp = lp->next; 73358c1b6884Sszhou if (title) { 73368c1b6884Sszhou if (lp->flags == BAM_TITLE && lp->arg && 7337eb2bd662Svikram strcmp(lp->arg, title) == 0) { 7338eb2bd662Svikram BAM_DPRINTF((D_MATCHED_TITLE, fcn, title)); 73398c1b6884Sszhou break; 7340eb2bd662Svikram } 7341eb2bd662Svikram BAM_DPRINTF((D_NOMATCH_TITLE, fcn, title, lp->arg)); 73428c1b6884Sszhou continue; /* check title only */ 73438c1b6884Sszhou } 73448c1b6884Sszhou 73458c1b6884Sszhou lp = lp->next; /* advance to root line */ 7346843e1988Sjohnlev if (lp == NULL) { 7347843e1988Sjohnlev continue; 7348eb2bd662Svikram } else if (strcmp(lp->cmd, menu_cmds[FINDROOT_CMD]) == 0) { 7349eb2bd662Svikram INJECT_ERROR1("FIND_BOOT_ENTRY_NULL_FINDROOT", 7350eb2bd662Svikram findroot = NULL); 7351eb2bd662Svikram if (findroot == NULL) { 7352eb2bd662Svikram BAM_DPRINTF((D_NOMATCH_FINDROOT_NULL, 7353eb2bd662Svikram fcn, lp->arg)); 73548c1b6884Sszhou continue; 73558c1b6884Sszhou } 7356eb2bd662Svikram /* findroot command found, try match */ 7357eb2bd662Svikram if (strcmp(lp->arg, findroot) != 0) { 7358eb2bd662Svikram BAM_DPRINTF((D_NOMATCH_FINDROOT, 7359eb2bd662Svikram fcn, findroot, lp->arg)); 7360eb2bd662Svikram continue; 7361eb2bd662Svikram } 7362eb2bd662Svikram BAM_DPRINTF((D_MATCHED_FINDROOT, fcn, findroot)); 7363eb2bd662Svikram lp = lp->next; /* advance to kernel line */ 7364eb2bd662Svikram } else if (strcmp(lp->cmd, menu_cmds[ROOT_CMD]) == 0) { 7365eb2bd662Svikram INJECT_ERROR1("FIND_BOOT_ENTRY_NULL_ROOT", root = NULL); 7366eb2bd662Svikram if (root == NULL) { 7367eb2bd662Svikram BAM_DPRINTF((D_NOMATCH_ROOT_NULL, 7368eb2bd662Svikram fcn, lp->arg)); 7369eb2bd662Svikram continue; 7370eb2bd662Svikram } 7371eb2bd662Svikram /* root cmd found, try match */ 7372eb2bd662Svikram if (strcmp(lp->arg, root) != 0) { 7373eb2bd662Svikram BAM_DPRINTF((D_NOMATCH_ROOT, 7374eb2bd662Svikram fcn, root, lp->arg)); 7375eb2bd662Svikram continue; 7376eb2bd662Svikram } 7377eb2bd662Svikram BAM_DPRINTF((D_MATCHED_ROOT, fcn, root)); 73788c1b6884Sszhou lp = lp->next; /* advance to kernel line */ 73798c1b6884Sszhou } else { 7380eb2bd662Svikram INJECT_ERROR1("FIND_BOOT_ENTRY_ROOT_OPT_NO", 7381eb2bd662Svikram root_opt = 0); 7382eb2bd662Svikram INJECT_ERROR1("FIND_BOOT_ENTRY_ROOT_OPT_YES", 7383eb2bd662Svikram root_opt = 1); 73848c1b6884Sszhou /* no root command, see if root is optional */ 73858c1b6884Sszhou if (root_opt == 0) { 7386eb2bd662Svikram BAM_DPRINTF((D_NO_ROOT_OPT, fcn)); 73878c1b6884Sszhou continue; 73888c1b6884Sszhou } 7389eb2bd662Svikram BAM_DPRINTF((D_ROOT_OPT, fcn)); 73908c1b6884Sszhou } 73918c1b6884Sszhou 73928c1b6884Sszhou if (lp == NULL || lp->next == NULL) { 73938c1b6884Sszhou continue; 73948c1b6884Sszhou } 73958c1b6884Sszhou 7396843e1988Sjohnlev if (kernel && 7397843e1988Sjohnlev (!check_cmd(lp->cmd, KERNEL_CMD, lp->arg, kernel))) { 7398bbcc54bdSEnrico Perla - Sun Microsystems if (!(ent->flags & BAM_ENTRY_FAILSAFE) || 7399bbcc54bdSEnrico Perla - Sun Microsystems !(ent->flags & BAM_ENTRY_DBOOT) || 7400bbcc54bdSEnrico Perla - Sun Microsystems strcmp(kernel, DIRECT_BOOT_FAILSAFE_LINE) != 0) 74018c1b6884Sszhou continue; 7402bbcc54bdSEnrico Perla - Sun Microsystems 7403bbcc54bdSEnrico Perla - Sun Microsystems ent->flags |= BAM_ENTRY_UPGFSKERNEL; 7404bbcc54bdSEnrico Perla - Sun Microsystems 74058c1b6884Sszhou } 7406eb2bd662Svikram BAM_DPRINTF((D_KERNEL_MATCH, fcn, kernel, lp->arg)); 7407843e1988Sjohnlev 7408843e1988Sjohnlev /* 7409843e1988Sjohnlev * Check for matching module entry (failsafe or normal). 7410843e1988Sjohnlev * If it fails to match, we go around the loop again. 7411843e1988Sjohnlev * For xpv entries, there are two module lines, so we 7412843e1988Sjohnlev * do the check twice. 7413843e1988Sjohnlev */ 7414843e1988Sjohnlev lp = lp->next; /* advance to module line */ 7415843e1988Sjohnlev if (check_cmd(lp->cmd, MODULE_CMD, lp->arg, module) || 7416843e1988Sjohnlev (((lp = lp->next) != NULL) && 7417843e1988Sjohnlev check_cmd(lp->cmd, MODULE_CMD, lp->arg, module))) { 7418843e1988Sjohnlev /* match found */ 7419eb2bd662Svikram BAM_DPRINTF((D_MODULE_MATCH, fcn, module, lp->arg)); 7420843e1988Sjohnlev break; 7421843e1988Sjohnlev } 7422bbcc54bdSEnrico Perla - Sun Microsystems 7423bbcc54bdSEnrico Perla - Sun Microsystems if (strcmp(module, FAILSAFE_ARCHIVE) == 0 && 7424bbcc54bdSEnrico Perla - Sun Microsystems (strcmp(lp->prev->arg, FAILSAFE_ARCHIVE_32) == 0 || 7425bbcc54bdSEnrico Perla - Sun Microsystems strcmp(lp->prev->arg, FAILSAFE_ARCHIVE_64) == 0)) { 7426bbcc54bdSEnrico Perla - Sun Microsystems ent->flags |= BAM_ENTRY_UPGFSMODULE; 7427bbcc54bdSEnrico Perla - Sun Microsystems break; 7428bbcc54bdSEnrico Perla - Sun Microsystems } 7429bbcc54bdSEnrico Perla - Sun Microsystems 74308c1b6884Sszhou } 74318c1b6884Sszhou 7432eb2bd662Svikram if (ent && entry_num) { 74338c1b6884Sszhou *entry_num = i; 7434843e1988Sjohnlev } 7435eb2bd662Svikram 7436eb2bd662Svikram if (ent) { 7437eb2bd662Svikram BAM_DPRINTF((D_RETURN_RET, fcn, i)); 7438eb2bd662Svikram } else { 7439eb2bd662Svikram BAM_DPRINTF((D_RETURN_RET, fcn, BAM_ERROR)); 7440eb2bd662Svikram } 74418c1b6884Sszhou return (ent); 74428c1b6884Sszhou } 74438c1b6884Sszhou 74448c1b6884Sszhou static int 7445eb2bd662Svikram update_boot_entry(menu_t *mp, char *title, char *findroot, char *root, 7446eb2bd662Svikram char *kernel, char *mod_kernel, char *module, int root_opt) 74478c1b6884Sszhou { 7448eb2bd662Svikram int i; 7449eb2bd662Svikram int change_kernel = 0; 74508c1b6884Sszhou entry_t *ent; 74518c1b6884Sszhou line_t *lp; 7452eb2bd662Svikram line_t *tlp; 74538c1b6884Sszhou char linebuf[BAM_MAXLINE]; 7454eb2bd662Svikram const char *fcn = "update_boot_entry()"; 74558c1b6884Sszhou 74568c1b6884Sszhou /* note: don't match on title, it's updated on upgrade */ 7457eb2bd662Svikram ent = find_boot_entry(mp, NULL, kernel, findroot, root, module, 7458eb2bd662Svikram root_opt, &i); 7459ae115bc7Smrj if ((ent == NULL) && (bam_direct == BAM_DIRECT_DBOOT)) { 7460ae115bc7Smrj /* 7461ae115bc7Smrj * We may be upgrading a kernel from multiboot to 7462eb2bd662Svikram * directboot. Look for a multiboot entry. A multiboot 7463eb2bd662Svikram * entry will not have a findroot line. 7464ae115bc7Smrj */ 7465eb2bd662Svikram ent = find_boot_entry(mp, NULL, "multiboot", NULL, root, 7466eb2bd662Svikram MULTIBOOT_ARCHIVE, root_opt, &i); 7467ae115bc7Smrj if (ent != NULL) { 7468eb2bd662Svikram BAM_DPRINTF((D_UPGRADE_FROM_MULTIBOOT, fcn, root)); 7469ae115bc7Smrj change_kernel = 1; 7470ae115bc7Smrj } 7471eb2bd662Svikram } else if (ent) { 7472eb2bd662Svikram BAM_DPRINTF((D_FOUND_FINDROOT, fcn, findroot)); 7473ae115bc7Smrj } 74748c1b6884Sszhou 7475eb2bd662Svikram if (ent == NULL) { 7476eb2bd662Svikram BAM_DPRINTF((D_ENTRY_NOT_FOUND_CREATING, fcn, findroot)); 7477eb2bd662Svikram return (add_boot_entry(mp, title, findroot, 7478eb2bd662Svikram kernel, mod_kernel, module)); 7479eb2bd662Svikram } 7480eb2bd662Svikram 7481eb2bd662Svikram /* replace title of existing entry and update findroot line */ 74828c1b6884Sszhou lp = ent->start; 74838c1b6884Sszhou lp = lp->next; /* title line */ 74848c1b6884Sszhou (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", 74858c1b6884Sszhou menu_cmds[TITLE_CMD], menu_cmds[SEP_CMD], title); 74868c1b6884Sszhou free(lp->arg); 74878c1b6884Sszhou free(lp->line); 74888c1b6884Sszhou lp->arg = s_strdup(title); 74898c1b6884Sszhou lp->line = s_strdup(linebuf); 7490eb2bd662Svikram BAM_DPRINTF((D_CHANGING_TITLE, fcn, title)); 74918c1b6884Sszhou 7492eb2bd662Svikram tlp = lp; /* title line */ 74938c1b6884Sszhou lp = lp->next; /* root line */ 7494eb2bd662Svikram 7495eb2bd662Svikram /* if no root or findroot command, create a new line_t */ 7496eb2bd662Svikram if (strcmp(lp->cmd, menu_cmds[ROOT_CMD]) != 0 && 7497eb2bd662Svikram strcmp(lp->cmd, menu_cmds[FINDROOT_CMD]) != 0) { 7498eb2bd662Svikram lp = s_calloc(1, sizeof (line_t)); 7499eb2bd662Svikram bam_add_line(mp, ent, tlp, lp); 7500eb2bd662Svikram } else { 7501eb2bd662Svikram free(lp->cmd); 7502eb2bd662Svikram free(lp->sep); 7503eb2bd662Svikram free(lp->arg); 7504eb2bd662Svikram free(lp->line); 75058c1b6884Sszhou } 7506ae115bc7Smrj 7507eb2bd662Svikram lp->cmd = s_strdup(menu_cmds[FINDROOT_CMD]); 7508eb2bd662Svikram lp->sep = s_strdup(menu_cmds[SEP_CMD]); 7509eb2bd662Svikram lp->arg = s_strdup(findroot); 7510eb2bd662Svikram (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", 7511eb2bd662Svikram menu_cmds[FINDROOT_CMD], menu_cmds[SEP_CMD], findroot); 7512eb2bd662Svikram lp->line = s_strdup(linebuf); 7513eb2bd662Svikram BAM_DPRINTF((D_ADDING_FINDROOT_LINE, fcn, findroot)); 7514eb2bd662Svikram 7515eb2bd662Svikram /* kernel line */ 7516eb2bd662Svikram lp = lp->next; 7517eb2bd662Svikram 7518bbcc54bdSEnrico Perla - Sun Microsystems if (ent->flags & BAM_ENTRY_UPGFSKERNEL) { 7519bbcc54bdSEnrico Perla - Sun Microsystems char *params = NULL; 7520bbcc54bdSEnrico Perla - Sun Microsystems 7521bbcc54bdSEnrico Perla - Sun Microsystems params = strstr(lp->line, "-s"); 7522bbcc54bdSEnrico Perla - Sun Microsystems if (params != NULL) 7523bbcc54bdSEnrico Perla - Sun Microsystems (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s%s", 7524bbcc54bdSEnrico Perla - Sun Microsystems menu_cmds[KERNEL_DOLLAR_CMD], menu_cmds[SEP_CMD], 7525bbcc54bdSEnrico Perla - Sun Microsystems kernel, params+2); 7526bbcc54bdSEnrico Perla - Sun Microsystems else 7527bbcc54bdSEnrico Perla - Sun Microsystems (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", 7528bbcc54bdSEnrico Perla - Sun Microsystems menu_cmds[KERNEL_DOLLAR_CMD], menu_cmds[SEP_CMD], 7529bbcc54bdSEnrico Perla - Sun Microsystems kernel); 7530bbcc54bdSEnrico Perla - Sun Microsystems 7531bbcc54bdSEnrico Perla - Sun Microsystems free(lp->cmd); 7532bbcc54bdSEnrico Perla - Sun Microsystems free(lp->arg); 7533bbcc54bdSEnrico Perla - Sun Microsystems free(lp->line); 7534bbcc54bdSEnrico Perla - Sun Microsystems lp->cmd = s_strdup(menu_cmds[KERNEL_DOLLAR_CMD]); 7535bbcc54bdSEnrico Perla - Sun Microsystems lp->arg = s_strdup(strstr(linebuf, "/")); 7536bbcc54bdSEnrico Perla - Sun Microsystems lp->line = s_strdup(linebuf); 7537bbcc54bdSEnrico Perla - Sun Microsystems ent->flags &= ~BAM_ENTRY_UPGFSKERNEL; 7538bbcc54bdSEnrico Perla - Sun Microsystems BAM_DPRINTF((D_ADDING_KERNEL_DOLLAR, fcn, lp->prev->cmd)); 7539bbcc54bdSEnrico Perla - Sun Microsystems } 7540bbcc54bdSEnrico Perla - Sun Microsystems 7541ae115bc7Smrj if (change_kernel) { 7542ae115bc7Smrj /* 7543ae115bc7Smrj * We're upgrading from multiboot to directboot. 7544ae115bc7Smrj */ 7545ae115bc7Smrj if (strcmp(lp->cmd, menu_cmds[KERNEL_CMD]) == 0) { 7546ae115bc7Smrj (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", 7547ae115bc7Smrj menu_cmds[KERNEL_DOLLAR_CMD], menu_cmds[SEP_CMD], 7548ae115bc7Smrj kernel); 7549eb2bd662Svikram free(lp->cmd); 7550ae115bc7Smrj free(lp->arg); 7551ae115bc7Smrj free(lp->line); 7552eb2bd662Svikram lp->cmd = s_strdup(menu_cmds[KERNEL_DOLLAR_CMD]); 7553ae115bc7Smrj lp->arg = s_strdup(kernel); 7554ae115bc7Smrj lp->line = s_strdup(linebuf); 7555ae115bc7Smrj lp = lp->next; 7556eb2bd662Svikram BAM_DPRINTF((D_ADDING_KERNEL_DOLLAR, fcn, kernel)); 7557ae115bc7Smrj } 7558ae115bc7Smrj if (strcmp(lp->cmd, menu_cmds[MODULE_CMD]) == 0) { 7559ae115bc7Smrj (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", 7560ae115bc7Smrj menu_cmds[MODULE_DOLLAR_CMD], menu_cmds[SEP_CMD], 7561ae115bc7Smrj module); 7562eb2bd662Svikram free(lp->cmd); 7563ae115bc7Smrj free(lp->arg); 7564ae115bc7Smrj free(lp->line); 7565eb2bd662Svikram lp->cmd = s_strdup(menu_cmds[MODULE_DOLLAR_CMD]); 7566ae115bc7Smrj lp->arg = s_strdup(module); 7567ae115bc7Smrj lp->line = s_strdup(linebuf); 7568ae115bc7Smrj lp = lp->next; 7569eb2bd662Svikram BAM_DPRINTF((D_ADDING_MODULE_DOLLAR, fcn, module)); 7570ae115bc7Smrj } 7571ae115bc7Smrj } 7572bbcc54bdSEnrico Perla - Sun Microsystems 7573bbcc54bdSEnrico Perla - Sun Microsystems /* module line */ 7574bbcc54bdSEnrico Perla - Sun Microsystems lp = lp->next; 7575bbcc54bdSEnrico Perla - Sun Microsystems 7576bbcc54bdSEnrico Perla - Sun Microsystems if (ent->flags & BAM_ENTRY_UPGFSMODULE) { 7577bbcc54bdSEnrico Perla - Sun Microsystems if (strcmp(lp->cmd, menu_cmds[MODULE_CMD]) == 0) { 7578bbcc54bdSEnrico Perla - Sun Microsystems (void) snprintf(linebuf, sizeof (linebuf), "%s%s%s", 7579bbcc54bdSEnrico Perla - Sun Microsystems menu_cmds[MODULE_DOLLAR_CMD], menu_cmds[SEP_CMD], 7580bbcc54bdSEnrico Perla - Sun Microsystems module); 7581bbcc54bdSEnrico Perla - Sun Microsystems free(lp->cmd); 7582bbcc54bdSEnrico Perla - Sun Microsystems free(lp->arg); 7583bbcc54bdSEnrico Perla - Sun Microsystems free(lp->line); 7584bbcc54bdSEnrico Perla - Sun Microsystems lp->cmd = s_strdup(menu_cmds[MODULE_DOLLAR_CMD]); 7585bbcc54bdSEnrico Perla - Sun Microsystems lp->arg = s_strdup(module); 7586bbcc54bdSEnrico Perla - Sun Microsystems lp->line = s_strdup(linebuf); 7587bbcc54bdSEnrico Perla - Sun Microsystems lp = lp->next; 7588bbcc54bdSEnrico Perla - Sun Microsystems ent->flags &= ~BAM_ENTRY_UPGFSMODULE; 7589bbcc54bdSEnrico Perla - Sun Microsystems BAM_DPRINTF((D_ADDING_MODULE_DOLLAR, fcn, module)); 7590bbcc54bdSEnrico Perla - Sun Microsystems } 7591bbcc54bdSEnrico Perla - Sun Microsystems } 7592bbcc54bdSEnrico Perla - Sun Microsystems 7593eb2bd662Svikram BAM_DPRINTF((D_RETURN_RET, fcn, i)); 75948c1b6884Sszhou return (i); 75958c1b6884Sszhou } 75968c1b6884Sszhou 7597eb2bd662Svikram int 7598eb2bd662Svikram root_optional(char *osroot, char *menu_root) 7599eb2bd662Svikram { 7600eb2bd662Svikram char *ospecial; 7601eb2bd662Svikram char *mspecial; 7602eb2bd662Svikram char *slash; 7603eb2bd662Svikram int root_opt; 7604eb2bd662Svikram int ret1; 7605eb2bd662Svikram int ret2; 7606eb2bd662Svikram const char *fcn = "root_optional()"; 7607eb2bd662Svikram 7608eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY2, fcn, osroot, menu_root)); 7609eb2bd662Svikram 7610eb2bd662Svikram /* 7611eb2bd662Svikram * For all filesystems except ZFS, a straight compare of osroot 7612eb2bd662Svikram * and menu_root will tell us if root is optional. 7613eb2bd662Svikram * For ZFS, the situation is complicated by the fact that 7614eb2bd662Svikram * menu_root and osroot are always different 7615eb2bd662Svikram */ 7616eb2bd662Svikram ret1 = is_zfs(osroot); 7617eb2bd662Svikram ret2 = is_zfs(menu_root); 7618eb2bd662Svikram INJECT_ERROR1("ROOT_OPT_NOT_ZFS", ret1 = 0); 7619eb2bd662Svikram if (!ret1 || !ret2) { 7620eb2bd662Svikram BAM_DPRINTF((D_ROOT_OPT_NOT_ZFS, fcn, osroot, menu_root)); 7621eb2bd662Svikram root_opt = (strcmp(osroot, menu_root) == 0); 7622eb2bd662Svikram goto out; 7623eb2bd662Svikram } 7624eb2bd662Svikram 7625eb2bd662Svikram ospecial = get_special(osroot); 7626eb2bd662Svikram INJECT_ERROR1("ROOT_OPTIONAL_OSPECIAL", ospecial = NULL); 7627eb2bd662Svikram if (ospecial == NULL) { 7628eb2bd662Svikram bam_error(GET_OSROOT_SPECIAL_ERR, osroot); 7629eb2bd662Svikram return (0); 7630eb2bd662Svikram } 7631eb2bd662Svikram BAM_DPRINTF((D_ROOT_OPTIONAL_OSPECIAL, fcn, ospecial, osroot)); 7632eb2bd662Svikram 7633eb2bd662Svikram mspecial = get_special(menu_root); 7634eb2bd662Svikram INJECT_ERROR1("ROOT_OPTIONAL_MSPECIAL", mspecial = NULL); 7635eb2bd662Svikram if (mspecial == NULL) { 7636eb2bd662Svikram bam_error(GET_MENU_ROOT_SPECIAL_ERR, menu_root); 7637eb2bd662Svikram free(ospecial); 7638eb2bd662Svikram return (0); 7639eb2bd662Svikram } 7640eb2bd662Svikram BAM_DPRINTF((D_ROOT_OPTIONAL_MSPECIAL, fcn, mspecial, menu_root)); 7641eb2bd662Svikram 7642eb2bd662Svikram slash = strchr(ospecial, '/'); 7643eb2bd662Svikram if (slash) 7644eb2bd662Svikram *slash = '\0'; 7645eb2bd662Svikram BAM_DPRINTF((D_ROOT_OPTIONAL_FIXED_OSPECIAL, fcn, ospecial, osroot)); 7646eb2bd662Svikram 7647eb2bd662Svikram root_opt = (strcmp(ospecial, mspecial) == 0); 7648eb2bd662Svikram 7649eb2bd662Svikram free(ospecial); 7650eb2bd662Svikram free(mspecial); 7651eb2bd662Svikram 7652eb2bd662Svikram out: 7653eb2bd662Svikram INJECT_ERROR1("ROOT_OPTIONAL_NO", root_opt = 0); 7654eb2bd662Svikram INJECT_ERROR1("ROOT_OPTIONAL_YES", root_opt = 1); 7655eb2bd662Svikram if (root_opt) { 7656eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 7657eb2bd662Svikram } else { 7658eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 7659eb2bd662Svikram } 7660eb2bd662Svikram 7661eb2bd662Svikram return (root_opt); 7662eb2bd662Svikram } 7663eb2bd662Svikram 76647c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 76657c478bd9Sstevel@tonic-gate static error_t 7666eb2bd662Svikram update_entry(menu_t *mp, char *menu_root, char *osdev) 76677c478bd9Sstevel@tonic-gate { 76687c478bd9Sstevel@tonic-gate int entry; 7669eb2bd662Svikram char *grubsign; 7670eb2bd662Svikram char *grubroot; 7671eb2bd662Svikram char *title; 7672eb2bd662Svikram char osroot[PATH_MAX]; 7673eb2bd662Svikram char *failsafe_kernel = NULL; 76748c1b6884Sszhou struct stat sbuf; 76758c1b6884Sszhou char failsafe[256]; 7676bbcc54bdSEnrico Perla - Sun Microsystems char failsafe_64[256]; 7677eb2bd662Svikram int ret; 7678eb2bd662Svikram const char *fcn = "update_entry()"; 76797c478bd9Sstevel@tonic-gate 76807c478bd9Sstevel@tonic-gate assert(mp); 7681eb2bd662Svikram assert(menu_root); 7682eb2bd662Svikram assert(osdev); 7683eb2bd662Svikram assert(bam_root); 76847c478bd9Sstevel@tonic-gate 7685eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY3, fcn, menu_root, osdev, bam_root)); 7686eb2bd662Svikram 7687eb2bd662Svikram (void) strlcpy(osroot, bam_root, sizeof (osroot)); 7688eb2bd662Svikram 76897c478bd9Sstevel@tonic-gate title = get_title(osroot); 7690eb2bd662Svikram assert(title); 76917c478bd9Sstevel@tonic-gate 7692eb2bd662Svikram grubsign = get_grubsign(osroot, osdev); 7693eb2bd662Svikram INJECT_ERROR1("GET_GRUBSIGN_FAIL", grubsign = NULL); 7694eb2bd662Svikram if (grubsign == NULL) { 7695eb2bd662Svikram bam_error(GET_GRUBSIGN_ERROR, osroot, osdev); 76967c478bd9Sstevel@tonic-gate return (BAM_ERROR); 76977c478bd9Sstevel@tonic-gate } 7698eb2bd662Svikram 7699eb2bd662Svikram /* 7700eb2bd662Svikram * It is not a fatal error if get_grubroot() fails 7701eb2bd662Svikram * We no longer rely on biosdev to populate the 7702eb2bd662Svikram * menu 7703eb2bd662Svikram */ 7704eb2bd662Svikram grubroot = get_grubroot(osroot, osdev, menu_root); 7705eb2bd662Svikram INJECT_ERROR1("GET_GRUBROOT_FAIL", grubroot = NULL); 7706eb2bd662Svikram if (grubroot) { 7707eb2bd662Svikram BAM_DPRINTF((D_GET_GRUBROOT_SUCCESS, 7708eb2bd662Svikram fcn, osroot, osdev, menu_root)); 7709eb2bd662Svikram } else { 7710eb2bd662Svikram BAM_DPRINTF((D_GET_GRUBROOT_FAILURE, 7711eb2bd662Svikram fcn, osroot, osdev, menu_root)); 77127c478bd9Sstevel@tonic-gate } 77137c478bd9Sstevel@tonic-gate 77147c478bd9Sstevel@tonic-gate /* add the entry for normal Solaris */ 7715eb2bd662Svikram INJECT_ERROR1("UPDATE_ENTRY_MULTIBOOT", 7716eb2bd662Svikram bam_direct = BAM_DIRECT_MULTIBOOT); 7717ae115bc7Smrj if (bam_direct == BAM_DIRECT_DBOOT) { 7718eb2bd662Svikram entry = update_boot_entry(mp, title, grubsign, grubroot, 7719e7cbe64fSgw25295 (bam_zfs ? DIRECT_BOOT_KERNEL_ZFS : DIRECT_BOOT_KERNEL), 7720eb2bd662Svikram NULL, DIRECT_BOOT_ARCHIVE, 7721eb2bd662Svikram root_optional(osroot, menu_root)); 7722eb2bd662Svikram BAM_DPRINTF((D_UPDATED_BOOT_ENTRY, fcn, bam_zfs, grubsign)); 7723843e1988Sjohnlev if ((entry != BAM_ERROR) && (bam_is_hv == BAM_HV_PRESENT)) { 7724eb2bd662Svikram (void) update_boot_entry(mp, NEW_HV_ENTRY, grubsign, 7725eb2bd662Svikram grubroot, XEN_MENU, bam_zfs ? 7726eb2bd662Svikram XEN_KERNEL_MODULE_LINE_ZFS : XEN_KERNEL_MODULE_LINE, 7727eb2bd662Svikram DIRECT_BOOT_ARCHIVE, 7728eb2bd662Svikram root_optional(osroot, menu_root)); 7729eb2bd662Svikram BAM_DPRINTF((D_UPDATED_HV_ENTRY, 7730eb2bd662Svikram fcn, bam_zfs, grubsign)); 7731ae115bc7Smrj } 7732843e1988Sjohnlev } else { 7733eb2bd662Svikram entry = update_boot_entry(mp, title, grubsign, grubroot, 7734eb2bd662Svikram MULTI_BOOT, NULL, MULTIBOOT_ARCHIVE, 7735eb2bd662Svikram root_optional(osroot, menu_root)); 7736eb2bd662Svikram 7737eb2bd662Svikram BAM_DPRINTF((D_UPDATED_MULTIBOOT_ENTRY, fcn, grubsign)); 7738843e1988Sjohnlev } 77397c478bd9Sstevel@tonic-gate 7740843e1988Sjohnlev /* 7741843e1988Sjohnlev * Add the entry for failsafe archive. On a bfu'd system, the 7742843e1988Sjohnlev * failsafe may be different than the installed kernel. 7743843e1988Sjohnlev */ 7744eb2bd662Svikram (void) snprintf(failsafe, sizeof (failsafe), "%s%s", 7745bbcc54bdSEnrico Perla - Sun Microsystems osroot, FAILSAFE_ARCHIVE_32); 7746bbcc54bdSEnrico Perla - Sun Microsystems (void) snprintf(failsafe_64, sizeof (failsafe_64), "%s%s", 7747bbcc54bdSEnrico Perla - Sun Microsystems osroot, FAILSAFE_ARCHIVE_64); 7748bbcc54bdSEnrico Perla - Sun Microsystems 7749bbcc54bdSEnrico Perla - Sun Microsystems /* 7750bbcc54bdSEnrico Perla - Sun Microsystems * Check if at least one of the two archives exists 7751bbcc54bdSEnrico Perla - Sun Microsystems * Using $ISADIR as the default line, we have an entry which works 7752bbcc54bdSEnrico Perla - Sun Microsystems * for both the cases. 7753bbcc54bdSEnrico Perla - Sun Microsystems */ 7754bbcc54bdSEnrico Perla - Sun Microsystems 7755bbcc54bdSEnrico Perla - Sun Microsystems if (stat(failsafe, &sbuf) == 0 || stat(failsafe_64, &sbuf) == 0) { 775660d0a590Srscott 775760d0a590Srscott /* Figure out where the kernel line should point */ 775860d0a590Srscott (void) snprintf(failsafe, sizeof (failsafe), "%s%s", osroot, 7759bbcc54bdSEnrico Perla - Sun Microsystems DIRECT_BOOT_FAILSAFE_32); 7760bbcc54bdSEnrico Perla - Sun Microsystems (void) snprintf(failsafe_64, sizeof (failsafe_64), "%s%s", 7761bbcc54bdSEnrico Perla - Sun Microsystems osroot, DIRECT_BOOT_FAILSAFE_64); 7762bbcc54bdSEnrico Perla - Sun Microsystems if (stat(failsafe, &sbuf) == 0 || 7763bbcc54bdSEnrico Perla - Sun Microsystems stat(failsafe_64, &sbuf) == 0) { 7764963390b4Svikram failsafe_kernel = DIRECT_BOOT_FAILSAFE_LINE; 776560d0a590Srscott } else { 776660d0a590Srscott (void) snprintf(failsafe, sizeof (failsafe), "%s%s", 776760d0a590Srscott osroot, MULTI_BOOT_FAILSAFE); 776860d0a590Srscott if (stat(failsafe, &sbuf) == 0) { 776960d0a590Srscott failsafe_kernel = MULTI_BOOT_FAILSAFE_LINE; 777060d0a590Srscott } 777160d0a590Srscott } 777260d0a590Srscott if (failsafe_kernel != NULL) { 7773eb2bd662Svikram (void) update_boot_entry(mp, FAILSAFE_TITLE, grubsign, 7774eb2bd662Svikram grubroot, failsafe_kernel, NULL, FAILSAFE_ARCHIVE, 7775eb2bd662Svikram root_optional(osroot, menu_root)); 7776eb2bd662Svikram BAM_DPRINTF((D_UPDATED_FAILSAFE_ENTRY, fcn, 7777eb2bd662Svikram failsafe_kernel)); 777860d0a590Srscott } 7779ae115bc7Smrj } 7780eb2bd662Svikram free(grubroot); 77817c478bd9Sstevel@tonic-gate 7782eb2bd662Svikram INJECT_ERROR1("UPDATE_ENTRY_ERROR", entry = BAM_ERROR); 77837c478bd9Sstevel@tonic-gate if (entry == BAM_ERROR) { 7784eb2bd662Svikram bam_error(FAILED_TO_ADD_BOOT_ENTRY, title, grubsign); 7785eb2bd662Svikram free(grubsign); 77867c478bd9Sstevel@tonic-gate return (BAM_ERROR); 77877c478bd9Sstevel@tonic-gate } 7788eb2bd662Svikram free(grubsign); 7789eb2bd662Svikram 7790eb2bd662Svikram update_numbering(mp); 7791eb2bd662Svikram ret = set_global(mp, menu_cmds[DEFAULT_CMD], entry); 7792eb2bd662Svikram INJECT_ERROR1("SET_DEFAULT_ERROR", ret = BAM_ERROR); 7793eb2bd662Svikram if (ret == BAM_ERROR) { 7794eb2bd662Svikram bam_error(SET_DEFAULT_FAILED, entry); 7795eb2bd662Svikram } 7796eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 77977c478bd9Sstevel@tonic-gate return (BAM_WRITE); 77987c478bd9Sstevel@tonic-gate } 77997c478bd9Sstevel@tonic-gate 78008c1b6884Sszhou static void 7801ae115bc7Smrj save_default_entry(menu_t *mp, const char *which) 78028c1b6884Sszhou { 7803eb2bd662Svikram int lineNum; 7804eb2bd662Svikram int entryNum; 78058c1b6884Sszhou int entry = 0; /* default is 0 */ 78068c1b6884Sszhou char linebuf[BAM_MAXLINE]; 78078c1b6884Sszhou line_t *lp = mp->curdefault; 7808eb2bd662Svikram const char *fcn = "save_default_entry()"; 78098c1b6884Sszhou 7810bff269d0Svikram if (mp->start) { 7811bff269d0Svikram lineNum = mp->end->lineNum; 7812bff269d0Svikram entryNum = mp->end->entryNum; 7813bff269d0Svikram } else { 7814bff269d0Svikram lineNum = LINE_INIT; 7815bff269d0Svikram entryNum = ENTRY_INIT; 7816bff269d0Svikram } 7817bff269d0Svikram 78188c1b6884Sszhou if (lp) 78198c1b6884Sszhou entry = s_strtol(lp->arg); 78208c1b6884Sszhou 7821ae115bc7Smrj (void) snprintf(linebuf, sizeof (linebuf), "#%s%d", which, entry); 7822eb2bd662Svikram BAM_DPRINTF((D_SAVING_DEFAULT_TO, fcn, linebuf)); 78238c1b6884Sszhou line_parser(mp, linebuf, &lineNum, &entryNum); 7824eb2bd662Svikram BAM_DPRINTF((D_SAVED_DEFAULT_TO, fcn, lineNum, entryNum)); 78258c1b6884Sszhou } 78268c1b6884Sszhou 78278c1b6884Sszhou static void 7828ae115bc7Smrj restore_default_entry(menu_t *mp, const char *which, line_t *lp) 78298c1b6884Sszhou { 78308c1b6884Sszhou int entry; 78318c1b6884Sszhou char *str; 7832eb2bd662Svikram const char *fcn = "restore_default_entry()"; 78338c1b6884Sszhou 7834eb2bd662Svikram if (lp == NULL) { 7835eb2bd662Svikram BAM_DPRINTF((D_RESTORE_DEFAULT_NULL, fcn)); 78368c1b6884Sszhou return; /* nothing to restore */ 7837eb2bd662Svikram } 7838eb2bd662Svikram 7839eb2bd662Svikram BAM_DPRINTF((D_RESTORE_DEFAULT_STR, fcn, which)); 78408c1b6884Sszhou 7841ae115bc7Smrj str = lp->arg + strlen(which); 78428c1b6884Sszhou entry = s_strtol(str); 78438c1b6884Sszhou (void) set_global(mp, menu_cmds[DEFAULT_CMD], entry); 78448c1b6884Sszhou 7845eb2bd662Svikram BAM_DPRINTF((D_RESTORED_DEFAULT_TO, fcn, entry)); 7846eb2bd662Svikram 78478c1b6884Sszhou /* delete saved old default line */ 78488c1b6884Sszhou unlink_line(mp, lp); 78498c1b6884Sszhou line_free(lp); 78508c1b6884Sszhou } 78518c1b6884Sszhou 78527c478bd9Sstevel@tonic-gate /* 78537c478bd9Sstevel@tonic-gate * This function is for supporting reboot with args. 78547c478bd9Sstevel@tonic-gate * The opt value can be: 78557c478bd9Sstevel@tonic-gate * NULL delete temp entry, if present 7856eb2bd662Svikram * entry=<n> switches default entry to <n> 78577c478bd9Sstevel@tonic-gate * else treated as boot-args and setup a temperary menu entry 78587c478bd9Sstevel@tonic-gate * and make it the default 7859eb2bd662Svikram * Note that we are always rebooting the current OS instance 7860eb2bd662Svikram * so osroot == / always. 78617c478bd9Sstevel@tonic-gate */ 78627c478bd9Sstevel@tonic-gate #define REBOOT_TITLE "Solaris_reboot_transient" 78637c478bd9Sstevel@tonic-gate 78648c1b6884Sszhou /*ARGSUSED*/ 78657c478bd9Sstevel@tonic-gate static error_t 7866eb2bd662Svikram update_temp(menu_t *mp, char *dummy, char *opt) 78677c478bd9Sstevel@tonic-gate { 78687c478bd9Sstevel@tonic-gate int entry; 7869eb2bd662Svikram char *osdev; 7870eb2bd662Svikram char *fstype; 7871eb2bd662Svikram char *sign; 7872eb2bd662Svikram char *opt_ptr; 7873eb2bd662Svikram char *path; 7874ae115bc7Smrj char kernbuf[BUFSIZ]; 7875ae115bc7Smrj char args_buf[BUFSIZ]; 7876eb2bd662Svikram char signbuf[PATH_MAX]; 7877eb2bd662Svikram int ret; 7878eb2bd662Svikram const char *fcn = "update_temp()"; 78797c478bd9Sstevel@tonic-gate 78807c478bd9Sstevel@tonic-gate assert(mp); 7881eb2bd662Svikram assert(dummy == NULL); 7882eb2bd662Svikram 7883eb2bd662Svikram /* opt can be NULL */ 7884eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY1, fcn, opt ? opt : "<NULL>")); 7885eb2bd662Svikram BAM_DPRINTF((D_BAM_ROOT, fcn, bam_alt_root, bam_root)); 7886eb2bd662Svikram 7887eb2bd662Svikram if (bam_alt_root || bam_rootlen != 1 || 7888eb2bd662Svikram strcmp(bam_root, "/") != 0 || 7889eb2bd662Svikram strcmp(rootbuf, "/") != 0) { 7890eb2bd662Svikram bam_error(ALT_ROOT_INVALID, bam_root); 7891eb2bd662Svikram return (BAM_ERROR); 7892eb2bd662Svikram } 78937c478bd9Sstevel@tonic-gate 78948c1b6884Sszhou /* If no option, delete exiting reboot menu entry */ 78958c1b6884Sszhou if (opt == NULL) { 7896eb2bd662Svikram entry_t *ent; 7897eb2bd662Svikram BAM_DPRINTF((D_OPT_NULL, fcn)); 7898eb2bd662Svikram ent = find_boot_entry(mp, REBOOT_TITLE, NULL, NULL, 7899eb2bd662Svikram NULL, NULL, 0, &entry); 7900eb2bd662Svikram if (ent == NULL) { /* not found is ok */ 7901eb2bd662Svikram BAM_DPRINTF((D_TRANSIENT_NOTFOUND, fcn)); 79028c1b6884Sszhou return (BAM_SUCCESS); 7903eb2bd662Svikram } 79048c1b6884Sszhou (void) do_delete(mp, entry); 7905ae115bc7Smrj restore_default_entry(mp, BAM_OLDDEF, mp->olddefault); 7906ae115bc7Smrj mp->olddefault = NULL; 7907eb2bd662Svikram BAM_DPRINTF((D_RESTORED_DEFAULT, fcn)); 7908eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 79098c1b6884Sszhou return (BAM_WRITE); 79108c1b6884Sszhou } 79118c1b6884Sszhou 79128c1b6884Sszhou /* if entry= is specified, set the default entry */ 7913eb2bd662Svikram if (strncmp(opt, "entry=", strlen("entry=")) == 0) { 7914eb2bd662Svikram int entryNum = s_strtol(opt + strlen("entry=")); 7915eb2bd662Svikram BAM_DPRINTF((D_ENTRY_EQUALS, fcn, opt)); 7916eb2bd662Svikram if (selector(mp, opt, &entry, NULL) == BAM_SUCCESS) { 79177c478bd9Sstevel@tonic-gate /* this is entry=# option */ 7918eb2bd662Svikram ret = set_global(mp, menu_cmds[DEFAULT_CMD], entry); 7919eb2bd662Svikram BAM_DPRINTF((D_ENTRY_SET_IS, fcn, entry, ret)); 7920eb2bd662Svikram return (ret); 7921eb2bd662Svikram } else { 7922eb2bd662Svikram bam_error(SET_DEFAULT_FAILED, entryNum); 7923eb2bd662Svikram return (BAM_ERROR); 7924eb2bd662Svikram } 79257c478bd9Sstevel@tonic-gate } 79267c478bd9Sstevel@tonic-gate 79277c478bd9Sstevel@tonic-gate /* 7928eb2bd662Svikram * add a new menu entry based on opt and make it the default 7929b610f78eSvikram */ 7930eb2bd662Svikram 7931eb2bd662Svikram fstype = get_fstype("/"); 7932eb2bd662Svikram INJECT_ERROR1("REBOOT_FSTYPE_NULL", fstype = NULL); 7933eb2bd662Svikram if (fstype == NULL) { 7934eb2bd662Svikram bam_error(REBOOT_FSTYPE_FAILED); 7935eb2bd662Svikram return (BAM_ERROR); 79367c478bd9Sstevel@tonic-gate } 7937eb2bd662Svikram 7938eb2bd662Svikram osdev = get_special("/"); 7939eb2bd662Svikram INJECT_ERROR1("REBOOT_SPECIAL_NULL", osdev = NULL); 7940eb2bd662Svikram if (osdev == NULL) { 7941eb2bd662Svikram free(fstype); 7942eb2bd662Svikram bam_error(REBOOT_SPECIAL_FAILED); 7943eb2bd662Svikram return (BAM_ERROR); 7944b610f78eSvikram } 7945eb2bd662Svikram 7946eb2bd662Svikram sign = find_existing_sign("/", osdev, fstype); 7947eb2bd662Svikram INJECT_ERROR1("REBOOT_SIGN_NULL", sign = NULL); 7948eb2bd662Svikram if (sign == NULL) { 7949eb2bd662Svikram free(fstype); 7950eb2bd662Svikram free(osdev); 7951eb2bd662Svikram bam_error(REBOOT_SIGN_FAILED); 7952eb2bd662Svikram return (BAM_ERROR); 7953eb2bd662Svikram } 7954eb2bd662Svikram 7955eb2bd662Svikram free(fstype); 7956eb2bd662Svikram free(osdev); 7957eb2bd662Svikram (void) strlcpy(signbuf, sign, sizeof (signbuf)); 7958eb2bd662Svikram free(sign); 7959eb2bd662Svikram 7960eb2bd662Svikram assert(strchr(signbuf, '(') == NULL && strchr(signbuf, ',') == NULL && 7961eb2bd662Svikram strchr(signbuf, ')') == NULL); 7962eb2bd662Svikram 7963eb2bd662Svikram /* 7964eb2bd662Svikram * There is no alternate root while doing reboot with args 7965eb2bd662Svikram * This version of bootadm is only delivered with a DBOOT 7966eb2bd662Svikram * version of Solaris. 7967eb2bd662Svikram */ 7968eb2bd662Svikram INJECT_ERROR1("REBOOT_NOT_DBOOT", bam_direct = BAM_DIRECT_MULTIBOOT); 7969eb2bd662Svikram if (bam_direct != BAM_DIRECT_DBOOT) { 7970eb2bd662Svikram bam_error(REBOOT_DIRECT_FAILED); 79717c478bd9Sstevel@tonic-gate return (BAM_ERROR); 79727c478bd9Sstevel@tonic-gate } 79737c478bd9Sstevel@tonic-gate 79747c478bd9Sstevel@tonic-gate /* add an entry for Solaris reboot */ 7975ae115bc7Smrj if (opt[0] == '-') { 7976ae115bc7Smrj /* It's an option - first see if boot-file is set */ 7977eb2bd662Svikram ret = get_kernel(mp, KERNEL_CMD, kernbuf, sizeof (kernbuf)); 7978eb2bd662Svikram INJECT_ERROR1("REBOOT_GET_KERNEL", ret = BAM_ERROR); 7979eb2bd662Svikram if (ret != BAM_SUCCESS) { 7980eb2bd662Svikram bam_error(REBOOT_GET_KERNEL_FAILED); 7981ae115bc7Smrj return (BAM_ERROR); 7982eb2bd662Svikram } 7983ae115bc7Smrj if (kernbuf[0] == '\0') 7984eb2bd662Svikram (void) strlcpy(kernbuf, DIRECT_BOOT_KERNEL, 7985eb2bd662Svikram sizeof (kernbuf)); 7986eb2bd662Svikram (void) strlcat(kernbuf, " ", sizeof (kernbuf)); 7987eb2bd662Svikram (void) strlcat(kernbuf, opt, sizeof (kernbuf)); 7988eb2bd662Svikram BAM_DPRINTF((D_REBOOT_OPTION, fcn, kernbuf)); 7989ae115bc7Smrj } else if (opt[0] == '/') { 7990455710d3Srscott /* It's a full path, so write it out. */ 7991eb2bd662Svikram (void) strlcpy(kernbuf, opt, sizeof (kernbuf)); 7992455710d3Srscott 7993455710d3Srscott /* 7994455710d3Srscott * If someone runs: 7995455710d3Srscott * 7996455710d3Srscott * # eeprom boot-args='-kd' 7997455710d3Srscott * # reboot /platform/i86pc/kernel/unix 7998455710d3Srscott * 7999455710d3Srscott * we want to use the boot-args as part of the boot 8000455710d3Srscott * line. On the other hand, if someone runs: 8001455710d3Srscott * 8002455710d3Srscott * # reboot "/platform/i86pc/kernel/unix -kd" 8003455710d3Srscott * 8004455710d3Srscott * we don't need to mess with boot-args. If there's 8005455710d3Srscott * no space in the options string, assume we're in the 8006455710d3Srscott * first case. 8007455710d3Srscott */ 8008455710d3Srscott if (strchr(opt, ' ') == NULL) { 8009eb2bd662Svikram ret = get_kernel(mp, ARGS_CMD, args_buf, 8010eb2bd662Svikram sizeof (args_buf)); 8011eb2bd662Svikram INJECT_ERROR1("REBOOT_GET_ARGS", ret = BAM_ERROR); 8012eb2bd662Svikram if (ret != BAM_SUCCESS) { 8013eb2bd662Svikram bam_error(REBOOT_GET_ARGS_FAILED); 8014455710d3Srscott return (BAM_ERROR); 8015eb2bd662Svikram } 8016455710d3Srscott 8017455710d3Srscott if (args_buf[0] != '\0') { 8018eb2bd662Svikram (void) strlcat(kernbuf, " ", sizeof (kernbuf)); 8019455710d3Srscott (void) strlcat(kernbuf, args_buf, 8020eb2bd662Svikram sizeof (kernbuf)); 8021455710d3Srscott } 8022455710d3Srscott } 8023eb2bd662Svikram BAM_DPRINTF((D_REBOOT_ABSPATH, fcn, kernbuf)); 8024ae115bc7Smrj } else { 8025455710d3Srscott /* 8026455710d3Srscott * It may be a partial path, or it may be a partial 8027455710d3Srscott * path followed by options. Assume that only options 8028455710d3Srscott * follow a space. If someone sends us a kernel path 8029455710d3Srscott * that includes a space, they deserve to be broken. 8030455710d3Srscott */ 8031455710d3Srscott opt_ptr = strchr(opt, ' '); 8032455710d3Srscott if (opt_ptr != NULL) { 8033455710d3Srscott *opt_ptr = '\0'; 8034455710d3Srscott } 8035455710d3Srscott 8036ae115bc7Smrj path = expand_path(opt); 8037ae115bc7Smrj if (path != NULL) { 8038eb2bd662Svikram (void) strlcpy(kernbuf, path, sizeof (kernbuf)); 8039ae115bc7Smrj free(path); 8040455710d3Srscott 8041455710d3Srscott /* 8042455710d3Srscott * If there were options given, use those. 8043455710d3Srscott * Otherwise, copy over the default options. 8044455710d3Srscott */ 8045455710d3Srscott if (opt_ptr != NULL) { 8046455710d3Srscott /* Restore the space in opt string */ 8047455710d3Srscott *opt_ptr = ' '; 8048455710d3Srscott (void) strlcat(kernbuf, opt_ptr, 8049eb2bd662Svikram sizeof (kernbuf)); 8050455710d3Srscott } else { 8051eb2bd662Svikram ret = get_kernel(mp, ARGS_CMD, args_buf, 8052eb2bd662Svikram sizeof (args_buf)); 8053eb2bd662Svikram INJECT_ERROR1("UPDATE_TEMP_PARTIAL_ARGS", 8054eb2bd662Svikram ret = BAM_ERROR); 8055eb2bd662Svikram if (ret != BAM_SUCCESS) { 8056eb2bd662Svikram bam_error(REBOOT_GET_ARGS_FAILED); 8057ae115bc7Smrj return (BAM_ERROR); 8058eb2bd662Svikram } 8059ae115bc7Smrj 8060ae115bc7Smrj if (args_buf[0] != '\0') { 8061ae115bc7Smrj (void) strlcat(kernbuf, " ", 8062eb2bd662Svikram sizeof (kernbuf)); 8063ae115bc7Smrj (void) strlcat(kernbuf, 8064eb2bd662Svikram args_buf, sizeof (kernbuf)); 8065ae115bc7Smrj } 8066ae115bc7Smrj } 8067eb2bd662Svikram BAM_DPRINTF((D_REBOOT_RESOLVED_PARTIAL, fcn, kernbuf)); 8068455710d3Srscott } else { 8069455710d3Srscott bam_error(UNKNOWN_KERNEL, opt); 8070455710d3Srscott bam_print_stderr(UNKNOWN_KERNEL_REBOOT); 8071455710d3Srscott return (BAM_ERROR); 8072ae115bc7Smrj } 8073ae115bc7Smrj } 8074eb2bd662Svikram entry = add_boot_entry(mp, REBOOT_TITLE, signbuf, kernbuf, 8075843e1988Sjohnlev NULL, NULL); 8076eb2bd662Svikram INJECT_ERROR1("REBOOT_ADD_BOOT_ENTRY", entry = BAM_ERROR); 80777c478bd9Sstevel@tonic-gate if (entry == BAM_ERROR) { 8078eb2bd662Svikram bam_error(REBOOT_WITH_ARGS_ADD_ENTRY_FAILED); 80797c478bd9Sstevel@tonic-gate return (BAM_ERROR); 80807c478bd9Sstevel@tonic-gate } 80818c1b6884Sszhou 8082ae115bc7Smrj save_default_entry(mp, BAM_OLDDEF); 8083eb2bd662Svikram ret = set_global(mp, menu_cmds[DEFAULT_CMD], entry); 8084eb2bd662Svikram INJECT_ERROR1("REBOOT_SET_GLOBAL", ret = BAM_ERROR); 8085eb2bd662Svikram if (ret == BAM_ERROR) { 8086eb2bd662Svikram bam_error(REBOOT_SET_DEFAULT_FAILED, entry); 8087eb2bd662Svikram } 8088eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 80897c478bd9Sstevel@tonic-gate return (BAM_WRITE); 80907c478bd9Sstevel@tonic-gate } 80917c478bd9Sstevel@tonic-gate 80927c478bd9Sstevel@tonic-gate static error_t 80937c478bd9Sstevel@tonic-gate set_global(menu_t *mp, char *globalcmd, int val) 80947c478bd9Sstevel@tonic-gate { 8095eb2bd662Svikram line_t *lp; 8096eb2bd662Svikram line_t *found; 8097eb2bd662Svikram line_t *last; 8098eb2bd662Svikram char *cp; 8099eb2bd662Svikram char *str; 81007c478bd9Sstevel@tonic-gate char prefix[BAM_MAXLINE]; 81017c478bd9Sstevel@tonic-gate size_t len; 8102eb2bd662Svikram const char *fcn = "set_global()"; 81037c478bd9Sstevel@tonic-gate 81047c478bd9Sstevel@tonic-gate assert(mp); 81057c478bd9Sstevel@tonic-gate assert(globalcmd); 81067c478bd9Sstevel@tonic-gate 8107b610f78eSvikram if (strcmp(globalcmd, menu_cmds[DEFAULT_CMD]) == 0) { 8108eb2bd662Svikram INJECT_ERROR1("SET_GLOBAL_VAL_NEG", val = -1); 8109eb2bd662Svikram INJECT_ERROR1("SET_GLOBAL_MENU_EMPTY", mp->end = NULL); 8110eb2bd662Svikram INJECT_ERROR1("SET_GLOBAL_VAL_TOO_BIG", val = 100); 8111b610f78eSvikram if (val < 0 || mp->end == NULL || val > mp->end->entryNum) { 8112b610f78eSvikram (void) snprintf(prefix, sizeof (prefix), "%d", val); 8113b610f78eSvikram bam_error(INVALID_ENTRY, prefix); 8114b610f78eSvikram return (BAM_ERROR); 8115b610f78eSvikram } 8116b610f78eSvikram } 8117b610f78eSvikram 81187c478bd9Sstevel@tonic-gate found = last = NULL; 81197c478bd9Sstevel@tonic-gate for (lp = mp->start; lp; lp = lp->next) { 81207c478bd9Sstevel@tonic-gate if (lp->flags != BAM_GLOBAL) 81217c478bd9Sstevel@tonic-gate continue; 81227c478bd9Sstevel@tonic-gate 81237c478bd9Sstevel@tonic-gate last = lp; /* track the last global found */ 81247c478bd9Sstevel@tonic-gate 8125eb2bd662Svikram INJECT_ERROR1("SET_GLOBAL_NULL_CMD", lp->cmd = NULL); 81267c478bd9Sstevel@tonic-gate if (lp->cmd == NULL) { 81277c478bd9Sstevel@tonic-gate bam_error(NO_CMD, lp->lineNum); 81287c478bd9Sstevel@tonic-gate continue; 81297c478bd9Sstevel@tonic-gate } 81307c478bd9Sstevel@tonic-gate if (strcmp(globalcmd, lp->cmd) != 0) 81317c478bd9Sstevel@tonic-gate continue; 81327c478bd9Sstevel@tonic-gate 8133eb2bd662Svikram BAM_DPRINTF((D_FOUND_GLOBAL, fcn, globalcmd)); 8134eb2bd662Svikram 81357c478bd9Sstevel@tonic-gate if (found) { 81367c478bd9Sstevel@tonic-gate bam_error(DUP_CMD, globalcmd, lp->lineNum, bam_root); 81377c478bd9Sstevel@tonic-gate } 81387c478bd9Sstevel@tonic-gate found = lp; 81397c478bd9Sstevel@tonic-gate } 81407c478bd9Sstevel@tonic-gate 81417c478bd9Sstevel@tonic-gate if (found == NULL) { 81427c478bd9Sstevel@tonic-gate lp = s_calloc(1, sizeof (line_t)); 81437c478bd9Sstevel@tonic-gate if (last == NULL) { 81447c478bd9Sstevel@tonic-gate lp->next = mp->start; 81457c478bd9Sstevel@tonic-gate mp->start = lp; 81467c478bd9Sstevel@tonic-gate mp->end = (mp->end) ? mp->end : lp; 81477c478bd9Sstevel@tonic-gate } else { 81487c478bd9Sstevel@tonic-gate lp->next = last->next; 81497c478bd9Sstevel@tonic-gate last->next = lp; 81507c478bd9Sstevel@tonic-gate if (lp->next == NULL) 81517c478bd9Sstevel@tonic-gate mp->end = lp; 81527c478bd9Sstevel@tonic-gate } 81537c478bd9Sstevel@tonic-gate lp->flags = BAM_GLOBAL; /* other fields not needed for writes */ 81547c478bd9Sstevel@tonic-gate len = strlen(globalcmd) + strlen(menu_cmds[SEP_CMD]); 81557c478bd9Sstevel@tonic-gate len += 10; /* val < 10 digits */ 81567c478bd9Sstevel@tonic-gate lp->line = s_calloc(1, len); 81577c478bd9Sstevel@tonic-gate (void) snprintf(lp->line, len, "%s%s%d", 81587c478bd9Sstevel@tonic-gate globalcmd, menu_cmds[SEP_CMD], val); 8159eb2bd662Svikram BAM_DPRINTF((D_SET_GLOBAL_WROTE_NEW, fcn, lp->line)); 8160eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 81617c478bd9Sstevel@tonic-gate return (BAM_WRITE); 81627c478bd9Sstevel@tonic-gate } 81637c478bd9Sstevel@tonic-gate 81647c478bd9Sstevel@tonic-gate /* 81657c478bd9Sstevel@tonic-gate * We are changing an existing entry. Retain any prefix whitespace, 81667c478bd9Sstevel@tonic-gate * but overwrite everything else. This preserves tabs added for 81677c478bd9Sstevel@tonic-gate * readability. 81687c478bd9Sstevel@tonic-gate */ 81697c478bd9Sstevel@tonic-gate str = found->line; 81707c478bd9Sstevel@tonic-gate cp = prefix; 81717c478bd9Sstevel@tonic-gate while (*str == ' ' || *str == '\t') 81727c478bd9Sstevel@tonic-gate *(cp++) = *(str++); 81737c478bd9Sstevel@tonic-gate *cp = '\0'; /* Terminate prefix */ 81747c478bd9Sstevel@tonic-gate len = strlen(prefix) + strlen(globalcmd); 81757c478bd9Sstevel@tonic-gate len += strlen(menu_cmds[SEP_CMD]) + 10; 81767c478bd9Sstevel@tonic-gate 81777c478bd9Sstevel@tonic-gate free(found->line); 81787c478bd9Sstevel@tonic-gate found->line = s_calloc(1, len); 81797c478bd9Sstevel@tonic-gate (void) snprintf(found->line, len, 81807c478bd9Sstevel@tonic-gate "%s%s%s%d", prefix, globalcmd, menu_cmds[SEP_CMD], val); 81817c478bd9Sstevel@tonic-gate 8182eb2bd662Svikram BAM_DPRINTF((D_SET_GLOBAL_REPLACED, fcn, found->line)); 8183eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 81847c478bd9Sstevel@tonic-gate return (BAM_WRITE); /* need a write to menu */ 81857c478bd9Sstevel@tonic-gate } 81867c478bd9Sstevel@tonic-gate 8187ae115bc7Smrj /* 8188ae115bc7Smrj * partial_path may be anything like "kernel/unix" or "kmdb". Try to 8189455710d3Srscott * expand it to a full unix path. The calling function is expected to 8190455710d3Srscott * output a message if an error occurs and NULL is returned. 8191ae115bc7Smrj */ 8192ae115bc7Smrj static char * 8193ae115bc7Smrj expand_path(const char *partial_path) 8194ae115bc7Smrj { 8195ae115bc7Smrj int new_path_len; 8196eb2bd662Svikram char *new_path; 8197eb2bd662Svikram char new_path2[PATH_MAX]; 8198ae115bc7Smrj struct stat sb; 8199eb2bd662Svikram const char *fcn = "expand_path()"; 8200ae115bc7Smrj 8201ae115bc7Smrj new_path_len = strlen(partial_path) + 64; 8202ae115bc7Smrj new_path = s_calloc(1, new_path_len); 8203ae115bc7Smrj 8204ae115bc7Smrj /* First, try the simplest case - something like "kernel/unix" */ 8205ae115bc7Smrj (void) snprintf(new_path, new_path_len, "/platform/i86pc/%s", 8206ae115bc7Smrj partial_path); 8207ae115bc7Smrj if (stat(new_path, &sb) == 0) { 8208eb2bd662Svikram BAM_DPRINTF((D_EXPAND_PATH, fcn, new_path)); 8209ae115bc7Smrj return (new_path); 8210ae115bc7Smrj } 8211ae115bc7Smrj 8212ae115bc7Smrj if (strcmp(partial_path, "kmdb") == 0) { 8213ae115bc7Smrj (void) snprintf(new_path, new_path_len, "%s -k", 8214ae115bc7Smrj DIRECT_BOOT_KERNEL); 8215eb2bd662Svikram BAM_DPRINTF((D_EXPAND_PATH, fcn, new_path)); 8216ae115bc7Smrj return (new_path); 8217ae115bc7Smrj } 8218ae115bc7Smrj 8219ae115bc7Smrj /* 8220ae115bc7Smrj * We've quickly reached unsupported usage. Try once more to 8221ae115bc7Smrj * see if we were just given a glom name. 8222ae115bc7Smrj */ 8223ae115bc7Smrj (void) snprintf(new_path, new_path_len, "/platform/i86pc/%s/unix", 8224ae115bc7Smrj partial_path); 8225ae115bc7Smrj (void) snprintf(new_path2, PATH_MAX, "/platform/i86pc/%s/amd64/unix", 8226ae115bc7Smrj partial_path); 8227ae115bc7Smrj if (stat(new_path, &sb) == 0) { 8228ae115bc7Smrj if (stat(new_path2, &sb) == 0) { 8229ae115bc7Smrj /* 8230ae115bc7Smrj * We matched both, so we actually 8231ae115bc7Smrj * want to write the $ISADIR version. 8232ae115bc7Smrj */ 8233ae115bc7Smrj (void) snprintf(new_path, new_path_len, 8234ae115bc7Smrj "/platform/i86pc/kernel/%s/$ISADIR/unix", 8235ae115bc7Smrj partial_path); 8236ae115bc7Smrj } 8237eb2bd662Svikram BAM_DPRINTF((D_EXPAND_PATH, fcn, new_path)); 8238ae115bc7Smrj return (new_path); 8239ae115bc7Smrj } 8240ae115bc7Smrj 8241ae115bc7Smrj free(new_path); 8242eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 8243ae115bc7Smrj return (NULL); 8244ae115bc7Smrj } 8245ae115bc7Smrj 8246ae115bc7Smrj /* 8247ae115bc7Smrj * The kernel cmd and arg have been changed, so 8248ae115bc7Smrj * check whether the archive line needs to change. 8249ae115bc7Smrj */ 8250ae115bc7Smrj static void 8251ae115bc7Smrj set_archive_line(entry_t *entryp, line_t *kernelp) 8252ae115bc7Smrj { 8253ae115bc7Smrj line_t *lp = entryp->start; 8254ae115bc7Smrj char *new_archive; 8255ae115bc7Smrj menu_cmd_t m_cmd; 8256eb2bd662Svikram const char *fcn = "set_archive_line()"; 8257ae115bc7Smrj 8258ae115bc7Smrj for (; lp != NULL; lp = lp->next) { 8259ae115bc7Smrj if (strncmp(lp->cmd, menu_cmds[MODULE_CMD], 8260ae115bc7Smrj sizeof (menu_cmds[MODULE_CMD]) - 1) == 0) { 8261ae115bc7Smrj break; 8262ae115bc7Smrj } 8263eb2bd662Svikram 8264eb2bd662Svikram INJECT_ERROR1("SET_ARCHIVE_LINE_END_ENTRY", lp = entryp->end); 8265eb2bd662Svikram if (lp == entryp->end) { 8266eb2bd662Svikram BAM_DPRINTF((D_ARCHIVE_LINE_NONE, fcn, 8267eb2bd662Svikram entryp->entryNum)); 8268ae115bc7Smrj return; 8269ae115bc7Smrj } 8270eb2bd662Svikram } 8271eb2bd662Svikram INJECT_ERROR1("SET_ARCHIVE_LINE_END_MENU", lp = NULL); 8272eb2bd662Svikram if (lp == NULL) { 8273eb2bd662Svikram BAM_DPRINTF((D_ARCHIVE_LINE_NONE, fcn, entryp->entryNum)); 8274ae115bc7Smrj return; 8275eb2bd662Svikram } 8276ae115bc7Smrj 8277ae115bc7Smrj if (strstr(kernelp->arg, "$ISADIR") != NULL) { 8278ae115bc7Smrj new_archive = DIRECT_BOOT_ARCHIVE; 8279ae115bc7Smrj m_cmd = MODULE_DOLLAR_CMD; 8280ae115bc7Smrj } else if (strstr(kernelp->arg, "amd64") != NULL) { 8281ae115bc7Smrj new_archive = DIRECT_BOOT_ARCHIVE_64; 8282ae115bc7Smrj m_cmd = MODULE_CMD; 8283ae115bc7Smrj } else { 8284ae115bc7Smrj new_archive = DIRECT_BOOT_ARCHIVE_32; 8285ae115bc7Smrj m_cmd = MODULE_CMD; 8286ae115bc7Smrj } 8287ae115bc7Smrj 8288eb2bd662Svikram if (strcmp(lp->arg, new_archive) == 0) { 8289eb2bd662Svikram BAM_DPRINTF((D_ARCHIVE_LINE_NOCHANGE, fcn, lp->arg)); 8290ae115bc7Smrj return; 8291eb2bd662Svikram } 8292ae115bc7Smrj 8293ae115bc7Smrj if (strcmp(lp->cmd, menu_cmds[m_cmd]) != 0) { 8294ae115bc7Smrj free(lp->cmd); 8295ae115bc7Smrj lp->cmd = s_strdup(menu_cmds[m_cmd]); 8296ae115bc7Smrj } 8297ae115bc7Smrj 8298ae115bc7Smrj free(lp->arg); 8299ae115bc7Smrj lp->arg = s_strdup(new_archive); 8300ae115bc7Smrj update_line(lp); 8301eb2bd662Svikram BAM_DPRINTF((D_ARCHIVE_LINE_REPLACED, fcn, lp->line)); 8302ae115bc7Smrj } 8303ae115bc7Smrj 8304ae115bc7Smrj /* 8305ae115bc7Smrj * Title for an entry to set properties that once went in bootenv.rc. 8306ae115bc7Smrj */ 8307ae115bc7Smrj #define BOOTENV_RC_TITLE "Solaris bootenv rc" 8308ae115bc7Smrj 8309ae115bc7Smrj /* 8310ae115bc7Smrj * If path is NULL, return the kernel (optnum == KERNEL_CMD) or arguments 8311ae115bc7Smrj * (optnum == ARGS_CMD) in the argument buf. If path is a zero-length 8312ae115bc7Smrj * string, reset the value to the default. If path is a non-zero-length 8313ae115bc7Smrj * string, set the kernel or arguments. 8314ae115bc7Smrj */ 8315ae115bc7Smrj static error_t 8316eb2bd662Svikram get_set_kernel( 8317eb2bd662Svikram menu_t *mp, 8318eb2bd662Svikram menu_cmd_t optnum, 8319eb2bd662Svikram char *path, 8320eb2bd662Svikram char *buf, 8321eb2bd662Svikram size_t bufsize) 8322ae115bc7Smrj { 8323eb2bd662Svikram int entryNum; 8324eb2bd662Svikram int rv = BAM_SUCCESS; 8325eb2bd662Svikram int free_new_path = 0; 8326ae115bc7Smrj entry_t *entryp; 8327eb2bd662Svikram line_t *ptr; 8328eb2bd662Svikram line_t *kernelp; 8329eb2bd662Svikram char *new_arg; 8330eb2bd662Svikram char *old_args; 8331eb2bd662Svikram char *space; 8332eb2bd662Svikram char *new_path; 8333ae115bc7Smrj char old_space; 8334eb2bd662Svikram size_t old_kernel_len; 8335eb2bd662Svikram size_t new_str_len; 8336eb2bd662Svikram char *fstype; 8337eb2bd662Svikram char *osdev; 8338eb2bd662Svikram char *sign; 8339eb2bd662Svikram char signbuf[PATH_MAX]; 8340eb2bd662Svikram int ret; 8341eb2bd662Svikram const char *fcn = "get_set_kernel()"; 8342ae115bc7Smrj 8343ae115bc7Smrj assert(bufsize > 0); 8344ae115bc7Smrj 8345ae115bc7Smrj ptr = kernelp = NULL; 8346ae115bc7Smrj new_arg = old_args = space = NULL; 8347eb2bd662Svikram new_path = NULL; 8348ae115bc7Smrj buf[0] = '\0'; 8349ae115bc7Smrj 8350eb2bd662Svikram INJECT_ERROR1("GET_SET_KERNEL_NOT_DBOOT", 8351eb2bd662Svikram bam_direct = BAM_DIRECT_MULTIBOOT); 8352ae115bc7Smrj if (bam_direct != BAM_DIRECT_DBOOT) { 8353ae115bc7Smrj bam_error(NOT_DBOOT, optnum == KERNEL_CMD ? "kernel" : "args"); 8354ae115bc7Smrj return (BAM_ERROR); 8355ae115bc7Smrj } 8356ae115bc7Smrj 8357ae115bc7Smrj /* 8358ae115bc7Smrj * If a user changed the default entry to a non-bootadm controlled 8359ae115bc7Smrj * one, we don't want to mess with it. Just print an error and 8360ae115bc7Smrj * return. 8361ae115bc7Smrj */ 8362ae115bc7Smrj if (mp->curdefault) { 8363ae115bc7Smrj entryNum = s_strtol(mp->curdefault->arg); 8364ae115bc7Smrj for (entryp = mp->entries; entryp; entryp = entryp->next) { 8365ae115bc7Smrj if (entryp->entryNum == entryNum) 8366ae115bc7Smrj break; 8367ae115bc7Smrj } 8368ae115bc7Smrj if ((entryp != NULL) && 8369ae115bc7Smrj ((entryp->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU)) == 0)) { 8370ae115bc7Smrj bam_error(DEFAULT_NOT_BAM); 8371ae115bc7Smrj return (BAM_ERROR); 8372ae115bc7Smrj } 8373ae115bc7Smrj } 8374ae115bc7Smrj 8375eb2bd662Svikram entryp = find_boot_entry(mp, BOOTENV_RC_TITLE, NULL, NULL, NULL, NULL, 8376eb2bd662Svikram 0, &entryNum); 8377ae115bc7Smrj 8378ae115bc7Smrj if (entryp != NULL) { 8379ae115bc7Smrj for (ptr = entryp->start; ptr && ptr != entryp->end; 8380ae115bc7Smrj ptr = ptr->next) { 8381ae115bc7Smrj if (strncmp(ptr->cmd, menu_cmds[KERNEL_CMD], 8382ae115bc7Smrj sizeof (menu_cmds[KERNEL_CMD]) - 1) == 0) { 8383ae115bc7Smrj kernelp = ptr; 8384ae115bc7Smrj break; 8385ae115bc7Smrj } 8386ae115bc7Smrj } 8387ae115bc7Smrj if (kernelp == NULL) { 8388ae115bc7Smrj bam_error(NO_KERNEL, entryNum); 8389ae115bc7Smrj return (BAM_ERROR); 8390ae115bc7Smrj } 8391ae115bc7Smrj 8392ae115bc7Smrj old_kernel_len = strcspn(kernelp->arg, " \t"); 8393ae115bc7Smrj space = old_args = kernelp->arg + old_kernel_len; 8394ae115bc7Smrj while ((*old_args == ' ') || (*old_args == '\t')) 8395ae115bc7Smrj old_args++; 8396ae115bc7Smrj } 8397ae115bc7Smrj 8398ae115bc7Smrj if (path == NULL) { 8399eb2bd662Svikram if (entryp == NULL) { 8400eb2bd662Svikram BAM_DPRINTF((D_GET_SET_KERNEL_NO_RC, fcn)); 8401eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 8402ae115bc7Smrj return (BAM_SUCCESS); 8403eb2bd662Svikram } 8404eb2bd662Svikram assert(kernelp); 8405ae115bc7Smrj if (optnum == ARGS_CMD) { 8406eb2bd662Svikram if (old_args[0] != '\0') { 8407ae115bc7Smrj (void) strlcpy(buf, old_args, bufsize); 8408eb2bd662Svikram BAM_DPRINTF((D_GET_SET_KERNEL_ARGS, fcn, buf)); 8409eb2bd662Svikram } 8410ae115bc7Smrj } else { 8411ae115bc7Smrj /* 8412ae115bc7Smrj * We need to print the kernel, so we just turn the 8413ae115bc7Smrj * first space into a '\0' and print the beginning. 8414ae115bc7Smrj * We don't print anything if it's the default kernel. 8415ae115bc7Smrj */ 8416ae115bc7Smrj old_space = *space; 8417ae115bc7Smrj *space = '\0'; 8418eb2bd662Svikram if (strcmp(kernelp->arg, DIRECT_BOOT_KERNEL) != 0) { 8419ae115bc7Smrj (void) strlcpy(buf, kernelp->arg, bufsize); 8420eb2bd662Svikram BAM_DPRINTF((D_GET_SET_KERNEL_KERN, fcn, buf)); 8421eb2bd662Svikram } 8422ae115bc7Smrj *space = old_space; 8423ae115bc7Smrj } 8424eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 8425ae115bc7Smrj return (BAM_SUCCESS); 8426ae115bc7Smrj } 8427ae115bc7Smrj 8428ae115bc7Smrj /* 8429ae115bc7Smrj * First, check if we're resetting an entry to the default. 8430ae115bc7Smrj */ 8431ae115bc7Smrj if ((path[0] == '\0') || 8432ae115bc7Smrj ((optnum == KERNEL_CMD) && 8433ae115bc7Smrj (strcmp(path, DIRECT_BOOT_KERNEL) == 0))) { 8434ae115bc7Smrj if ((entryp == NULL) || (kernelp == NULL)) { 8435ae115bc7Smrj /* No previous entry, it's already the default */ 8436eb2bd662Svikram BAM_DPRINTF((D_GET_SET_KERNEL_ALREADY, fcn)); 8437ae115bc7Smrj return (BAM_SUCCESS); 8438ae115bc7Smrj } 8439ae115bc7Smrj 8440ae115bc7Smrj /* 8441ae115bc7Smrj * Check if we can delete the entry. If we're resetting the 8442ae115bc7Smrj * kernel command, and the args is already empty, or if we're 8443ae115bc7Smrj * resetting the args command, and the kernel is already the 8444ae115bc7Smrj * default, we can restore the old default and delete the entry. 8445ae115bc7Smrj */ 8446ae115bc7Smrj if (((optnum == KERNEL_CMD) && 8447ae115bc7Smrj ((old_args == NULL) || (old_args[0] == '\0'))) || 8448ae115bc7Smrj ((optnum == ARGS_CMD) && 8449ae115bc7Smrj (strncmp(kernelp->arg, DIRECT_BOOT_KERNEL, 8450ae115bc7Smrj sizeof (DIRECT_BOOT_KERNEL) - 1) == 0))) { 8451ae115bc7Smrj kernelp = NULL; 8452ae115bc7Smrj (void) do_delete(mp, entryNum); 8453ae115bc7Smrj restore_default_entry(mp, BAM_OLD_RC_DEF, 8454ae115bc7Smrj mp->old_rc_default); 8455ae115bc7Smrj mp->old_rc_default = NULL; 8456ae115bc7Smrj rv = BAM_WRITE; 8457eb2bd662Svikram BAM_DPRINTF((D_GET_SET_KERNEL_RESTORE_DEFAULT, fcn)); 8458ae115bc7Smrj goto done; 8459ae115bc7Smrj } 8460ae115bc7Smrj 8461ae115bc7Smrj if (optnum == KERNEL_CMD) { 8462ae115bc7Smrj /* 8463ae115bc7Smrj * At this point, we've already checked that old_args 8464ae115bc7Smrj * and entryp are valid pointers. The "+ 2" is for 8465ae115bc7Smrj * a space a the string termination character. 8466ae115bc7Smrj */ 8467ae115bc7Smrj new_str_len = (sizeof (DIRECT_BOOT_KERNEL) - 1) + 8468ae115bc7Smrj strlen(old_args) + 2; 8469ae115bc7Smrj new_arg = s_calloc(1, new_str_len); 8470ae115bc7Smrj (void) snprintf(new_arg, new_str_len, "%s %s", 8471ae115bc7Smrj DIRECT_BOOT_KERNEL, old_args); 8472ae115bc7Smrj free(kernelp->arg); 8473ae115bc7Smrj kernelp->arg = new_arg; 8474ae115bc7Smrj 8475ae115bc7Smrj /* 8476ae115bc7Smrj * We have changed the kernel line, so we may need 8477ae115bc7Smrj * to update the archive line as well. 8478ae115bc7Smrj */ 8479ae115bc7Smrj set_archive_line(entryp, kernelp); 8480eb2bd662Svikram BAM_DPRINTF((D_GET_SET_KERNEL_RESET_KERNEL_SET_ARG, 8481eb2bd662Svikram fcn, kernelp->arg)); 8482ae115bc7Smrj } else { 8483ae115bc7Smrj /* 8484ae115bc7Smrj * We're resetting the boot args to nothing, so 8485ae115bc7Smrj * we only need to copy the kernel. We've already 8486ae115bc7Smrj * checked that the kernel is not the default. 8487ae115bc7Smrj */ 8488ae115bc7Smrj new_arg = s_calloc(1, old_kernel_len + 1); 8489ae115bc7Smrj (void) snprintf(new_arg, old_kernel_len + 1, "%s", 8490ae115bc7Smrj kernelp->arg); 8491ae115bc7Smrj free(kernelp->arg); 8492ae115bc7Smrj kernelp->arg = new_arg; 8493eb2bd662Svikram BAM_DPRINTF((D_GET_SET_KERNEL_RESET_ARG_SET_KERNEL, 8494eb2bd662Svikram fcn, kernelp->arg)); 8495ae115bc7Smrj } 8496ae115bc7Smrj rv = BAM_WRITE; 8497ae115bc7Smrj goto done; 8498ae115bc7Smrj } 8499ae115bc7Smrj 8500ae115bc7Smrj /* 8501ae115bc7Smrj * Expand the kernel file to a full path, if necessary 8502ae115bc7Smrj */ 8503ae115bc7Smrj if ((optnum == KERNEL_CMD) && (path[0] != '/')) { 8504ae115bc7Smrj new_path = expand_path(path); 8505ae115bc7Smrj if (new_path == NULL) { 8506455710d3Srscott bam_error(UNKNOWN_KERNEL, path); 8507eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 8508ae115bc7Smrj return (BAM_ERROR); 8509ae115bc7Smrj } 8510ae115bc7Smrj free_new_path = 1; 8511ae115bc7Smrj } else { 8512ae115bc7Smrj new_path = path; 8513ae115bc7Smrj free_new_path = 0; 8514ae115bc7Smrj } 8515ae115bc7Smrj 8516ae115bc7Smrj /* 8517ae115bc7Smrj * At this point, we know we're setting a new value. First, take care 8518ae115bc7Smrj * of the case where there was no previous entry. 8519ae115bc7Smrj */ 8520ae115bc7Smrj if (entryp == NULL) { 8521eb2bd662Svikram 8522ae115bc7Smrj /* Similar to code in update_temp */ 8523eb2bd662Svikram fstype = get_fstype("/"); 8524eb2bd662Svikram INJECT_ERROR1("GET_SET_KERNEL_FSTYPE", fstype = NULL); 8525eb2bd662Svikram if (fstype == NULL) { 8526eb2bd662Svikram bam_error(BOOTENV_FSTYPE_FAILED); 8527ae115bc7Smrj rv = BAM_ERROR; 8528ae115bc7Smrj goto done; 8529ae115bc7Smrj } 8530eb2bd662Svikram 8531eb2bd662Svikram osdev = get_special("/"); 8532eb2bd662Svikram INJECT_ERROR1("GET_SET_KERNEL_SPECIAL", osdev = NULL); 8533eb2bd662Svikram if (osdev == NULL) { 8534eb2bd662Svikram free(fstype); 8535eb2bd662Svikram bam_error(BOOTENV_SPECIAL_FAILED); 8536eb2bd662Svikram rv = BAM_ERROR; 8537eb2bd662Svikram goto done; 8538eb2bd662Svikram } 8539eb2bd662Svikram 8540eb2bd662Svikram sign = find_existing_sign("/", osdev, fstype); 8541eb2bd662Svikram INJECT_ERROR1("GET_SET_KERNEL_SIGN", sign = NULL); 8542eb2bd662Svikram if (sign == NULL) { 8543eb2bd662Svikram free(fstype); 8544eb2bd662Svikram free(osdev); 8545eb2bd662Svikram bam_error(BOOTENV_SIGN_FAILED); 8546eb2bd662Svikram rv = BAM_ERROR; 8547eb2bd662Svikram goto done; 8548eb2bd662Svikram } 8549eb2bd662Svikram 8550eb2bd662Svikram free(fstype); 8551eb2bd662Svikram free(osdev); 8552eb2bd662Svikram (void) strlcpy(signbuf, sign, sizeof (signbuf)); 8553eb2bd662Svikram free(sign); 8554eb2bd662Svikram assert(strchr(signbuf, '(') == NULL && 8555eb2bd662Svikram strchr(signbuf, ',') == NULL && 8556eb2bd662Svikram strchr(signbuf, ')') == NULL); 8557eb2bd662Svikram 8558ae115bc7Smrj if (optnum == KERNEL_CMD) { 8559eb2bd662Svikram BAM_DPRINTF((D_GET_SET_KERNEL_NEW_KERN, fcn, new_path)); 8560ae115bc7Smrj entryNum = add_boot_entry(mp, BOOTENV_RC_TITLE, 8561eb2bd662Svikram signbuf, new_path, NULL, NULL); 8562ae115bc7Smrj } else { 8563ae115bc7Smrj new_str_len = strlen(DIRECT_BOOT_KERNEL) + 8564ae115bc7Smrj strlen(path) + 8; 8565ae115bc7Smrj new_arg = s_calloc(1, new_str_len); 8566ae115bc7Smrj 8567ae115bc7Smrj (void) snprintf(new_arg, new_str_len, "%s %s", 8568ae115bc7Smrj DIRECT_BOOT_KERNEL, path); 8569eb2bd662Svikram BAM_DPRINTF((D_GET_SET_KERNEL_NEW_ARG, fcn, new_arg)); 8570ae115bc7Smrj entryNum = add_boot_entry(mp, BOOTENV_RC_TITLE, 8571eb2bd662Svikram signbuf, new_arg, NULL, DIRECT_BOOT_ARCHIVE); 8572eb2bd662Svikram free(new_arg); 8573eb2bd662Svikram } 8574eb2bd662Svikram INJECT_ERROR1("GET_SET_KERNEL_ADD_BOOT_ENTRY", 8575eb2bd662Svikram entryNum = BAM_ERROR); 8576eb2bd662Svikram if (entryNum == BAM_ERROR) { 8577eb2bd662Svikram bam_error(GET_SET_KERNEL_ADD_BOOT_ENTRY, 8578eb2bd662Svikram BOOTENV_RC_TITLE); 8579eb2bd662Svikram rv = BAM_ERROR; 8580eb2bd662Svikram goto done; 8581ae115bc7Smrj } 8582ae115bc7Smrj save_default_entry(mp, BAM_OLD_RC_DEF); 8583eb2bd662Svikram ret = set_global(mp, menu_cmds[DEFAULT_CMD], entryNum); 8584eb2bd662Svikram INJECT_ERROR1("GET_SET_KERNEL_SET_GLOBAL", ret = BAM_ERROR); 8585eb2bd662Svikram if (ret == BAM_ERROR) { 8586eb2bd662Svikram bam_error(GET_SET_KERNEL_SET_GLOBAL, entryNum); 8587eb2bd662Svikram } 8588ae115bc7Smrj rv = BAM_WRITE; 8589ae115bc7Smrj goto done; 8590ae115bc7Smrj } 8591ae115bc7Smrj 8592ae115bc7Smrj /* 8593ae115bc7Smrj * There was already an bootenv entry which we need to edit. 8594ae115bc7Smrj */ 8595ae115bc7Smrj if (optnum == KERNEL_CMD) { 8596ae115bc7Smrj new_str_len = strlen(new_path) + strlen(old_args) + 2; 8597ae115bc7Smrj new_arg = s_calloc(1, new_str_len); 8598ae115bc7Smrj (void) snprintf(new_arg, new_str_len, "%s %s", new_path, 8599ae115bc7Smrj old_args); 8600ae115bc7Smrj free(kernelp->arg); 8601ae115bc7Smrj kernelp->arg = new_arg; 8602ae115bc7Smrj 8603ae115bc7Smrj /* 8604ae115bc7Smrj * If we have changed the kernel line, we may need to update 8605ae115bc7Smrj * the archive line as well. 8606ae115bc7Smrj */ 8607ae115bc7Smrj set_archive_line(entryp, kernelp); 8608eb2bd662Svikram BAM_DPRINTF((D_GET_SET_KERNEL_REPLACED_KERNEL_SAME_ARG, fcn, 8609eb2bd662Svikram kernelp->arg)); 8610ae115bc7Smrj } else { 8611ae115bc7Smrj new_str_len = old_kernel_len + strlen(path) + 8; 8612ae115bc7Smrj new_arg = s_calloc(1, new_str_len); 8613ae115bc7Smrj (void) strncpy(new_arg, kernelp->arg, old_kernel_len); 8614ae115bc7Smrj (void) strlcat(new_arg, " ", new_str_len); 8615ae115bc7Smrj (void) strlcat(new_arg, path, new_str_len); 8616ae115bc7Smrj free(kernelp->arg); 8617ae115bc7Smrj kernelp->arg = new_arg; 8618eb2bd662Svikram BAM_DPRINTF((D_GET_SET_KERNEL_SAME_KERNEL_REPLACED_ARG, fcn, 8619eb2bd662Svikram kernelp->arg)); 8620ae115bc7Smrj } 8621ae115bc7Smrj rv = BAM_WRITE; 8622ae115bc7Smrj 8623ae115bc7Smrj done: 8624ae115bc7Smrj if ((rv == BAM_WRITE) && kernelp) 8625ae115bc7Smrj update_line(kernelp); 8626ae115bc7Smrj if (free_new_path) 8627ae115bc7Smrj free(new_path); 8628eb2bd662Svikram if (rv == BAM_WRITE) { 8629eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 8630eb2bd662Svikram } else { 8631eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 8632eb2bd662Svikram } 8633ae115bc7Smrj return (rv); 8634ae115bc7Smrj } 8635ae115bc7Smrj 8636eb2bd662Svikram static error_t 8637eb2bd662Svikram get_kernel(menu_t *mp, menu_cmd_t optnum, char *buf, size_t bufsize) 8638eb2bd662Svikram { 8639eb2bd662Svikram const char *fcn = "get_kernel()"; 8640eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY1, fcn, menu_cmds[optnum])); 8641eb2bd662Svikram return (get_set_kernel(mp, optnum, NULL, buf, bufsize)); 8642eb2bd662Svikram } 8643eb2bd662Svikram 8644eb2bd662Svikram static error_t 8645eb2bd662Svikram set_kernel(menu_t *mp, menu_cmd_t optnum, char *path, char *buf, size_t bufsize) 8646eb2bd662Svikram { 8647eb2bd662Svikram const char *fcn = "set_kernel()"; 8648eb2bd662Svikram assert(path != NULL); 8649eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY2, fcn, menu_cmds[optnum], path)); 8650eb2bd662Svikram return (get_set_kernel(mp, optnum, path, buf, bufsize)); 8651eb2bd662Svikram } 8652eb2bd662Svikram 86537c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 86547c478bd9Sstevel@tonic-gate static error_t 8655eb2bd662Svikram set_option(menu_t *mp, char *dummy, char *opt) 86567c478bd9Sstevel@tonic-gate { 8657eb2bd662Svikram int optnum; 8658eb2bd662Svikram int optval; 86597c478bd9Sstevel@tonic-gate char *val; 8660ae115bc7Smrj char buf[BUFSIZ] = ""; 8661ae115bc7Smrj error_t rv; 8662eb2bd662Svikram const char *fcn = "set_option()"; 86637c478bd9Sstevel@tonic-gate 86647c478bd9Sstevel@tonic-gate assert(mp); 86657c478bd9Sstevel@tonic-gate assert(opt); 8666eb2bd662Svikram assert(dummy == NULL); 8667eb2bd662Svikram 8668eb2bd662Svikram /* opt is set from bam_argv[0] and is always non-NULL */ 8669eb2bd662Svikram BAM_DPRINTF((D_FUNC_ENTRY1, fcn, opt)); 86707c478bd9Sstevel@tonic-gate 86717c478bd9Sstevel@tonic-gate val = strchr(opt, '='); 8672ae115bc7Smrj if (val != NULL) { 8673ae115bc7Smrj *val = '\0'; 86747c478bd9Sstevel@tonic-gate } 86757c478bd9Sstevel@tonic-gate 86767c478bd9Sstevel@tonic-gate if (strcmp(opt, "default") == 0) { 86777c478bd9Sstevel@tonic-gate optnum = DEFAULT_CMD; 86787c478bd9Sstevel@tonic-gate } else if (strcmp(opt, "timeout") == 0) { 86797c478bd9Sstevel@tonic-gate optnum = TIMEOUT_CMD; 8680ae115bc7Smrj } else if (strcmp(opt, menu_cmds[KERNEL_CMD]) == 0) { 8681ae115bc7Smrj optnum = KERNEL_CMD; 8682ae115bc7Smrj } else if (strcmp(opt, menu_cmds[ARGS_CMD]) == 0) { 8683ae115bc7Smrj optnum = ARGS_CMD; 86847c478bd9Sstevel@tonic-gate } else { 8685eb2bd662Svikram bam_error(INVALID_OPTION, opt); 86867c478bd9Sstevel@tonic-gate return (BAM_ERROR); 86877c478bd9Sstevel@tonic-gate } 86887c478bd9Sstevel@tonic-gate 8689ae115bc7Smrj /* 8690ae115bc7Smrj * kernel and args are allowed without "=new_value" strings. All 8691ae115bc7Smrj * others cause errors 8692ae115bc7Smrj */ 8693ae115bc7Smrj if ((val == NULL) && (optnum != KERNEL_CMD) && (optnum != ARGS_CMD)) { 8694eb2bd662Svikram bam_error(NO_OPTION_ARG, opt); 8695ae115bc7Smrj return (BAM_ERROR); 8696ae115bc7Smrj } else if (val != NULL) { 86977c478bd9Sstevel@tonic-gate *val = '='; 8698ae115bc7Smrj } 8699ae115bc7Smrj 8700ae115bc7Smrj if ((optnum == KERNEL_CMD) || (optnum == ARGS_CMD)) { 8701eb2bd662Svikram BAM_DPRINTF((D_SET_OPTION, fcn, menu_cmds[optnum], 8702eb2bd662Svikram val ? val + 1 : "NULL")); 8703eb2bd662Svikram 8704eb2bd662Svikram if (val) 8705eb2bd662Svikram rv = set_kernel(mp, optnum, val + 1, buf, sizeof (buf)); 8706eb2bd662Svikram else 8707eb2bd662Svikram rv = get_kernel(mp, optnum, buf, sizeof (buf)); 8708ae115bc7Smrj if ((rv == BAM_SUCCESS) && (buf[0] != '\0')) 8709ae115bc7Smrj (void) printf("%s\n", buf); 8710ae115bc7Smrj } else { 8711ae115bc7Smrj optval = s_strtol(val + 1); 8712eb2bd662Svikram BAM_DPRINTF((D_SET_OPTION, fcn, menu_cmds[optnum], val + 1)); 8713eb2bd662Svikram rv = set_global(mp, menu_cmds[optnum], optval); 87147c478bd9Sstevel@tonic-gate } 8715eb2bd662Svikram 8716eb2bd662Svikram if (rv == BAM_WRITE || rv == BAM_SUCCESS) { 8717eb2bd662Svikram BAM_DPRINTF((D_RETURN_SUCCESS, fcn)); 8718eb2bd662Svikram } else { 8719eb2bd662Svikram BAM_DPRINTF((D_RETURN_FAILURE, fcn)); 8720eb2bd662Svikram } 8721eb2bd662Svikram 8722eb2bd662Svikram return (rv); 8723ae115bc7Smrj } 87247c478bd9Sstevel@tonic-gate 87257c478bd9Sstevel@tonic-gate /* 87267c478bd9Sstevel@tonic-gate * The quiet argument suppresses messages. This is used 87277c478bd9Sstevel@tonic-gate * when invoked in the context of other commands (e.g. list_entry) 87287c478bd9Sstevel@tonic-gate */ 87297c478bd9Sstevel@tonic-gate static error_t 87307c478bd9Sstevel@tonic-gate read_globals(menu_t *mp, char *menu_path, char *globalcmd, int quiet) 87317c478bd9Sstevel@tonic-gate { 87327c478bd9Sstevel@tonic-gate line_t *lp; 87337c478bd9Sstevel@tonic-gate char *arg; 87347c478bd9Sstevel@tonic-gate int done, ret = BAM_SUCCESS; 87357c478bd9Sstevel@tonic-gate 87367c478bd9Sstevel@tonic-gate assert(mp); 87377c478bd9Sstevel@tonic-gate assert(menu_path); 87387c478bd9Sstevel@tonic-gate assert(globalcmd); 87397c478bd9Sstevel@tonic-gate 87407c478bd9Sstevel@tonic-gate if (mp->start == NULL) { 87417c478bd9Sstevel@tonic-gate if (!quiet) 87427c478bd9Sstevel@tonic-gate bam_error(NO_MENU, menu_path); 87437c478bd9Sstevel@tonic-gate return (BAM_ERROR); 87447c478bd9Sstevel@tonic-gate } 87457c478bd9Sstevel@tonic-gate 87467c478bd9Sstevel@tonic-gate done = 0; 87477c478bd9Sstevel@tonic-gate for (lp = mp->start; lp; lp = lp->next) { 87487c478bd9Sstevel@tonic-gate if (lp->flags != BAM_GLOBAL) 87497c478bd9Sstevel@tonic-gate continue; 87507c478bd9Sstevel@tonic-gate 87517c478bd9Sstevel@tonic-gate if (lp->cmd == NULL) { 87527c478bd9Sstevel@tonic-gate if (!quiet) 87537c478bd9Sstevel@tonic-gate bam_error(NO_CMD, lp->lineNum); 87547c478bd9Sstevel@tonic-gate continue; 87557c478bd9Sstevel@tonic-gate } 87567c478bd9Sstevel@tonic-gate 87577c478bd9Sstevel@tonic-gate if (strcmp(globalcmd, lp->cmd) != 0) 87587c478bd9Sstevel@tonic-gate continue; 87597c478bd9Sstevel@tonic-gate 87607c478bd9Sstevel@tonic-gate /* Found global. Check for duplicates */ 87617c478bd9Sstevel@tonic-gate if (done && !quiet) { 87627c478bd9Sstevel@tonic-gate bam_error(DUP_CMD, globalcmd, lp->lineNum, bam_root); 87637c478bd9Sstevel@tonic-gate ret = BAM_ERROR; 87647c478bd9Sstevel@tonic-gate } 87657c478bd9Sstevel@tonic-gate 87667c478bd9Sstevel@tonic-gate arg = lp->arg ? lp->arg : ""; 87677c478bd9Sstevel@tonic-gate bam_print(GLOBAL_CMD, globalcmd, arg); 87687c478bd9Sstevel@tonic-gate done = 1; 87697c478bd9Sstevel@tonic-gate } 87707c478bd9Sstevel@tonic-gate 87717c478bd9Sstevel@tonic-gate if (!done && bam_verbose) 87727c478bd9Sstevel@tonic-gate bam_print(NO_ENTRY, globalcmd); 87737c478bd9Sstevel@tonic-gate 87747c478bd9Sstevel@tonic-gate return (ret); 87757c478bd9Sstevel@tonic-gate } 87767c478bd9Sstevel@tonic-gate 87777c478bd9Sstevel@tonic-gate static error_t 87787c478bd9Sstevel@tonic-gate menu_write(char *root, menu_t *mp) 87797c478bd9Sstevel@tonic-gate { 8780eb2bd662Svikram const char *fcn = "menu_write()"; 8781eb2bd662Svikram 8782eb2bd662Svikram BAM_DPRINTF((D_MENU_WRITE_ENTER, fcn, root)); 87837c478bd9Sstevel@tonic-gate return (list2file(root, MENU_TMP, GRUB_MENU, mp->start)); 87847c478bd9Sstevel@tonic-gate } 87857c478bd9Sstevel@tonic-gate 8786eb2bd662Svikram void 87877c478bd9Sstevel@tonic-gate line_free(line_t *lp) 87887c478bd9Sstevel@tonic-gate { 87897c478bd9Sstevel@tonic-gate if (lp == NULL) 87907c478bd9Sstevel@tonic-gate return; 87917c478bd9Sstevel@tonic-gate 87927c478bd9Sstevel@tonic-gate if (lp->cmd) 87937c478bd9Sstevel@tonic-gate free(lp->cmd); 87947c478bd9Sstevel@tonic-gate if (lp->sep) 87957c478bd9Sstevel@tonic-gate free(lp->sep); 87967c478bd9Sstevel@tonic-gate if (lp->arg) 87977c478bd9Sstevel@tonic-gate free(lp->arg); 87987c478bd9Sstevel@tonic-gate if (lp->line) 87997c478bd9Sstevel@tonic-gate free(lp->line); 88007c478bd9Sstevel@tonic-gate free(lp); 88017c478bd9Sstevel@tonic-gate } 88027c478bd9Sstevel@tonic-gate 88037c478bd9Sstevel@tonic-gate static void 88047c478bd9Sstevel@tonic-gate linelist_free(line_t *start) 88057c478bd9Sstevel@tonic-gate { 88067c478bd9Sstevel@tonic-gate line_t *lp; 88077c478bd9Sstevel@tonic-gate 88087c478bd9Sstevel@tonic-gate while (start) { 88097c478bd9Sstevel@tonic-gate lp = start; 88107c478bd9Sstevel@tonic-gate start = start->next; 88117c478bd9Sstevel@tonic-gate line_free(lp); 88127c478bd9Sstevel@tonic-gate } 88137c478bd9Sstevel@tonic-gate } 88147c478bd9Sstevel@tonic-gate 88157c478bd9Sstevel@tonic-gate static void 88167c478bd9Sstevel@tonic-gate filelist_free(filelist_t *flistp) 88177c478bd9Sstevel@tonic-gate { 88187c478bd9Sstevel@tonic-gate linelist_free(flistp->head); 88197c478bd9Sstevel@tonic-gate flistp->head = NULL; 88207c478bd9Sstevel@tonic-gate flistp->tail = NULL; 88217c478bd9Sstevel@tonic-gate } 88227c478bd9Sstevel@tonic-gate 88237c478bd9Sstevel@tonic-gate static void 88247c478bd9Sstevel@tonic-gate menu_free(menu_t *mp) 88257c478bd9Sstevel@tonic-gate { 88268c1b6884Sszhou entry_t *ent, *tmp; 88277c478bd9Sstevel@tonic-gate assert(mp); 88287c478bd9Sstevel@tonic-gate 88297c478bd9Sstevel@tonic-gate if (mp->start) 88307c478bd9Sstevel@tonic-gate linelist_free(mp->start); 88318c1b6884Sszhou ent = mp->entries; 88328c1b6884Sszhou while (ent) { 88338c1b6884Sszhou tmp = ent; 88348c1b6884Sszhou ent = tmp->next; 88358c1b6884Sszhou free(tmp); 88368c1b6884Sszhou } 88377c478bd9Sstevel@tonic-gate 88388c1b6884Sszhou free(mp); 88397c478bd9Sstevel@tonic-gate } 88407c478bd9Sstevel@tonic-gate 88417c478bd9Sstevel@tonic-gate /* 88427c478bd9Sstevel@tonic-gate * Utility routines 88437c478bd9Sstevel@tonic-gate */ 88447c478bd9Sstevel@tonic-gate 88457c478bd9Sstevel@tonic-gate 88467c478bd9Sstevel@tonic-gate /* 88477c478bd9Sstevel@tonic-gate * Returns 0 on success 88487c478bd9Sstevel@tonic-gate * Any other value indicates an error 88497c478bd9Sstevel@tonic-gate */ 88507c478bd9Sstevel@tonic-gate static int 8851986fd29aSsetje exec_cmd(char *cmdline, filelist_t *flistp) 88527c478bd9Sstevel@tonic-gate { 88537c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 88547c478bd9Sstevel@tonic-gate int ret; 88557c478bd9Sstevel@tonic-gate FILE *ptr; 88567c478bd9Sstevel@tonic-gate sigset_t set; 88577c478bd9Sstevel@tonic-gate void (*disp)(int); 88587c478bd9Sstevel@tonic-gate 88597c478bd9Sstevel@tonic-gate /* 88607c478bd9Sstevel@tonic-gate * For security 88617c478bd9Sstevel@tonic-gate * - only absolute paths are allowed 88627c478bd9Sstevel@tonic-gate * - set IFS to space and tab 88637c478bd9Sstevel@tonic-gate */ 88647c478bd9Sstevel@tonic-gate if (*cmdline != '/') { 88657c478bd9Sstevel@tonic-gate bam_error(ABS_PATH_REQ, cmdline); 88667c478bd9Sstevel@tonic-gate return (-1); 88677c478bd9Sstevel@tonic-gate } 88687c478bd9Sstevel@tonic-gate (void) putenv("IFS= \t"); 88697c478bd9Sstevel@tonic-gate 88707c478bd9Sstevel@tonic-gate /* 88717c478bd9Sstevel@tonic-gate * We may have been exec'ed with SIGCHLD blocked 88727c478bd9Sstevel@tonic-gate * unblock it here 88737c478bd9Sstevel@tonic-gate */ 88747c478bd9Sstevel@tonic-gate (void) sigemptyset(&set); 88757c478bd9Sstevel@tonic-gate (void) sigaddset(&set, SIGCHLD); 88767c478bd9Sstevel@tonic-gate if (sigprocmask(SIG_UNBLOCK, &set, NULL) != 0) { 88777c478bd9Sstevel@tonic-gate bam_error(CANT_UNBLOCK_SIGCHLD, strerror(errno)); 88787c478bd9Sstevel@tonic-gate return (-1); 88797c478bd9Sstevel@tonic-gate } 88807c478bd9Sstevel@tonic-gate 88817c478bd9Sstevel@tonic-gate /* 88827c478bd9Sstevel@tonic-gate * Set SIGCHLD disposition to SIG_DFL for popen/pclose 88837c478bd9Sstevel@tonic-gate */ 88847c478bd9Sstevel@tonic-gate disp = sigset(SIGCHLD, SIG_DFL); 88857c478bd9Sstevel@tonic-gate if (disp == SIG_ERR) { 88867c478bd9Sstevel@tonic-gate bam_error(FAILED_SIG, strerror(errno)); 88877c478bd9Sstevel@tonic-gate return (-1); 88887c478bd9Sstevel@tonic-gate } 88897c478bd9Sstevel@tonic-gate if (disp == SIG_HOLD) { 88907c478bd9Sstevel@tonic-gate bam_error(BLOCKED_SIG, cmdline); 88917c478bd9Sstevel@tonic-gate return (-1); 88927c478bd9Sstevel@tonic-gate } 88937c478bd9Sstevel@tonic-gate 88947c478bd9Sstevel@tonic-gate ptr = popen(cmdline, "r"); 88957c478bd9Sstevel@tonic-gate if (ptr == NULL) { 88967c478bd9Sstevel@tonic-gate bam_error(POPEN_FAIL, cmdline, strerror(errno)); 88977c478bd9Sstevel@tonic-gate return (-1); 88987c478bd9Sstevel@tonic-gate } 88997c478bd9Sstevel@tonic-gate 89007c478bd9Sstevel@tonic-gate /* 89017c478bd9Sstevel@tonic-gate * If we simply do a pclose() following a popen(), pclose() 89027c478bd9Sstevel@tonic-gate * will close the reader end of the pipe immediately even 89037c478bd9Sstevel@tonic-gate * if the child process has not started/exited. pclose() 89047c478bd9Sstevel@tonic-gate * does wait for cmd to terminate before returning though. 89057c478bd9Sstevel@tonic-gate * When the executed command writes its output to the pipe 89067c478bd9Sstevel@tonic-gate * there is no reader process and the command dies with 89077c478bd9Sstevel@tonic-gate * SIGPIPE. To avoid this we read repeatedly until read 89087c478bd9Sstevel@tonic-gate * terminates with EOF. This indicates that the command 89097c478bd9Sstevel@tonic-gate * (writer) has closed the pipe and we can safely do a 89107c478bd9Sstevel@tonic-gate * pclose(). 89117c478bd9Sstevel@tonic-gate * 89127c478bd9Sstevel@tonic-gate * Since pclose() does wait for the command to exit, 89137c478bd9Sstevel@tonic-gate * we can safely reap the exit status of the command 89147c478bd9Sstevel@tonic-gate * from the value returned by pclose() 89157c478bd9Sstevel@tonic-gate */ 8916986fd29aSsetje while (s_fgets(buf, sizeof (buf), ptr) != NULL) { 8917986fd29aSsetje if (flistp == NULL) { 8918986fd29aSsetje /* s_fgets strips newlines, so insert them at the end */ 8919986fd29aSsetje bam_print(PRINT, buf); 8920986fd29aSsetje } else { 8921986fd29aSsetje append_to_flist(flistp, buf); 89227c478bd9Sstevel@tonic-gate } 89237c478bd9Sstevel@tonic-gate } 89247c478bd9Sstevel@tonic-gate 89257c478bd9Sstevel@tonic-gate ret = pclose(ptr); 89267c478bd9Sstevel@tonic-gate if (ret == -1) { 89277c478bd9Sstevel@tonic-gate bam_error(PCLOSE_FAIL, cmdline, strerror(errno)); 89287c478bd9Sstevel@tonic-gate return (-1); 89297c478bd9Sstevel@tonic-gate } 89307c478bd9Sstevel@tonic-gate 89317c478bd9Sstevel@tonic-gate if (WIFEXITED(ret)) { 89327c478bd9Sstevel@tonic-gate return (WEXITSTATUS(ret)); 89337c478bd9Sstevel@tonic-gate } else { 89347c478bd9Sstevel@tonic-gate bam_error(EXEC_FAIL, cmdline, ret); 89357c478bd9Sstevel@tonic-gate return (-1); 89367c478bd9Sstevel@tonic-gate } 89377c478bd9Sstevel@tonic-gate } 89387c478bd9Sstevel@tonic-gate 89397c478bd9Sstevel@tonic-gate /* 89407c478bd9Sstevel@tonic-gate * Since this function returns -1 on error 89417c478bd9Sstevel@tonic-gate * it cannot be used to convert -1. However, 89427c478bd9Sstevel@tonic-gate * that is sufficient for what we need. 89437c478bd9Sstevel@tonic-gate */ 89447c478bd9Sstevel@tonic-gate static long 89457c478bd9Sstevel@tonic-gate s_strtol(char *str) 89467c478bd9Sstevel@tonic-gate { 89477c478bd9Sstevel@tonic-gate long l; 89487c478bd9Sstevel@tonic-gate char *res = NULL; 89497c478bd9Sstevel@tonic-gate 89507c478bd9Sstevel@tonic-gate if (str == NULL) { 89517c478bd9Sstevel@tonic-gate return (-1); 89527c478bd9Sstevel@tonic-gate } 89537c478bd9Sstevel@tonic-gate 89547c478bd9Sstevel@tonic-gate errno = 0; 89557c478bd9Sstevel@tonic-gate l = strtol(str, &res, 10); 89567c478bd9Sstevel@tonic-gate if (errno || *res != '\0') { 89577c478bd9Sstevel@tonic-gate return (-1); 89587c478bd9Sstevel@tonic-gate } 89597c478bd9Sstevel@tonic-gate 89607c478bd9Sstevel@tonic-gate return (l); 89617c478bd9Sstevel@tonic-gate } 89627c478bd9Sstevel@tonic-gate 89637c478bd9Sstevel@tonic-gate /* 89647c478bd9Sstevel@tonic-gate * Wrapper around fputs, that adds a newline (since fputs doesn't) 89657c478bd9Sstevel@tonic-gate */ 89667c478bd9Sstevel@tonic-gate static int 89677c478bd9Sstevel@tonic-gate s_fputs(char *str, FILE *fp) 89687c478bd9Sstevel@tonic-gate { 89697c478bd9Sstevel@tonic-gate char linebuf[BAM_MAXLINE]; 89707c478bd9Sstevel@tonic-gate 89717c478bd9Sstevel@tonic-gate (void) snprintf(linebuf, sizeof (linebuf), "%s\n", str); 89727c478bd9Sstevel@tonic-gate return (fputs(linebuf, fp)); 89737c478bd9Sstevel@tonic-gate } 89747c478bd9Sstevel@tonic-gate 89757c478bd9Sstevel@tonic-gate /* 89767c478bd9Sstevel@tonic-gate * Wrapper around fgets, that strips newlines returned by fgets 89777c478bd9Sstevel@tonic-gate */ 8978ae115bc7Smrj char * 89797c478bd9Sstevel@tonic-gate s_fgets(char *buf, int buflen, FILE *fp) 89807c478bd9Sstevel@tonic-gate { 89817c478bd9Sstevel@tonic-gate int n; 89827c478bd9Sstevel@tonic-gate 89837c478bd9Sstevel@tonic-gate buf = fgets(buf, buflen, fp); 89847c478bd9Sstevel@tonic-gate if (buf) { 89857c478bd9Sstevel@tonic-gate n = strlen(buf); 89867c478bd9Sstevel@tonic-gate if (n == buflen - 1 && buf[n-1] != '\n') 89877c478bd9Sstevel@tonic-gate bam_error(TOO_LONG, buflen - 1, buf); 89887c478bd9Sstevel@tonic-gate buf[n-1] = (buf[n-1] == '\n') ? '\0' : buf[n-1]; 89897c478bd9Sstevel@tonic-gate } 89907c478bd9Sstevel@tonic-gate 89917c478bd9Sstevel@tonic-gate return (buf); 89927c478bd9Sstevel@tonic-gate } 89937c478bd9Sstevel@tonic-gate 8994ae115bc7Smrj void * 89957c478bd9Sstevel@tonic-gate s_calloc(size_t nelem, size_t sz) 89967c478bd9Sstevel@tonic-gate { 89977c478bd9Sstevel@tonic-gate void *ptr; 89987c478bd9Sstevel@tonic-gate 89997c478bd9Sstevel@tonic-gate ptr = calloc(nelem, sz); 90007c478bd9Sstevel@tonic-gate if (ptr == NULL) { 90017c478bd9Sstevel@tonic-gate bam_error(NO_MEM, nelem*sz); 90027c478bd9Sstevel@tonic-gate bam_exit(1); 90037c478bd9Sstevel@tonic-gate } 90047c478bd9Sstevel@tonic-gate return (ptr); 90057c478bd9Sstevel@tonic-gate } 90067c478bd9Sstevel@tonic-gate 9007ae115bc7Smrj void * 9008ae115bc7Smrj s_realloc(void *ptr, size_t sz) 9009ae115bc7Smrj { 9010ae115bc7Smrj ptr = realloc(ptr, sz); 9011ae115bc7Smrj if (ptr == NULL) { 9012ae115bc7Smrj bam_error(NO_MEM, sz); 9013ae115bc7Smrj bam_exit(1); 9014ae115bc7Smrj } 9015ae115bc7Smrj return (ptr); 9016ae115bc7Smrj } 9017ae115bc7Smrj 9018eb2bd662Svikram char * 90197c478bd9Sstevel@tonic-gate s_strdup(char *str) 90207c478bd9Sstevel@tonic-gate { 90217c478bd9Sstevel@tonic-gate char *ptr; 90227c478bd9Sstevel@tonic-gate 90237c478bd9Sstevel@tonic-gate if (str == NULL) 90247c478bd9Sstevel@tonic-gate return (NULL); 90257c478bd9Sstevel@tonic-gate 90267c478bd9Sstevel@tonic-gate ptr = strdup(str); 90277c478bd9Sstevel@tonic-gate if (ptr == NULL) { 90287c478bd9Sstevel@tonic-gate bam_error(NO_MEM, strlen(str) + 1); 90297c478bd9Sstevel@tonic-gate bam_exit(1); 90307c478bd9Sstevel@tonic-gate } 90317c478bd9Sstevel@tonic-gate return (ptr); 90327c478bd9Sstevel@tonic-gate } 90337c478bd9Sstevel@tonic-gate 90347c478bd9Sstevel@tonic-gate /* 90357c478bd9Sstevel@tonic-gate * Returns 1 if amd64 (or sparc, for syncing x86 diskless clients) 90367c478bd9Sstevel@tonic-gate * Returns 0 otherwise 90377c478bd9Sstevel@tonic-gate */ 90387c478bd9Sstevel@tonic-gate static int 90397c478bd9Sstevel@tonic-gate is_amd64(void) 90407c478bd9Sstevel@tonic-gate { 90417c478bd9Sstevel@tonic-gate static int amd64 = -1; 90427c478bd9Sstevel@tonic-gate char isabuf[257]; /* from sysinfo(2) manpage */ 90437c478bd9Sstevel@tonic-gate 90447c478bd9Sstevel@tonic-gate if (amd64 != -1) 90457c478bd9Sstevel@tonic-gate return (amd64); 90467c478bd9Sstevel@tonic-gate 9047d876c67dSjg if (bam_alt_platform) { 9048d876c67dSjg if (strcmp(bam_platform, "i86pc") == 0) { 90497c478bd9Sstevel@tonic-gate amd64 = 1; /* diskless server */ 9050d876c67dSjg } 9051d876c67dSjg } else { 9052d876c67dSjg if (sysinfo(SI_ISALIST, isabuf, sizeof (isabuf)) > 0 && 9053d876c67dSjg strncmp(isabuf, "amd64 ", strlen("amd64 ")) == 0) { 9054d876c67dSjg amd64 = 1; 9055d876c67dSjg } else if (strstr(isabuf, "i386") == NULL) { 9056d876c67dSjg amd64 = 1; /* diskless server */ 9057d876c67dSjg } 9058d876c67dSjg } 9059d876c67dSjg if (amd64 == -1) 90607c478bd9Sstevel@tonic-gate amd64 = 0; 90617c478bd9Sstevel@tonic-gate 90627c478bd9Sstevel@tonic-gate return (amd64); 90637c478bd9Sstevel@tonic-gate } 90647c478bd9Sstevel@tonic-gate 906579755401Ssetje static char * 906679755401Ssetje get_machine(void) 9067986fd29aSsetje { 906879755401Ssetje static int cached = -1; 906979755401Ssetje static char mbuf[257]; /* from sysinfo(2) manpage */ 9070986fd29aSsetje 907179755401Ssetje if (cached == 0) 907279755401Ssetje return (mbuf); 9073d876c67dSjg 9074d876c67dSjg if (bam_alt_platform) { 907579755401Ssetje return (bam_platform); 9076d876c67dSjg } else { 907779755401Ssetje if (sysinfo(SI_MACHINE, mbuf, sizeof (mbuf)) > 0) { 907879755401Ssetje cached = 1; 9079d876c67dSjg } 9080d876c67dSjg } 908179755401Ssetje if (cached == -1) { 908279755401Ssetje mbuf[0] = '\0'; 908379755401Ssetje cached = 0; 9084986fd29aSsetje } 9085986fd29aSsetje 908679755401Ssetje return (mbuf); 9087986fd29aSsetje } 9088986fd29aSsetje 9089eb2bd662Svikram int 9090eb2bd662Svikram is_sparc(void) 9091eb2bd662Svikram { 909279755401Ssetje static int issparc = -1; 909379755401Ssetje char mbuf[257]; /* from sysinfo(2) manpage */ 909479755401Ssetje 909579755401Ssetje if (issparc != -1) 909679755401Ssetje return (issparc); 909779755401Ssetje 909879755401Ssetje if (bam_alt_platform) { 909979755401Ssetje if (strncmp(bam_platform, "sun4", 4) == 0) { 910079755401Ssetje issparc = 1; 910179755401Ssetje } 910279755401Ssetje } else { 910379755401Ssetje if (sysinfo(SI_ARCHITECTURE, mbuf, sizeof (mbuf)) > 0 && 9104d7d0f93bSjg strcmp(mbuf, "sparc") == 0) { 910579755401Ssetje issparc = 1; 910679755401Ssetje } 9107d7d0f93bSjg } 9108d7d0f93bSjg if (issparc == -1) 9109d7d0f93bSjg issparc = 0; 911079755401Ssetje 911179755401Ssetje return (issparc); 9112eb2bd662Svikram } 9113986fd29aSsetje 91147c478bd9Sstevel@tonic-gate static void 91157c478bd9Sstevel@tonic-gate append_to_flist(filelist_t *flistp, char *s) 91167c478bd9Sstevel@tonic-gate { 91177c478bd9Sstevel@tonic-gate line_t *lp; 91187c478bd9Sstevel@tonic-gate 91197c478bd9Sstevel@tonic-gate lp = s_calloc(1, sizeof (line_t)); 91207c478bd9Sstevel@tonic-gate lp->line = s_strdup(s); 91217c478bd9Sstevel@tonic-gate if (flistp->head == NULL) 91227c478bd9Sstevel@tonic-gate flistp->head = lp; 91237c478bd9Sstevel@tonic-gate else 91247c478bd9Sstevel@tonic-gate flistp->tail->next = lp; 91257c478bd9Sstevel@tonic-gate flistp->tail = lp; 91267c478bd9Sstevel@tonic-gate } 91272449e17fSsherrym 9128986fd29aSsetje #if !defined(_OPB) 91292449e17fSsherrym 91302449e17fSsherrym UCODE_VENDORS; 91312449e17fSsherrym 91322449e17fSsherrym /*ARGSUSED*/ 91332449e17fSsherrym static void 91342449e17fSsherrym ucode_install(char *root) 91352449e17fSsherrym { 91362449e17fSsherrym int i; 91372449e17fSsherrym 91382449e17fSsherrym for (i = 0; ucode_vendors[i].filestr != NULL; i++) { 91392449e17fSsherrym int cmd_len = PATH_MAX + 256; 91402449e17fSsherrym char cmd[PATH_MAX + 256]; 91412449e17fSsherrym char file[PATH_MAX]; 91422449e17fSsherrym char timestamp[PATH_MAX]; 91432449e17fSsherrym struct stat fstatus, tstatus; 91442449e17fSsherrym struct utimbuf u_times; 91452449e17fSsherrym 9146adc586deSMark Johnson (void) snprintf(file, PATH_MAX, "%s/%s/%s-ucode.%s", 9147adc586deSMark Johnson bam_root, UCODE_INSTALL_PATH, ucode_vendors[i].filestr, 9148adc586deSMark Johnson ucode_vendors[i].extstr); 91492449e17fSsherrym 91502449e17fSsherrym if (stat(file, &fstatus) != 0 || !(S_ISREG(fstatus.st_mode))) 91512449e17fSsherrym continue; 91522449e17fSsherrym 91532449e17fSsherrym (void) snprintf(timestamp, PATH_MAX, "%s.ts", file); 91542449e17fSsherrym 91552449e17fSsherrym if (stat(timestamp, &tstatus) == 0 && 91562449e17fSsherrym fstatus.st_mtime <= tstatus.st_mtime) 91572449e17fSsherrym continue; 91582449e17fSsherrym 91592449e17fSsherrym (void) snprintf(cmd, cmd_len, "/usr/sbin/ucodeadm -i -R " 91602449e17fSsherrym "%s/%s/%s %s > /dev/null 2>&1", bam_root, 91612449e17fSsherrym UCODE_INSTALL_PATH, ucode_vendors[i].vendorstr, file); 91622449e17fSsherrym if (system(cmd) != 0) 91632449e17fSsherrym return; 91642449e17fSsherrym 91652449e17fSsherrym if (creat(timestamp, S_IRUSR | S_IWUSR) == -1) 91662449e17fSsherrym return; 91672449e17fSsherrym 91682449e17fSsherrym u_times.actime = fstatus.st_atime; 91692449e17fSsherrym u_times.modtime = fstatus.st_mtime; 91702449e17fSsherrym (void) utime(timestamp, &u_times); 91712449e17fSsherrym } 91722449e17fSsherrym } 91732449e17fSsherrym #endif 9174