Exemple #1
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);

  char *out, *err;
  int r;

  udev_settle ();

  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);

  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);
    free (out);
    return -1;
  }

  free (out);
  return id;
}
Exemple #2
0
static int
dosfslabel (const char *device, const char *label)
{
  int r;
  CLEANUP_FREE char *err = NULL;

  r = command (NULL, &err, str_dosfslabel, device, label, NULL);
  if (r == -1) {
    reply_with_error ("%s", err);
    return -1;
  }

  return 0;
}
Exemple #3
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;
}
Exemple #4
0
int
swap_set_uuid (const char *device, const char *uuid)
{
  int r;
  CLEANUP_FREE char *err = NULL;

  r = command (NULL, &err, "swaplabel", "-U", uuid, device, NULL);
  if (r == -1) {
    reply_with_error ("%s", err);
    return -1;
  }

  return 0;
}
Exemple #5
0
int
do_md_stop (const char *md)
{
  int r;
  CLEANUP_FREE char *err = NULL;

  const char *mdadm[] = { str_mdadm, "--stop", md, NULL};
  r = commandv (NULL, &err, mdadm);
  if (r == -1) {
    reply_with_error ("%s", err);
    return -1;
  }
  return 0;
}
Exemple #6
0
int
do_scrub_device (const char *device)
{
  CLEANUP_FREE char *err = NULL;
  int r;

  r = command (NULL, &err, str_scrub, device, NULL);
  if (r == -1) {
    reply_with_error ("%s: %s", device, err);
    return -1;
  }

  return 0;
}
Exemple #7
0
static int
e2uuid (const char *device, const char *uuid)
{
  /* Don't allow the magic values here.  If callers want to do this
   * we'll add alternate set_uuid_* calls.
   */
  if (STREQ (uuid, "clear") || STREQ (uuid, "random") ||
      STREQ (uuid, "time")) {
    reply_with_error ("e2: invalid new UUID");
    return -1;
  }

  return do_set_e2uuid (device, uuid);
}
Exemple #8
0
/* Takes optional arguments, consult optargs_bitmask. */
int
do_ntfsresize (const char *device, int64_t size, int force)
{
  CLEANUP_FREE char *err = NULL;
  int r;
  const char *argv[MAX_ARGS];
  size_t i = 0;
  char size_str[32];

  ADD_ARG (argv, i, str_ntfsresize);
  ADD_ARG (argv, i, "-P");

  if (optargs_bitmask & GUESTFS_NTFSRESIZE_SIZE_BITMASK) {
    if (size <= 0) {
      reply_with_error ("size is zero or negative");
      return -1;
    }

    snprintf (size_str, sizeof size_str, "%" PRIi64, size);
    ADD_ARG (argv, i, "--size");
    ADD_ARG (argv, i, size_str);
  }

  if (optargs_bitmask & GUESTFS_NTFSRESIZE_FORCE_BITMASK && force)
    ADD_ARG (argv, i, "--force");

  ADD_ARG (argv, i, device);
  ADD_ARG (argv, i, NULL);

  r = commandvf (NULL, &err, COMMAND_FLAG_FOLD_STDOUT_ON_STDERR, argv);
  if (r == -1) {
    reply_with_error ("%s: %s", device, err);
    return -1;
  }

  return 0;
}
Exemple #9
0
/* Run 'ldd' on a file from the appliance.
 * See tests/regressions/rhbz727178.sh
 */
static char *
debug_ldd (const char *subcmd, size_t argc, char *const *const argv)
{
  int r;
  char *out, *ret;
  CLEANUP_FREE char *err = NULL;

  if (argc != 1) {
    reply_with_error ("ldd: no file argument");
    return NULL;
  }

  /* Note that 'ldd' doesn't fail if it finds errors.  We have to grep
   * for errors in the regression test instead.  'ldd' only fails here
   * if the binary is not a binary at all (eg. for shell scripts).
   * Also 'ldd' randomly sends messages to stderr and errors to stdout
   * depending on the phase of the moon.
   */
  r = command (&out, &err, str_ldd, "-r", argv[0], NULL);
  if (r == -1) {
    reply_with_error ("ldd: %s: %s", argv[0], err);
    free (out);
    return NULL;
  }

  /* Concatenate stdout and stderr in the result. */
  ret = realloc (out, strlen (out) + strlen (err) + 1);
  if (ret == NULL) {
    reply_with_perror ("realloc");
    free (out);
    return NULL;
  }

  strcat (ret, err);

  return ret;
}
Exemple #10
0
char *
get_blkid_tag (const char *device, const char *tag)
{
  char *out;
  CLEANUP_FREE char *err = NULL;
  int r;
  size_t len;

  r = commandr (&out, &err,
                str_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);
    return NULL;
  }

  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. */
  len = strlen (out);
  if (len > 0 && out[len-1] == '\n')
    out[len-1] = '\0';

  return out;                   /* caller frees */
}
Exemple #11
0
int
do_mke2fs_JL (const char *fstype, int blocksize, const char *device,
              const char *label)
{
    CLEANUP_FREE char *err = NULL;
    int r;

    if (!fstype_is_extfs (fstype)) {
        reply_with_error ("%s: not a valid extended filesystem type", fstype);
        return -1;
    }

    if (strlen (label) > EXT2_LABEL_MAX) {
        reply_with_error ("%s: ext2/3/4 labels are limited to %d bytes",
                          label, EXT2_LABEL_MAX);
        return -1;
    }

    char blocksize_s[32];
    snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize);

    size_t len = strlen (label);
    char jdev[len+32];
    snprintf (jdev, len+32, "device=LABEL=%s", label);

    wipe_device_before_mkfs (device);

    r = command (NULL, &err,
                 str_mke2fs, "-F", "-t", fstype, "-J", jdev, "-b", blocksize_s,
                 device, NULL);
    if (r == -1) {
        reply_with_error ("%s", err);
        return -1;
    }

    return 0;
}
Exemple #12
0
/* zcat | file */
char *
do_zfile (const char *method, const char *path)
{
  size_t len;
  const char *zcat;
  CLEANUP_FREE char *cmd = NULL;
  FILE *fp;
  char line[256];

  if (STREQ (method, "gzip") || STREQ (method, "compress"))
    zcat = str_zcat;
  else if (STREQ (method, "bzip2"))
    zcat = str_bzcat;
  else {
    reply_with_error ("unknown method");
    return NULL;
  }

  if (asprintf_nowarn (&cmd, "%s %R | file -bsL -", zcat, path) == -1) {
    reply_with_perror ("asprintf");
    return NULL;
  }

  if (verbose)
    fprintf (stderr, "%s\n", cmd);

  fp = popen (cmd, "r");
  if (fp == NULL) {
    reply_with_perror ("%s", cmd);
    return NULL;
  }

  if (fgets (line, sizeof line, fp) == NULL) {
    reply_with_perror ("fgets");
    pclose (fp);
    return NULL;
  }

  if (pclose (fp) == -1) {
    reply_with_perror ("pclose");
    return NULL;
  }

  len = strlen (line);
  if (len > 0 && line[len-1] == '\n')
    line[len-1] = '\0';

  return strdup (line);
}
Exemple #13
0
void
reply (xdrproc_t xdrp, char *ret)
{
  XDR xdr;
  CLEANUP_FREE char *buf = NULL;
  char lenbuf[4];
  struct guestfs_message_header hdr;
  uint32_t len;

  buf = malloc (GUESTFS_MESSAGE_MAX);
  if (!buf)
    error (EXIT_FAILURE, errno, "malloc");
  xdrmem_create (&xdr, buf, GUESTFS_MESSAGE_MAX, XDR_ENCODE);

  memset (&hdr, 0, sizeof hdr);
  hdr.prog = GUESTFS_PROGRAM;
  hdr.vers = GUESTFS_PROTOCOL_VERSION;
  hdr.direction = GUESTFS_DIRECTION_REPLY;
  hdr.status = GUESTFS_STATUS_OK;
  hdr.proc = proc_nr;
  hdr.serial = serial;

  if (!xdr_guestfs_message_header (&xdr, &hdr))
    error (EXIT_FAILURE, 0, "failed to encode reply header");

  if (xdrp) {
    /* This can fail if the reply body is too large, for example
     * if it exceeds the maximum message size.  In that case
     * we want to return an error message instead. (RHBZ#509597).
     */
    if (!(*xdrp) (&xdr, ret)) {
      reply_with_error ("guestfsd: failed to encode reply body\n(maybe the reply exceeds the maximum message size in the protocol?)");
      xdr_destroy (&xdr);
      return;
    }
  }

  len = xdr_getpos (&xdr);
  xdr_destroy (&xdr);

  xdrmem_create (&xdr, lenbuf, 4, XDR_ENCODE);
  xdr_u_int (&xdr, &len);
  xdr_destroy (&xdr);

  if (xwrite (sock, lenbuf, 4) == -1)
    error (EXIT_FAILURE, 0, "xwrite failed");
  if (xwrite (sock, buf, (size_t) len) == -1)
    error (EXIT_FAILURE, 0, "xwrite failed");
}
Exemple #14
0
int
do_touch (const char *path)
{
  int fd;
  int r;
  struct stat buf;

  /* RHBZ#582484: Restrict touch to regular files.  It's also OK
   * here if the file does not exist, since we will create it.
   */
  CHROOT_IN;
  r = lstat (path, &buf);
  CHROOT_OUT;

  if (r == -1) {
    if (errno != ENOENT) {
      reply_with_perror ("lstat: %s", path);
      return -1;
    }
  } else {
    if (! S_ISREG (buf.st_mode)) {
      reply_with_error ("%s: touch can only be used on a regular files", path);
      return -1;
    }
  }

  CHROOT_IN;
  fd = open (path, O_WRONLY | O_CREAT | O_NOCTTY, 0666);
  CHROOT_OUT;

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

  r = futimens (fd, NULL);
  if (r == -1) {
    reply_with_perror ("futimens: %s", path);
    close (fd);
    return -1;
  }

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

  return 0;
}
Exemple #15
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;
}
Exemple #16
0
char *
do_ldmtool_diskgroup_name (const char *diskgroup)
{
  int r;
  CLEANUP_FREE char *out = NULL, *err = NULL;

  r = command (&out, &err, "ldmtool", "show", "diskgroup", diskgroup, NULL);
  if (r == -1) {
    reply_with_error ("%s", err);
    return NULL;
  }

  return parse_json_get_object_string (out, "name", 0,
                                       __func__, "ldmtool show diskgroup");
}
Exemple #17
0
/* Return canonical name of LV to caller (RHBZ#638899). */
char *
do_lvm_canonical_lv_name (const char *device)
{
  char *canonical;
  int r = lv_canonical (device, &canonical);
  if (r == -1)
    return NULL;

  if (r == 0) {
    reply_with_error ("%s: not a logical volume", device);
    return NULL;
  }

  return canonical;             /* caller frees */
}
Exemple #18
0
int
do_part_to_partnum (const char *part)
{
  int err = 1;
  size_t n = strlen (part);

  while (n >= 1 && c_isdigit (part[n-1])) {
    err = 0;
    n--;
  }

  if (err) {
    reply_with_error ("device name is not a partition");
    return -1;
  }

  int r;
  if (sscanf (&part[n], "%d", &r) != 1) {
    reply_with_error ("could not parse number");
    return -1;
  }

  return r;
}
Exemple #19
0
char *
do_part_get_name (const char *device, int partnum)
{
  CLEANUP_FREE char *parttype;

  parttype = do_part_get_parttype (device);
  if (parttype == NULL)
    return NULL;

  if (STREQ (parttype, "gpt")) {
    CLEANUP_FREE char *out = print_partition_table (device, true);
    if (!out)
      return NULL;

    CLEANUP_FREE_STRING_LIST char **lines = split_lines (out);

    if (!lines)
      return NULL;

    if (lines[0] == NULL || STRNEQ (lines[0], "BYT;")) {
      reply_with_error ("unknown signature, expected \"BYT;\" as first line of the output: %s",
                        lines[0] ? lines[0] : "(signature was null)");
      return NULL;
    }

    if (lines[1] == NULL) {
      reply_with_error ("parted didn't return a line describing the device");
      return NULL;
    }

    size_t row;
    int pnum;
    for (row = 2; lines[row] != NULL; ++row) {
      if (sscanf (lines[row], "%d:", &pnum) != 1) {
        reply_with_error ("could not parse row from output of parted print command: %s", lines[row]);
        return NULL;
      }
      if (pnum == partnum)
        break;
    }

    if (lines[row] == NULL) {
      reply_with_error ("partition number %d not found", partnum);
      return NULL;
    }

    char *name = get_table_field (lines[row], 5);
    if (name == NULL)
      reply_with_error ("cannot get the name field from '%s'", lines[row]);

    return name;
  } else {
    reply_with_error ("part-get-name can only be used on GUID Partition Tables");
    return NULL;
  }
}
Exemple #20
0
int
do_vgscan (void)
{
  CLEANUP_FREE char *err = NULL;
  int r;

  r = command (NULL, &err,
               str_lvm, "vgscan", NULL);
  if (r == -1) {
    reply_with_error ("%s", err);
    return -1;
  }

  return 0;
}
Exemple #21
0
/* setcon is only valid under the following circumstances:
 * - single threaded
 * - enforcing=0
 */
int
do_setcon (const char *context)
{
#if defined(HAVE_SETCON)
    if (setcon ((char *) context) == -1) {
        reply_with_perror ("setcon");
        return -1;
    }

    return 0;
#else
    reply_with_error ("function not available");
    return -1;
#endif
}
Exemple #22
0
int64_t
xfs_minimum_size (const char *path)
{
  CLEANUP_FREE guestfs_int_xfsinfo *info = do_xfs_info (path);

  if (info == NULL)
    return -1;

  // XFS does not support shrinking.
  if (INT64_MAX / info->xfs_blocksize < info->xfs_datablocks) {
    reply_with_error ("filesystem size too big: overflow");
    return -1;
  }
  return info->xfs_blocksize * info->xfs_datablocks;
}
Exemple #23
0
/* Send back an error of different lengths. */
static char *
debug_error (const char *subcmd, size_t argc, char *const *const argv)
{
  unsigned len;
  CLEANUP_FREE char *buf = NULL;

  if (argc != 1) {
  error:
    reply_with_error ("debug error: expecting one arg: length of error message");
    return NULL;
  }

  if (sscanf (argv[0], "%u", &len) != 1)
    goto error;

  if (len > 1000000) {
    reply_with_error ("debug error: length argument too large");
    return NULL;
  }

  buf = malloc (len + 1);
  if (buf == NULL) {
    reply_with_perror ("malloc");
    return NULL;
  }

  memset (buf, 'a', len);
  buf[len] = '\0';

  /* So that the regression test can tell this is the true return path
   * from the function and not an actual error, we set errno to some
   * value that cannot be returned by any other error path.
   */
  reply_with_error_errno (EROFS, "%s", buf);
  return NULL;
}
Exemple #24
0
static int
wc (const char *flag, const char *path)
{
  CLEANUP_FREE char *out = NULL, *err = NULL;
  int fd, flags, r;

  CHROOT_IN;
  fd = open (path, O_RDONLY|O_CLOEXEC);
  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);
    return -1;
  }

#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);
    return -1;
  }

  return r;
}
Exemple #25
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;
}
Exemple #26
0
/* Print the environment that commands get (by running external printenv). */
static char *
debug_env (const char *subcmd, size_t argc, char *const *const argv)
{
  int r;
  char *out;
  CLEANUP_FREE char *err = NULL;

  r = command (&out, &err, str_printenv, NULL);
  if (r == -1) {
    reply_with_error ("printenv: %s", err);
    free (out);
    return NULL;
  }

  return out;
}
Exemple #27
0
int
do_md_stop(const char *md)
{
  int r;
  char *err = NULL;

  const char *mdadm[] = { "mdadm", "--stop", md, NULL};
  r = commandv(NULL, &err, mdadm);
  if (r == -1) {
    reply_with_error("%s", err);
    free(err);
    return -1;
  }
  free (err);
  return 0;
}
Exemple #28
0
int
do_fsck (const char *fstype, const char *device)
{
  char *err;
  int r;

  r = commandr (NULL, &err, "fsck", "-a", "-t", fstype, device, NULL);
  if (r == -1) {
    reply_with_error ("%s: %s", device, err);
    free (err);
    return -1;
  }

  free (err);
  return r;
}
Exemple #29
0
char *
do_debug (const char *subcmd, char *const *argv)
{
  size_t argc, i;

  for (i = argc = 0; argv[i] != NULL; ++i)
    argc++;

  for (i = 0; cmds[i].cmd != NULL; ++i) {
    if (STRCASEEQ (subcmd, cmds[i].cmd))
      return cmds[i].f (subcmd, argc, argv);
  }

  reply_with_error ("use 'debug help 0' to list the supported commands");
  return NULL;
}
Exemple #30
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;
}