12912Sartem /***************************************************************************
22912Sartem *
32912Sartem * probe-volume.c : probe volumes
42912Sartem *
5*12528SFei.Feng@Sun.COM * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
62912Sartem *
72912Sartem * Licensed under the Academic Free License version 2.1
82912Sartem *
92912Sartem **************************************************************************/
102912Sartem
112912Sartem #ifdef HAVE_CONFIG_H
122912Sartem # include <config.h>
132912Sartem #endif
142912Sartem
152912Sartem #include <errno.h>
162912Sartem #include <string.h>
172912Sartem #include <stdlib.h>
182912Sartem #include <stdio.h>
192912Sartem #include <sys/ioctl.h>
202912Sartem #include <sys/types.h>
212912Sartem #include <sys/stat.h>
222912Sartem #include <fcntl.h>
232912Sartem #include <unistd.h>
242912Sartem #include <ctype.h>
252912Sartem #include <time.h>
262912Sartem #include <sys/time.h>
272912Sartem #include <sys/dkio.h>
282912Sartem #include <sys/cdio.h>
292912Sartem #include <sys/fdio.h>
302912Sartem #include <libnvpair.h>
312912Sartem #include <libfstyp.h>
322912Sartem #include <sys/vtoc.h>
332912Sartem #include <sys/efi_partition.h>
343020Sartem #include <sys/fs/hsfs_spec.h>
353020Sartem #include <sys/fs/hsfs_isospec.h>
362912Sartem #include <priv.h>
379823SLin.Guo@Sun.COM #include <sys/u8_textprep.h>
382912Sartem
392912Sartem #include <libhal.h>
402912Sartem #include <cdutils.h>
412912Sartem #include <fsutils.h>
422912Sartem #include <logger.h>
432912Sartem
442912Sartem static void
my_dbus_error_free(DBusError * error)452912Sartem my_dbus_error_free(DBusError *error)
462912Sartem {
472912Sartem if (dbus_error_is_set(error)) {
482912Sartem dbus_error_free(error);
492912Sartem }
502912Sartem }
512912Sartem
522912Sartem /*
532912Sartem * Return a copy of a string without trailing spaces. If 'len' is non-zero,
542912Sartem * it specifies max length, otherwise the string must be null-terminated.
552912Sartem */
562912Sartem static char *
rtrim_copy(char * src,int len)572912Sartem rtrim_copy(char *src, int len)
582912Sartem {
592912Sartem char *dst, *p;
602912Sartem
612912Sartem if (len == 0) {
622912Sartem len = strlen(src);
632912Sartem }
642912Sartem if ((dst = calloc(1, len + 1)) != NULL) {
652912Sartem strncpy(dst, src, len);
662912Sartem p = dst + len - 1;
672912Sartem while ((p >= dst) && (isspace(*p))) {
682912Sartem *p-- = '\0';
692912Sartem }
702912Sartem }
712912Sartem return (dst);
722912Sartem }
732912Sartem
742912Sartem static void
set_fstyp_properties(LibHalContext * ctx,const char * udi,const char * fstype,nvlist_t * fsattr)752912Sartem set_fstyp_properties (LibHalContext *ctx, const char *udi, const char *fstype, nvlist_t *fsattr)
762912Sartem {
772912Sartem char buf[256];
782912Sartem DBusError error;
792912Sartem char *uuid = NULL;
802912Sartem char *label_orig = NULL;
812912Sartem char *label = NULL;
829823SLin.Guo@Sun.COM int err;
832912Sartem LibHalChangeSet *cs;
842912Sartem
852912Sartem dbus_error_init (&error);
862912Sartem
872912Sartem if ((cs = libhal_device_new_changeset (udi)) == NULL) {
882912Sartem return;
892912Sartem }
902912Sartem
912912Sartem libhal_changeset_set_property_string (cs, "volume.fsusage", "filesystem");
922912Sartem libhal_changeset_set_property_string (cs, "volume.fstype", fstype);
932912Sartem
942912Sartem /* label */
952912Sartem (void) nvlist_lookup_string(fsattr, "gen_volume_label", &label_orig);
962912Sartem if (label_orig != NULL) {
972912Sartem label = rtrim_copy(label_orig, 0);
982912Sartem }
999823SLin.Guo@Sun.COM /* Check if label is utf8 format */
1009823SLin.Guo@Sun.COM if ((label != NULL) && (label[0] != '\0') &&
1019823SLin.Guo@Sun.COM (u8_validate(label, strlen(label), (char **)NULL,
1029823SLin.Guo@Sun.COM U8_VALIDATE_ENTIRE, &err) != -1)) {
1039823SLin.Guo@Sun.COM libhal_changeset_set_property_string (cs, "volume.label", label);
1049823SLin.Guo@Sun.COM libhal_changeset_set_property_string (cs, "info.product", label);
1052912Sartem } else {
1062912Sartem libhal_changeset_set_property_string (cs, "volume.label", "");
1072912Sartem snprintf (buf, sizeof (buf), "Volume (%s)", fstype);
1082912Sartem libhal_changeset_set_property_string (cs, "info.product", buf);
1092912Sartem }
1102912Sartem free(label);
1112912Sartem
1122912Sartem /* uuid */
1132912Sartem if (nvlist_lookup_string(fsattr, "gen_uuid", &uuid) == 0) {
1142912Sartem libhal_changeset_set_property_string (cs, "volume.uuid", uuid);
1152912Sartem } else {
1162912Sartem libhal_changeset_set_property_string (cs, "volume.uuid", "");
1172912Sartem }
1182912Sartem
1192912Sartem libhal_device_commit_changeset (ctx, cs, &error);
1202912Sartem libhal_device_free_changeset (cs);
1212912Sartem
1222912Sartem my_dbus_error_free (&error);
1232912Sartem }
1242912Sartem
1253020Sartem /*
1263020Sartem * hsfs/iso9660 contents detection: Video DVD, Video CD, etc.
1273020Sartem */
1283020Sartem static void
hsfs_contents(int fd,off_t probe_offset,LibHalContext * ctx,const char * udi)1293020Sartem hsfs_contents(int fd, off_t probe_offset, LibHalContext *ctx, const char *udi)
1303020Sartem {
1313020Sartem size_t secsz = ISO_SECTOR_SIZE;
1323020Sartem uchar_t buf[ISO_SECTOR_SIZE];
1333020Sartem int ptbl_lbn, ptbl_size;
1343020Sartem int off, reloff, readoff;
1353020Sartem uchar_t *p;
1363020Sartem char *name;
1373020Sartem int name_len;
1383020Sartem int ipe_len;
1393020Sartem DBusError error;
1403020Sartem
1413020Sartem /*
1423020Sartem * find 1st Primary Volume Descriptor
1433020Sartem */
1443020Sartem readoff = probe_offset + ISO_VOLDESC_SEC * secsz;
1453020Sartem if (pread (fd, buf, secsz, readoff) != secsz) {
1463020Sartem return;
1473020Sartem }
1483020Sartem while (ISO_DESC_TYPE (buf) != ISO_VD_PVD) {
1493020Sartem if (ISO_DESC_TYPE (buf) == ISO_VD_EOV) {
1503020Sartem return;
1513020Sartem }
1523020Sartem readoff += secsz;
1533020Sartem if (pread (fd, buf, secsz, readoff) != secsz) {
1543020Sartem return;
1553020Sartem }
1563020Sartem }
1573020Sartem
1583020Sartem /*
1593020Sartem * PVD contains size and offset of the LSB/MSB path table
1603020Sartem */
1613020Sartem ptbl_size = ISO_PTBL_SIZE (buf);
1623020Sartem #if defined(_LITTLE_ENDIAN)
1633020Sartem ptbl_lbn = ISO_PTBL_MAN_LS (buf);
1643020Sartem #else
1653020Sartem ptbl_lbn = ISO_PTBL_MAN_MS (buf);
1663020Sartem #endif
1673020Sartem
1683020Sartem /*
1693020Sartem * Look through path table entries
1703020Sartem */
1713020Sartem readoff = probe_offset + ptbl_lbn * secsz;
1723020Sartem if (pread (fd, buf, secsz, readoff) != secsz) {
1733020Sartem return;
1743020Sartem }
1753020Sartem dbus_error_init (&error);
1763020Sartem
1773020Sartem for (off = reloff = 0;
1783020Sartem off < ptbl_size;
1793020Sartem off += ipe_len, reloff += ipe_len) {
1803020Sartem
1813020Sartem /* load sectors on demand */
1823020Sartem if (reloff >= secsz) {
1833020Sartem readoff += secsz;
1843020Sartem if (pread (fd, buf, secsz, readoff) != secsz) {
1853020Sartem break;
1863020Sartem }
1873020Sartem reloff -= secsz;
1883020Sartem }
1893020Sartem
1903020Sartem p = buf + reloff;
1913020Sartem name_len = IPE_NAME_LEN(p);
1923020Sartem ipe_len = IPE_FPESIZE + name_len + (name_len % 2);
1933020Sartem
1943020Sartem /* only interested in root directories */
1953020Sartem if (IPE_PARENT_NO (p) != 1) {
1963020Sartem continue;
1973020Sartem }
1983020Sartem if ((name_len < 2) || (name_len > IDE_MAX_NAME_LEN)) {
1993020Sartem continue;
2003020Sartem }
2013020Sartem
2023020Sartem name = (char *)IPE_NAME (p);
2033020Sartem if (strncasecmp (name, "VIDEO_TS", min (8, name_len)) == 0) {
2043020Sartem libhal_device_set_property_bool (ctx, udi,
2053020Sartem "volume.disc.is_videodvd", TRUE, &error);
2063020Sartem } else if (strncasecmp (name, "VCD", min (3, name_len)) == 0) {
2073020Sartem libhal_device_set_property_bool (ctx, udi,
2083020Sartem "volume.disc.is_vcd", TRUE, &error);
2093020Sartem } else if (strncasecmp (name, "SVCD", min (4, name_len)) == 0) {
2103020Sartem libhal_device_set_property_bool (ctx, udi,
2113020Sartem "volume.disc.is_svcd", TRUE, &error);
2123020Sartem }
2133020Sartem }
2143020Sartem
2153020Sartem my_dbus_error_free (&error);
2163020Sartem }
2173020Sartem
2183020Sartem static dbus_bool_t
probe_disc(int fd,LibHalContext * ctx,const char * udi,dbus_bool_t * has_data,dbus_bool_t * has_audio)2193502Sartem probe_disc (int fd, LibHalContext *ctx, const char *udi, dbus_bool_t *has_data,
2203502Sartem dbus_bool_t *has_audio)
2212912Sartem {
2222912Sartem DBusError error;
2232912Sartem disc_info_t di;
2242912Sartem int profile;
2253502Sartem dbus_bool_t is_blank, is_appendable, is_rewritable;
2262912Sartem char *disc_type = "cd_rom";
2272912Sartem uint64_t capacity = 0;
2282912Sartem int i;
2292912Sartem LibHalChangeSet *cs;
2302912Sartem
2312912Sartem dbus_error_init (&error);
2322912Sartem
2332912Sartem if (get_disc_info (fd, &di)) {
2342912Sartem is_blank = (di.disc_status == 0);
2352912Sartem is_appendable = (di.disc_status == 1);
2362912Sartem is_rewritable = (di.erasable != 0);
2372912Sartem } else {
2382912Sartem is_blank = is_appendable = is_rewritable = FALSE;
2392912Sartem }
2402912Sartem
2412912Sartem if (get_current_profile (fd, &profile)) {
2422912Sartem switch (profile) {
2432912Sartem case 0x08: /* CD-ROM */
2442912Sartem disc_type = "cd_rom";
2452912Sartem break;
2462912Sartem case 0x09: /* CD-R */
2472912Sartem disc_type = "cd_r";
2482912Sartem break;
2492912Sartem case 0x0A: /* CD-RW */
2502912Sartem disc_type = "cd_rw";
2512912Sartem is_rewritable = TRUE;
2522912Sartem break;
2532912Sartem case 0x10: /* DVD-ROM */
2542912Sartem disc_type = "dvd_rom";
2552912Sartem break;
2562912Sartem case 0x11: /* DVD-R Sequential */
2572912Sartem disc_type = "dvd_r";
2582912Sartem break;
2592912Sartem case 0x12: /* DVD-RAM */
2602912Sartem disc_type = "dvd_ram";
2612912Sartem is_rewritable = TRUE;
2622912Sartem break;
2632912Sartem case 0x13: /* DVD-RW Restricted Overwrite */
2642912Sartem disc_type = "dvd_rw";
2652912Sartem is_rewritable = TRUE;
2662912Sartem break;
2672912Sartem case 0x14: /* DVD-RW Sequential */
2682912Sartem disc_type = "dvd_rw";
2692912Sartem is_rewritable = TRUE;
2702912Sartem break;
2712912Sartem case 0x1A: /* DVD+RW */
2722912Sartem disc_type = "dvd_plus_rw";
2732912Sartem is_rewritable = TRUE;
2742912Sartem break;
2752912Sartem case 0x1B: /* DVD+R */
2762912Sartem disc_type = "dvd_plus_r";
2772912Sartem break;
2782912Sartem case 0x2B: /* DVD+R Double Layer */
2792912Sartem disc_type = "dvd_plus_r_dl";
2802912Sartem break;
2812912Sartem case 0x40: /* BD-ROM */
2822912Sartem disc_type = "bd_rom";
2832912Sartem break;
2842912Sartem case 0x41: /* BD-R Sequential */
2852912Sartem disc_type = "bd_r";
2862912Sartem break;
2872912Sartem case 0x42: /* BD-R Random */
2882912Sartem disc_type = "bd_r";
2892912Sartem break;
2902912Sartem case 0x43: /* BD-RE */
2912912Sartem disc_type = "bd_re";
2922912Sartem is_rewritable = TRUE;
2932912Sartem break;
2942912Sartem case 0x50: /* HD DVD-ROM */
2952912Sartem disc_type = "hddvd_rom";
2962912Sartem break;
2972912Sartem case 0x51: /* HD DVD-R */
2982912Sartem disc_type = "hddvd_r";
2992912Sartem break;
3002912Sartem case 0x52: /* HD DVD-Rewritable */
3012912Sartem disc_type = "hddvd_rw";
3022912Sartem is_rewritable = TRUE;
3032912Sartem break;
3042912Sartem }
3052912Sartem
3062912Sartem (void) get_disc_capacity_for_profile(fd, profile, &capacity);
3072912Sartem }
3082912Sartem
3093502Sartem *has_audio = *has_data = FALSE;
3102912Sartem if (!is_blank) {
3112912Sartem uchar_t smalltoc[12];
3122912Sartem size_t toc_size;
3132912Sartem uchar_t *toc, *p;
3142912Sartem
3152912Sartem /*
3162912Sartem * XXX for some reason CDROMREADTOCENTRY fails on video DVDs,
317*12528SFei.Feng@Sun.COM * but extracting the toc directly works okay. And the toc
318*12528SFei.Feng@Sun.COM * data buffer length passed to read_toc() should be the same
319*12528SFei.Feng@Sun.COM * as the real buffer size.
3202912Sartem */
321*12528SFei.Feng@Sun.COM if (!read_toc(fd, 0, 1, 12, smalltoc)) {
3222912Sartem HAL_DEBUG(("read_toc failed"));
3233502Sartem *has_data = B_TRUE; /* probe for fs anyway */
3242912Sartem } else {
3252912Sartem toc_size = smalltoc[0] * 256 + smalltoc[1] + 2;
3262912Sartem toc = (uchar_t *)calloc(1, toc_size);
3272912Sartem if (toc == NULL || !read_toc(fd, 0, 1, toc_size, toc)) {
3282912Sartem HAL_DEBUG (("read_toc again failed"));
3292912Sartem } else {
3302912Sartem for (p = &toc[4]; p < (toc + toc_size); p += 8) {
3312912Sartem /* skip leadout */
3322912Sartem if (p[2] == 0xAA) {
3332912Sartem continue;
3342912Sartem }
3352912Sartem if (p[1] & 4) {
3363502Sartem *has_data = B_TRUE;
3372912Sartem } else {
3383502Sartem *has_audio = B_TRUE;
3392912Sartem }
3402912Sartem }
3412912Sartem }
3422912Sartem free(toc);
3432912Sartem }
3442912Sartem }
3452912Sartem
3462912Sartem if ((cs = libhal_device_new_changeset (udi)) == NULL) {
3472912Sartem return (FALSE);
3482912Sartem }
3492912Sartem libhal_changeset_set_property_string (cs, "volume.disc.type", disc_type);
3502912Sartem libhal_changeset_set_property_bool (cs, "volume.disc.is_blank", is_blank);
3513502Sartem libhal_changeset_set_property_bool (cs, "volume.disc.has_audio", *has_audio);
3523502Sartem libhal_changeset_set_property_bool (cs, "volume.disc.has_data", *has_data);
3532912Sartem libhal_changeset_set_property_bool (cs, "volume.disc.is_appendable", is_appendable);
3542912Sartem libhal_changeset_set_property_bool (cs, "volume.disc.is_rewritable", is_rewritable);
3552912Sartem libhal_changeset_set_property_uint64 (cs, "volume.disc.capacity", capacity);
3562912Sartem
3573020Sartem libhal_changeset_set_property_bool (cs, "volume.disc.is_videodvd", FALSE);
3583020Sartem libhal_changeset_set_property_bool (cs, "volume.disc.is_vcd", FALSE);
3593020Sartem libhal_changeset_set_property_bool (cs, "volume.disc.is_svcd", FALSE);
3603020Sartem
3612912Sartem libhal_device_commit_changeset (ctx, cs, &error);
3622912Sartem libhal_device_free_changeset (cs);
3632912Sartem
3642912Sartem out:
3652912Sartem my_dbus_error_free (&error);
3662912Sartem
3672912Sartem return (TRUE);
3682912Sartem }
3692912Sartem
3703020Sartem static void
drop_privileges()3712912Sartem drop_privileges ()
3722912Sartem {
3732912Sartem priv_set_t *pPrivSet = NULL;
3742912Sartem priv_set_t *lPrivSet = NULL;
3752912Sartem
3762912Sartem /*
3772912Sartem * Start with the 'basic' privilege set and then remove any
3782912Sartem * of the 'basic' privileges that will not be needed.
3792912Sartem */
3802912Sartem if ((pPrivSet = priv_str_to_set("basic", ",", NULL)) == NULL) {
3812912Sartem return;
3822912Sartem }
3832912Sartem
3842912Sartem /* Clear privileges we will not need from the 'basic' set */
3852912Sartem (void) priv_delset(pPrivSet, PRIV_FILE_LINK_ANY);
3862912Sartem (void) priv_delset(pPrivSet, PRIV_PROC_INFO);
3872912Sartem (void) priv_delset(pPrivSet, PRIV_PROC_SESSION);
3882912Sartem (void) priv_delset(pPrivSet, PRIV_PROC_EXEC);
3892912Sartem (void) priv_delset(pPrivSet, PRIV_PROC_FORK);
3902912Sartem
3912912Sartem /* for uscsi */
3922912Sartem (void) priv_addset(pPrivSet, PRIV_SYS_DEVICES);
3932912Sartem
3942912Sartem
3952912Sartem /* to open logindevperm'd devices */
3962912Sartem (void) priv_addset(pPrivSet, PRIV_FILE_DAC_READ);
3972912Sartem
3982912Sartem /* Set the permitted privilege set. */
3992912Sartem if (setppriv(PRIV_SET, PRIV_PERMITTED, pPrivSet) != 0) {
4002912Sartem return;
4012912Sartem }
4022912Sartem
4032912Sartem /* Clear the limit set. */
4042912Sartem if ((lPrivSet = priv_allocset()) == NULL) {
4052912Sartem return;
4062912Sartem }
4072912Sartem
4082912Sartem priv_emptyset(lPrivSet);
4092912Sartem
4102912Sartem if (setppriv(PRIV_SET, PRIV_LIMIT, lPrivSet) != 0) {
4112912Sartem return;
4122912Sartem }
4132912Sartem
4142912Sartem priv_freeset(lPrivSet);
4152912Sartem }
4162912Sartem
4172912Sartem int
main(int argc,char * argv[])4182912Sartem main (int argc, char *argv[])
4192912Sartem {
4202912Sartem int fd, rfd;
4212912Sartem int ret;
4222912Sartem char *udi;
4232912Sartem char *device_file, *raw_device_file;
4242912Sartem char *devpath, *rdevpath;
4252912Sartem boolean_t is_dos;
4262912Sartem int dos_num;
4272912Sartem LibHalContext *ctx = NULL;
4282912Sartem DBusError error;
4292912Sartem DBusConnection *conn;
4302912Sartem char *parent_udi;
4312912Sartem char *storage_device;
4322912Sartem char *is_disc_str;
4332912Sartem int fdc;
4342912Sartem dbus_bool_t is_disc = FALSE;
4352912Sartem dbus_bool_t is_floppy = FALSE;
4362912Sartem unsigned int block_size;
4372912Sartem dbus_uint64_t vol_size;
4383502Sartem dbus_bool_t has_data = TRUE; /* probe for fs by default */
4393502Sartem dbus_bool_t has_audio = FALSE;
4402912Sartem char *partition_scheme = NULL;
4412912Sartem dbus_uint64_t partition_start = 0;
4422937Sartem int partition_number = 0;
4437563SPrasad.Singamsetty@Sun.COM struct extvtoc vtoc;
4442912Sartem dk_gpt_t *gpt;
4452912Sartem struct dk_minfo mi;
4462912Sartem int i, dos_cnt;
4472912Sartem fstyp_handle_t fstyp_handle;
4482912Sartem off_t probe_offset = 0;
4492912Sartem int num_volumes;
4502912Sartem char **volumes;
4512912Sartem dbus_uint64_t v_start;
4522912Sartem const char *fstype;
4532912Sartem nvlist_t *fsattr;
4542912Sartem
4552912Sartem fd = rfd = -1;
4562912Sartem
4572912Sartem ret = 1;
4582912Sartem
4592912Sartem if ((udi = getenv ("UDI")) == NULL) {
4602912Sartem goto out;
4612912Sartem }
4622912Sartem if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL) {
4632912Sartem goto out;
4642912Sartem }
4652912Sartem if ((raw_device_file = getenv ("HAL_PROP_BLOCK_SOLARIS_RAW_DEVICE")) == NULL) {
4662912Sartem goto out;
4672912Sartem }
4686395Sartem if (!dos_to_dev(raw_device_file, &rdevpath, &dos_num)) {
4692912Sartem rdevpath = raw_device_file;
4702912Sartem }
4712912Sartem if (!(is_dos = dos_to_dev(device_file, &devpath, &dos_num))) {
4722912Sartem devpath = device_file;
4732912Sartem }
4742912Sartem if ((parent_udi = getenv ("HAL_PROP_INFO_PARENT")) == NULL) {
4752912Sartem goto out;
4762912Sartem }
4772912Sartem if ((storage_device = getenv ("HAL_PROP_BLOCK_STORAGE_DEVICE")) == NULL) {
4782912Sartem goto out;
4792912Sartem }
4802912Sartem
4812912Sartem is_disc_str = getenv ("HAL_PROP_VOLUME_IS_DISC");
4822912Sartem if (is_disc_str != NULL && strcmp (is_disc_str, "true") == 0) {
4832912Sartem is_disc = TRUE;
4842912Sartem } else {
4852912Sartem is_disc = FALSE;
4862912Sartem }
4872912Sartem
4882912Sartem drop_privileges ();
4892912Sartem
4902912Sartem setup_logger ();
4912912Sartem
4922912Sartem dbus_error_init (&error);
4932912Sartem if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
4942912Sartem goto out;
4952912Sartem
4962912Sartem HAL_DEBUG (("Doing probe-volume for %s\n", device_file));
4972912Sartem
4982912Sartem fd = open (devpath, O_RDONLY | O_NONBLOCK);
4992912Sartem if (fd < 0) {
5002912Sartem goto out;
5012912Sartem }
5022912Sartem rfd = open (rdevpath, O_RDONLY | O_NONBLOCK);
5032912Sartem if (rfd < 0) {
5042912Sartem goto out;
5052912Sartem }
5062912Sartem
5072912Sartem /* if it's a floppy with no media, bail out */
5082912Sartem if (ioctl(rfd, FDGETCHANGE, &fdc) == 0) {
5092912Sartem is_floppy = TRUE;
5102912Sartem if (fdc & FDGC_CURRENT) {
5112912Sartem goto out;
5122912Sartem }
5132912Sartem }
5142912Sartem
5152912Sartem /* block size and total size */
5162912Sartem if (ioctl(rfd, DKIOCGMEDIAINFO, &mi) != -1) {
5172912Sartem block_size = mi.dki_lbsize;
5182912Sartem vol_size = mi.dki_capacity * block_size;
5195778Sartem } else if (errno == ENXIO) {
5205778Sartem /* driver supports ioctl, but media is not available */
5215778Sartem goto out;
5222912Sartem } else {
5235778Sartem /* driver does not support ioctl, e.g. lofi */
5242912Sartem block_size = 512;
5252912Sartem vol_size = 0;
5262912Sartem }
5272912Sartem libhal_device_set_property_int (ctx, udi, "volume.block_size", block_size, &error);
5282912Sartem my_dbus_error_free (&error);
5292912Sartem libhal_device_set_property_uint64 (ctx, udi, "volume.size", vol_size, &error);
5302912Sartem my_dbus_error_free (&error);
5312912Sartem
5322912Sartem if (is_disc) {
5333502Sartem if (!probe_disc (rfd, ctx, udi, &has_data, &has_audio)) {
5342912Sartem HAL_DEBUG (("probe_disc failed, skipping fstyp"));
5352912Sartem goto out;
5362912Sartem }
5373502Sartem /* with audio present, create volume even if fs probing fails */
5383502Sartem if (has_audio) {
5393502Sartem ret = 0;
5403502Sartem }
5412912Sartem }
5422912Sartem
5433502Sartem if (!has_data) {
5442912Sartem goto skip_fs;
5452912Sartem }
5462912Sartem
5472912Sartem /* don't support partitioned floppy */
5482912Sartem if (is_floppy) {
5492912Sartem goto skip_part;
5502912Sartem }
5512912Sartem
5522912Sartem /*
5532912Sartem * first get partitioning info
5542912Sartem */
5552912Sartem if (is_dos) {
5562912Sartem /* for a dos drive find partition offset */
5576395Sartem if (!find_dos_drive(fd, dos_num, block_size, &probe_offset)) {
5582912Sartem goto out;
5592912Sartem }
5602912Sartem partition_scheme = "mbr";
5616395Sartem partition_start = (dbus_uint64_t)probe_offset;
5622912Sartem partition_number = dos_num;
5632912Sartem } else {
5647563SPrasad.Singamsetty@Sun.COM if ((partition_number = read_extvtoc(rfd, &vtoc)) >= 0) {
5652912Sartem if (!vtoc_one_slice_entire_disk(&vtoc)) {
5662912Sartem partition_scheme = "smi";
5672912Sartem if (partition_number < vtoc.v_nparts) {
5682912Sartem if (vtoc.v_part[partition_number].p_size == 0) {
5692912Sartem HAL_DEBUG (("zero size partition"));
5702912Sartem }
5712912Sartem partition_start = vtoc.v_part[partition_number].p_start * block_size;
5722912Sartem }
5732912Sartem }
5742912Sartem } else if ((partition_number = efi_alloc_and_read(rfd, &gpt)) >= 0) {
5752912Sartem partition_scheme = "gpt";
5762912Sartem if (partition_number < gpt->efi_nparts) {
5772912Sartem if (gpt->efi_parts[partition_number].p_size == 0) {
5782912Sartem HAL_DEBUG (("zero size partition"));
5792912Sartem }
5802912Sartem partition_start = gpt->efi_parts[partition_number].p_start * block_size;
5812912Sartem }
5822912Sartem efi_free(gpt);
5832912Sartem }
5842912Sartem probe_offset = 0;
5852912Sartem }
5862912Sartem
5872912Sartem if (partition_scheme != NULL) {
5882912Sartem libhal_device_set_property_string (ctx, udi, "volume.partition.scheme", partition_scheme, &error);
5892912Sartem my_dbus_error_free (&error);
5902912Sartem libhal_device_set_property_int (ctx, udi, "volume.partition.number", partition_number, &error);
5912912Sartem my_dbus_error_free (&error);
5922912Sartem libhal_device_set_property_uint64 (ctx, udi, "volume.partition.start", partition_start, &error);
5932912Sartem my_dbus_error_free (&error);
5942912Sartem libhal_device_set_property_bool (ctx, udi, "volume.is_partition", TRUE, &error);
5952912Sartem my_dbus_error_free (&error);
5962912Sartem } else {
5972912Sartem libhal_device_set_property_bool (ctx, udi, "volume.is_partition", FALSE, &error);
5982912Sartem my_dbus_error_free (&error);
5992912Sartem }
6002912Sartem
6012912Sartem /*
6022912Sartem * ignore duplicate partitions
6032912Sartem */
6042912Sartem if ((volumes = libhal_manager_find_device_string_match (
6052912Sartem ctx, "block.storage_device", storage_device, &num_volumes, &error)) != NULL) {
6062912Sartem my_dbus_error_free (&error);
6072912Sartem for (i = 0; i < num_volumes; i++) {
6082912Sartem if (strcmp (udi, volumes[i]) == 0) {
6092912Sartem continue; /* skip self */
6102912Sartem }
6112912Sartem v_start = libhal_device_get_property_uint64 (ctx, volumes[i], "volume.partition.start", &error);
6122912Sartem if (dbus_error_is_set(&error)) {
6132912Sartem dbus_error_free(&error);
6142912Sartem continue;
6152912Sartem }
6162912Sartem if (v_start == partition_start) {
6172912Sartem HAL_DEBUG (("duplicate partition"));
6182912Sartem goto out;
6192912Sartem }
6202912Sartem }
6212912Sartem libhal_free_string_array (volumes);
6222912Sartem }
6232912Sartem
6242912Sartem skip_part:
6252912Sartem
6262912Sartem /*
6272912Sartem * now determine fs type
6283502Sartem *
6293502Sartem * XXX We could get better performance from block device,
6303502Sartem * but for now we use raw device because:
6313502Sartem *
6323502Sartem * - fstyp_udfs has a bug that it only works on raw
6333502Sartem *
6343502Sartem * - sd has a bug that causes extremely slow reads
6353502Sartem * and incorrect probing of hybrid audio/data media
6362912Sartem */
6373502Sartem if (fstyp_init(rfd, probe_offset, NULL, &fstyp_handle) != 0) {
6382912Sartem HAL_DEBUG (("fstyp_init failed"));
6392912Sartem goto out;
6402912Sartem }
6412912Sartem if ((fstyp_ident(fstyp_handle, NULL, &fstype) != 0) ||
6422912Sartem (fstyp_get_attr(fstyp_handle, &fsattr) != 0)) {
6432912Sartem HAL_DEBUG (("fstyp ident or get_attr failed"));
6442912Sartem fstyp_fini(fstyp_handle);
6453502Sartem goto out;
6462912Sartem }
6472912Sartem set_fstyp_properties (ctx, udi, fstype, fsattr);
6483020Sartem
6493020Sartem if (strcmp (fstype, "hsfs") == 0) {
6503020Sartem hsfs_contents (fd, probe_offset, ctx, udi);
6513020Sartem }
6523020Sartem
6532912Sartem fstyp_fini(fstyp_handle);
6542912Sartem
6552912Sartem skip_fs:
6562912Sartem
6572912Sartem ret = 0;
6582912Sartem
6592912Sartem out:
6602912Sartem if (fd >= 0)
6612912Sartem close (fd);
6622912Sartem if (rfd >= 0)
6632912Sartem close (rfd);
6642912Sartem
6652912Sartem if (ctx != NULL) {
6662912Sartem my_dbus_error_free (&error);
6672912Sartem libhal_ctx_shutdown (ctx, &error);
6682912Sartem libhal_ctx_free (ctx);
6692912Sartem }
6702912Sartem
6712912Sartem return ret;
6722912Sartem
6732912Sartem }
674