X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=daemon%2Fparted.c;h=9c65570f47ee46415a74693fcddc6bb72173b488;hp=2b0df4419cfc03855f99b4b6b5dde17d0a41470f;hb=b68c030adfdbefe65bc9ecdd673844c01bddb32a;hpb=3833ddc6566f92783dc5a8894383c304e3d2c0b4 diff --git a/daemon/parted.c b/daemon/parted.c index 2b0df44..9c65570 100644 --- a/daemon/parted.c +++ b/daemon/parted.c @@ -46,7 +46,7 @@ recover_blkrrpart (const char *device, const char *err) "Error informing the kernel about modifications to partition")) return -1; - r = command (NULL, NULL, "/sbin/blockdev", "--rereadpt", device, NULL); + r = command (NULL, NULL, "blockdev", "--rereadpt", device, NULL); if (r == -1) return -1; @@ -55,18 +55,18 @@ recover_blkrrpart (const char *device, const char *err) return 0; } -#define RUN_PARTED(device,...) \ +#define RUN_PARTED(error,device,...) \ do { \ int r; \ char *err; \ \ r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, \ - "/sbin/parted", "-s", "--", (device), __VA_ARGS__); \ + "parted", "-s", "--", (device), __VA_ARGS__); \ if (r == -1) { \ if (recover_blkrrpart ((device), err) == -1) { \ reply_with_error ("%s: parted: %s: %s", __func__, (device), err); \ free (err); \ - return -1; \ + error; \ } \ } \ \ @@ -103,11 +103,11 @@ do_part_init (const char *device, const char *parttype) { parttype = check_parttype (parttype); if (!parttype) { - reply_with_error ("part-init: unknown partition type: common choices are \"gpt\" and \"msdos\""); + reply_with_error ("unknown partition type: common choices are \"gpt\" and \"msdos\""); return -1; } - RUN_PARTED (device, "mklabel", parttype, NULL); + RUN_PARTED (return -1, device, "mklabel", parttype, NULL); udev_settle (); @@ -133,12 +133,12 @@ do_part_add (const char *device, const char *prlogex, else if (STREQ (prlogex, "e")) prlogex = "extended"; else { - reply_with_error ("part-add: unknown partition type: %s: this should be \"primary\", \"logical\" or \"extended\"", prlogex); + reply_with_error ("unknown partition type: %s: this should be \"primary\", \"logical\" or \"extended\"", prlogex); return -1; } if (startsect < 0) { - reply_with_error ("part-add: startsect cannot be negative"); + reply_with_error ("startsect cannot be negative"); return -1; } /* but endsect can be negative */ @@ -151,7 +151,7 @@ do_part_add (const char *device, const char *prlogex, * name_ to prlogex, eg. "primary". I would essentially describe * this as a bug in the parted mkpart command. */ - RUN_PARTED (device, "mkpart", prlogex, startstr, endstr, NULL); + RUN_PARTED (return -1, device, "mkpart", prlogex, startstr, endstr, NULL); udev_settle (); @@ -159,6 +159,18 @@ do_part_add (const char *device, const char *prlogex, } int +do_part_del (const char *device, int partnum) +{ + char partnum_str[16]; + snprintf (partnum_str, sizeof partnum_str, "%d", partnum); + + RUN_PARTED (return -1, device, "rm", partnum_str, NULL); + + udev_settle (); + return 0; +} + +int do_part_disk (const char *device, const char *parttype) { const char *startstr; @@ -166,7 +178,7 @@ do_part_disk (const char *device, const char *parttype) parttype = check_parttype (parttype); if (!parttype) { - reply_with_error ("part-disk: unknown partition type: common choices are \"gpt\" and \"msdos\""); + reply_with_error ("unknown partition type: common choices are \"gpt\" and \"msdos\""); return -1; } @@ -183,7 +195,8 @@ do_part_disk (const char *device, const char *parttype) endstr = "-1s"; } - RUN_PARTED (device, + RUN_PARTED (return -1, + device, "mklabel", parttype, /* See comment about about the parted mkpart command. */ "mkpart", STREQ (parttype, "gpt") ? "p1" : "primary", @@ -201,7 +214,8 @@ do_part_set_bootable (const char *device, int partnum, int bootable) snprintf (partstr, sizeof partstr, "%d", partnum); - RUN_PARTED (device, "set", partstr, "boot", bootable ? "on" : "off", NULL); + RUN_PARTED (return -1, + device, "set", partstr, "boot", bootable ? "on" : "off", NULL); udev_settle (); @@ -215,13 +229,43 @@ do_part_set_name (const char *device, int partnum, const char *name) snprintf (partstr, sizeof partstr, "%d", partnum); - RUN_PARTED (device, "name", partstr, name, NULL); + RUN_PARTED (return -1, device, "name", partstr, name, NULL); udev_settle (); return 0; } +/* Return the nth field from a string of ':'/';'-delimited strings. + * Useful for parsing the return value from print_partition_table + * function below. + */ +static char * +get_table_field (const char *line, int n) +{ + const char *p = line; + + while (*p && n > 0) { + p += strcspn (p, ":;") + 1; + n--; + } + + if (n > 0) { + reply_with_error ("not enough fields in output of parted print command: %s", + line); + return NULL; + } + + size_t len = strcspn (p, ":;"); + char *q = strndup (p, len); + if (q == NULL) { + reply_with_perror ("strndup"); + return NULL; + } + + return q; +} + static char ** print_partition_table (const char *device) { @@ -229,7 +273,7 @@ print_partition_table (const char *device) int r; char **lines; - r = command (&out, &err, "/sbin/parted", "-m", "--", device, + r = command (&out, &err, "parted", "-m", "--", device, "unit", "b", "print", NULL); if (r == -1) { @@ -249,14 +293,14 @@ print_partition_table (const char *device) return NULL; if (lines[0] == NULL || STRNEQ (lines[0], "BYT;")) { - reply_with_error ("parted print: unknown signature, expected \"BYT;\" as first line of the output: %s", + reply_with_error ("unknown signature, expected \"BYT;\" as first line of the output: %s", lines[0] ? lines[0] : "(signature was null)"); free_strings (lines); return NULL; } if (lines[1] == NULL) { - reply_with_error ("parted print: parted didn't return a line describing the device"); + reply_with_error ("parted didn't return a line describing the device"); free_strings (lines); return NULL; } @@ -267,31 +311,15 @@ print_partition_table (const char *device) char * do_part_get_parttype (const char *device) { - char **lines; - char *r; - - lines = print_partition_table (device); + char **lines = print_partition_table (device); if (!lines) return NULL; /* lines[1] is something like: * "/dev/sda:1953525168s:scsi:512:512:msdos:ATA Hitachi HDT72101;" */ - if (strtok (lines[1], ":") == NULL /* device */ - || strtok (NULL, ":") == NULL /* size */ - || strtok (NULL, ":") == NULL /* transport */ - || strtok (NULL, ":") == NULL /* sector size */ - || strtok (NULL, ":") == NULL /* physical sector size */ - || (r = strtok (NULL, ":")) == NULL /* return value */ - ) { - reply_with_error ("part_get_parttype: too few fields in output from parted print command: %s", lines[1]); - free_strings (lines); - return NULL; - } - - r = strdup (r); - if (!r) { - reply_with_perror ("strdup"); + char *r = get_table_field (lines[1], 5); + if (r == NULL) { free_strings (lines); return NULL; } @@ -339,7 +367,7 @@ do_part_list (const char *device) &r->guestfs_int_partition_list_val[i].part_start, &r->guestfs_int_partition_list_val[i].part_end, &r->guestfs_int_partition_list_val[i].part_size) != 4) { - reply_with_error ("part_list: could not parse row from output of parted print command: %s", lines[row]); + reply_with_error ("could not parse row from output of parted print command: %s", lines[row]); goto error3; } } @@ -355,3 +383,92 @@ do_part_list (const char *device) free_strings (lines); return NULL; } + +int +do_part_get_bootable (const char *device, int partnum) +{ + char **lines = print_partition_table (device); + if (!lines) + return -1; + + /* We want lines[1+partnum]. */ + if (count_strings (lines) < 1+partnum) { + reply_with_error ("partition number out of range: %d", partnum); + free_strings (lines); + return -1; + } + + char *boot = get_table_field (lines[1+partnum], 6); + if (boot == NULL) { + free_strings (lines); + return -1; + } + + int r = STREQ (boot, "boot"); + + free (boot); + free_strings (lines); + + return r; +} + +/* Currently we use sfdisk for getting and setting the ID byte. In + * future, extend parted to provide this functionality. As a result + * of using sfdisk, this won't work for non-MBR-style partitions, but + * that limitation is noted in the documentation and we can extend it + * later without breaking the ABI. + */ +int +do_part_get_mbr_id (const char *device, int partnum) +{ + char partnum_str[16]; + snprintf (partnum_str, sizeof partnum_str, "%d", partnum); + + char *out, *err; + int r; + + r = command (&out, &err, "sfdisk", "--print-id", device, partnum_str, NULL); + if (r == -1) { + reply_with_error ("sfdisk --print-id: %s", err); + free (out); + free (err); + return -1; + } + + free (err); + + /* It's printed in hex ... */ + int id; + if (sscanf (out, "%x", &id) != 1) { + reply_with_error ("sfdisk --print-id: cannot parse output: %s", out); + free (out); + return -1; + } + + free (out); + return id; +} + +int +do_part_set_mbr_id (const char *device, int partnum, int idbyte) +{ + char partnum_str[16]; + snprintf (partnum_str, sizeof partnum_str, "%d", partnum); + + char idbyte_str[16]; + snprintf (idbyte_str, sizeof partnum_str, "%x", idbyte); /* NB: hex */ + + char *err; + int r; + + r = command (NULL, &err, "sfdisk", + "--change-id", device, partnum_str, idbyte_str, NULL); + if (r == -1) { + reply_with_error ("sfdisk --change-id: %s", err); + free (err); + return -1; + } + + free (err); + return 0; +}