int main (int argc, char **argv) { char *device_file; char *parent_udi; char *grandparent_udi; char *parent_drive_type; int fd = -1; struct volume_id *vid = NULL; int ret = 1; gboolean has_children; gboolean is_swap; gboolean is_cdrom; gboolean is_partition = FALSE; gboolean has_audio = FALSE; gboolean has_data = FALSE; gboolean is_blank = FALSE; const char *usage; char *label; unsigned int sector_size = 0; off_t media_size = 0; if (! hfp_init(argc, argv)) goto end; device_file = getenv("HAL_PROP_BLOCK_DEVICE"); if (! device_file) goto end; parent_udi = getenv("HAL_PROP_INFO_PARENT"); if (! parent_udi) goto end; /* give a meaningful process title for ps(1) */ setproctitle("%s", device_file); has_children = hfp_getenv_bool("HF_HAS_CHILDREN"); is_swap = hfp_getenv_bool("HF_IS_SWAP"); fd = open(device_file, O_RDONLY); if (fd < 0) goto end; parent_drive_type = libhal_device_get_property_string(hfp_ctx, parent_udi, "storage.drive_type", &hfp_error); dbus_error_free(&hfp_error); grandparent_udi = libhal_device_get_property_string(hfp_ctx, parent_udi, "info.parent", &hfp_error); dbus_error_free(&hfp_error); is_cdrom = parent_drive_type && ! strcmp(parent_drive_type, "cdrom"); g_free(parent_drive_type); if (is_cdrom) { hf_probe_volume_get_disc_info(fd, &has_audio, &has_data); is_blank = (! has_audio && ! has_data); } ioctl(fd, DIOCGMEDIASIZE, &media_size); /* * We only check for filesystems if the volume has no children, * otherwise volume_id might find a filesystem in what is actually * the first child partition of the volume. * * If hald (which has looked at the partition type) reports that it * is a swap partition, we probe it nevertheless in case the * partition type is incorrect. */ if (! has_children && ! (is_cdrom && ! has_data)) { vid = volume_id_open_fd(fd); if (vid) { if (volume_id_probe_all(vid, 0, media_size) == 0) has_data = TRUE; else { volume_id_close(vid); vid = NULL; } } } if (! has_children && ! is_swap && ! has_audio && ! has_data && ! is_blank) goto end; libhal_device_add_capability(hfp_ctx, hfp_udi, "volume", &hfp_error); if (is_cdrom) { HFPCDROM *cdrom; int type; guint64 capacity; libhal_device_set_property_string(hfp_ctx, hfp_udi, "info.category", "volume.disc", &hfp_error); libhal_device_add_capability(hfp_ctx, hfp_udi, "volume.disc", &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.has_audio", has_audio, &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.has_data", has_data, &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_vcd", FALSE, &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_svcd", FALSE, &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_videodvd", FALSE, &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_appendable", FALSE, &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_blank", is_blank, &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_rewritable", FALSE, &hfp_error); libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "unknown", &hfp_error); /* the following code was adapted from linux's probe-volume.c */ cdrom = hfp_cdrom_new_from_fd(fd, device_file, grandparent_udi); if (cdrom) { type = get_disc_type(cdrom); if (type != -1) switch (type) { case 0x08: /* CD-ROM */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "cd_rom", &hfp_error); break; case 0x09: /* CD-R */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "cd_r", &hfp_error); break; case 0x0a: /* CD-RW */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "cd_rw", &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_rewritable", TRUE, &hfp_error); break; case 0x10: /* DVD-ROM */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "dvd_rom", &hfp_error); break; case 0x11: /* DVD-R Sequential */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "dvd_r", &hfp_error); break; case 0x12: /* DVD-RAM */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "dvd_ram", &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_rewritable", TRUE, &hfp_error); break; case 0x13: /* DVD-RW Restricted Overwrite */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "dvd_rw", &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_rewritable", TRUE, &hfp_error); break; case 0x14: /* DVD-RW Sequential */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "dvd_rw", &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_rewritable", TRUE, &hfp_error); break; case 0x1A: /* DVD+RW */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "dvd_plus_rw", &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_rewritable", TRUE, &hfp_error); break; case 0x1B: /* DVD+R */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "dvd_plus_r", &hfp_error); break; case 0x2B: /* DVD+R Double Layer */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "dvd_plus_r_dl", &hfp_error); break; case 0x40: /* BD-ROM */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "bd_rom", &hfp_error); break; case 0x41: /* BD-R Sequential */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "bd_r", &hfp_error); break; case 0x42: /* BD-R Random */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "bd_r", &hfp_error); break; case 0x43: /* BD-RE */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "bd_re", &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_rewritable", TRUE, &hfp_error); break; case 0x50: /* HD DVD-ROM */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "hddvd_rom", &hfp_error); break; case 0x51: /* HD DVD-R */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "hddvd_r", &hfp_error); break; case 0x52: /* HD DVD-Rewritable */ libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.disc.type", "hddvd_rw", &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_rewritable", TRUE, &hfp_error); break; } if (get_disc_capacity_for_type(cdrom, type, &capacity) == 0) libhal_device_set_property_uint64(hfp_ctx, hfp_udi, "volume.disc.capacity", capacity, &hfp_error); /* * linux's probe-volume.c: "on some hardware the get_disc_type * call fails, so we use this as a backup". */ if (disc_is_rewritable(cdrom)) libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.disc.is_rewritable", TRUE, &hfp_error); if (disc_is_appendable(cdrom)) libhal_device_set_property_bool (hfp_ctx, hfp_udi, "volume.disc.is_appendable", TRUE, &hfp_error); hfp_cdrom_free(cdrom); } if (has_data && vid && (! strcmp(vid->type, "iso9660") || ! strcmp(vid->type, "udf"))) hf_probe_volume_advanced_disc_detect(fd); } else { libhal_device_set_property_string(hfp_ctx, hfp_udi, "info.category", "volume", &hfp_error); if (libhal_device_query_capability(hfp_ctx, parent_udi, "storage", &hfp_error)) { char *geom_class; char *type; char *scheme; int number; guint64 mediasize; guint64 offset; geom_class = getenv("HF_VOLUME_GEOM_CLASS"); if (geom_class) { if (hf_probe_volume_get_partition_info(geom_class, device_file, &number, &type, &scheme, &mediasize, &offset)) { is_partition = TRUE; libhal_device_set_property_int(hfp_ctx, hfp_udi, "volume.partition.number", number, &hfp_error); libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.partition.scheme", scheme, &hfp_error); libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.partition.type", type, &hfp_error); /* FIXME We need to fill in the supported partition flags. */ libhal_device_set_property_uint64(hfp_ctx, hfp_udi, "volume.partition.media_size", mediasize, &hfp_error); libhal_device_set_property_uint64(hfp_ctx, hfp_udi, "volume.partition.start", offset, &hfp_error); if (! strcmp(scheme, "gpt")) libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.partition.uuid", type, &hfp_error); if (! strcmp(scheme, "gpt") || ! strcmp(scheme, "apm")) libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.partition.label", "", &hfp_error); g_free(type); g_free(scheme); } } } else dbus_error_free(&hfp_error); } libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.is_disc", is_cdrom, &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.is_partition", is_partition, &hfp_error); libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.ignore", has_children || is_swap, &hfp_error); #ifdef HAVE_LIBUFS if (vid && ! strcmp (vid->type, "ufs")) { struct uufsd ufsdisk; if (ufs_disk_fillout(&ufsdisk, device_file) == 0) { char ufsid[64]; char **ufs_devs = NULL; int num_udis; int i; snprintf(ufsid, sizeof(ufsid), "%08x%08x", ufsdisk.d_fs.fs_id[0], ufsdisk.d_fs.fs_id[1]); libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.freebsd.ufsid", ufsid, &hfp_error); dbus_error_free(&hfp_error); ufs_devs = libhal_manager_find_device_string_match(hfp_ctx, "volume.freebsd.ufsid", ufsid, &num_udis, &hfp_error); dbus_error_free(&hfp_error); for (i = 0; i < num_udis; i++) { if (ufs_devs[i] != NULL && strcmp(ufs_devs[i], hfp_udi)) { gboolean mounted; mounted = libhal_device_get_property_bool(hfp_ctx, ufs_devs[i], "volume.is_mounted", &hfp_error); dbus_error_free(&hfp_error); if (mounted) { libhal_device_set_property_bool(hfp_ctx, hfp_udi, "volume.ignore", TRUE, &hfp_error); dbus_error_free(&hfp_error); break; } } } if (ufs_devs) libhal_free_string_array(ufs_devs); ufs_disk_close(&ufsdisk); } } #endif /* HAVE_LIBUFS */ if (has_children) usage = "partitiontable"; else if (is_swap) usage = "other"; else switch (vid ? vid->usage_id : (enum volume_id_usage) -1) { case VOLUME_ID_FILESYSTEM: usage = "filesystem"; break; case VOLUME_ID_DISKLABEL: usage = "disklabel"; break; case VOLUME_ID_OTHER: usage = "other"; break; case VOLUME_ID_RAID: usage = "raid"; break; case VOLUME_ID_CRYPTO: usage = "crypto"; break; case VOLUME_ID_UNUSED: usage = "unused"; break; default: usage = "unknown"; break; } libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.fsusage", usage, &hfp_error); libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.fstype", vid ? vid->type: "", &hfp_error); if (vid && *vid->type_version) libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.fsversion", vid->type_version, &hfp_error); label = hf_probe_volume_get_label(vid); libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.label", label ? label : "", &hfp_error); g_free(label); libhal_device_set_property_string(hfp_ctx, hfp_udi, "volume.uuid", vid ? vid->uuid : "", &hfp_error); ioctl(fd, DIOCGSECTORSIZE, §or_size); if (sector_size != 0) libhal_device_set_property_uint64(hfp_ctx, hfp_udi, "volume.block_size", sector_size, &hfp_error); if (media_size != 0) libhal_device_set_property_uint64(hfp_ctx, hfp_udi, "volume.size", media_size, &hfp_error); if (sector_size != 0 && media_size != 0) libhal_device_set_property_uint64(hfp_ctx, hfp_udi, "volume.num_blocks", media_size / sector_size, &hfp_error); ret = 0; /* is a volume */ end: return ret; }
HalDevice * devinfo_mass_disklabel_add(HalDevice *parent, const char *devnode, char *devfs_path, char *device_type) { HalDevice *d = NULL; struct disklabel label; struct partition *part; struct stat st; const char *driver; char *devpath, *rdevpath, *partname; char *childnode; char unit; struct volume_id *vid; uint64_t psize, msize; int i, fd; partname = devnode; unit = partname[strlen (partname) - 1] - 'a'; if (unit >= MAXPARTITIONS) return NULL; devpath = g_strdup_printf ("/dev/%s", partname); rdevpath = g_strdup_printf ("/dev/r%s", partname); fd = open (rdevpath, O_RDONLY); if (fd < 0) { HAL_WARNING (("couldn't open %s: %s", rdevpath, strerror (errno))); g_free (rdevpath); return NULL; } if (ioctl (fd, DIOCGDINFO, &label) == -1) { HAL_WARNING (("DIOCGDINFO failed on %s: %s", rdevpath, strerror (errno))); g_free (rdevpath); close (fd); return NULL; } part = &label.d_partitions[unit]; d = hal_device_new (); devinfo_set_default_properties (d, parent, devnode, devfs_path); hal_device_add_capability (d, "block"); hal_device_property_set_string (d, "info.subsystem", "block"); hal_device_property_set_string (d, "info.category", "volume"); hal_device_property_set_string (d, "block.device", devpath); hal_device_property_set_string (d, "block.storage_device", hal_device_property_get_string (parent, "info.udi")); if (stat (devpath, &st) == 0) { hal_device_property_set_int (d, "block.major", major (st.st_rdev)); hal_device_property_set_int (d, "block.minor", minor (st.st_rdev)); } hal_device_property_set_bool (d, "block.is_volume", TRUE); hal_device_property_set_bool (d, "block.no_partitions", FALSE); hal_device_property_set_bool (d, "block.have_scanned", TRUE); hal_device_add_capability (d, "volume"); hal_device_property_set_bool (d, "volume.ignore", FALSE); hal_device_property_set_bool (d, "volume.is_mounted", FALSE); hal_device_property_set_bool (d, "volume.is_mounted_read_only", FALSE); hal_device_property_set_string (d, "volume.mount_point", ""); hal_device_property_set_string (d, "volume.fsusage", "filesystem"); hal_device_property_set_string (d, "volume.fstype", devinfo_mass_get_fstype (part->p_fstype)); hal_device_property_set_bool (d, "volume.is_disc", FALSE); hal_device_property_set_string (d, "volume.label", ""); hal_device_property_set_string (d, "volume.partition.label", ""); hal_device_property_set_string (d, "volume.uuid", ""); hal_device_property_set_string (d, "volume.partition.uuid", ""); psize = (uint64_t)part->p_size * (uint64_t)label.d_secsize; msize = (uint64_t)label.d_secsize * (uint64_t)label.d_secperunit; hal_device_property_set_uint64 (d, "volume.size", psize); hal_device_property_set_int (d, "volume.block_size", label.d_secsize); hal_device_property_set_uint64 (d, "volume.num_blocks", part->p_size); hal_device_property_set_uint64 (d, "volume.partition.media_size", msize); hal_device_property_set_bool (d, "volume.is_partition", TRUE); hal_device_property_set_int (d, "volume.partition.number", unit); hal_device_property_set_string (d, "volume.partition.scheme", "mbr"); vid = volume_id_open_fd (fd); if (vid) { if (volume_id_probe_all (vid, 0, psize) == 0) { const char *type,*fstype; hal_device_property_set_string (d, "volume.label", vid->label); hal_device_property_set_string (d, "volume.partition.label", vid->label); hal_device_property_set_string (d, "volume.uuid", vid->uuid); hal_device_property_set_string (d, "volume.partition.uuid", vid->uuid); if ( type && volume_id_get_type (vid, &type)) { fstype=devinfo_mass_get_fstype (part->p_fstype); if (strcmp (type, fstype)) { HAL_INFO (("%s disklabel reports [%s] but libvolume_id says it is " "[%s], assuming disklabel is incorrect", devpath, fstype, type)); hal_device_property_set_string (d, "volume.fstype", type); } } } volume_id_close (vid); } devinfo_add_enqueue (d, devfs_path, &devinfo_mass_disklabel_handler); close (fd); g_free (rdevpath); g_free (devpath); return d; }