118c2aff7Sartem /***************************************************************************
218c2aff7Sartem *
318c2aff7Sartem * probe-volume.c : probe volumes
418c2aff7Sartem *
50ae7db0fSfei 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
my_dbus_error_free(DBusError * error)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 *
rtrim_copy(char * src,int len)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
set_fstyp_properties(LibHalContext * ctx,const char * udi,const char * fstype,nvlist_t * fsattr)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)) {
103de7d23d8SLin Guo - Sun Microsystems libhal_changeset_set_property_string (cs, "volume.label", label);
104de7d23d8SLin Guo - Sun Microsystems 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
hsfs_contents(int fd,off_t probe_offset,LibHalContext * ctx,const char * udi)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
probe_disc(int fd,LibHalContext * ctx,const char * udi,dbus_bool_t * has_data,dbus_bool_t * has_audio)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,
3170ae7db0fSfei feng - Sun Microsystems - Beijing China * but extracting the toc directly works okay. And the toc
3180ae7db0fSfei feng - Sun Microsystems - Beijing China * data buffer length passed to read_toc() should be the same
3190ae7db0fSfei feng - Sun Microsystems - Beijing China * as the real buffer size.
32018c2aff7Sartem */
3210ae7db0fSfei 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
drop_privileges()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
417*55fea89dSDan Cross int
main(int argc,char * argv[])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);
645b941d3fcSartem 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