int do_part_set_name (const char *device, int partnum, const char *name) { int r; CLEANUP_FREE char *err = NULL; if (partnum <= 0) { reply_with_error ("partition number must be >= 1"); return -1; } char partstr[16]; snprintf (partstr, sizeof partstr, "%d", partnum); udev_settle (); r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, "parted", "-s", "--", device, "name", partstr, name, NULL); if (r == -1) { reply_with_error ("parted: %s: %s", device, err); return -1; } udev_settle (); return 0; }
int do_part_init (const char *device, const char *parttype) { int r; CLEANUP_FREE char *err = NULL; parttype = check_parttype (parttype); if (!parttype) { reply_with_error ("unknown partition type: common choices are \"gpt\" and \"msdos\""); return -1; } udev_settle (); r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, "parted", "-s", "--", device, "mklabel", parttype, NULL); if (r == -1) { reply_with_error ("parted: %s: %s", device, err); return -1; } udev_settle (); return 0; }
static char * print_partition_table (const char *device, bool add_m_option) { char *out; CLEANUP_FREE char *err = NULL; int r; udev_settle (); if (add_m_option) r = command (&out, &err, "parted", "-m", "-s", "--", device, "unit", "b", "print", NULL); else r = command (&out, &err, "parted", "-s", "--", device, "unit", "b", "print", NULL); udev_settle (); if (r == -1) { int errcode = 0; /* Translate "unrecognised disk label" into an errno code. */ if (err && strstr (err, "unrecognised disk label") != NULL) errcode = EINVAL; reply_with_error_errno (errcode, "parted print: %s: %s", device, err); free (out); return NULL; } return out; }
int do_part_set_mbr_id (const char *device, int partnum, int idbyte) { if (partnum <= 0) { reply_with_error ("partition number must be >= 1"); return -1; } 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 */ CLEANUP_FREE char *err = NULL; int r; udev_settle (); r = command (NULL, &err, str_sfdisk, "--change-id", device, partnum_str, idbyte_str, NULL); if (r == -1) { reply_with_error ("sfdisk --change-id: %s", err); return -1; } udev_settle (); return 0; }
int do_part_resize (const char *device, int partnum, int64_t endsect) { int r; CLEANUP_FREE char *err = NULL; char endstr[32]; char partnum_str[16]; if (partnum <= 0) { reply_with_error ("partition number must be >= 1"); return -1; } snprintf (partnum_str, sizeof partnum_str, "%d", partnum); snprintf (endstr, sizeof endstr, "%" PRIi64 "s", endsect); udev_settle (); r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, "parted", "-s", "--", device, "resizepart", partnum_str, endstr, NULL); if (r == -1) { reply_with_error ("parted: %s: %s:", device, err); return -1; } udev_settle(); return 0; }
/* 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) { if (partnum <= 0) { reply_with_error ("partition number must be >= 1"); return -1; } char partnum_str[16]; snprintf (partnum_str, sizeof partnum_str, "%d", partnum); CLEANUP_FREE char *out = NULL, *err = NULL; int r; udev_settle (); r = command (&out, &err, str_sfdisk, "--print-id", device, partnum_str, NULL); if (r == -1) { reply_with_error ("sfdisk --print-id: %s", err); return -1; } udev_settle (); /* It's printed in hex ... */ int id; if (sscanf (out, "%x", &id) != 1) { reply_with_error ("sfdisk --print-id: cannot parse output: %s", out); return -1; } return id; }
int do_part_set_bootable (const char *device, int partnum, int bootable) { int r; char *err; if (partnum <= 0) { reply_with_error ("partition number must be >= 1"); return -1; } char partstr[16]; snprintf (partstr, sizeof partstr, "%d", partnum); udev_settle (); r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, "parted", "-s", "--", device, "set", partstr, "boot", bootable ? "on" : "off", NULL); if (r == -1) { reply_with_error ("parted: %s: %s", device, err); free (err); return -1; } free (err); udev_settle (); return 0; }
int do_part_set_mbr_id (const char *device, int partnum, int idbyte) { if (partnum <= 0) { reply_with_error ("partition number must be >= 1"); return -1; } const char *param = test_sfdisk_has_part_type () ? "--part-type" : "--change-id"; char partnum_str[16]; snprintf (partnum_str, sizeof partnum_str, "%d", partnum); char idbyte_str[16]; /* NB: hex */ snprintf (idbyte_str, sizeof partnum_str, "%x", (unsigned) idbyte); CLEANUP_FREE char *err = NULL; int r; udev_settle (); r = command (NULL, &err, "sfdisk", param, device, partnum_str, idbyte_str, NULL); if (r == -1) { reply_with_error ("sfdisk %s: %s", param, err); return -1; } udev_settle (); return 0; }
int do_part_add (const char *device, const char *prlogex, int64_t startsect, int64_t endsect) { int r; char *err; char startstr[32]; char endstr[32]; /* Check and translate prlogex. */ if (STREQ (prlogex, "primary") || STREQ (prlogex, "logical") || STREQ (prlogex, "extended")) ; else if (STREQ (prlogex, "p")) prlogex = "primary"; else if (STREQ (prlogex, "l")) prlogex = "logical"; else if (STREQ (prlogex, "e")) prlogex = "extended"; else { reply_with_error ("unknown partition type: %s: this should be \"primary\", \"logical\" or \"extended\"", prlogex); return -1; } if (startsect < 0) { reply_with_error ("startsect cannot be negative"); return -1; } /* but endsect can be negative */ snprintf (startstr, sizeof startstr, "%" PRIi64 "s", startsect); snprintf (endstr, sizeof endstr, "%" PRIi64 "s", endsect); udev_settle (); /* XXX Bug: If the partition table type (which we don't know in this * function) is GPT, then this parted command sets the _partition * name_ to prlogex, eg. "primary". I would essentially describe * this as a bug in the parted mkpart command. */ r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, "parted", "-s", "--", device, "mkpart", prlogex, startstr, endstr, NULL); if (r == -1) { reply_with_error ("parted: %s: %s", device, err); free (err); return -1; } free (err); udev_settle (); return 0; }
int do_lvcreate_free (const char *logvol, const char *volgroup, int percent) { CLEANUP_FREE char *err = NULL; int r; if (percent < 0 || percent > 100) { reply_with_error ("percentage must be [0..100] (was %d)", percent); return -1; } char size[64]; snprintf (size, sizeof size, "%d%%FREE", percent); r = command (NULL, &err, str_lvm, "lvcreate", "-l", size, "-n", logvol, volgroup, NULL); if (r == -1) { reply_with_error ("%s", err); return -1; } udev_settle (); return 0; }
int do_luks_close (const char *device) { /* Must be /dev/mapper/... */ if (! STRPREFIX (device, "/dev/mapper/")) { reply_with_error ("luks_close: you must call this on the /dev/mapper device created by luks_open"); return -1; } const char *mapname = &device[12]; char *err; int r = command (NULL, &err, str_cryptsetup, "luksClose", mapname, NULL); if (r == -1) { reply_with_error ("%s", err); free (err); return -1; } free (err); udev_settle (); return 0; }
int do_vg_activate (int activate, char *const *volgroups) { int r, i, argc; CLEANUP_FREE char *err = NULL; CLEANUP_FREE const char **argv = NULL; argc = count_strings (volgroups) + 4; argv = malloc (sizeof (char *) * (argc+1)); if (argv == NULL) { reply_with_perror ("malloc"); return -1; } argv[0] = str_lvm; argv[1] = "vgchange"; argv[2] = "-a"; argv[3] = activate ? "y" : "n"; for (i = 4; i < argc+1; ++i) argv[i] = volgroups[i-4]; r = commandv (NULL, &err, (const char * const*) argv); if (r == -1) { reply_with_error ("vgchange: %s", err); return -1; } udev_settle (); return 0; }
int do_vgcreate (const char *volgroup, char *const *physvols) { char *err; int r, argc, i; const char **argv; argc = count_strings (physvols) + 3; argv = malloc (sizeof (char *) * (argc + 1)); if (argv == NULL) { reply_with_perror ("malloc"); return -1; } argv[0] = "lvm"; argv[1] = "vgcreate"; argv[2] = volgroup; for (i = 3; i <= argc; ++i) argv[i] = physvols[i-3]; r = commandv (NULL, &err, (const char * const*) argv); if (r == -1) { reply_with_error ("%s", err); free (err); free (argv); return -1; } free (err); free (argv); udev_settle (); return 0; }
int do_part_disk (const char *device, const char *parttype) { parttype = check_parttype (parttype); if (!parttype) { reply_with_error ("unknown partition type: common choices are \"gpt\" and \"msdos\""); return -1; } /* Align all partitions created this way to 128 sectors, and leave * the last 128 sectors at the end of the disk free. This wastes * 64K+64K = 128K on 512-byte sector disks. The rationale is: * * - aligned operations are faster * - absolute minimum recommended alignment is 64K (1M would be better) * - GPT requires at least 34 sectors at the end of the disk. */ const char *startstr = "128s"; const char *endstr = "-128s"; RUN_PARTED (return -1, device, "mklabel", parttype, /* See comment about about the parted mkpart command. */ "mkpart", STREQ (parttype, "gpt") ? "p1" : "primary", startstr, endstr, NULL); udev_settle (); return 0; }
static int pwrite_fd (int fd, const char *content, size_t size, int64_t offset, const char *display_path, int settle) { ssize_t r; r = pwrite (fd, content, size, offset); if (r == -1) { reply_with_perror ("pwrite: %s", display_path); close (fd); return -1; } if (close (fd) == -1) { reply_with_perror ("close: %s", display_path); return -1; } /* When you call close on any block device, udev kicks off a rule * which runs blkid to reexamine the device. We need to wait for * this rule to finish running since it holds the device open and * can cause other operations to fail, notably BLKRRPART. 'settle' * flag is only set on block devices. * * XXX We should be smarter about when we do this or should get rid * of the udev rules since we don't use blkid in cached mode. */ if (settle) udev_settle (); return r; }
int do_vgcreate (const char *volgroup, char *const *physvols) { int r, argc, i; CLEANUP_FREE char *err = NULL; CLEANUP_FREE const char **argv = NULL; argc = count_strings (physvols) + 3; argv = malloc (sizeof (char *) * (argc + 1)); if (argv == NULL) { reply_with_perror ("malloc"); return -1; } argv[0] = str_lvm; argv[1] = "vgcreate"; argv[2] = volgroup; for (i = 3; i < argc+1; ++i) argv[i] = physvols[i-3]; r = commandv (NULL, &err, (const char * const*) argv); if (r == -1) { reply_with_error ("%s", err); return -1; } udev_settle (); return 0; }
int do_part_disk (const char *device, const char *parttype) { int r; char *err; parttype = check_parttype (parttype); if (!parttype) { reply_with_error ("unknown partition type: common choices are \"gpt\" and \"msdos\""); return -1; } /* Align all partitions created this way to 128 sectors, and leave * the last 128 sectors at the end of the disk free. This wastes * 64K+64K = 128K on 512-byte sector disks. The rationale is: * * - aligned operations are faster * - absolute minimum recommended alignment is 64K (1M would be better) * - GPT requires at least 34 sectors* at the end of the disk. * * *=except for 4k sector disks, where only 6 sectors are required */ const char *startstr = "128s"; const char *endstr = "-128s"; udev_settle (); r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, "parted", "-s", "--", device, "mklabel", parttype, /* See comment about about the parted mkpart command. */ "mkpart", STREQ (parttype, "gpt") ? "p1" : "primary", startstr, endstr, NULL); if (r == -1) { reply_with_error ("parted: %s: %s", device, err); free (err); return -1; } free (err); udev_settle (); return 0; }
int do_part_init (const char *device, const char *parttype) { parttype = check_parttype (parttype); if (!parttype) { reply_with_error ("unknown partition type: common choices are \"gpt\" and \"msdos\""); return -1; } RUN_PARTED (return -1, device, "mklabel", parttype, NULL); udev_settle (); return 0; }
static int luks_open (const char *device, const char *key, const char *mapname, int readonly) { /* Sanity check: /dev/mapper/mapname must not exist already. Note * that the device-mapper control device (/dev/mapper/control) is * always there, so you can't ever have mapname == "control". */ size_t len = strlen (mapname); char devmapper[len+32]; snprintf (devmapper, len+32, "/dev/mapper/%s", mapname); if (access (devmapper, F_OK) == 0) { reply_with_error ("%s: device already exists", devmapper); return -1; } char *tempfile = write_key_to_temp (key); if (!tempfile) return -1; const char *argv[MAX_ARGS]; size_t i = 0; ADD_ARG (argv, i, str_cryptsetup); ADD_ARG (argv, i, "-d"); ADD_ARG (argv, i, tempfile); if (readonly) ADD_ARG (argv, i, "--readonly"); ADD_ARG (argv, i, "luksOpen"); ADD_ARG (argv, i, device); ADD_ARG (argv, i, mapname); ADD_ARG (argv, i, NULL); char *err; int r = commandv (NULL, &err, (const char * const *) argv); remove_temp (tempfile); if (r == -1) { reply_with_error ("%s", err); free (err); return -1; } free (err); udev_settle (); return 0; }
int do_part_del (const char *device, int partnum) { if (partnum <= 0) { reply_with_error ("partition number must be >= 1"); return -1; } 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_pvremove (const char *device) { CLEANUP_FREE char *err = NULL; int r; r = command (NULL, &err, str_lvm, "pvremove", "-ff", device, NULL); if (r == -1) { reply_with_error ("%s", err); return -1; } udev_settle (); return 0; }
int do_vgchange_uuid_all (void) { CLEANUP_FREE char *err = NULL; int r; r = command (NULL, &err, str_lvm, "vgchange", "-u", NULL); if (r == -1) { reply_with_error ("%s", err); return -1; } udev_settle (); return 0; }
/* Notes: * * Parted 1.9 sends error messages to stdout, hence use of the * COMMAND_FLAG_FOLD_STDOUT_ON_STDERR flag. * * parted occasionally fails to do ioctl(BLKRRPART) on the device, * probably because udev monitors all 'close' on block devices * and runs 'blkid' which opens and examines the device. We attempt * to detect and recover from this error if we can. */ static int recover_blkrrpart (const char *device, const char *err) { int r; if (!strstr (err, "Error informing the kernel about modifications to partition")) return -1; r = command (NULL, NULL, "blockdev", "--rereadpt", device, NULL); if (r == -1) return -1; udev_settle (); return 0; }
int do_vgrename (const char *volgroup, const char *newvolgroup) { CLEANUP_FREE char *err = NULL; int r; r = command (NULL, &err, str_lvm, "vgrename", volgroup, newvolgroup, NULL); if (r == -1) { reply_with_error ("%s -> %s: %s", volgroup, newvolgroup, err); return -1; } udev_settle (); return 0; }
int do_lvrename (const char *logvol, const char *newlogvol) { CLEANUP_FREE char *err = NULL; int r; r = command (NULL, &err, str_lvm, "lvrename", logvol, newlogvol, NULL); if (r == -1) { reply_with_error ("%s -> %s: %s", logvol, newlogvol, err); return -1; } udev_settle (); return 0; }
/* Takes optional arguments, consult optargs_bitmask. */ int do_mkswap (const char *device, const char *label, const char *uuid) { const size_t MAX_ARGS = 64; const char *argv[MAX_ARGS]; size_t i = 0; int r; CLEANUP_FREE char *err = NULL; ADD_ARG (argv, i, "mkswap"); ADD_ARG (argv, i, "-f"); if (optargs_bitmask & GUESTFS_MKSWAP_LABEL_BITMASK) { assert (label != NULL); /* suppress a warning with -O3 */ if (strlen (label) > SWAP_LABEL_MAX) { reply_with_error ("%s: Linux swap labels are limited to %d bytes", label, SWAP_LABEL_MAX); return -1; } ADD_ARG (argv, i, "-L"); ADD_ARG (argv, i, label); } if (optargs_bitmask & GUESTFS_MKSWAP_UUID_BITMASK) { ADD_ARG (argv, i, "-U"); ADD_ARG (argv, i, uuid); } ADD_ARG (argv, i, device); ADD_ARG (argv, i, NULL); wipe_device_before_mkfs (device); r = commandv (NULL, &err, argv); if (r == -1) { reply_with_error ("%s: %s", device, err); return -1; } udev_settle (); return 0; }
int do_part_set_bootable (const char *device, int partnum, int bootable) { if (partnum <= 0) { reply_with_error ("partition number must be >= 1"); return -1; } char partstr[16]; snprintf (partstr, sizeof partstr, "%d", partnum); RUN_PARTED (return -1, device, "set", partstr, "boot", bootable ? "on" : "off", NULL); udev_settle (); return 0; }
static int luks_format (const char *device, const char *key, int keyslot, const char *cipher) { char *tempfile = write_key_to_temp (key); if (!tempfile) return -1; const char *argv[MAX_ARGS]; char keyslot_s[16]; size_t i = 0; ADD_ARG (argv, i, str_cryptsetup); ADD_ARG (argv, i, "-q"); if (cipher) { ADD_ARG (argv, i, "--cipher"); ADD_ARG (argv, i, cipher); } ADD_ARG (argv, i, "--key-slot"); snprintf (keyslot_s, sizeof keyslot_s, "%d", keyslot); ADD_ARG (argv, i, keyslot_s); ADD_ARG (argv, i, "luksFormat"); ADD_ARG (argv, i, device); ADD_ARG (argv, i, tempfile); ADD_ARG (argv, i, NULL); char *err; int r = commandv (NULL, &err, (const char * const *) argv); remove_temp (tempfile); if (r == -1) { reply_with_error ("%s", err); free (err); return -1; } free (err); udev_settle (); return 0; }
int do_pvremove (const char *device) { char *err; int r; r = command (NULL, &err, "lvm", "pvremove", "-ff", device, NULL); if (r == -1) { reply_with_error ("%s", err); free (err); return -1; } free (err); udev_settle (); return 0; }
int do_lvcreate (const char *logvol, const char *volgroup, int mbytes) { CLEANUP_FREE char *err = NULL; int r; char size[64]; snprintf (size, sizeof size, "%d", mbytes); r = command (NULL, &err, str_lvm, "lvcreate", "-L", size, "-n", logvol, volgroup, NULL); if (r == -1) { reply_with_error ("%s", err); return -1; } udev_settle (); return 0; }