Esempio n. 1
0
int main(int argc, char ** argv)
{
	struct lookupList expect = {0};
	struct lookupList print = {0};
	struct lookupList copy = {0};
	const char * outdir = "/tmp/rw";
	const char * link = NULL; // "/tmp/rw/root";
	int verbose = 0;

	for (int i = 1; i < argc; i++) {
		if (!strcmp("-e", argv[i]) || !strcmp("--expect", argv[i])) {
			expect.name[expect.count++] = argv[++i];
		} else if (!strcmp("-p", argv[i]) || !strcmp("--print", argv[i])) {
			print.name[print.count++] = argv[++i];
		} else if (!strcmp("-c", argv[i]) || !strcmp("--copy", argv[i])) {
			copy.name[copy.count++] = argv[++i];
		} else if (!strcmp("-o", argv[i]) || !strcmp("--out", argv[i])) {
			outdir = argv[++i];
		} else if (!strcmp("-l", argv[i]) || !strcmp("--link", argv[i])) {
			link = argv[++i];
		} else if (!strcmp("-v", argv[i])) {
			verbose++;
		} else {
			fprintf(stderr, "%s\n"
					"\t[-e|--expect] <filename> : only select FS with <filename> present\n"
					"\t[-p|--print] <filename>] : print <filename> on console, if present\n"
					"\t[-o|--out] <dir> : destination for copied files (optional, def /tmp/rw)\n"
					"\t[-c|--copy] <filename> : copy <filename> to local directory\n"
					"\t[-l|--link] <name> : symlink found device to <name>\n"
					"\t[-v] : verbose mode\n",
					argv[0]);
			exit(0);
		}
	}

	DIR * disks = opendir("/sys/block/");

	if (!disks) {
		fprintf(stderr, "%s: unable to open /sys/block\n", argv[0]);
		exit(1);
	}

	/*
	 * First scan the disks, and partitions for likely FAT filesystem, and gather them
	 * into a list.
	 */
	int partitionCount = 0;
	const int maxPart = 16;
	struct volume_id * partition[maxPart];

	struct dirent * disk;
	while ((disk = readdir(disks)) != NULL && partitionCount < maxPart) {
		if (strncmp(disk->d_name, "sd", 2) && strncmp(disk->d_name, "mmc", 3))
			continue;
	//	printf("disk %s\n", disk->d_name);
		char diskpath[128];
		sprintf(diskpath, "/sys/block/%s", disk->d_name);
		DIR * disk_dir = opendir(diskpath);
		struct dirent * part;
		int ro = -1;
		int removable = -1;
		read_sys_int(diskpath, "removable", &removable);
		read_sys_int(diskpath, "ro", &ro);
		if (verbose)
			printf("disk %s removable=%d read-only=%d\n", disk->d_name, removable, ro);
		while ((part = readdir(disk_dir)) != NULL && partitionCount < maxPart) {
			if (strncmp(part->d_name, disk->d_name, strlen(disk->d_name)))
				continue;
	//		printf("partition %s\n", part->d_name);

			char dev[64];
			sprintf(dev, "/dev/%s", part->d_name);
			struct volume_id * tst = malloc(sizeof(*tst));
			if (volume_id_open(tst, dev) == 0) {
				g_libfat_volume_id = tst;
				tst->fat = libfat_open(readfunc, 0);
				if (tst->fat != NULL) {
					tst->removable = removable;
					tst->ro = ro;
					volume_id_read_dir(tst->fat, 0, &tst->root);
					if (verbose)
						printf("%s is a valid fat!\n", dev);
					partition[partitionCount++] = tst;
				} else {
					volume_id_close(tst);
					free(tst);
				}
			}
		}
		closedir(disk_dir);
	}
	closedir(disks);

	/*
	 * For each partition look to see if they have the 'expected' files, otherwise,
	 * discard it.
	 * If the partition is the one we look for, print & copy files from it
	 */
	for (int i = 0; i < partitionCount; i++) {
		struct volume_id *p = partition[i];
		if (!p)
			continue;
		if (verbose)
			printf("%s\n", p->dev);

		if (verbose)
			for (int j = 0; j < p->root.count; j++)
				printf("\t'%s' %u\n", p->root.entry[j].longname,
						read32(&p->root.entry[j].entry.size));

		for (int ei = 0; ei < expect.count; ei++) {
			int found = 0;
			for (int j = 0; j < p->root.count; j++) {
				if (!strcasecmp(expect.name[ei], p->root.entry[j].longname) ||
					!strcasecmp(expect.name[ei], p->root.entry[j].name)) {
					found++;
					if (verbose)
						printf("%s: found '%s'\n", p->dev, expect.name[ei]);
					break;
				}
			}
			if (!found) {
				printf("%s: '%s' NOT found, discarding\n", p->dev, expect.name[ei]);
				p = partition[i] = NULL;
				break;
			}
		}
		if (!p)
			continue;

		printf("%s ", p->dev);
		for (int pi = 0; pi < print.count; pi++) {
			for (int j = 0; j < p->root.count; j++) {
				if (!strcasecmp(print.name[pi], p->root.entry[j].longname) ||
					!strcasecmp(print.name[pi], p->root.entry[j].name)) {

					if (verbose)
						printf("%s: print '%s' (%d)\n",
							p->dev, print.name[pi],
							(int)p->root.entry[j].size);
					printf("%s=", print.name[pi]); fflush(stdout);
					g_libfat_volume_id = p;
					volume_id_read_file(p, &p->root.entry[j], 1);
					printf(" ");
				}
			}
		}

		if (copy.count > 0)
			mkdir(outdir, 0755);

		chdir(outdir);
		if (link) {
			unlink(link);
			if (symlink(p->dev, link)) {
				perror(link);
			}
		}

		for (int pi = 0; pi < copy.count; pi++) {
			for (int j = 0; j < p->root.count; j++) {
				if (!strcasecmp(copy.name[pi], p->root.entry[j].longname) ||
					!strcasecmp(copy.name[pi], p->root.entry[j].name)) {

					if (verbose)
						printf("%s: copy '%s' (%d) to %s\n",
							p->dev, copy.name[pi],
							(int)p->root.entry[j].size,
							outdir);
					int fd = open(p->root.entry[j].longname, O_CREAT|O_TRUNC|O_WRONLY, 0644);
					if (fd == -1) {
						fprintf(stderr, "%s could not copy %s from %s to %s\n", argv[0],
								p->root.entry[j].longname, p->dev, outdir);
					} else {
						g_libfat_volume_id = p;
						volume_id_read_file(p, &p->root.entry[j], fd);
						close(fd);
					}
				}
			}
		}
		printf("\n");
		// exit if we were copying files
		if (copy.count || link)
			exit(0);
	}
	exit(1);
}
Esempio n. 2
0
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, &sector_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;
}
Esempio n. 3
0
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;
}