Пример #1
0
static char *
checksum (const char *csumtype, int fd)
{
  const char *program;
  char *out;
  CLEANUP_FREE char *err = NULL;
  int flags, r;
  size_t len;

  program = program_of_csum (csumtype);
  if (program == NULL)
    return NULL;

  pulse_mode_start ();

  flags = COMMAND_FLAG_CHROOT_COPY_FILE_TO_STDIN | fd;
  r = commandf (&out, &err, flags, program, NULL);
  if (r == -1) {
    pulse_mode_cancel ();
    reply_with_error ("%s: %s", program, err);
    free (out);
    return NULL;
  }

  /* Split it at the first whitespace. */
  len = strcspn (out, " \t\n");
  out[len] = '\0';

  pulse_mode_end ();

  return out;			/* Caller frees. */
}
Пример #2
0
char *
do_get_e2uuid (const char *device)
{
    const mountable_t mountable = {
        .type = MOUNTABLE_DEVICE,
        .device = /* not really ... */ (char *) device,
        .volume = NULL,
    };
    return do_vfs_uuid (&mountable);
}

/* If the filesystem is not mounted, run e2fsck -f on it unconditionally. */
static int
if_not_mounted_run_e2fsck (const char *device)
{
    CLEANUP_FREE char *err = NULL;
    int r, mounted;

    mounted = is_device_mounted (device);
    if (mounted == -1)
        return -1;

    if (!mounted) {
        r = commandf (NULL, &err,
                      COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
                      str_e2fsck, "-fy", device, NULL);
        if (r == -1) {
            reply_with_error ("%s", err);
            return -1;
        }
    }

    return 0;
}
Пример #3
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;
}
Пример #4
0
int
do_part_set_gpt_guid (const char *device, int partnum, const char *guid)
{
  if (partnum <= 0) {
    reply_with_error ("partition number must be >= 1");
    return -1;
  }

  CLEANUP_FREE char *typecode = NULL;
  if (asprintf (&typecode, "%i:%s", partnum, guid) == -1) {
    reply_with_perror ("asprintf");
    return -1;
  }

  CLEANUP_FREE char *err = NULL;
  int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
                    "sgdisk", device, "-u", typecode, NULL);

  if (r == -1) {
    reply_with_error ("%s %s -u %s: %s", "sgdisk", device, typecode, err);
    return -1;
  }

  return 0;
}
Пример #5
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;
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
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;
}
Пример #9
0
/* Run an arbitrary shell command using /bin/sh from the appliance.
 *
 * Note this is somewhat different from the ordinary guestfs_sh command
 * because it's not using the guest shell, and is not chrooted.
 */
static char *
debug_sh (const char *subcmd, size_t argc, char *const *const argv)
{
  CLEANUP_FREE char *cmd = NULL;
  size_t len, i, j;

  if (argc < 1) {
    reply_with_error ("sh: expecting a command to run");
    return NULL;
  }

  /* guestfish splits the parameter(s) into a list of strings,
   * and we have to reassemble them here.  Not ideal. XXX
   */
  for (i = len = 0; i < argc; ++i)
    len += strlen (argv[i]) + 1;
  cmd = malloc (len);
  if (!cmd) {
    reply_with_perror ("malloc");
    return NULL;
  }
  for (i = j = 0; i < argc; ++i) {
    len = strlen (argv[i]);
    memcpy (&cmd[j], argv[i], len);
    j += len;
    cmd[j] = ' ';
    j++;
  }
  cmd[j-1] = '\0';

  /* Set up some environment variables. */
  setenv ("root", sysroot, 1);
  if (access ("/sys/block/sda", F_OK) == 0)
    setenv ("sd", "sd", 1);
  else if (access ("/sys/block/hda", F_OK) == 0)
    setenv ("sd", "hd", 1);
  else if (access ("/sys/block/ubda", F_OK) == 0)
    setenv ("sd", "ubd", 1);
  else if (access ("/sys/block/vda", F_OK) == 0)
    setenv ("sd", "vd", 1);

  char *err;
  int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
                    "/bin/sh", "-c", cmd, NULL);
  if (r == -1) {
    reply_with_error ("%s", err);
    free (err);
    return NULL;
  }

  return err;
}
Пример #10
0
int
do_part_set_disk_guid_random (const char *device)
{
  CLEANUP_FREE char *err = NULL;
  int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
                    "sgdisk", device, "-U", "R", NULL);

  if (r == -1) {
    reply_with_error ("%s %s -U R: %s", "sgdisk", device, err);
    return -1;
  }

  return 0;
}
Пример #11
0
int
do_part_expand_gpt(const char *device)
{
  CLEANUP_FREE char *err = NULL;

  int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
                    "sgdisk", "-e", device, NULL);

  if (r == -1) {
    reply_with_error ("%s -e %s: %s", "sgdisk", device, err);
    return -1;
  }

  return 0;
}
Пример #12
0
/* Convenient place to test for the later version of e2fsprogs
 * and util-linux which supports -U parameters to specify UUIDs.
 * (Not supported in RHEL 5).
 */
int
optgroup_linuxfsuuid_available (void)
{
  CLEANUP_FREE char *err = NULL;
  int av;

  /* Upstream util-linux have been gradually changing '--help' to go
   * from stderr to stdout, and changing the return code from 1 to 0.
   * Thus we need to fold stdout and stderr together, and ignore the
   * return code.
   */
  ignore_value (commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
                          str_mkswap, "--help", NULL));

  av = strstr (err, "-U") != NULL;
  return av;
}
Пример #13
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;
}
Пример #14
0
char *
do_part_get_disk_guid (const char *device)
{
  const char *pattern = "Disk identifier (GUID):";
  size_t i;

  CLEANUP_FREE char *err = NULL;
  int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
                    "sgdisk", device, "-p", NULL);
  if (r == -1) {
    reply_with_error ("%s %s -p: %s", "sgdisk", device, err);
    return NULL;
  }

  CLEANUP_FREE_STRING_LIST char **lines = split_lines (err);
  if (lines == NULL) {
    reply_with_error ("'%s %s -p' returned no output",
                      "sgdisk", device);
    return NULL;
  }

  for (i = 0; lines[i] != NULL; ++i) {
    if (STRPREFIX (lines[i], pattern)) {
      char *value = lines[i] + strlen (pattern);

      /* Skip any leading whitespace */
      value += strspn (value, " \t");

      /* Extract the actual information from the field. */
      char *ret = extract_uuid (value);
      if (ret == NULL) {
        /* The extraction function already sends the error. */
        return NULL;
      }

      return ret;
    }
  }

  /* If we got here it means we didn't find the field */
  reply_with_error ("sgdisk output did not contain disk GUID. "
                    "See LIBGUESTFS_DEBUG output for more details");
  return NULL;
}
Пример #15
0
static int
wc (const char *flag, const char *path)
{
  char *out, *err;
  int fd, flags, r;

  CHROOT_IN;
  fd = open (path, O_RDONLY);
  CHROOT_OUT;

  if (fd == -1) {
    reply_with_perror ("wc %s: %s", flag, path);
    return -1;
  }

  flags = COMMAND_FLAG_CHROOT_COPY_FILE_TO_STDIN | fd;
  r = commandf (&out, &err, flags, "wc", flag, NULL);
  if (r == -1) {
    reply_with_error ("wc %s: %s", flag, err);
    free (out);
    free (err);
    return -1;
  }

  free (err);

#if 0
  /* Split it at the first whitespace. */
  len = strcspn (out, " \t\n");
  out[len] = '\0';
#endif

  /* Parse the number. */
  if (sscanf (out, "%d", &r) != 1) {
    reply_with_error ("cannot parse number: %s", out);
    free (out);
    return -1;
  }

  free (out);
  return r;
}
Пример #16
0
char *
do_part_get_gpt_type(const char *device, int partnum)
{
  if (partnum <= 0) {
    reply_with_error ("partition number must be >= 1");
    return NULL;
  }

  CLEANUP_FREE char *partnum_str = NULL;
  if (asprintf (&partnum_str, "%i", partnum) == -1) {
    reply_with_perror ("asprintf");
    return NULL;
  }

  CLEANUP_FREE char *err = NULL;
  int r = commandf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR,
                    str_sgdisk, device, "-i", partnum_str, NULL);

  if (r == -1) {
    reply_with_error ("%s %s -i %s: %s", str_sgdisk, device, partnum_str, err);
    return NULL;
  }

  char **lines = split_lines (err);
  if (lines == NULL) {
    reply_with_error ("'%s %s -i %i' returned no output",
                      str_sgdisk, device, partnum);
    return NULL;
  }

  /* Parse the output of sgdisk -i:
   * Partition GUID code: 21686148-6449-6E6F-744E-656564454649 (BIOS boot partition)
   * Partition unique GUID: 19AEC5FE-D63A-4A15-9D37-6FCBFB873DC0
   * First sector: 2048 (at 1024.0 KiB)
   * Last sector: 411647 (at 201.0 MiB)
   * Partition size: 409600 sectors (200.0 MiB)
   * Attribute flags: 0000000000000000
   * Partition name: 'EFI System Partition'
   */
  for (char **i = lines; *i != NULL; i++) {
    char *line = *i;

    /* Skip blank lines */
    if (line[0] == '\0') continue;

    /* Split the line in 2 at the colon */
    char *colon = strchr (line, ':');
    if (colon) {
#define SEARCH "Partition GUID code"
      if (colon - line == strlen(SEARCH) &&
          memcmp (line, SEARCH, strlen(SEARCH)) == 0)
      {
#undef SEARCH
        /* The value starts after the colon */
        char *value = colon + 1;

        /* Skip any leading whitespace */
        value += strspn (value, " \t");

        /* The value contains only valid GUID characters */
        size_t value_len = strspn (value, "-0123456789ABCDEF");

        char *ret = malloc (value_len + 1);
        if (ret == NULL) {
          reply_with_perror ("malloc");
          return NULL;
        }

        memcpy (ret, value, value_len);
        ret[value_len] = '\0';
        return ret;
      }
    } else {
      /* Ignore lines with no colon. Log to stderr so it will show up in
       * LIBGUESTFS_DEBUG. */
      if (verbose) {
        fprintf (stderr, "get-gpt-type: unexpected sgdisk output ignored: %s\n",
                 line);
      }
    }
  }

  /* If we got here it means we didn't find the Partition GUID code */
  reply_with_error ("sgdisk output did not contain Partition GUID code. "
                    "See LIBGUESTFS_DEBUG output for more details");
  return NULL;
}