753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * CDDL HEADER START
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore *
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * The contents of this file are subject to the terms of the
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Common Development and Distribution License (the "License").
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * You may not use this file except in compliance with the License.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore *
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * or http://www.opensolaris.org/os/licensing.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * See the License for the specific language governing permissions
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * and limitations under the License.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore *
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * When distributing Covered Code, include this CDDL HEADER in each
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * If applicable, add the following below this CDDL HEADER, with the
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * fields enclosed by brackets "[]" replaced with your own identifying
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * information: Portions Copyright [yyyy] [name of copyright owner]
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore *
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * CDDL HEADER END
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Use is subject to license terms.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka/*
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome * Copyright 2015 Toomas Soome <tsoome@me.com>
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka * This file contains all the functions that manipulate the file
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * system where the GRUB menu resides.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <stdio.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <errno.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <stdlib.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <strings.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <unistd.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <fcntl.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <assert.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <sys/types.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <sys/stat.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <sys/mount.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <sys/mntent.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <sys/mnttab.h>
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome#include <sys/efi_partition.h>
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome#include <sys/vtoc.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <sys/fs/ufs_mount.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <sys/dktp/fdisk.h>
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include <libfstyp.h>
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka#if defined(i386) || defined(__amd64)
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka#include <libfdisk.h>
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka#endif
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore#include "libgrub_impl.h"
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic int
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreslice_match(const char *physpath, int slice)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore const char *pos;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome /* always match whole disk slice */
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome if (slice == SLCNUM_WHOLE_DISK)
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome return (0);
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return ((pos = strrchr(physpath, slice)) == NULL ||
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore pos[1] != 0 || pos[-1] != ':');
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Returns zero if path contains ufs
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic int
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreslice_ufs(const char *path)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int fd, ret;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore const char *id;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore fstyp_handle_t hdl;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore fd = open(path, O_RDONLY);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((ret = fstyp_init(fd, 0, NULL, &hdl)) == 0) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ret = fstyp_ident(hdl, "ufs", &id);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore fstyp_fini(hdl);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) close(fd);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (ret);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic int
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreget_sol_prtnum(const char *physpath)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int i, fd;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char *pos;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore size_t sz;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore struct mboot *mb;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore struct ipart *ipart;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char boot_sect[512];
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char rdev[MAXNAMELEN];
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka#if defined(i386) || defined(__amd64)
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka ext_part_t *epp;
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka int ext_part_found = 0;
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka#endif
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) snprintf(rdev, sizeof (rdev), "/devices%s,raw", physpath);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((pos = strrchr(rdev, ':')) == NULL)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (PRTNUM_INVALID);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome /*
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome * first check for EFI partitioning, efi_alloc_and_read()
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome * will return partition number.
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome */
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome if ((fd = open(rdev, O_RDONLY|O_NDELAY)) >= 0) {
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome struct dk_gpt *vtoc;
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome if ((i = efi_alloc_and_read(fd, &vtoc)) >= 0) {
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome /* zfs is using V_USR */
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome if (vtoc->efi_parts[i].p_tag != V_USR)
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome i = PRTNUM_INVALID; /* error */
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome efi_free(vtoc);
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome (void) close(fd);
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome return (i);
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome }
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome (void) close(fd);
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome } else {
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome return (PRTNUM_INVALID);
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome }
57631629e78d7cda75d1f6ec529fc985298b24f4Toomas Soome
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore pos[1] = SLCNUM_WHOLE_DISK;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore fd = open(rdev, O_RDONLY);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sz = read(fd, boot_sect, sizeof (boot_sect));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) close(fd);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (sz != sizeof (boot_sect))
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (PRTNUM_INVALID);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /* parse fdisk table */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore mb = (struct mboot *)(uintptr_t)boot_sect;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ipart = (struct ipart *)(uintptr_t)mb->parts;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore for (i = 0; i < FD_NUMPART; ++i) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (ipart[i].systid == SUNIXOS || ipart[i].systid == SUNIXOS2)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (i);
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka#if defined(i386) || defined(__amd64)
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka if (!fdisk_is_dos_extended(ipart[i].systid) ||
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka (ext_part_found == 1))
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka continue;
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka ext_part_found = 1;
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka if (libfdisk_init(&epp, rdev, NULL, FDISK_READ_DISK) ==
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka FDISK_SUCCESS) {
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka uint32_t begs, nums;
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka int pno;
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka int rval;
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka rval = fdisk_get_solaris_part(epp, &pno, &begs, &nums);
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka libfdisk_fini(&epp);
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka if (rval == FDISK_SUCCESS)
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka return (pno - 1);
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka }
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka#endif
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (PRTNUM_INVALID);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Get physpath, topfs and bootfs for ZFS root dataset.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Return 0 on success, non-zero (not errno) on failure.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic int
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreget_zfs_root(zfs_handle_t *zfh, grub_fs_t *fs, grub_root_t *root)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int ret;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore zpool_handle_t *zph;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore const char *name;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (zfs_get_type(zfh) != ZFS_TYPE_FILESYSTEM ||
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (name = zfs_get_name(zfh)) == NULL ||
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (zph = zpool_open(fs->gf_lzfh, name)) == NULL)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (-1);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((ret = zpool_get_physpath(zph, root->gr_physpath,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sizeof (root->gr_physpath))) == 0 &&
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (ret = zpool_get_prop(zph, ZPOOL_PROP_BOOTFS,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore root->gr_fs[GRBM_ZFS_BOOTFS].gfs_dev,
c58b352673e88983cd2b8a388a8c7625f35e2f18Adam Stevko sizeof (root->gr_fs[GRBM_ZFS_BOOTFS].gfs_dev), NULL,
c58b352673e88983cd2b8a388a8c7625f35e2f18Adam Stevko B_FALSE)) == 0) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) strlcpy(root->gr_fs[GRBM_ZFS_TOPFS].gfs_dev, name,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sizeof (root->gr_fs[GRBM_ZFS_TOPFS].gfs_dev));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) grub_fsd_get_mountp(root->gr_fs + GRBM_ZFS_BOOTFS,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore MNTTYPE_ZFS);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) grub_fsd_get_mountp(root->gr_fs + GRBM_ZFS_TOPFS,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore MNTTYPE_ZFS);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore zpool_close(zph);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (ret);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * On entry physpath parameter supposed to contain:
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * <disk_physpath>[<space><disk_physpath>]*.
01f9868a8d2cedd96c3aeefbd7233aa77f7b72ffMarcel Telka * Retrieves first <disk_physpath> that matches both partition and slice.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * If any partition and slice is acceptable, first <disk_physpath> is returned.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic int
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreget_one_physpath(char *physpath, uint_t prtnum, uint_t slcnum)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int ret;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char *tmp, *tok;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (!IS_SLCNUM_VALID(slcnum) && !IS_PRTNUM_VALID(prtnum)) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) strtok(physpath, " ");
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (0);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((tmp = strdup(physpath)) == NULL)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (errno);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore ret = ENODEV;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore for (tok = strtok(tmp, " "); tok != NULL; tok = strtok(NULL, " ")) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((ret = (slice_match(tok, slcnum) != 0 ||
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore get_sol_prtnum(tok) != prtnum)) == 0) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) strcpy(physpath, tok);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore break;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore free(tmp);
8c7cfd880e3f539ab3041a3168beec560e4ff5d9Sherry Moore if (ret)
8c7cfd880e3f539ab3041a3168beec560e4ff5d9Sherry Moore ret = ENODEV;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (ret);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic int
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorezfs_bootsign(zfs_handle_t *zfh, void *data)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore grub_barg_t *barg;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore grub_menu_t *menu;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore struct stat st;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char path[MAXPATHLEN];
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg = (grub_barg_t *)data;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore menu = barg->gb_entry->ge_menu;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore do {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (get_zfs_root(zfh, &menu->gm_fs, &barg->gb_root) != 0 ||
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore get_one_physpath(barg->gb_root.gr_physpath, barg->gb_prtnum,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_slcnum) != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore break;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * if top zfs dataset is not mounted, mount it now
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (barg->gb_root.gr_fs[GRBM_ZFS_TOPFS].gfs_mountp[0] == 0) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (grub_fsd_mount_tmp(barg->gb_root.gr_fs +
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore GRBM_ZFS_TOPFS, MNTTYPE_ZFS) != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore break;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /* check that bootsign exists and it is a regular file */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) snprintf(path, sizeof (path), "%s%s",
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_root.gr_fs[GRBM_ZFS_TOPFS].gfs_mountp,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_bootsign);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (lstat(path, &st) != 0 || S_ISREG(st.st_mode) == 0 ||
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (st.st_mode & S_IRUSR) == 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore break;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) strlcpy(barg->gb_root.gr_fstyp, MNTTYPE_ZFS,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sizeof (barg->gb_root.gr_fstyp));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_walkret = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /* LINTED: E_CONSTANT_CONDITION */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore } while (0);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore grub_fsd_umount_tmp(barg->gb_root.gr_fs + GRBM_ZFS_TOPFS);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore zfs_close(zfh);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /* return non-zero to terminate the walk */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (barg->gb_walkret == 0);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic int
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreget_devlink(di_devlink_t dl, void *arg)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore const char *path;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore grub_barg_t *barg;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg = (grub_barg_t *)arg;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((path = di_devlink_path(dl)) != NULL)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) strlcpy(barg->gb_root.gr_fs[GRBM_UFS].gfs_dev, path,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sizeof (barg->gb_root.gr_fs[GRBM_UFS].gfs_dev));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (DI_WALK_TERMINATE);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic int
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreufs_bootsign_check(grub_barg_t *barg)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int ret;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore struct stat st;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore grub_menu_t *mp;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char path[MAXPATHLEN];
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore mp = barg->gb_entry->ge_menu;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /* get /dev/dsk link */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (di_devlink_walk(mp->gm_fs.gf_dvlh, "^dsk/",
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_root.gr_physpath, DI_PRIMARY_LINK, barg, get_devlink) != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (errno);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * if disk is not mounted, mount it now
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (grub_fsd_get_mountp(barg->gb_root.gr_fs + GRBM_UFS,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore MNTTYPE_UFS) != 0) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((ret =
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore slice_ufs(barg->gb_root.gr_fs[GRBM_UFS].gfs_dev)) != 0 ||
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (ret = grub_fsd_mount_tmp(barg->gb_root.gr_fs + GRBM_UFS,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore MNTTYPE_UFS)) != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (ret);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) snprintf(path, sizeof (path), "%s%s",
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_root.gr_fs[GRBM_UFS].gfs_mountp, barg->gb_bootsign);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (lstat(path, &st) == 0 && S_ISREG(st.st_mode) &&
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (st.st_mode & S_IRUSR) != 0) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_walkret = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) strlcpy(barg->gb_root.gr_fstyp, MNTTYPE_UFS,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sizeof (barg->gb_root.gr_fstyp));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore grub_fsd_umount_tmp(barg->gb_root.gr_fs + GRBM_UFS);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (barg->gb_walkret);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic int
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreufs_bootsign(di_node_t node, di_minor_t minor, void *arg)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore uint_t prtnum;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char *name, *path;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore grub_barg_t *barg;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg = (grub_barg_t *)arg;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (di_minor_spectype(minor) != S_IFBLK)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (DI_WALK_CONTINUE);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore name = di_minor_name(minor);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (name[0] != barg->gb_slcnum || name[1] != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (DI_WALK_CONTINUE);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore path = di_devfs_path(node);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) snprintf(barg->gb_root.gr_physpath,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sizeof (barg->gb_root.gr_physpath), "%s:%c", path, barg->gb_slcnum);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore di_devfs_path_free(path);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore prtnum = get_sol_prtnum(barg->gb_root.gr_physpath);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (!IS_PRTNUM_VALID(prtnum))
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (DI_WALK_CONTINUE);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * check only specified partition, slice
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (IS_PRTNUM_VALID(barg->gb_prtnum)) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (prtnum != barg->gb_prtnum || ufs_bootsign_check(barg) != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (DI_WALK_CONTINUE);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (DI_WALK_TERMINATE);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Walk through all slices in found solaris partition
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_prtnum = prtnum;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore minor = DI_MINOR_NIL;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (di_minor_spectype(minor) != S_IFBLK)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore continue;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore name = di_minor_name(minor);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (!IS_SLCNUM_VALID(name[0]) || name[1] != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore continue;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_slcnum = name[0];
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore path = strrchr(barg->gb_root.gr_physpath, ':');
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore path[1] = barg->gb_slcnum;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (ufs_bootsign_check(barg) == 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (DI_WALK_TERMINATE);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_prtnum = (uint_t)PRTNUM_INVALID;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_slcnum = (uint_t)SLCNUM_WHOLE_DISK;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (DI_WALK_CONTINUE);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Differs from what GRUB is doing: GRUB searchs through all disks seen by bios
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * for bootsign, if bootsign is found on ufs slice GRUB sets it as a root,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * if on zfs, then GRUB uses zfs slice as root only if bootsign wasn't found
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * on other slices.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * That function first searches through all top datasets of active zpools,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * then if bootsign still not found walks through all disks and tries to
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * find ufs slice with the bootsign.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreint
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooregrub_find_bootsign(grub_barg_t *barg)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore grub_menu_t *mp;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore mp = barg->gb_entry->ge_menu;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /* try to find bootsign over zfs pools */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore barg->gb_walkret = EG_BOOTSIGN;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) zfs_iter_root(mp->gm_fs.gf_lzfh, zfs_bootsign, barg);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /* try ufs now */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (barg->gb_walkret != 0 && di_walk_minor(mp->gm_fs.gf_diroot,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore DDI_NT_BLOCK, 0, barg, ufs_bootsign) != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (errno);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (barg->gb_walkret);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Get current root file system.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Return 0 on success, errno code on failure.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreint
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooregrub_current_root(grub_fs_t *fs, grub_root_t *root)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int rc = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore FILE *fp = NULL;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char *name = NULL;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore zfs_handle_t *zfh = NULL;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore struct mnttab mp = {0};
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore struct mnttab mpref = {0};
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char buf[MAXNAMELEN] = {0};
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore mpref.mnt_mountp = "/";
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((fp = fopen(MNTTAB, "r")) == NULL)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (errno);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * getmntany returns non-zero for failure, and sets errno
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore rc = getmntany(fp, &mp, &mpref);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (rc != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore rc = errno;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) fclose(fp);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (rc != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (rc);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) strlcpy(root->gr_fstyp, mp.mnt_fstype, sizeof (root->gr_fstyp));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (strcmp(root->gr_fstyp, MNTTYPE_ZFS) == 0) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) strlcpy(buf, mp.mnt_special, sizeof (buf));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((name = strtok(buf, "/")) == NULL)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EG_CURROOT);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((zfh = zfs_open(fs->gf_lzfh, name, ZFS_TYPE_FILESYSTEM)) ==
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore NULL)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EG_OPENZFS);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /*
8c7cfd880e3f539ab3041a3168beec560e4ff5d9Sherry Moore * get_zfs_root returns non-zero on failure, not errno.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (get_zfs_root(zfh, fs, root))
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore rc = EG_CURROOT;
8c7cfd880e3f539ab3041a3168beec560e4ff5d9Sherry Moore else
8c7cfd880e3f539ab3041a3168beec560e4ff5d9Sherry Moore /*
8c7cfd880e3f539ab3041a3168beec560e4ff5d9Sherry Moore * For mirrored root physpath would contain the list of
8c7cfd880e3f539ab3041a3168beec560e4ff5d9Sherry Moore * all bootable devices, pick up the first one.
8c7cfd880e3f539ab3041a3168beec560e4ff5d9Sherry Moore */
8c7cfd880e3f539ab3041a3168beec560e4ff5d9Sherry Moore rc = get_one_physpath(root->gr_physpath, SLCNUM_INVALID,
8c7cfd880e3f539ab3041a3168beec560e4ff5d9Sherry Moore PRTNUM_INVALID);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore zfs_close(zfh);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore } else if (strcmp(mp.mnt_fstype, MNTTYPE_UFS) == 0) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) strlcpy(root->gr_fs[GRBM_UFS].gfs_dev, mp.mnt_special,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sizeof (root->gr_fs[GRBM_UFS].gfs_dev));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) strlcpy(root->gr_fs[GRBM_UFS].gfs_mountp, mp.mnt_mountp,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sizeof (root->gr_fs[GRBM_UFS].gfs_mountp));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore } else {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore rc = EG_UNKNOWNFS;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (rc);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooregrub_fsdesc_t *
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooregrub_get_rootfsd(const grub_root_t *root)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore grub_fsdesc_t *fsd = NULL;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore assert(root);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (strcmp(MNTTYPE_UFS, root->gr_fstyp) == 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore fsd = (grub_fsdesc_t *)root->gr_fs + GRBM_UFS;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore else if (strcmp(MNTTYPE_ZFS, root->gr_fstyp) == 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore fsd = (grub_fsdesc_t *)root->gr_fs + GRBM_ZFS_BOOTFS;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (fsd);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Gets file systems mount point if any.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Return 0 if filesystem is mounted, errno on failure.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreint
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooregrub_fsd_get_mountp(grub_fsdesc_t *fsd, char *fstyp)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int rc;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore FILE *fp = NULL;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore struct mnttab mp = {0};
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore struct mnttab mpref = {0};
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore fsd->gfs_mountp[0] = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((fp = fopen(MNTTAB, "r")) == NULL)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (errno);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore mpref.mnt_special = fsd->gfs_dev;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore mpref.mnt_fstype = fstyp;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((rc = getmntany(fp, &mp, &mpref)) == 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) strlcpy(fsd->gfs_mountp, mp.mnt_mountp,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore sizeof (fsd->gfs_mountp));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore else
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore rc = EG_GETMNTTAB;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) fclose(fp);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (rc);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorestatic const char tmp_mountp[] = "/tmp/.libgrubmgmt.%s.XXXXXX";
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Mount file system at tmp_mountp.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Return 0 on success, errno on failure.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooreint
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooregrub_fsd_mount_tmp(grub_fsdesc_t *fsd, const char *fstyp)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore const char *pos;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore void *data = NULL;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int dtsz = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore struct ufs_args ufs_args = {UFSMNT_LARGEFILES};
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore char mntopts[MNT_LINE_MAX] = "";
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore int rc = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore assert(fsd);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore assert(!fsd->gfs_is_tmp_mounted);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore fsd->gfs_mountp[0] = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (strcmp(fstyp, MNTTYPE_UFS) == 0) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) strlcpy(mntopts, MNTOPT_LARGEFILES, sizeof (mntopts));
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore data = &ufs_args;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore dtsz = sizeof (ufs_args);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore } else if (strcmp(fstyp, MNTTYPE_ZFS) != 0) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (EG_UNKNOWNFS);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /* construct name for temporary mount point */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore pos = strrchr(fsd->gfs_dev, '/');
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore pos = (pos == NULL) ? fsd->gfs_dev : pos + 1;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) snprintf(fsd->gfs_mountp, sizeof (fsd->gfs_mountp),
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore tmp_mountp, pos);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (mkdtemp(fsd->gfs_mountp) != NULL) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if ((rc = mount(fsd->gfs_dev, fsd->gfs_mountp,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore MS_DATA | MS_OPTIONSTR | MS_RDONLY,
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore fstyp, data, dtsz, mntopts, sizeof (mntopts))) != 0) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * mount failed, collect errno and remove temp dir
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore rc = errno;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) rmdir(fsd->gfs_mountp);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore } else {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore rc = errno;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (rc != 0)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore fsd->gfs_mountp[0] = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore /*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Note that valid values for gfs_is_tmp_mounted are 0,1.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Any other value indicates that something bad happened.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Probably grub_fsd_umount_tmp() wasn't called or didn't
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * work as expected.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore fsd->gfs_is_tmp_mounted += (rc == 0);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return (rc);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore/*
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore * Unmount file system at tmp_mountp.
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore */
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moorevoid
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Mooregrub_fsd_umount_tmp(grub_fsdesc_t *fsd)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore{
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (fsd == NULL)
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore return;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (fsd->gfs_is_tmp_mounted) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore if (fsd->gfs_mountp[0] != 0) {
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) umount2(fsd->gfs_mountp, 0);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore (void) rmdir(fsd->gfs_mountp);
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore fsd->gfs_mountp[0] = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore fsd->gfs_is_tmp_mounted = 0;
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore }
753a6d457b330b1b29b2d3eefcd0831116ce950dSherry Moore}