118c2aff7Sartem /*************************************************************************** 218c2aff7Sartem * 318c2aff7Sartem * probe-volume.c : probe volumes 418c2aff7Sartem * 5*0ae7db0fSfei feng - Sun Microsystems - Beijing China * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 618c2aff7Sartem * 718c2aff7Sartem * Licensed under the Academic Free License version 2.1 818c2aff7Sartem * 918c2aff7Sartem **************************************************************************/ 1018c2aff7Sartem 1118c2aff7Sartem #ifdef HAVE_CONFIG_H 1218c2aff7Sartem # include <config.h> 1318c2aff7Sartem #endif 1418c2aff7Sartem 1518c2aff7Sartem #include <errno.h> 1618c2aff7Sartem #include <string.h> 1718c2aff7Sartem #include <stdlib.h> 1818c2aff7Sartem #include <stdio.h> 1918c2aff7Sartem #include <sys/ioctl.h> 2018c2aff7Sartem #include <sys/types.h> 2118c2aff7Sartem #include <sys/stat.h> 2218c2aff7Sartem #include <fcntl.h> 2318c2aff7Sartem #include <unistd.h> 2418c2aff7Sartem #include <ctype.h> 2518c2aff7Sartem #include <time.h> 2618c2aff7Sartem #include <sys/time.h> 2718c2aff7Sartem #include <sys/dkio.h> 2818c2aff7Sartem #include <sys/cdio.h> 2918c2aff7Sartem #include <sys/fdio.h> 3018c2aff7Sartem #include <libnvpair.h> 3118c2aff7Sartem #include <libfstyp.h> 3218c2aff7Sartem #include <sys/vtoc.h> 3318c2aff7Sartem #include <sys/efi_partition.h> 347544909dSartem #include <sys/fs/hsfs_spec.h> 357544909dSartem #include <sys/fs/hsfs_isospec.h> 3618c2aff7Sartem #include <priv.h> 37de7d23d8SLin Guo - Sun Microsystems #include <sys/u8_textprep.h> 3818c2aff7Sartem 3918c2aff7Sartem #include <libhal.h> 4018c2aff7Sartem #include <cdutils.h> 4118c2aff7Sartem #include <fsutils.h> 4218c2aff7Sartem #include <logger.h> 4318c2aff7Sartem 4418c2aff7Sartem static void 4518c2aff7Sartem my_dbus_error_free(DBusError *error) 4618c2aff7Sartem { 4718c2aff7Sartem if (dbus_error_is_set(error)) { 4818c2aff7Sartem dbus_error_free(error); 4918c2aff7Sartem } 5018c2aff7Sartem } 5118c2aff7Sartem 5218c2aff7Sartem /* 5318c2aff7Sartem * Return a copy of a string without trailing spaces. If 'len' is non-zero, 5418c2aff7Sartem * it specifies max length, otherwise the string must be null-terminated. 5518c2aff7Sartem */ 5618c2aff7Sartem static char * 5718c2aff7Sartem rtrim_copy(char *src, int len) 5818c2aff7Sartem { 5918c2aff7Sartem char *dst, *p; 6018c2aff7Sartem 6118c2aff7Sartem if (len == 0) { 6218c2aff7Sartem len = strlen(src); 6318c2aff7Sartem } 6418c2aff7Sartem if ((dst = calloc(1, len + 1)) != NULL) { 6518c2aff7Sartem strncpy(dst, src, len); 6618c2aff7Sartem p = dst + len - 1; 6718c2aff7Sartem while ((p >= dst) && (isspace(*p))) { 6818c2aff7Sartem *p-- = '\0'; 6918c2aff7Sartem } 7018c2aff7Sartem } 7118c2aff7Sartem return (dst); 7218c2aff7Sartem } 7318c2aff7Sartem 7418c2aff7Sartem static void 7518c2aff7Sartem set_fstyp_properties (LibHalContext *ctx, const char *udi, const char *fstype, nvlist_t *fsattr) 7618c2aff7Sartem { 7718c2aff7Sartem char buf[256]; 7818c2aff7Sartem DBusError error; 7918c2aff7Sartem char *uuid = NULL; 8018c2aff7Sartem char *label_orig = NULL; 8118c2aff7Sartem char *label = NULL; 82de7d23d8SLin Guo - Sun Microsystems int err; 8318c2aff7Sartem LibHalChangeSet *cs; 8418c2aff7Sartem 8518c2aff7Sartem dbus_error_init (&error); 8618c2aff7Sartem 8718c2aff7Sartem if ((cs = libhal_device_new_changeset (udi)) == NULL) { 8818c2aff7Sartem return; 8918c2aff7Sartem } 9018c2aff7Sartem 9118c2aff7Sartem libhal_changeset_set_property_string (cs, "volume.fsusage", "filesystem"); 9218c2aff7Sartem libhal_changeset_set_property_string (cs, "volume.fstype", fstype); 9318c2aff7Sartem 9418c2aff7Sartem /* label */ 9518c2aff7Sartem (void) nvlist_lookup_string(fsattr, "gen_volume_label", &label_orig); 9618c2aff7Sartem if (label_orig != NULL) { 9718c2aff7Sartem label = rtrim_copy(label_orig, 0); 9818c2aff7Sartem } 99de7d23d8SLin Guo - Sun Microsystems /* Check if label is utf8 format */ 100de7d23d8SLin Guo - Sun Microsystems if ((label != NULL) && (label[0] != '\0') && 101de7d23d8SLin Guo - Sun Microsystems (u8_validate(label, strlen(label), (char **)NULL, 102de7d23d8SLin Guo - Sun Microsystems U8_VALIDATE_ENTIRE, &err) != -1)) { 10318c2aff7Sartem libhal_changeset_set_property_string (cs, "volume.label", label); 10418c2aff7Sartem libhal_changeset_set_property_string (cs, "info.product", label); 10518c2aff7Sartem } else { 10618c2aff7Sartem libhal_changeset_set_property_string (cs, "volume.label", ""); 10718c2aff7Sartem snprintf (buf, sizeof (buf), "Volume (%s)", fstype); 10818c2aff7Sartem libhal_changeset_set_property_string (cs, "info.product", buf); 10918c2aff7Sartem } 11018c2aff7Sartem free(label); 11118c2aff7Sartem 11218c2aff7Sartem /* uuid */ 11318c2aff7Sartem if (nvlist_lookup_string(fsattr, "gen_uuid", &uuid) == 0) { 11418c2aff7Sartem libhal_changeset_set_property_string (cs, "volume.uuid", uuid); 11518c2aff7Sartem } else { 11618c2aff7Sartem libhal_changeset_set_property_string (cs, "volume.uuid", ""); 11718c2aff7Sartem } 11818c2aff7Sartem 11918c2aff7Sartem libhal_device_commit_changeset (ctx, cs, &error); 12018c2aff7Sartem libhal_device_free_changeset (cs); 12118c2aff7Sartem 12218c2aff7Sartem my_dbus_error_free (&error); 12318c2aff7Sartem } 12418c2aff7Sartem 1257544909dSartem /* 1267544909dSartem * hsfs/iso9660 contents detection: Video DVD, Video CD, etc. 1277544909dSartem */ 1287544909dSartem static void 1297544909dSartem hsfs_contents(int fd, off_t probe_offset, LibHalContext *ctx, const char *udi) 1307544909dSartem { 1317544909dSartem size_t secsz = ISO_SECTOR_SIZE; 1327544909dSartem uchar_t buf[ISO_SECTOR_SIZE]; 1337544909dSartem int ptbl_lbn, ptbl_size; 1347544909dSartem int off, reloff, readoff; 1357544909dSartem uchar_t *p; 1367544909dSartem char *name; 1377544909dSartem int name_len; 1387544909dSartem int ipe_len; 1397544909dSartem DBusError error; 1407544909dSartem 1417544909dSartem /* 1427544909dSartem * find 1st Primary Volume Descriptor 1437544909dSartem */ 1447544909dSartem readoff = probe_offset + ISO_VOLDESC_SEC * secsz; 1457544909dSartem if (pread (fd, buf, secsz, readoff) != secsz) { 1467544909dSartem return; 1477544909dSartem } 1487544909dSartem while (ISO_DESC_TYPE (buf) != ISO_VD_PVD) { 1497544909dSartem if (ISO_DESC_TYPE (buf) == ISO_VD_EOV) { 1507544909dSartem return; 1517544909dSartem } 1527544909dSartem readoff += secsz; 1537544909dSartem if (pread (fd, buf, secsz, readoff) != secsz) { 1547544909dSartem return; 1557544909dSartem } 1567544909dSartem } 1577544909dSartem 1587544909dSartem /* 1597544909dSartem * PVD contains size and offset of the LSB/MSB path table 1607544909dSartem */ 1617544909dSartem ptbl_size = ISO_PTBL_SIZE (buf); 1627544909dSartem #if defined(_LITTLE_ENDIAN) 1637544909dSartem ptbl_lbn = ISO_PTBL_MAN_LS (buf); 1647544909dSartem #else 1657544909dSartem ptbl_lbn = ISO_PTBL_MAN_MS (buf); 1667544909dSartem #endif 1677544909dSartem 1687544909dSartem /* 1697544909dSartem * Look through path table entries 1707544909dSartem */ 1717544909dSartem readoff = probe_offset + ptbl_lbn * secsz; 1727544909dSartem if (pread (fd, buf, secsz, readoff) != secsz) { 1737544909dSartem return; 1747544909dSartem } 1757544909dSartem dbus_error_init (&error); 1767544909dSartem 1777544909dSartem for (off = reloff = 0; 1787544909dSartem off < ptbl_size; 1797544909dSartem off += ipe_len, reloff += ipe_len) { 1807544909dSartem 1817544909dSartem /* load sectors on demand */ 1827544909dSartem if (reloff >= secsz) { 1837544909dSartem readoff += secsz; 1847544909dSartem if (pread (fd, buf, secsz, readoff) != secsz) { 1857544909dSartem break; 1867544909dSartem } 1877544909dSartem reloff -= secsz; 1887544909dSartem } 1897544909dSartem 1907544909dSartem p = buf + reloff; 1917544909dSartem name_len = IPE_NAME_LEN(p); 1927544909dSartem ipe_len = IPE_FPESIZE + name_len + (name_len % 2); 1937544909dSartem 1947544909dSartem /* only interested in root directories */ 1957544909dSartem if (IPE_PARENT_NO (p) != 1) { 1967544909dSartem continue; 1977544909dSartem } 1987544909dSartem if ((name_len < 2) || (name_len > IDE_MAX_NAME_LEN)) { 1997544909dSartem continue; 2007544909dSartem } 2017544909dSartem 2027544909dSartem name = (char *)IPE_NAME (p); 2037544909dSartem if (strncasecmp (name, "VIDEO_TS", min (8, name_len)) == 0) { 2047544909dSartem libhal_device_set_property_bool (ctx, udi, 2057544909dSartem "volume.disc.is_videodvd", TRUE, &error); 2067544909dSartem } else if (strncasecmp (name, "VCD", min (3, name_len)) == 0) { 2077544909dSartem libhal_device_set_property_bool (ctx, udi, 2087544909dSartem "volume.disc.is_vcd", TRUE, &error); 2097544909dSartem } else if (strncasecmp (name, "SVCD", min (4, name_len)) == 0) { 2107544909dSartem libhal_device_set_property_bool (ctx, udi, 2117544909dSartem "volume.disc.is_svcd", TRUE, &error); 2127544909dSartem } 2137544909dSartem } 2147544909dSartem 2157544909dSartem my_dbus_error_free (&error); 2167544909dSartem } 2177544909dSartem 2187544909dSartem static dbus_bool_t 219b941d3fcSartem probe_disc (int fd, LibHalContext *ctx, const char *udi, dbus_bool_t *has_data, 220b941d3fcSartem dbus_bool_t *has_audio) 22118c2aff7Sartem { 22218c2aff7Sartem DBusError error; 22318c2aff7Sartem disc_info_t di; 22418c2aff7Sartem int profile; 225b941d3fcSartem dbus_bool_t is_blank, is_appendable, is_rewritable; 22618c2aff7Sartem char *disc_type = "cd_rom"; 22718c2aff7Sartem uint64_t capacity = 0; 22818c2aff7Sartem int i; 22918c2aff7Sartem LibHalChangeSet *cs; 23018c2aff7Sartem 23118c2aff7Sartem dbus_error_init (&error); 23218c2aff7Sartem 23318c2aff7Sartem if (get_disc_info (fd, &di)) { 23418c2aff7Sartem is_blank = (di.disc_status == 0); 23518c2aff7Sartem is_appendable = (di.disc_status == 1); 23618c2aff7Sartem is_rewritable = (di.erasable != 0); 23718c2aff7Sartem } else { 23818c2aff7Sartem is_blank = is_appendable = is_rewritable = FALSE; 23918c2aff7Sartem } 24018c2aff7Sartem 24118c2aff7Sartem if (get_current_profile (fd, &profile)) { 24218c2aff7Sartem switch (profile) { 24318c2aff7Sartem case 0x08: /* CD-ROM */ 24418c2aff7Sartem disc_type = "cd_rom"; 24518c2aff7Sartem break; 24618c2aff7Sartem case 0x09: /* CD-R */ 24718c2aff7Sartem disc_type = "cd_r"; 24818c2aff7Sartem break; 24918c2aff7Sartem case 0x0A: /* CD-RW */ 25018c2aff7Sartem disc_type = "cd_rw"; 25118c2aff7Sartem is_rewritable = TRUE; 25218c2aff7Sartem break; 25318c2aff7Sartem case 0x10: /* DVD-ROM */ 25418c2aff7Sartem disc_type = "dvd_rom"; 25518c2aff7Sartem break; 25618c2aff7Sartem case 0x11: /* DVD-R Sequential */ 25718c2aff7Sartem disc_type = "dvd_r"; 25818c2aff7Sartem break; 25918c2aff7Sartem case 0x12: /* DVD-RAM */ 26018c2aff7Sartem disc_type = "dvd_ram"; 26118c2aff7Sartem is_rewritable = TRUE; 26218c2aff7Sartem break; 26318c2aff7Sartem case 0x13: /* DVD-RW Restricted Overwrite */ 26418c2aff7Sartem disc_type = "dvd_rw"; 26518c2aff7Sartem is_rewritable = TRUE; 26618c2aff7Sartem break; 26718c2aff7Sartem case 0x14: /* DVD-RW Sequential */ 26818c2aff7Sartem disc_type = "dvd_rw"; 26918c2aff7Sartem is_rewritable = TRUE; 27018c2aff7Sartem break; 27118c2aff7Sartem case 0x1A: /* DVD+RW */ 27218c2aff7Sartem disc_type = "dvd_plus_rw"; 27318c2aff7Sartem is_rewritable = TRUE; 27418c2aff7Sartem break; 27518c2aff7Sartem case 0x1B: /* DVD+R */ 27618c2aff7Sartem disc_type = "dvd_plus_r"; 27718c2aff7Sartem break; 27818c2aff7Sartem case 0x2B: /* DVD+R Double Layer */ 27918c2aff7Sartem disc_type = "dvd_plus_r_dl"; 28018c2aff7Sartem break; 28118c2aff7Sartem case 0x40: /* BD-ROM */ 28218c2aff7Sartem disc_type = "bd_rom"; 28318c2aff7Sartem break; 28418c2aff7Sartem case 0x41: /* BD-R Sequential */ 28518c2aff7Sartem disc_type = "bd_r"; 28618c2aff7Sartem break; 28718c2aff7Sartem case 0x42: /* BD-R Random */ 28818c2aff7Sartem disc_type = "bd_r"; 28918c2aff7Sartem break; 29018c2aff7Sartem case 0x43: /* BD-RE */ 29118c2aff7Sartem disc_type = "bd_re"; 29218c2aff7Sartem is_rewritable = TRUE; 29318c2aff7Sartem break; 29418c2aff7Sartem case 0x50: /* HD DVD-ROM */ 29518c2aff7Sartem disc_type = "hddvd_rom"; 29618c2aff7Sartem break; 29718c2aff7Sartem case 0x51: /* HD DVD-R */ 29818c2aff7Sartem disc_type = "hddvd_r"; 29918c2aff7Sartem break; 30018c2aff7Sartem case 0x52: /* HD DVD-Rewritable */ 30118c2aff7Sartem disc_type = "hddvd_rw"; 30218c2aff7Sartem is_rewritable = TRUE; 30318c2aff7Sartem break; 30418c2aff7Sartem } 30518c2aff7Sartem 30618c2aff7Sartem (void) get_disc_capacity_for_profile(fd, profile, &capacity); 30718c2aff7Sartem } 30818c2aff7Sartem 309b941d3fcSartem *has_audio = *has_data = FALSE; 31018c2aff7Sartem if (!is_blank) { 31118c2aff7Sartem uchar_t smalltoc[12]; 31218c2aff7Sartem size_t toc_size; 31318c2aff7Sartem uchar_t *toc, *p; 31418c2aff7Sartem 31518c2aff7Sartem /* 31618c2aff7Sartem * XXX for some reason CDROMREADTOCENTRY fails on video DVDs, 317*0ae7db0fSfei feng - Sun Microsystems - Beijing China * but extracting the toc directly works okay. And the toc 318*0ae7db0fSfei feng - Sun Microsystems - Beijing China * data buffer length passed to read_toc() should be the same 319*0ae7db0fSfei feng - Sun Microsystems - Beijing China * as the real buffer size. 32018c2aff7Sartem */ 321*0ae7db0fSfei feng - Sun Microsystems - Beijing China if (!read_toc(fd, 0, 1, 12, smalltoc)) { 32218c2aff7Sartem HAL_DEBUG(("read_toc failed")); 323b941d3fcSartem *has_data = B_TRUE; /* probe for fs anyway */ 32418c2aff7Sartem } else { 32518c2aff7Sartem toc_size = smalltoc[0] * 256 + smalltoc[1] + 2; 32618c2aff7Sartem toc = (uchar_t *)calloc(1, toc_size); 32718c2aff7Sartem if (toc == NULL || !read_toc(fd, 0, 1, toc_size, toc)) { 32818c2aff7Sartem HAL_DEBUG (("read_toc again failed")); 32918c2aff7Sartem } else { 33018c2aff7Sartem for (p = &toc[4]; p < (toc + toc_size); p += 8) { 33118c2aff7Sartem /* skip leadout */ 33218c2aff7Sartem if (p[2] == 0xAA) { 33318c2aff7Sartem continue; 33418c2aff7Sartem } 33518c2aff7Sartem if (p[1] & 4) { 336b941d3fcSartem *has_data = B_TRUE; 33718c2aff7Sartem } else { 338b941d3fcSartem *has_audio = B_TRUE; 33918c2aff7Sartem } 34018c2aff7Sartem } 34118c2aff7Sartem } 34218c2aff7Sartem free(toc); 34318c2aff7Sartem } 34418c2aff7Sartem } 34518c2aff7Sartem 34618c2aff7Sartem if ((cs = libhal_device_new_changeset (udi)) == NULL) { 34718c2aff7Sartem return (FALSE); 34818c2aff7Sartem } 34918c2aff7Sartem libhal_changeset_set_property_string (cs, "volume.disc.type", disc_type); 35018c2aff7Sartem libhal_changeset_set_property_bool (cs, "volume.disc.is_blank", is_blank); 351b941d3fcSartem libhal_changeset_set_property_bool (cs, "volume.disc.has_audio", *has_audio); 352b941d3fcSartem libhal_changeset_set_property_bool (cs, "volume.disc.has_data", *has_data); 35318c2aff7Sartem libhal_changeset_set_property_bool (cs, "volume.disc.is_appendable", is_appendable); 35418c2aff7Sartem libhal_changeset_set_property_bool (cs, "volume.disc.is_rewritable", is_rewritable); 35518c2aff7Sartem libhal_changeset_set_property_uint64 (cs, "volume.disc.capacity", capacity); 35618c2aff7Sartem 3577544909dSartem libhal_changeset_set_property_bool (cs, "volume.disc.is_videodvd", FALSE); 3587544909dSartem libhal_changeset_set_property_bool (cs, "volume.disc.is_vcd", FALSE); 3597544909dSartem libhal_changeset_set_property_bool (cs, "volume.disc.is_svcd", FALSE); 3607544909dSartem 36118c2aff7Sartem libhal_device_commit_changeset (ctx, cs, &error); 36218c2aff7Sartem libhal_device_free_changeset (cs); 36318c2aff7Sartem 36418c2aff7Sartem out: 36518c2aff7Sartem my_dbus_error_free (&error); 36618c2aff7Sartem 36718c2aff7Sartem return (TRUE); 36818c2aff7Sartem } 36918c2aff7Sartem 3707544909dSartem static void 37118c2aff7Sartem drop_privileges () 37218c2aff7Sartem { 37318c2aff7Sartem priv_set_t *pPrivSet = NULL; 37418c2aff7Sartem priv_set_t *lPrivSet = NULL; 37518c2aff7Sartem 37618c2aff7Sartem /* 37718c2aff7Sartem * Start with the 'basic' privilege set and then remove any 37818c2aff7Sartem * of the 'basic' privileges that will not be needed. 37918c2aff7Sartem */ 38018c2aff7Sartem if ((pPrivSet = priv_str_to_set("basic", ",", NULL)) == NULL) { 38118c2aff7Sartem return; 38218c2aff7Sartem } 38318c2aff7Sartem 38418c2aff7Sartem /* Clear privileges we will not need from the 'basic' set */ 38518c2aff7Sartem (void) priv_delset(pPrivSet, PRIV_FILE_LINK_ANY); 38618c2aff7Sartem (void) priv_delset(pPrivSet, PRIV_PROC_INFO); 38718c2aff7Sartem (void) priv_delset(pPrivSet, PRIV_PROC_SESSION); 38818c2aff7Sartem (void) priv_delset(pPrivSet, PRIV_PROC_EXEC); 38918c2aff7Sartem (void) priv_delset(pPrivSet, PRIV_PROC_FORK); 39018c2aff7Sartem 39118c2aff7Sartem /* for uscsi */ 39218c2aff7Sartem (void) priv_addset(pPrivSet, PRIV_SYS_DEVICES); 39318c2aff7Sartem 39418c2aff7Sartem 39518c2aff7Sartem /* to open logindevperm'd devices */ 39618c2aff7Sartem (void) priv_addset(pPrivSet, PRIV_FILE_DAC_READ); 39718c2aff7Sartem 39818c2aff7Sartem /* Set the permitted privilege set. */ 39918c2aff7Sartem if (setppriv(PRIV_SET, PRIV_PERMITTED, pPrivSet) != 0) { 40018c2aff7Sartem return; 40118c2aff7Sartem } 40218c2aff7Sartem 40318c2aff7Sartem /* Clear the limit set. */ 40418c2aff7Sartem if ((lPrivSet = priv_allocset()) == NULL) { 40518c2aff7Sartem return; 40618c2aff7Sartem } 40718c2aff7Sartem 40818c2aff7Sartem priv_emptyset(lPrivSet); 40918c2aff7Sartem 41018c2aff7Sartem if (setppriv(PRIV_SET, PRIV_LIMIT, lPrivSet) != 0) { 41118c2aff7Sartem return; 41218c2aff7Sartem } 41318c2aff7Sartem 41418c2aff7Sartem priv_freeset(lPrivSet); 41518c2aff7Sartem } 41618c2aff7Sartem 41718c2aff7Sartem int 41818c2aff7Sartem main (int argc, char *argv[]) 41918c2aff7Sartem { 42018c2aff7Sartem int fd, rfd; 42118c2aff7Sartem int ret; 42218c2aff7Sartem char *udi; 42318c2aff7Sartem char *device_file, *raw_device_file; 42418c2aff7Sartem char *devpath, *rdevpath; 42518c2aff7Sartem boolean_t is_dos; 42618c2aff7Sartem int dos_num; 42718c2aff7Sartem LibHalContext *ctx = NULL; 42818c2aff7Sartem DBusError error; 42918c2aff7Sartem DBusConnection *conn; 43018c2aff7Sartem char *parent_udi; 43118c2aff7Sartem char *storage_device; 43218c2aff7Sartem char *is_disc_str; 43318c2aff7Sartem int fdc; 43418c2aff7Sartem dbus_bool_t is_disc = FALSE; 43518c2aff7Sartem dbus_bool_t is_floppy = FALSE; 43618c2aff7Sartem unsigned int block_size; 43718c2aff7Sartem dbus_uint64_t vol_size; 438b941d3fcSartem dbus_bool_t has_data = TRUE; /* probe for fs by default */ 439b941d3fcSartem dbus_bool_t has_audio = FALSE; 44018c2aff7Sartem char *partition_scheme = NULL; 44118c2aff7Sartem dbus_uint64_t partition_start = 0; 44289522cbbSartem int partition_number = 0; 443342440ecSPrasad Singamsetty struct extvtoc vtoc; 44418c2aff7Sartem dk_gpt_t *gpt; 44518c2aff7Sartem struct dk_minfo mi; 44618c2aff7Sartem int i, dos_cnt; 44718c2aff7Sartem fstyp_handle_t fstyp_handle; 44818c2aff7Sartem off_t probe_offset = 0; 44918c2aff7Sartem int num_volumes; 45018c2aff7Sartem char **volumes; 45118c2aff7Sartem dbus_uint64_t v_start; 45218c2aff7Sartem const char *fstype; 45318c2aff7Sartem nvlist_t *fsattr; 45418c2aff7Sartem 45518c2aff7Sartem fd = rfd = -1; 45618c2aff7Sartem 45718c2aff7Sartem ret = 1; 45818c2aff7Sartem 45918c2aff7Sartem if ((udi = getenv ("UDI")) == NULL) { 46018c2aff7Sartem goto out; 46118c2aff7Sartem } 46218c2aff7Sartem if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL) { 46318c2aff7Sartem goto out; 46418c2aff7Sartem } 46518c2aff7Sartem if ((raw_device_file = getenv ("HAL_PROP_BLOCK_SOLARIS_RAW_DEVICE")) == NULL) { 46618c2aff7Sartem goto out; 46718c2aff7Sartem } 468422ee277Sartem if (!dos_to_dev(raw_device_file, &rdevpath, &dos_num)) { 46918c2aff7Sartem rdevpath = raw_device_file; 47018c2aff7Sartem } 47118c2aff7Sartem if (!(is_dos = dos_to_dev(device_file, &devpath, &dos_num))) { 47218c2aff7Sartem devpath = device_file; 47318c2aff7Sartem } 47418c2aff7Sartem if ((parent_udi = getenv ("HAL_PROP_INFO_PARENT")) == NULL) { 47518c2aff7Sartem goto out; 47618c2aff7Sartem } 47718c2aff7Sartem if ((storage_device = getenv ("HAL_PROP_BLOCK_STORAGE_DEVICE")) == NULL) { 47818c2aff7Sartem goto out; 47918c2aff7Sartem } 48018c2aff7Sartem 48118c2aff7Sartem is_disc_str = getenv ("HAL_PROP_VOLUME_IS_DISC"); 48218c2aff7Sartem if (is_disc_str != NULL && strcmp (is_disc_str, "true") == 0) { 48318c2aff7Sartem is_disc = TRUE; 48418c2aff7Sartem } else { 48518c2aff7Sartem is_disc = FALSE; 48618c2aff7Sartem } 48718c2aff7Sartem 48818c2aff7Sartem drop_privileges (); 48918c2aff7Sartem 49018c2aff7Sartem setup_logger (); 49118c2aff7Sartem 49218c2aff7Sartem dbus_error_init (&error); 49318c2aff7Sartem if ((ctx = libhal_ctx_init_direct (&error)) == NULL) 49418c2aff7Sartem goto out; 49518c2aff7Sartem 49618c2aff7Sartem HAL_DEBUG (("Doing probe-volume for %s\n", device_file)); 49718c2aff7Sartem 49818c2aff7Sartem fd = open (devpath, O_RDONLY | O_NONBLOCK); 49918c2aff7Sartem if (fd < 0) { 50018c2aff7Sartem goto out; 50118c2aff7Sartem } 50218c2aff7Sartem rfd = open (rdevpath, O_RDONLY | O_NONBLOCK); 50318c2aff7Sartem if (rfd < 0) { 50418c2aff7Sartem goto out; 50518c2aff7Sartem } 50618c2aff7Sartem 50718c2aff7Sartem /* if it's a floppy with no media, bail out */ 50818c2aff7Sartem if (ioctl(rfd, FDGETCHANGE, &fdc) == 0) { 50918c2aff7Sartem is_floppy = TRUE; 51018c2aff7Sartem if (fdc & FDGC_CURRENT) { 51118c2aff7Sartem goto out; 51218c2aff7Sartem } 51318c2aff7Sartem } 51418c2aff7Sartem 51518c2aff7Sartem /* block size and total size */ 51618c2aff7Sartem if (ioctl(rfd, DKIOCGMEDIAINFO, &mi) != -1) { 51718c2aff7Sartem block_size = mi.dki_lbsize; 51818c2aff7Sartem vol_size = mi.dki_capacity * block_size; 519b96e88d7Sartem } else if (errno == ENXIO) { 520b96e88d7Sartem /* driver supports ioctl, but media is not available */ 521b96e88d7Sartem goto out; 52218c2aff7Sartem } else { 523b96e88d7Sartem /* driver does not support ioctl, e.g. lofi */ 52418c2aff7Sartem block_size = 512; 52518c2aff7Sartem vol_size = 0; 52618c2aff7Sartem } 52718c2aff7Sartem libhal_device_set_property_int (ctx, udi, "volume.block_size", block_size, &error); 52818c2aff7Sartem my_dbus_error_free (&error); 52918c2aff7Sartem libhal_device_set_property_uint64 (ctx, udi, "volume.size", vol_size, &error); 53018c2aff7Sartem my_dbus_error_free (&error); 53118c2aff7Sartem 53218c2aff7Sartem if (is_disc) { 533b941d3fcSartem if (!probe_disc (rfd, ctx, udi, &has_data, &has_audio)) { 53418c2aff7Sartem HAL_DEBUG (("probe_disc failed, skipping fstyp")); 53518c2aff7Sartem goto out; 53618c2aff7Sartem } 537b941d3fcSartem /* with audio present, create volume even if fs probing fails */ 538b941d3fcSartem if (has_audio) { 539b941d3fcSartem ret = 0; 540b941d3fcSartem } 54118c2aff7Sartem } 54218c2aff7Sartem 543b941d3fcSartem if (!has_data) { 54418c2aff7Sartem goto skip_fs; 54518c2aff7Sartem } 54618c2aff7Sartem 54718c2aff7Sartem /* don't support partitioned floppy */ 54818c2aff7Sartem if (is_floppy) { 54918c2aff7Sartem goto skip_part; 55018c2aff7Sartem } 55118c2aff7Sartem 55218c2aff7Sartem /* 55318c2aff7Sartem * first get partitioning info 55418c2aff7Sartem */ 55518c2aff7Sartem if (is_dos) { 55618c2aff7Sartem /* for a dos drive find partition offset */ 557422ee277Sartem if (!find_dos_drive(fd, dos_num, block_size, &probe_offset)) { 55818c2aff7Sartem goto out; 55918c2aff7Sartem } 56018c2aff7Sartem partition_scheme = "mbr"; 561422ee277Sartem partition_start = (dbus_uint64_t)probe_offset; 56218c2aff7Sartem partition_number = dos_num; 56318c2aff7Sartem } else { 564342440ecSPrasad Singamsetty if ((partition_number = read_extvtoc(rfd, &vtoc)) >= 0) { 56518c2aff7Sartem if (!vtoc_one_slice_entire_disk(&vtoc)) { 56618c2aff7Sartem partition_scheme = "smi"; 56718c2aff7Sartem if (partition_number < vtoc.v_nparts) { 56818c2aff7Sartem if (vtoc.v_part[partition_number].p_size == 0) { 56918c2aff7Sartem HAL_DEBUG (("zero size partition")); 57018c2aff7Sartem } 57118c2aff7Sartem partition_start = vtoc.v_part[partition_number].p_start * block_size; 57218c2aff7Sartem } 57318c2aff7Sartem } 57418c2aff7Sartem } else if ((partition_number = efi_alloc_and_read(rfd, &gpt)) >= 0) { 57518c2aff7Sartem partition_scheme = "gpt"; 57618c2aff7Sartem if (partition_number < gpt->efi_nparts) { 57718c2aff7Sartem if (gpt->efi_parts[partition_number].p_size == 0) { 57818c2aff7Sartem HAL_DEBUG (("zero size partition")); 57918c2aff7Sartem } 58018c2aff7Sartem partition_start = gpt->efi_parts[partition_number].p_start * block_size; 58118c2aff7Sartem } 58218c2aff7Sartem efi_free(gpt); 58318c2aff7Sartem } 58418c2aff7Sartem probe_offset = 0; 58518c2aff7Sartem } 58618c2aff7Sartem 58718c2aff7Sartem if (partition_scheme != NULL) { 58818c2aff7Sartem libhal_device_set_property_string (ctx, udi, "volume.partition.scheme", partition_scheme, &error); 58918c2aff7Sartem my_dbus_error_free (&error); 59018c2aff7Sartem libhal_device_set_property_int (ctx, udi, "volume.partition.number", partition_number, &error); 59118c2aff7Sartem my_dbus_error_free (&error); 59218c2aff7Sartem libhal_device_set_property_uint64 (ctx, udi, "volume.partition.start", partition_start, &error); 59318c2aff7Sartem my_dbus_error_free (&error); 59418c2aff7Sartem libhal_device_set_property_bool (ctx, udi, "volume.is_partition", TRUE, &error); 59518c2aff7Sartem my_dbus_error_free (&error); 59618c2aff7Sartem } else { 59718c2aff7Sartem libhal_device_set_property_bool (ctx, udi, "volume.is_partition", FALSE, &error); 59818c2aff7Sartem my_dbus_error_free (&error); 59918c2aff7Sartem } 60018c2aff7Sartem 60118c2aff7Sartem /* 60218c2aff7Sartem * ignore duplicate partitions 60318c2aff7Sartem */ 60418c2aff7Sartem if ((volumes = libhal_manager_find_device_string_match ( 60518c2aff7Sartem ctx, "block.storage_device", storage_device, &num_volumes, &error)) != NULL) { 60618c2aff7Sartem my_dbus_error_free (&error); 60718c2aff7Sartem for (i = 0; i < num_volumes; i++) { 60818c2aff7Sartem if (strcmp (udi, volumes[i]) == 0) { 60918c2aff7Sartem continue; /* skip self */ 61018c2aff7Sartem } 61118c2aff7Sartem v_start = libhal_device_get_property_uint64 (ctx, volumes[i], "volume.partition.start", &error); 61218c2aff7Sartem if (dbus_error_is_set(&error)) { 61318c2aff7Sartem dbus_error_free(&error); 61418c2aff7Sartem continue; 61518c2aff7Sartem } 61618c2aff7Sartem if (v_start == partition_start) { 61718c2aff7Sartem HAL_DEBUG (("duplicate partition")); 61818c2aff7Sartem goto out; 61918c2aff7Sartem } 62018c2aff7Sartem } 62118c2aff7Sartem libhal_free_string_array (volumes); 62218c2aff7Sartem } 62318c2aff7Sartem 62418c2aff7Sartem skip_part: 62518c2aff7Sartem 62618c2aff7Sartem /* 62718c2aff7Sartem * now determine fs type 628b941d3fcSartem * 629b941d3fcSartem * XXX We could get better performance from block device, 630b941d3fcSartem * but for now we use raw device because: 631b941d3fcSartem * 632b941d3fcSartem * - fstyp_udfs has a bug that it only works on raw 633b941d3fcSartem * 634b941d3fcSartem * - sd has a bug that causes extremely slow reads 635b941d3fcSartem * and incorrect probing of hybrid audio/data media 63618c2aff7Sartem */ 637b941d3fcSartem if (fstyp_init(rfd, probe_offset, NULL, &fstyp_handle) != 0) { 63818c2aff7Sartem HAL_DEBUG (("fstyp_init failed")); 63918c2aff7Sartem goto out; 64018c2aff7Sartem } 64118c2aff7Sartem if ((fstyp_ident(fstyp_handle, NULL, &fstype) != 0) || 64218c2aff7Sartem (fstyp_get_attr(fstyp_handle, &fsattr) != 0)) { 64318c2aff7Sartem HAL_DEBUG (("fstyp ident or get_attr failed")); 64418c2aff7Sartem fstyp_fini(fstyp_handle); 64518c2aff7Sartem goto out; 64618c2aff7Sartem } 64718c2aff7Sartem set_fstyp_properties (ctx, udi, fstype, fsattr); 6487544909dSartem 6497544909dSartem if (strcmp (fstype, "hsfs") == 0) { 6507544909dSartem hsfs_contents (fd, probe_offset, ctx, udi); 6517544909dSartem } 6527544909dSartem 65318c2aff7Sartem fstyp_fini(fstyp_handle); 65418c2aff7Sartem 65518c2aff7Sartem skip_fs: 65618c2aff7Sartem 65718c2aff7Sartem ret = 0; 65818c2aff7Sartem 65918c2aff7Sartem out: 66018c2aff7Sartem if (fd >= 0) 66118c2aff7Sartem close (fd); 66218c2aff7Sartem if (rfd >= 0) 66318c2aff7Sartem close (rfd); 66418c2aff7Sartem 66518c2aff7Sartem if (ctx != NULL) { 66618c2aff7Sartem my_dbus_error_free (&error); 66718c2aff7Sartem libhal_ctx_shutdown (ctx, &error); 66818c2aff7Sartem libhal_ctx_free (ctx); 66918c2aff7Sartem } 67018c2aff7Sartem 67118c2aff7Sartem return ret; 67218c2aff7Sartem 67318c2aff7Sartem } 674