X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=daemon%2Fblkid.c;h=f23eac68bd2d51ccdcc827bd70f601c6e77f5acb;hb=01e717b3c141c509a7200b0a6c560f75815c08f2;hp=4e14881f1c757854670b7fd6665de33ff7a4f728;hpb=d609130cb65fe7795b168a796426e39d64ceda97;p=libguestfs.git diff --git a/daemon/blkid.c b/daemon/blkid.c index 4e14881..f23eac6 100644 --- a/daemon/blkid.c +++ b/daemon/blkid.c @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include @@ -27,16 +27,22 @@ #include "daemon.h" #include "actions.h" -char * -do_vfs_type (const char *device) +static char * +get_blkid_tag (const char *device, const char *tag) { char *out, *err; int r; - r = command (&out, &err, - "/sbin/blkid", "-o", "value", "-s", "TYPE", device, NULL); - if (r == -1) { - reply_with_error ("vfs_type: %s: %s", device, err); + 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); return NULL; @@ -44,6 +50,14 @@ do_vfs_type (const char *device) free (err); + if (r == 2) { /* means UUID etc not found */ + free (out); + out = strdup (""); + if (out == NULL) + reply_with_perror ("strdup"); + return out; + } + /* Trim trailing \n if present. */ size_t len = strlen (out); if (len > 0 && out[len-1] == '\n') @@ -51,3 +65,162 @@ do_vfs_type (const char *device) return out; /* caller frees */ } + +char * +do_vfs_type (const char *device) +{ + return get_blkid_tag (device, "TYPE"); +} + +char * +do_vfs_label (const char *device) +{ + return get_blkid_tag (device, "LABEL"); +} + +char * +do_vfs_uuid (const char *device) +{ + return get_blkid_tag (device, "UUID"); +} + +/* RHEL5 blkid doesn't have the -p(partition info) option and the + * -i(I/O limits) option so we must test for these options the first + * time the function is called. + */ +static int +test_blkid_p_opt(void) +{ + static int result; + char *err = NULL; + + int r = commandr(NULL, &err, "blkid", "-p", "/dev/null", NULL); + if (r == -1) { + reply_with_error("could not run 'blkid' command: %s", err); + free(err); + return -1; + } + + if (strstr(err, "invalid option --")) + result = 0; + else + result = 1; + free(err); + return result; +} + +static char ** +blkid_with_p_opt(const char *device) +{ + int r; + char *out = NULL, *err = NULL; + char **lines = NULL; + char **ret = NULL; + int size = 0, alloc = 0; + + r = command(&out, &err, "blkid", "-c", "/dev/null", + "-p", "-i", "-o", "export", device, NULL); + if (r == -1) { + reply_with_error("%s", err); + goto error; + } + + /* Split the command output into lines */ + lines = split_lines(out); + if (lines == NULL) { + reply_with_perror("malloc"); + goto error; + } + + /* Parse the output of blkid -p -i -o export: + * UUID=b6d83437-c6b4-4bf0-8381-ef3fc3578590 + * VERSION=1.0 + * TYPE=ext2 + * USAGE=filesystem + * MINIMUM_IO_SIZE=512 + * PHYSICAL_SECTOR_SIZE=512 + * LOGICAL_SECTOR_SIZE=512 + * PART_ENTRY_SCHEME=dos + * PART_ENTRY_TYPE=0x83 + * PART_ENTRY_NUMBER=6 + * PART_ENTRY_OFFSET=642875153 + * PART_ENTRY_SIZE=104857600 + * PART_ENTRY_DISK=8:0 + */ + for (char **i = lines; *i != NULL; i++) { + char *line = *i; + + /* Skip blank lines (shouldn't happen) */ + if (line[0] == '\0') continue; + + /* Split the line in 2 at the equals sign */ + char *eq = strchr(line, '='); + if (eq) { + *eq = '\0'; eq++; + + /* Add the key/value pair to the output */ + if (add_string(&ret, &size, &alloc, line) == -1 || + add_string(&ret, &size, &alloc, eq) == -1) goto error; + } else { + fprintf(stderr, "blkid: unexpected blkid output ignored: %s", line); + } + } + + if (add_string(&ret, &size, &alloc, NULL) == -1) goto error; + + free(out); + free(err); + free(lines); + + return ret; + +error: + free(out); + free(err); + if (lines) free(lines); + if (ret) free_strings(ret); + + return NULL; +} + +static char ** +blkid_without_p_opt(const char *device) +{ + char **ret = NULL; + int size = 0, alloc = 0; + + if (add_string(&ret, &size, &alloc, "TYPE") == -1) goto error; + if (add_string(&ret, &size, &alloc, get_blkid_tag(device, "TYPE")) == -1) + goto error; + if (add_string(&ret, &size, &alloc, "LABEL") == -1) goto error; + if (add_string(&ret, &size, &alloc, get_blkid_tag(device, "LABEL")) == -1) + goto error; + if (add_string(&ret, &size, &alloc, "UUID") == -1) goto error; + if (add_string(&ret, &size, &alloc, get_blkid_tag(device, "UUID")) == -1) + goto error; + if (add_string_nodup(&ret, &size, &alloc, NULL) == -1) goto error; + + return ret; +error: + if (ret) free_strings(ret); + return NULL; +} + +char ** +do_blkid(const char *device) +{ + int r; + char *out = NULL, *err = NULL; + char **lines = NULL; + + char **ret = NULL; + int size = 0, alloc = 0; + int blkid_has_p_opt; + + if ((blkid_has_p_opt = test_blkid_p_opt()) == -1) + return NULL; + else if (blkid_has_p_opt) + return blkid_with_p_opt(device); + else + return blkid_without_p_opt(device); +}