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
--
Karel Zak <kzak(a)redhat.com>
http://karelzak.blogspot.com