On 02/14/2012 06:53 PM, Karel Zak wrote:
On Tue, Feb 14, 2012 at 08:56:12AM +0000, Richard W.M. Jones wrote:
> On Tue, Feb 14, 2012 at 03:30:26PM +0800, Wanlong Gao wrote:
> It's one of those things that might be an improvement, but it would
> have to be distinctly better than the existing approach of calling out
> to the 'blkid' binary.
>
> Is the libblkid library interface stable? Is it meant to be used by
> programs other than the blkid binary?
Yes, for example the latest udevd is linked with libblkid.
>> +#include <blkid/blkid.h>
#include <blkid.h> if you want to use pkg-config
>> static char *
>> get_blkid_tag (const char *device, const char *tag)
>> {
>> - char *out, *err;
>> - int r;
>> + int fd, rc;
>> + const char *data = NULL;
>> + blkid_probe blkprobe;
>>
>> - r = commandr (&out, &err,
>> - "blkid",
>> - /* Adding -c option kills all caching, even on RHEL 5. */
>> - "-c", "/dev/null",
>> - "-o", "value", "-s", tag, device,
NULL);
>> - if (r != 0 && r != 2) {
>> - if (r >= 0)
>> - reply_with_error ("%s: %s (blkid returned %d)", device, err,
r);
>> - else
>> - reply_with_error ("%s: %s", device, err);
>> - free (out);
>> - free (err);
>> + if (!device || !tag)
>> return NULL;
>> - }
>>
>> - free (err);
>> + fd = open (device, O_RDONLY);
>> + if (fd < 0)
>> + return NULL;
>>
>> - if (r == 2) { /* means UUID etc not found */
>> - free (out);
>> - out = strdup ("");
>> - if (out == NULL)
>> - reply_with_perror ("strdup");
>> - return out;
>> - }
>> + blkprobe = blkid_new_probe ();
>> + if (!blkprobe)
>> + goto done;
>> + if (blkid_probe_set_device (blkprobe, fd, 0, 0))
>> + goto done;
>> +
>> + blkid_probe_enable_superblocks(blkprobe, 1);
You can also optionally enable
blkid_probe_enable_partitions(pr, 1);
to check for collisions between raids and partition tables (for example
RAID1 could be partitioned -- then PT could be at the begin of the device
and raid superblock at the end of the device, etc.)
>> + blkid_probe_set_superblocks_flags (blkprobe, BLKID_SUBLKS_LABEL |
>> + BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE);
>>
>> - /* Trim trailing \n if present. */
>> - size_t len = strlen (out);
>> - if (len > 0 && out[len-1] == '\n')
>> - out[len-1] = '\0';
>> + rc = blkid_do_safeprobe (blkprobe);
>> + if (!rc)
>> + blkid_probe_lookup_value (blkprobe, tag, &data, NULL);
>>
>> - return out; /* caller frees */
>> +done:
>> + close (fd);
>> + if (blkprobe)
>> + blkid_free_probe (blkprobe);
>> + return data ? strdup ((char *) data) : NULL;
after blkid_free_probe() the "data" are deallocated, must be:
done:
close (fd);
if (data)
data = strdup ((char *) data);
blkid_free_probe (blkprobe);
return data;
Note that if-before-free is unnecessary for blkid_free_probe.
Karel
I did like this.
Now get a problem like below:
The *vfs_type* calls this *get_blkid_tag* function.
I added a disk image to guestfish, this disk image
contains a partition "/dev/vda1" with "ext4" filesystem.
Then I ran *vfs_type /dev/vda1", I got the result,
but with "vfs_type /dev/vda", it hang.
It seems that the vfs_type can't get a type of /dev/vda,
it's right that the type of /dev/vda is unknown, but
why can't it go back with unknown result or NULL result?
Maybe there's something wrong with the code of *get_blkid_tag* ?
Can you give some advise? Karel? Rich?
Thanks
-Wanlong Gao