static void check_slices(avl_tree_t *r, int fd, const char *sname) { #ifdef sun struct extvtoc vtoc; struct dk_gpt *gpt; char diskname[MAXNAMELEN]; char *ptr; int i; (void) strncpy(diskname, sname, MAXNAMELEN); if ((ptr = strrchr(diskname, 's')) == NULL || !isdigit(ptr[1])) return; ptr[1] = '\0'; if (read_extvtoc(fd, &vtoc) >= 0) { for (i = 0; i < NDKMAP; i++) check_one_slice(r, diskname, i, vtoc.v_part[i].p_size, vtoc.v_sectorsz); } else if (efi_alloc_and_read(fd, &gpt) >= 0) { /* * on x86 we'll still have leftover links that point * to slices s[9-15], so use NDKMAP instead */ for (i = 0; i < NDKMAP; i++) check_one_slice(r, diskname, i, gpt->efi_parts[i].p_size, gpt->efi_lbasize); /* nodes p[1-4] are never used with EFI labels */ ptr[0] = 'p'; for (i = 1; i <= FD_NUMPART; i++) check_one_slice(r, diskname, i, 0, 1); efi_free(gpt); } #endif }
/* * readefi(): Read a partition map. */ static int readefi(int fd, char *name, struct dk_gpt **efi) { int retval; if ((retval = efi_alloc_and_read(fd, efi)) >= 0) return (0); switch (retval) { case (VT_EIO): return (warn(name, "Unable to read VTOC")); case (VT_EINVAL): return (warn(name, "Invalid VTOC")); case (VT_ERROR): return (warn(name, "Unknown problem reading VTOC")); } return (retval); }
/* * returns NULL if the slice is good (e.g. does not start at block * zero, or a string describing the error if it doesn't */ static boolean_t is_good_slice(char *sfile, char **err) { int fd, rc; struct vtoc vtoc; dk_gpt_t *gpt; char rdskname[MAXPATHLEN]; char *x, *y; *err = NULL; /* convert from dsk to rdsk */ STRCPYLIM(rdskname, sfile, "disk name"); x = strstr(rdskname, "dsk/"); y = strstr(sfile, "dsk/"); if (x != NULL) { *x++ = 'r'; (void) strcpy(x, y); } if ((fd = open(rdskname, O_RDONLY)) == -1) { *err = "could not open '%s'\n"; } else if ((rc = read_vtoc(fd, &vtoc)) >= 0) { /* * we got a slice number; now check the block * number where the slice starts */ if (vtoc.v_part[rc].p_start < 2) *err = "using '%s' would clobber the disk label\n"; (void) close(fd); return (*err ? B_FALSE : B_TRUE); } else if ((rc == VT_ENOTSUP) && (efi_alloc_and_read(fd, &gpt)) >= 0) { /* EFI slices don't clobber the disk label */ free(gpt); (void) close(fd); return (B_TRUE); } else *err = "could not read partition table from '%s'\n"; return (B_FALSE); }
static void partinfo(int fd, char *device) { int i; int slice; major_t maj; minor_t min; struct stat64 statbuf; struct vtoc vtdata; struct dk_gpt *efi; i = stat64(device, &statbuf); if (i < 0) exit(DRERR); maj = major(statbuf.st_rdev); min = minor(statbuf.st_rdev); if ((slice = readvtoc(fd, device, &vtdata)) >= 0) { (void) printf("%s\t%0lx\t%0lx\t%ld\t%ld\t%x\t%x\n", device, maj, min, vtdata.v_part[slice].p_start, vtdata.v_part[slice].p_size, vtdata.v_part[slice].p_flag, vtdata.v_part[slice].p_tag); } else if ((slice == VT_ENOTSUP) && (slice = efi_alloc_and_read(fd, &efi)) >= 0) { (void) printf("%s\t%lx\t%lx\t%lld\t%lld\t%hx\t%hx\n", device, maj, min, efi->efi_parts[slice].p_start, efi->efi_parts[slice].p_size, efi->efi_parts[slice].p_flag, efi->efi_parts[slice].p_tag); } else { exit(DRERR); } }
int main (int argc, char *argv[]) { int fd, rfd; int ret; char *udi; char *device_file, *raw_device_file; char *devpath, *rdevpath; boolean_t is_dos; int dos_num; LibHalContext *ctx = NULL; DBusError error; DBusConnection *conn; char *parent_udi; char *storage_device; char *is_disc_str; int fdc; dbus_bool_t is_disc = FALSE; dbus_bool_t is_floppy = FALSE; unsigned int block_size; dbus_uint64_t vol_size; dbus_bool_t has_data = TRUE; /* probe for fs by default */ dbus_bool_t has_audio = FALSE; char *partition_scheme = NULL; dbus_uint64_t partition_start = 0; int partition_number = 0; struct vtoc vtoc; dk_gpt_t *gpt; struct dk_minfo mi; int i, dos_cnt; fstyp_handle_t fstyp_handle; int systid, relsect, numsect; off_t probe_offset = 0; int num_volumes; char **volumes; dbus_uint64_t v_start; const char *fstype; nvlist_t *fsattr; fd = rfd = -1; ret = 1; if ((udi = getenv ("UDI")) == NULL) { goto out; } if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL) { goto out; } if ((raw_device_file = getenv ("HAL_PROP_BLOCK_SOLARIS_RAW_DEVICE")) == NULL) { goto out; } if (!dos_to_dev(device_file, &rdevpath, &dos_num)) { rdevpath = raw_device_file; } if (!(is_dos = dos_to_dev(device_file, &devpath, &dos_num))) { devpath = device_file; } if ((parent_udi = getenv ("HAL_PROP_INFO_PARENT")) == NULL) { goto out; } if ((storage_device = getenv ("HAL_PROP_BLOCK_STORAGE_DEVICE")) == NULL) { goto out; } is_disc_str = getenv ("HAL_PROP_VOLUME_IS_DISC"); if (is_disc_str != NULL && strcmp (is_disc_str, "true") == 0) { is_disc = TRUE; } else { is_disc = FALSE; } drop_privileges (); setup_logger (); dbus_error_init (&error); if ((ctx = libhal_ctx_init_direct (&error)) == NULL) goto out; HAL_DEBUG (("Doing probe-volume for %s\n", device_file)); fd = open (devpath, O_RDONLY | O_NONBLOCK); if (fd < 0) { goto out; } rfd = open (rdevpath, O_RDONLY | O_NONBLOCK); if (rfd < 0) { goto out; } /* if it's a floppy with no media, bail out */ if (ioctl(rfd, FDGETCHANGE, &fdc) == 0) { is_floppy = TRUE; if (fdc & FDGC_CURRENT) { goto out; } } /* block size and total size */ if (ioctl(rfd, DKIOCGMEDIAINFO, &mi) != -1) { block_size = mi.dki_lbsize; vol_size = mi.dki_capacity * block_size; } else if (errno == ENXIO) { /* driver supports ioctl, but media is not available */ goto out; } else { /* driver does not support ioctl, e.g. lofi */ block_size = 512; vol_size = 0; } libhal_device_set_property_int (ctx, udi, "volume.block_size", block_size, &error); my_dbus_error_free (&error); libhal_device_set_property_uint64 (ctx, udi, "volume.size", vol_size, &error); my_dbus_error_free (&error); if (is_disc) { if (!probe_disc (rfd, ctx, udi, &has_data, &has_audio)) { HAL_DEBUG (("probe_disc failed, skipping fstyp")); goto out; } /* with audio present, create volume even if fs probing fails */ if (has_audio) { ret = 0; } } if (!has_data) { goto skip_fs; } /* don't support partitioned floppy */ if (is_floppy) { goto skip_part; } /* * first get partitioning info */ if (is_dos) { /* for a dos drive find partition offset */ if (!find_dos_drive(fd, dos_num, &relsect, &numsect, &systid)) { goto out; } partition_scheme = "mbr"; partition_start = (dbus_uint64_t)relsect * 512; partition_number = dos_num; probe_offset = (off_t)relsect * 512; } else { if ((partition_number = read_vtoc(rfd, &vtoc)) >= 0) { if (!vtoc_one_slice_entire_disk(&vtoc)) { partition_scheme = "smi"; if (partition_number < vtoc.v_nparts) { if (vtoc.v_part[partition_number].p_size == 0) { HAL_DEBUG (("zero size partition")); } partition_start = vtoc.v_part[partition_number].p_start * block_size; } } } else if ((partition_number = efi_alloc_and_read(rfd, &gpt)) >= 0) { partition_scheme = "gpt"; if (partition_number < gpt->efi_nparts) { if (gpt->efi_parts[partition_number].p_size == 0) { HAL_DEBUG (("zero size partition")); } partition_start = gpt->efi_parts[partition_number].p_start * block_size; } efi_free(gpt); } probe_offset = 0; } if (partition_scheme != NULL) { libhal_device_set_property_string (ctx, udi, "volume.partition.scheme", partition_scheme, &error); my_dbus_error_free (&error); libhal_device_set_property_int (ctx, udi, "volume.partition.number", partition_number, &error); my_dbus_error_free (&error); libhal_device_set_property_uint64 (ctx, udi, "volume.partition.start", partition_start, &error); my_dbus_error_free (&error); libhal_device_set_property_bool (ctx, udi, "volume.is_partition", TRUE, &error); my_dbus_error_free (&error); } else { libhal_device_set_property_bool (ctx, udi, "volume.is_partition", FALSE, &error); my_dbus_error_free (&error); } /* * ignore duplicate partitions */ if ((volumes = libhal_manager_find_device_string_match ( ctx, "block.storage_device", storage_device, &num_volumes, &error)) != NULL) { my_dbus_error_free (&error); for (i = 0; i < num_volumes; i++) { if (strcmp (udi, volumes[i]) == 0) { continue; /* skip self */ } v_start = libhal_device_get_property_uint64 (ctx, volumes[i], "volume.partition.start", &error); if (dbus_error_is_set(&error)) { dbus_error_free(&error); continue; } if (v_start == partition_start) { HAL_DEBUG (("duplicate partition")); goto out; } } libhal_free_string_array (volumes); } skip_part: /* * now determine fs type * * XXX We could get better performance from block device, * but for now we use raw device because: * * - fstyp_udfs has a bug that it only works on raw * * - sd has a bug that causes extremely slow reads * and incorrect probing of hybrid audio/data media */ if (fstyp_init(rfd, probe_offset, NULL, &fstyp_handle) != 0) { HAL_DEBUG (("fstyp_init failed")); goto out; } if ((fstyp_ident(fstyp_handle, NULL, &fstype) != 0) || (fstyp_get_attr(fstyp_handle, &fsattr) != 0)) { HAL_DEBUG (("fstyp ident or get_attr failed")); fstyp_fini(fstyp_handle); goto out; } set_fstyp_properties (ctx, udi, fstype, fsattr); if (strcmp (fstype, "hsfs") == 0) { hsfs_contents (fd, probe_offset, ctx, udi); } fstyp_fini(fstyp_handle); skip_fs: ret = 0; out: if (fd >= 0) close (fd); if (rfd >= 0) close (rfd); if (ctx != NULL) { my_dbus_error_free (&error); libhal_ctx_shutdown (ctx, &error); libhal_ctx_free (ctx); } return ret; }
static int get_start_sector(ig_device_t *device) { uint32_t secnum = 0, numsec = 0; int i, pno, rval, log_part = 0; struct mboot *mboot; struct ipart *part; ext_part_t *epp; struct part_info dkpi; struct extpart_info edkpi; if (is_efi(device->type)) { struct dk_gpt *vtoc; if (efi_alloc_and_read(device->disk_fd, &vtoc) < 0) return (BC_ERROR); device->start_sector = vtoc->efi_parts[device->slice].p_start; /* GPT doesn't use traditional slice letters */ device->slice = 0xff; device->partition = 0; efi_free(vtoc); goto found_part; } mboot = (struct mboot *)device->boot_sector; if (is_bootpar(device->type)) { if (find_x86_bootpar(mboot, &pno, &secnum) != BC_SUCCESS) { (void) fprintf(stderr, NOBOOTPAR); return (BC_ERROR); } else { device->start_sector = secnum; device->partition = pno; goto found_part; } } /* * Search for Solaris fdisk partition * Get the solaris partition information from the device * and compare the offset of S2 with offset of solaris partition * from fdisk partition table. */ if (ioctl(device->part_fd, DKIOCEXTPARTINFO, &edkpi) < 0) { if (ioctl(device->part_fd, DKIOCPARTINFO, &dkpi) < 0) { (void) fprintf(stderr, PART_FAIL); return (BC_ERROR); } else { edkpi.p_start = dkpi.p_start; } } for (i = 0; i < FD_NUMPART; i++) { part = (struct ipart *)mboot->parts + i; if (part->relsect == 0) { (void) fprintf(stderr, BAD_PART, i); return (BC_ERROR); } if (edkpi.p_start >= part->relsect && edkpi.p_start < (part->relsect + part->numsect)) { /* Found the partition */ break; } } if (i == FD_NUMPART) { /* No solaris fdisk partitions (primary or logical) */ (void) fprintf(stderr, NOSOLPAR); return (BC_ERROR); } /* * We have found a Solaris fdisk partition (primary or extended) * Handle the simple case first: Solaris in a primary partition */ if (!fdisk_is_dos_extended(part->systid)) { device->start_sector = part->relsect; device->partition = i; goto found_part; } /* * Solaris in a logical partition. Find that partition in the * extended part. */ if ((rval = libfdisk_init(&epp, device->path_p0, NULL, FDISK_READ_DISK)) != FDISK_SUCCESS) { switch (rval) { /* * The first 3 cases are not an error per-se, just that * there is no Solaris logical partition */ case FDISK_EBADLOGDRIVE: case FDISK_ENOLOGDRIVE: case FDISK_EBADMAGIC: (void) fprintf(stderr, NOSOLPAR); return (BC_ERROR); case FDISK_ENOVGEOM: (void) fprintf(stderr, NO_VIRT_GEOM); return (BC_ERROR); case FDISK_ENOPGEOM: (void) fprintf(stderr, NO_PHYS_GEOM); return (BC_ERROR); case FDISK_ENOLGEOM: (void) fprintf(stderr, NO_LABEL_GEOM); return (BC_ERROR); default: (void) fprintf(stderr, LIBFDISK_INIT_FAIL); return (BC_ERROR); } } rval = fdisk_get_solaris_part(epp, &pno, &secnum, &numsec); libfdisk_fini(&epp); if (rval != FDISK_SUCCESS) { /* No solaris logical partition */ (void) fprintf(stderr, NOSOLPAR); return (BC_ERROR); } device->start_sector = secnum; device->partition = pno - 1; log_part = 1; found_part: /* get confirmation for -m */ if (write_mbr && !force_mbr) { (void) fprintf(stdout, MBOOT_PROMPT); if (!yes()) { write_mbr = 0; (void) fprintf(stdout, MBOOT_NOT_UPDATED); return (BC_ERROR); } } /* * Currently if Solaris is in an extended partition we need to * write GRUB to the MBR. Check for this. */ if (log_part && !write_mbr) { (void) fprintf(stdout, gettext("Installing Solaris on an " "extended partition... forcing MBR update\n")); write_mbr = 1; } /* * warn, if Solaris in primary partition and GRUB not in MBR and * partition is not active */ if (!log_part && part->bootid != 128 && !write_mbr) { (void) fprintf(stdout, SOLPAR_INACTIVE, device->partition + 1); } return (BC_SUCCESS); }
/* * open the device and fill the various members of ig_device_t. */ static int init_device(ig_device_t *device, char *path) { struct dk_gpt *vtoc; fstyp_handle_t fhdl; const char *fident; bzero(device, sizeof (*device)); device->part_fd = -1; device->disk_fd = -1; device->path_p0 = NULL; device->path = strdup(path); if (device->path == NULL) { perror(gettext("Memory allocation failed")); return (BC_ERROR); } if (strstr(device->path, "diskette")) { (void) fprintf(stderr, gettext("installing GRUB to a floppy " "disk is no longer supported\n")); return (BC_ERROR); } /* Detect if the target device is a pcfs partition. */ if (strstr(device->path, "p0:boot")) device->type = IG_DEV_X86BOOTPAR; if (get_disk_fd(device) != BC_SUCCESS) return (BC_ERROR); /* read in the device boot sector. */ if (read(device->disk_fd, device->boot_sector, SECTOR_SIZE) != SECTOR_SIZE) { (void) fprintf(stderr, gettext("Error reading boot sector\n")); perror("read"); return (BC_ERROR); } if (efi_alloc_and_read(device->disk_fd, &vtoc) >= 0) { device->type = IG_DEV_EFI; efi_free(vtoc); } if (get_raw_partition_fd(device) != BC_SUCCESS) return (BC_ERROR); if (is_efi(device->type)) { if (fstyp_init(device->part_fd, 0, NULL, &fhdl) != 0) return (BC_ERROR); if (fstyp_ident(fhdl, "zfs", &fident) != 0) { fstyp_fini(fhdl); (void) fprintf(stderr, gettext("Booting of EFI labeled " "disks is only supported with ZFS\n")); return (BC_ERROR); } fstyp_fini(fhdl); } if (get_start_sector(device) != BC_SUCCESS) return (BC_ERROR); return (BC_SUCCESS); }
/* * Just look for the name on the devpaths we have cached. Return 1 if we * find the name and the size of that slice is non-zero. */ static int match_fixed_name(disk_t *diskp, char *name, int *errp) { slice_t *dp = NULL; alias_t *ap; int slice_num; int fd; int status; int data_format = FMT_UNKNOWN; struct extvtoc vtoc; struct dk_gpt *efip; ap = diskp->aliases; while (ap != NULL) { slice_t *devp; devp = ap->devpaths; while (devp != NULL) { char path[MAXPATHLEN]; slice_rdsk2dsk(devp->devpath, path, sizeof (path)); if (libdiskmgt_str_eq(path, name)) { /* found it */ dp = devp; break; } devp = devp->next; } if (dp != NULL) { break; } ap = ap->next; } if (dp == NULL) { *errp = 0; return (0); } /* * If we found a match on the name we now have to check that this * slice really exists (non-0 size). */ slice_num = get_slice_num(dp); /* can't get slicenum, so no slice */ if (slice_num == -1) { *errp = ENODEV; return (1); } if ((fd = drive_open_disk(diskp, NULL, 0)) < 0) { *errp = ENODEV; return (1); } if ((status = read_extvtoc(fd, &vtoc)) >= 0) { data_format = FMT_VTOC; } else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) { data_format = FMT_EFI; } else { (void) close(fd); *errp = ENODEV; return (1); } (void) close(fd); if (data_format == FMT_VTOC) { if (slice_num < vtoc.v_nparts && vtoc.v_part[slice_num].p_size > 0) { *errp = 0; return (1); } } else { /* data_format == FMT_EFI */ if (slice_num < efip->efi_nparts && efip->efi_parts[slice_num].p_size > 0) { efi_free(efip); *errp = 0; return (1); } efi_free(efip); } *errp = ENODEV; return (1); }
static int make_fixed_descriptors(disk_t *dp) { int error = 0; alias_t *ap; slice_t *devp; char mname[MAXPATHLEN]; int data_format = FMT_UNKNOWN; struct extvtoc vtoc; struct dk_gpt *efip; /* Just check the first drive name. */ if ((ap = dp->aliases) == NULL) { return (0); } mname[0] = 0; (void) media_read_name(dp, mname, sizeof (mname)); for (devp = ap->devpaths; devp != NULL; devp = devp->next) { int slice_num; char devpath[MAXPATHLEN]; slice_num = get_slice_num(devp); /* can't get slicenum, so no need to keep trying the drive */ if (slice_num == -1) { break; } if (data_format == FMT_UNKNOWN) { int fd; int status; if ((fd = drive_open_disk(dp, NULL, 0)) >= 0) { if ((status = read_extvtoc(fd, &vtoc)) >= 0) { data_format = FMT_VTOC; } else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) { data_format = FMT_EFI; } (void) close(fd); } } /* can't get slice data, so no need to keep trying the drive */ if (data_format == FMT_UNKNOWN) { break; } if (data_format == FMT_VTOC) { if (slice_num >= vtoc.v_nparts || vtoc.v_part[slice_num].p_size == 0) { continue; } } else { /* data_format == FMT_EFI */ if (slice_num >= efip->efi_nparts || efip->efi_parts[slice_num].p_size == 0) { continue; } } slice_rdsk2dsk(devp->devpath, devpath, sizeof (devpath)); cache_load_desc(DM_SLICE, dp, devpath, mname, &error); if (error != 0) { break; } } if (data_format == FMT_EFI) { efi_free(efip); } return (error); }
static int get_attrs(descriptor_t *dp, int fd, nvlist_t *attrs) { struct dk_minfo minfo; int status; int data_format = FMT_UNKNOWN; int snum = -1; int error; struct extvtoc vtoc; struct dk_gpt *efip; struct dk_cinfo dkinfo; int cooked_fd; struct stat buf; if (fd < 0) { return (ENODEV); } /* First make sure media is inserted and spun up. */ if (!media_read_info(fd, &minfo)) { return (ENODEV); } if ((status = read_extvtoc(fd, &vtoc)) >= 0) { data_format = FMT_VTOC; } else if (status == VT_ENOTSUP && efi_alloc_and_read(fd, &efip) >= 0) { data_format = FMT_EFI; if (nvlist_add_boolean(attrs, DM_EFI) != 0) { efi_free(efip); return (ENOMEM); } } if (data_format == FMT_UNKNOWN) { return (ENODEV); } if (ioctl(fd, DKIOCINFO, &dkinfo) >= 0) { snum = dkinfo.dki_partition; } /* check the slice */ if (data_format == FMT_VTOC) { if (snum < 0 || snum >= vtoc.v_nparts || vtoc.v_part[snum].p_size == 0) { return (ENODEV); } } else { /* data_format == FMT_EFI */ if (snum < 0 || snum >= efip->efi_nparts || efip->efi_parts[snum].p_size == 0) { efi_free(efip); return (ENODEV); } } /* the slice exists */ if (nvlist_add_uint32(attrs, DM_INDEX, snum) != 0) { if (data_format == FMT_EFI) { efi_free(efip); } return (ENOMEM); } if (data_format == FMT_VTOC) { if (nvlist_add_uint64(attrs, DM_START, vtoc.v_part[snum].p_start) != 0) { return (ENOMEM); } if (nvlist_add_uint64(attrs, DM_SIZE, vtoc.v_part[snum].p_size) != 0) { return (ENOMEM); } if (nvlist_add_uint32(attrs, DM_TAG, vtoc.v_part[snum].p_tag) != 0) { return (ENOMEM); } if (nvlist_add_uint32(attrs, DM_FLAG, vtoc.v_part[snum].p_flag) != 0) { return (ENOMEM); } } else { /* data_format == FMT_EFI */ if (nvlist_add_uint64(attrs, DM_START, efip->efi_parts[snum].p_start) != 0) { efi_free(efip); return (ENOMEM); } if (nvlist_add_uint64(attrs, DM_SIZE, efip->efi_parts[snum].p_size) != 0) { efi_free(efip); return (ENOMEM); } if (efip->efi_parts[snum].p_name[0] != 0) { char label[EFI_PART_NAME_LEN + 1]; (void) snprintf(label, sizeof (label), "%.*s", EFI_PART_NAME_LEN, efip->efi_parts[snum].p_name); if (nvlist_add_string(attrs, DM_EFI_NAME, label) != 0) { efi_free(efip); return (ENOMEM); } } } if (data_format == FMT_EFI) { efi_free(efip); } if (inuse_mnt(dp->name, attrs, &error)) { if (error != 0) return (error); } if (fstat(fd, &buf) != -1) { if (nvlist_add_uint64(attrs, DM_DEVT, buf.st_rdev) != 0) { return (ENOMEM); } } /* * We need to open the cooked slice (not the raw one) to get the * correct devid. */ cooked_fd = open(dp->name, O_RDONLY|O_NDELAY); if (cooked_fd >= 0) { int no_mem = 0; ddi_devid_t devid; if (devid_get(cooked_fd, &devid) == 0) { char *minor; if (devid_get_minor_name(cooked_fd, &minor) == 0) { char *devidstr; if ((devidstr = devid_str_encode(devid, minor)) != 0) { if (nvlist_add_string(attrs, DM_DEVICEID, devidstr) != 0) { no_mem = 1; } devid_str_free(devidstr); } devid_str_free(minor); } devid_free(devid); } (void) close(cooked_fd); if (no_mem) { return (ENOMEM); } } return (0); }
static int get_attrs(disk_t *dp, int fd, nvlist_t *attrs) { struct dk_minfo minfo; struct dk_geom geometry; if (fd < 0) { return (ENODEV); } bzero(&minfo, sizeof (struct dk_minfo)); /* The first thing to do is read the media */ if (!media_read_info(fd, &minfo)) { return (ENODEV); } if (partition_has_fdisk(dp, fd)) { if (nvlist_add_boolean(attrs, DM_FDISK) != 0) { return (ENOMEM); } } if (dp->removable) { if (nvlist_add_boolean(attrs, DM_REMOVABLE) != 0) { return (ENOMEM); } if (nvlist_add_boolean(attrs, DM_LOADED) != 0) { return (ENOMEM); } } if (nvlist_add_uint64(attrs, DM_SIZE, minfo.dki_capacity) != 0) { return (ENOMEM); } if (nvlist_add_uint32(attrs, DM_BLOCKSIZE, minfo.dki_lbsize) != 0) { return (ENOMEM); } if (nvlist_add_uint32(attrs, DM_MTYPE, get_media_type(minfo.dki_media_type)) != 0) { return (ENOMEM); } /* only for disks < 1TB and x86 */ #if defined(i386) || defined(__amd64) if (ioctl(fd, DKIOCG_PHYGEOM, &geometry) >= 0) { #else /* sparc call */ if (ioctl(fd, DKIOCGGEOM, &geometry) >= 0) { #endif struct extvtoc vtoc; if (nvlist_add_uint64(attrs, DM_START, 0) != 0) { return (ENOMEM); } if (nvlist_add_uint64(attrs, DM_NACCESSIBLE, geometry.dkg_ncyl * geometry.dkg_nhead * geometry.dkg_nsect) != 0) { return (ENOMEM); } if (nvlist_add_uint32(attrs, DM_NCYLINDERS, geometry.dkg_ncyl) != 0) { return (ENOMEM); } if (nvlist_add_uint32(attrs, DM_NPHYSCYLINDERS, geometry.dkg_pcyl) != 0) { return (ENOMEM); } if (nvlist_add_uint32(attrs, DM_NALTCYLINDERS, geometry.dkg_acyl) != 0) { return (ENOMEM); } if (nvlist_add_uint32(attrs, DM_NHEADS, geometry.dkg_nhead) != 0) { return (ENOMEM); } if (nvlist_add_uint32(attrs, DM_NSECTORS, geometry.dkg_nsect) != 0) { return (ENOMEM); } if (nvlist_add_uint32(attrs, DM_NACTUALCYLINDERS, geometry.dkg_ncyl) != 0) { return (ENOMEM); } if (read_extvtoc(fd, &vtoc) >= 0 && vtoc.v_volume[0] != 0) { char label[LEN_DKL_VVOL + 1]; (void) snprintf(label, sizeof (label), "%.*s", LEN_DKL_VVOL, vtoc.v_volume); if (nvlist_add_string(attrs, DM_LABEL, label) != 0) { return (ENOMEM); } } } else { /* check for disks > 1TB for accessible size */ struct dk_gpt *efip; if (efi_alloc_and_read(fd, &efip) >= 0) { diskaddr_t p8size = 0; if (nvlist_add_boolean(attrs, DM_EFI) != 0) { return (ENOMEM); } if (nvlist_add_uint64(attrs, DM_START, efip->efi_first_u_lba) != 0) { return (ENOMEM); } /* partition 8 is reserved on EFI labels */ if (efip->efi_nparts >= 9) { p8size = efip->efi_parts[8].p_size; } if (nvlist_add_uint64(attrs, DM_NACCESSIBLE, (efip->efi_last_u_lba - p8size) - efip->efi_first_u_lba) != 0) { efi_free(efip); return (ENOMEM); } efi_free(efip); } } return (0); } static int get_media_type(uint_t media_type) { switch (media_type) { case DK_UNKNOWN: return (DM_MT_UNKNOWN); case DK_MO_ERASABLE: return (DM_MT_MO_ERASABLE); case DK_MO_WRITEONCE: return (DM_MT_MO_WRITEONCE); case DK_AS_MO: return (DM_MT_AS_MO); case DK_CDROM: return (DM_MT_CDROM); case DK_CDR: return (DM_MT_CDR); case DK_CDRW: return (DM_MT_CDRW); case DK_DVDROM: return (DM_MT_DVDROM); case DK_DVDR: return (DM_MT_DVDR); case DK_DVDRAM: return (DM_MT_DVDRAM); case DK_FIXED_DISK: return (DM_MT_FIXED); case DK_FLOPPY: return (DM_MT_FLOPPY); case DK_ZIP: return (DM_MT_ZIP); case DK_JAZ: return (DM_MT_JAZ); default: return (DM_MT_UNKNOWN); } } /* * This function handles removable media. */ static int get_rmm_name(disk_t *dp, char *mname, int size) { int loaded; int fd; loaded = 0; if ((fd = drive_open_disk(dp, NULL, 0)) >= 0) { struct dk_minfo minfo; if ((loaded = media_read_info(fd, &minfo))) { struct extvtoc vtoc; if (read_extvtoc(fd, &vtoc) >= 0) { if (vtoc.v_volume[0] != NULL) { if (LEN_DKL_VVOL < size) { (void) strlcpy(mname, vtoc.v_volume, LEN_DKL_VVOL); } else { (void) strlcpy(mname, vtoc.v_volume, size); } } } } (void) close(fd); } return (loaded); }