Example #1
0
int
do_luks_kill_slot (const char *device, const char *key, int keyslot)
{
  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");
  ADD_ARG (argv, i, "-d");
  ADD_ARG (argv, i, tempfile);
  ADD_ARG (argv, i, "luksKillSlot");
  ADD_ARG (argv, i, device);
  snprintf (keyslot_s, sizeof keyslot_s, "%d", keyslot);
  ADD_ARG (argv, i, keyslot_s);
  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);

  return 0;
}
Example #2
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;
}
Example #3
0
/* Internal function used to wipe disks before we do 'mkfs'-type
 * operations on them.  For the rationale see RHBZ#889888 and
 * RHBZ#907554.
 *
 * Note this is really destructive, so only call it just before doing
 * the 'mkfs' operation (ie. after doing as much pre-checking as
 * possible).  Otherwise you could end up with a 'mkfs' operation
 * failing with an error but still wiping data.
 */
void
wipe_device_before_mkfs (const char *device)
{
  int force;
  const size_t MAX_ARGS = 16;
  const char *argv[MAX_ARGS];
  size_t i = 0;

  force = wipefs_has_force_option ();
  if (force == -1)
    return;

  ADD_ARG (argv, i, str_wipefs);
  ADD_ARG (argv, i, "-a");
  if (force)
    ADD_ARG (argv, i, "--force");
  ADD_ARG (argv, i, device);
  ADD_ARG (argv, i, NULL);

  ignore_value (commandv (NULL, NULL, argv));

  /* XXX We could fall back to overwriting bits of disk here, but if
   * they don't have working wipefs, it seems unlikely they are using
   * btrfs which is what mostly causes this problem.  See:
   * http://www.spinics.net/lists/linux-btrfs/msg21197.html
   */
}
Example #4
0
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;
}
Example #5
0
int
do_wipefs (const char *device)
{
  int force;
  int r;
  CLEANUP_FREE char *err = NULL;
  const size_t MAX_ARGS = 16;
  const char *argv[MAX_ARGS];
  size_t i = 0;

  force = wipefs_has_force_option ();
  if (force == -1)
    return -1;

  ADD_ARG (argv, i, str_wipefs);
  ADD_ARG (argv, i, "-a");
  if (force)
    ADD_ARG (argv, i, "--force");
  ADD_ARG (argv, i, device);
  ADD_ARG (argv, i, NULL);

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

  return 0;
}
Example #6
0
/* List files in the appliance. */
static char *
debug_ll (const char *subcmd, size_t argc, char *const *const argv)
{
  const size_t len = guestfs_int_count_strings (argv);
  CLEANUP_FREE const char **cargv = NULL;
  size_t i;
  int r;
  char *out;
  CLEANUP_FREE char *err = NULL;

  cargv = malloc (sizeof (char *) * (len+3));
  if (cargv == NULL) {
    reply_with_perror ("malloc");
    return NULL;
  }

  cargv[0] = "ls";
  cargv[1] = "-la";
  for (i = 0; i < len; ++i)
    cargv[2+i] = argv[i];
  cargv[2+len] = NULL;

  r = commandv (&out, &err, (void *) cargv);
  if (r == -1) {
    reply_with_error ("ll: %s", err);
    free (out);
    return NULL;
  }

  return out;
}
Example #7
0
/* Takes optional arguments, consult optargs_bitmask. */
int
do_ntfsfix (const char *device, int clearbadsectors)
{
  const char *argv[MAX_ARGS];
  size_t i = 0;
  int r;
  CLEANUP_FREE char *err = NULL;

  ADD_ARG (argv, i, str_ntfsfix);

  if ((optargs_bitmask & GUESTFS_NTFSFIX_CLEARBADSECTORS_BITMASK) &&
      clearbadsectors)
    ADD_ARG (argv, i, "-b");

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

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

  return 0;
}
Example #8
0
static int
rsync (const char *src, const char *src_orig,
       const char *dest, const char *dest_orig,
       int archive, int deletedest)
{
  const char *argv[MAX_ARGS];
  size_t i = 0;
  int r;
  CLEANUP_FREE char *err = NULL;

  ADD_ARG (argv, i, str_rsync);

  if (archive)
    ADD_ARG (argv, i, "--archive");

  if (deletedest)
    ADD_ARG (argv, i, "--delete");

  ADD_ARG (argv, i, src);
  ADD_ARG (argv, i, dest);
  ADD_ARG (argv, i, NULL);

  r = commandv (NULL, &err, argv);
  if (r == -1) {
    reply_with_error ("'%s' to '%s': %s", src_orig, dest_orig, err);
    return -1;
  }

  return 0;
}
Example #9
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;
}
Example #10
0
/* List files in the appliance. */
static char *
debug_ll (const char *subcmd, size_t argc, char *const *const argv)
{
  size_t len = count_strings (argv);
  const char *cargv[len+3];
  size_t i;
  int r;
  char *out;
  CLEANUP_FREE char *err = NULL;

  cargv[0] = str_ls;
  cargv[1] = "-la";
  for (i = 0; i < len; ++i)
    cargv[2+i] = argv[i];
  cargv[2+len] = NULL;

  r = commandv (&out, &err, (void *) cargv);
  if (r == -1) {
    reply_with_error ("ll: %s", err);
    free (out);
    return NULL;
  }

  return out;
}
Example #11
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;
}
Example #12
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;
}
Example #13
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;
}
Example #14
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;
}
Example #15
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;
}
Example #16
0
/* Takes optional arguments, consult optargs_bitmask. */
int
do_ntfsresize (const char *device, int64_t size, int force)
{
  char *err;
  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 = commandv (NULL, &err, argv);
  if (r == -1) {
    reply_with_error ("%s: %s", device, err);
    free (err);
    return -1;
  }

  free (err);
  return 0;
}
Example #17
0
/* Takes optional arguments, consult optargs_bitmask. */
int
do_md_create (const char *name, char *const *devices,
              int64_t missingbitmap, int nrdevices, int spare,
              int64_t chunk, const char *level)
{
  char nrdevices_s[32];
  char spare_s[32];
  char chunk_s[32];
  size_t j;
  int r;
  char *err;
  uint64_t umissingbitmap = (uint64_t) missingbitmap;

  /* Check the optional parameters and set defaults where appropriate. */
  if (!(optargs_bitmask & GUESTFS_MD_CREATE_MISSINGBITMAP_BITMASK))
    umissingbitmap = 0;

  if (optargs_bitmask & GUESTFS_MD_CREATE_SPARE_BITMASK) {
    if (spare < 0) {
      reply_with_error ("spare must not be negative");
      return -1;
    }
  }
  else
    spare = 0;

  if (optargs_bitmask & GUESTFS_MD_CREATE_NRDEVICES_BITMASK) {
    if (nrdevices < 2) {
      reply_with_error ("nrdevices is less than 2");
      return -1;
    }
  }
  else
    nrdevices = count_strings (devices) + count_bits (umissingbitmap);

  if (optargs_bitmask & GUESTFS_MD_CREATE_LEVEL_BITMASK) {
    if (STRNEQ (level, "linear") && STRNEQ (level, "raid0") &&
        STRNEQ (level, "0") && STRNEQ (level, "stripe") &&
        STRNEQ (level, "raid1") && STRNEQ (level, "1") &&
        STRNEQ (level, "mirror") &&
        STRNEQ (level, "raid4") && STRNEQ (level, "4") &&
        STRNEQ (level, "raid5") && STRNEQ (level, "5") &&
        STRNEQ (level, "raid6") && STRNEQ (level, "6") &&
        STRNEQ (level, "raid10") && STRNEQ (level, "10")) {
      reply_with_error ("unknown level parameter: %s", level);
      return -1;
    }
  }
  else
    level = "raid1";

  if (optargs_bitmask & GUESTFS_MD_CREATE_CHUNK_BITMASK) {
    /* chunk is bytes in the libguestfs API, but K when we pass it to mdadm */
    if ((chunk & 1023) != 0) {
      reply_with_error ("chunk size must be a multiple of 1024 bytes");
      return -1;
    }
  }

  /* Check invariant. */
  if (count_strings (devices) + count_bits (umissingbitmap) !=
      (size_t) (nrdevices + spare)) {
    reply_with_error ("devices (%zu) + bits set in missingbitmap (%zu) is not equal to nrdevices (%d) + spare (%d)",
                      count_strings (devices), count_bits (umissingbitmap),
                      nrdevices, spare);
    return -1;
  }

  size_t MAX_ARGS = nrdevices + 16;
  const char *argv[MAX_ARGS];
  size_t i = 0;

  ADD_ARG (argv, i, "mdadm");
  ADD_ARG (argv, i, "--create");
  /* --run suppresses "Continue creating array" question */
  ADD_ARG (argv, i, "--run");
  ADD_ARG (argv, i, name);
  ADD_ARG (argv, i, "--level");
  ADD_ARG (argv, i, level);
  ADD_ARG (argv, i, "--raid-devices");
  snprintf (nrdevices_s, sizeof nrdevices_s, "%d", nrdevices);
  ADD_ARG (argv, i, nrdevices_s);
  if (optargs_bitmask & GUESTFS_MD_CREATE_SPARE_BITMASK) {
    ADD_ARG (argv, i, "--spare-devices");
    snprintf (spare_s, sizeof spare_s, "%d", spare);
    ADD_ARG (argv, i, spare_s);
  }
  if (optargs_bitmask & GUESTFS_MD_CREATE_CHUNK_BITMASK) {
    ADD_ARG (argv, i, "--chunk");
    snprintf (chunk_s, sizeof chunk_s, "%" PRIi64, chunk / 1024);
    ADD_ARG (argv, i, chunk_s);
  }

  /* Add devices and "missing". */
  j = 0;
  while (devices[j] != NULL || umissingbitmap != 0) {
    if (umissingbitmap & 1)
      ADD_ARG (argv, i, "missing");
    else {
      ADD_ARG (argv, i, devices[j]);
      j++;
    }
    umissingbitmap >>= 1;
  }

  ADD_ARG (argv, i, NULL);

  r = commandv (NULL, &err, argv);
  if (r == -1) {
    reply_with_error ("mdadm: %s: %s", name, err);
    free (err);
    return -1;
  }

  free (err);

  udev_settle ();

  return 0;
}
Example #18
0
/* Takes optional arguments, consult optargs_bitmask. */
int
do_tune2fs (const char *device, /* only required parameter */
            int force,
            int maxmountcount,
            int mountcount,
            const char *errorbehavior,
            int64_t group,
            int intervalbetweenchecks,
            int reservedblockspercentage,
            const char *lastmounteddirectory,
            int64_t reservedblockscount,
            int64_t user)
{
    const char *argv[MAX_ARGS];
    size_t i = 0;
    int r;
    CLEANUP_FREE char *err = NULL;
    char maxmountcount_s[64];
    char mountcount_s[64];
    char group_s[64];
    char intervalbetweenchecks_s[64];
    char reservedblockspercentage_s[64];
    char reservedblockscount_s[64];
    char user_s[64];

    ADD_ARG (argv, i, str_tune2fs);

    if (optargs_bitmask & GUESTFS_TUNE2FS_FORCE_BITMASK) {
        if (force)
            ADD_ARG (argv, i, "-f");
    }

    if (optargs_bitmask & GUESTFS_TUNE2FS_MAXMOUNTCOUNT_BITMASK) {
        if (maxmountcount < 0) {
            reply_with_error ("maxmountcount cannot be negative");
            return -1;
        }
        ADD_ARG (argv, i, "-c");
        snprintf (maxmountcount_s, sizeof maxmountcount_s, "%d", maxmountcount);
        ADD_ARG (argv, i, maxmountcount_s);
    }

    if (optargs_bitmask & GUESTFS_TUNE2FS_MOUNTCOUNT_BITMASK) {
        if (mountcount < 0) {
            reply_with_error ("mountcount cannot be negative");
            return -1;
        }
        ADD_ARG (argv, i, "-C");
        snprintf (mountcount_s, sizeof mountcount_s, "%d", mountcount);
        ADD_ARG (argv, i, mountcount_s);
    }

    if (optargs_bitmask & GUESTFS_TUNE2FS_ERRORBEHAVIOR_BITMASK) {
        if (STRNEQ (errorbehavior, "continue") &&
                STRNEQ (errorbehavior, "remount-ro") &&
                STRNEQ (errorbehavior, "panic")) {
            reply_with_error ("invalid errorbehavior parameter: %s", errorbehavior);
            return -1;
        }
        ADD_ARG (argv, i, "-e");
        ADD_ARG (argv, i, errorbehavior);
    }

    if (optargs_bitmask & GUESTFS_TUNE2FS_GROUP_BITMASK) {
        if (group < 0) {
            reply_with_error ("group cannot be negative");
            return -1;
        }
        ADD_ARG (argv, i, "-g");
        snprintf (group_s, sizeof group_s, "%" PRIi64, group);
        ADD_ARG (argv, i, group_s);
    }

    if (optargs_bitmask & GUESTFS_TUNE2FS_INTERVALBETWEENCHECKS_BITMASK) {
        if (intervalbetweenchecks < 0) {
            reply_with_error ("intervalbetweenchecks cannot be negative");
            return -1;
        }
        ADD_ARG (argv, i, "-i");
        if (intervalbetweenchecks > 0) {
            /* -i <NN>s is not documented in the man page, but has been
             * supported in tune2fs for several years.
             */
            snprintf (intervalbetweenchecks_s, sizeof intervalbetweenchecks_s,
                      "%ds", intervalbetweenchecks);
            ADD_ARG (argv, i, intervalbetweenchecks_s);
        }
        else
            ADD_ARG (argv, i, "0");
    }

    if (optargs_bitmask & GUESTFS_TUNE2FS_RESERVEDBLOCKSPERCENTAGE_BITMASK) {
        if (reservedblockspercentage < 0) {
            reply_with_error ("reservedblockspercentage cannot be negative");
            return -1;
        }
        ADD_ARG (argv, i, "-m");
        snprintf (reservedblockspercentage_s, sizeof reservedblockspercentage_s,
                  "%d", reservedblockspercentage);
        ADD_ARG (argv, i, reservedblockspercentage_s);
    }

    if (optargs_bitmask & GUESTFS_TUNE2FS_LASTMOUNTEDDIRECTORY_BITMASK) {
        ADD_ARG (argv, i, "-M");
        ADD_ARG (argv, i, lastmounteddirectory);
    }

    if (optargs_bitmask & GUESTFS_TUNE2FS_RESERVEDBLOCKSCOUNT_BITMASK) {
        if (reservedblockscount < 0) {
            reply_with_error ("reservedblockscount cannot be negative");
            return -1;
        }
        ADD_ARG (argv, i, "-r");
        snprintf (reservedblockscount_s, sizeof reservedblockscount_s,
                  "%" PRIi64, reservedblockscount);
        ADD_ARG (argv, i, reservedblockscount_s);
    }

    if (optargs_bitmask & GUESTFS_TUNE2FS_USER_BITMASK) {
        if (user < 0) {
            reply_with_error ("user cannot be negative");
            return -1;
        }
        ADD_ARG (argv, i, "-u");
        snprintf (user_s, sizeof user_s, "%" PRIi64, user);
        ADD_ARG (argv, i, user_s);
    }

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

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

    return 0;
}
Example #19
0
int
do_mke2fs (const char *device,               /* 0 */
           int64_t blockscount,
           int64_t blocksize,
           int64_t fragsize,
           int64_t blockspergroup,
           int64_t numberofgroups,           /* 5 */
           int64_t bytesperinode,
           int64_t inodesize,
           int64_t journalsize,
           int64_t numberofinodes,
           int64_t stridesize,               /* 10 */
           int64_t stripewidth,
           int64_t maxonlineresize,
           int reservedblockspercentage,
           int mmpupdateinterval,
           const char *journaldevice,        /* 15 */
           const char *label,
           const char *lastmounteddir,
           const char *creatoros,
           const char *fstype,
           const char *usagetype,            /* 20 */
           const char *uuid,
           int forcecreate,
           int writesbandgrouponly,
           int lazyitableinit,
           int lazyjournalinit,              /* 25 */
           int testfs,
           int discard,
           int quotatype,
           int extent,
           int filetype,                     /* 30 */
           int flexbg,
           int hasjournal,
           int journaldev,
           int largefile,
           int quota,                        /* 35 */
           int resizeinode,
           int sparsesuper,
           int uninitbg)
{
    int r;
    CLEANUP_FREE char *err = NULL;
    const char *argv[MAX_ARGS];
    char blockscount_s[64];
    char blocksize_s[64];
    char fragsize_s[64];
    char blockspergroup_s[64];
    char numberofgroups_s[64];
    char bytesperinode_s[64];
    char inodesize_s[64];
    char journalsize_s[64];
    CLEANUP_FREE char *journaldevice_translated = NULL;
    CLEANUP_FREE char *journaldevice_s = NULL;
    char reservedblockspercentage_s[64];
    char numberofinodes_s[64];
    char mmpupdateinterval_s[84];
    char stridesize_s[74];
    char stripewidth_s[84];
    char maxonlineresize_s[74];
    size_t i = 0;

    ADD_ARG (argv, i, str_mke2fs);

    if (optargs_bitmask & GUESTFS_MKE2FS_BLOCKSIZE_BITMASK) {
        if (blocksize < 0) {
            reply_with_error ("blocksize must be >= 0");
            return -1;
        }
        snprintf (blocksize_s, sizeof blocksize_s, "%" PRIi64, blocksize);
        ADD_ARG (argv, i, "-b");
        ADD_ARG (argv, i, blocksize_s);
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_FRAGSIZE_BITMASK) {
        if (fragsize < 0) {
            reply_with_error ("fragsize must be >= 0");
            return -1;
        }
        snprintf (fragsize_s, sizeof fragsize_s, "%" PRIi64, fragsize);
        ADD_ARG (argv, i, "-f");
        ADD_ARG (argv, i, fragsize_s);
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_FORCECREATE_BITMASK) {
        if (forcecreate)
            ADD_ARG (argv, i, "-F");
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_BLOCKSPERGROUP_BITMASK) {
        if (blockspergroup < 0) {
            reply_with_error ("blockspergroup must be >= 0");
            return -1;
        }
        snprintf (blockspergroup_s, sizeof blockspergroup_s,
                  "%" PRIi64, blockspergroup);
        ADD_ARG (argv, i, "-g");
        ADD_ARG (argv, i, blockspergroup_s);
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_NUMBEROFGROUPS_BITMASK) {
        if (numberofgroups < 0) {
            reply_with_error ("numberofgroups must be >= 0");
            return -1;
        }
        snprintf (numberofgroups_s, sizeof numberofgroups_s,
                  "%" PRIi64, numberofgroups);
        ADD_ARG (argv, i, "-G");
        ADD_ARG (argv, i, numberofgroups_s);
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_BYTESPERINODE_BITMASK) {
        if (bytesperinode < 0) {
            reply_with_error ("bytesperinode must be >= 0");
            return -1;
        }
        snprintf (bytesperinode_s, sizeof bytesperinode_s, "%" PRIi64, bytesperinode);
        ADD_ARG (argv, i, "-i");
        ADD_ARG (argv, i, bytesperinode_s);
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_INODESIZE_BITMASK) {
        if (inodesize < 0) {
            reply_with_error ("inodesize must be >= 0");
            return -1;
        }
        snprintf (inodesize_s, sizeof inodesize_s, "%" PRIi64, inodesize);
        ADD_ARG (argv, i, "-I");
        ADD_ARG (argv, i, inodesize_s);
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_JOURNALSIZE_BITMASK) {
        if (journalsize < 0) {
            reply_with_error ("journalsize must be >= 0");
            return -1;
        }
        snprintf (journalsize_s, sizeof journalsize_s,
                  "size=" "%" PRIi64, journalsize);
        ADD_ARG (argv, i, "-J");
        ADD_ARG (argv, i, journalsize_s);
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_JOURNALDEVICE_BITMASK) {
        if (journaldevice) {
            /* OString doesn't do device name translation (RHBZ#876579).  We
             * have to do it manually here, but note that LABEL=.. and
             * UUID=.. are valid strings which do not require translation.
             */
            if (STRPREFIX (journaldevice, "/dev/")) {
                if (is_root_device (journaldevice)) {
                    reply_with_error ("%s: device not found", journaldevice);
                    return -1;
                }
                journaldevice_translated = device_name_translation (journaldevice);
                if (journaldevice_translated == NULL) {
                    reply_with_perror ("%s", journaldevice);
                    return -1;
                }

                journaldevice_s = malloc (strlen (journaldevice_translated) + 8);
                if (!journaldevice_s) {
                    reply_with_perror ("malloc");
                    return -1;
                }

                sprintf (journaldevice_s, "device=%s", journaldevice_translated);
            }
            else {
                journaldevice_s = malloc (strlen (journaldevice) + 8);
                if (!journaldevice_s) {
                    reply_with_perror ("malloc");
                    return -1;
                }

                sprintf (journaldevice_s, "device=%s", journaldevice);
            }

            ADD_ARG (argv, i, "-J");
            ADD_ARG (argv, i, journaldevice_s);
        }
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_LABEL_BITMASK) {
        if (label) {
            ADD_ARG (argv, i, "-L");
            ADD_ARG (argv, i, label);
        }
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_RESERVEDBLOCKSPERCENTAGE_BITMASK) {
        if (reservedblockspercentage < 0) {
            reply_with_error ("reservedblockspercentage must be >= 0");
            return -1;
        }
        snprintf (reservedblockspercentage_s, sizeof reservedblockspercentage_s,
                  "%" PRIi32, reservedblockspercentage);
        ADD_ARG (argv, i, "-m");
        ADD_ARG (argv, i, reservedblockspercentage_s);
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_LASTMOUNTEDDIR_BITMASK) {
        if (lastmounteddir) {
            ADD_ARG (argv, i, "-M");
            ADD_ARG (argv, i, lastmounteddir);
        }
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_NUMBEROFINODES_BITMASK) {
        if (numberofinodes < 0) {
            reply_with_error ("numberofinodes must be >= 0");
            return -1;
        }
        snprintf (numberofinodes_s, sizeof numberofinodes_s,
                  "%" PRIi64, numberofinodes);
        ADD_ARG (argv, i, "-N");
        ADD_ARG (argv, i, numberofinodes_s);
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_CREATOROS_BITMASK) {
        if (creatoros) {
            ADD_ARG (argv, i, "-o");
            ADD_ARG (argv, i, creatoros);
        }
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_WRITESBANDGROUPONLY_BITMASK) {
        if (writesbandgrouponly)
            ADD_ARG (argv, i, "-S");
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_FSTYPE_BITMASK) {
        if (fstype) {
            if (!fstype_is_extfs (fstype)) {
                reply_with_error ("%s: not a valid extended filesystem type", fstype);
                return -1;
            }

            ADD_ARG (argv, i, "-t");
            ADD_ARG (argv, i, fstype);
        }
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_USAGETYPE_BITMASK) {
        if (usagetype) {
            ADD_ARG (argv, i, "-T");
            ADD_ARG (argv, i, usagetype);
        }
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_UUID_BITMASK) {
        if (uuid) {
            ADD_ARG (argv, i, "-U");
            ADD_ARG (argv, i, uuid);
        }
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_MMPUPDATEINTERVAL_BITMASK) {
        if (mmpupdateinterval < 0) {
            reply_with_error ("mmpupdateinterval must be >= 0");
            return -1;
        }
        snprintf (mmpupdateinterval_s, sizeof mmpupdateinterval_s,
                  "mmp_update_interval=" "%" PRIi32, mmpupdateinterval);
        ADD_ARG (argv, i, "-E");
        ADD_ARG (argv, i, mmpupdateinterval_s);
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_STRIDESIZE_BITMASK) {
        if (stridesize < 0) {
            reply_with_error ("stridesize must be >= 0");
            return -1;
        }
        snprintf (stridesize_s, sizeof stridesize_s,
                  "stride=" "%" PRIi64, stridesize);
        ADD_ARG (argv, i, "-E");
        ADD_ARG (argv, i, stridesize_s);
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_STRIPEWIDTH_BITMASK) {
        if (stripewidth< 0) {
            reply_with_error ("stripewidth must be >= 0");
            return -1;
        }
        snprintf (stripewidth_s, sizeof stripewidth_s,
                  "stripe_width=" "%" PRIi64, stripewidth);
        ADD_ARG (argv, i, "-E");
        ADD_ARG (argv, i, stripewidth_s);
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_MAXONLINERESIZE_BITMASK) {
        if (maxonlineresize < 0) {
            reply_with_error ("maxonlineresize must be >= 0");
            return -1;
        }
        snprintf (maxonlineresize_s, sizeof maxonlineresize_s,
                  "resize=" "%" PRIi64, maxonlineresize);
        ADD_ARG (argv, i, "-E");
        ADD_ARG (argv, i, maxonlineresize_s);
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_LAZYITABLEINIT_BITMASK) {
        ADD_ARG (argv, i, "-E");
        if (lazyitableinit)
            ADD_ARG (argv, i, "lazy_itable_init=1");
        else
            ADD_ARG (argv, i, "lazy_itable_init=0");
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_LAZYJOURNALINIT_BITMASK) {
        ADD_ARG (argv, i, "-E");
        if (lazyjournalinit)
            ADD_ARG (argv, i, "lazy_journal_init=1");
        else
            ADD_ARG (argv, i, "lazy_journal_init=0");
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_TESTFS_BITMASK) {
        if (testfs) {
            ADD_ARG (argv, i, "-E");
            ADD_ARG (argv, i, "test_fs");
        }
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_DISCARD_BITMASK) {
        ADD_ARG (argv, i, "-E");
        if (discard)
            ADD_ARG (argv, i, "discard");
        else
            ADD_ARG (argv, i, "nodiscard");
    }

    if (optargs_bitmask & GUESTFS_MKE2FS_EXTENT_BITMASK) {
        ADD_ARG (argv, i, "-O");
        if (extent)
            ADD_ARG (argv, i, "extent");
        else
            ADD_ARG (argv, i, "^extent");
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_FILETYPE_BITMASK) {
        ADD_ARG (argv, i, "-O");
        if (filetype)
            ADD_ARG (argv, i, "filetype");
        else
            ADD_ARG (argv, i, "^filetype");
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_FLEXBG_BITMASK) {
        ADD_ARG (argv, i, "-O");
        if (flexbg)
            ADD_ARG (argv, i, "flexbg");
        else
            ADD_ARG (argv, i, "^flexbg");
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_HASJOURNAL_BITMASK) {
        ADD_ARG (argv, i, "-O");
        if (hasjournal)
            ADD_ARG (argv, i, "has_journal");
        else
            ADD_ARG (argv, i, "^has_journal");
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_JOURNALDEV_BITMASK) {
        ADD_ARG (argv, i, "-O");
        if (journaldev)
            ADD_ARG (argv, i, "journal_dev");
        else
            ADD_ARG (argv, i, "^journal_dev");
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_LARGEFILE_BITMASK) {
        ADD_ARG (argv, i, "-O");
        if (largefile)
            ADD_ARG (argv, i, "large_file");
        else
            ADD_ARG (argv, i, "^large_file");
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_QUOTA_BITMASK) {
        ADD_ARG (argv, i, "-O");
        if (quota)
            ADD_ARG (argv, i, "quota");
        else
            ADD_ARG (argv, i, "^quota");
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_RESIZEINODE_BITMASK) {
        ADD_ARG (argv, i, "-O");
        if (resizeinode)
            ADD_ARG (argv, i, "resize_inode");
        else
            ADD_ARG (argv, i, "^resize_inode");
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_SPARSESUPER_BITMASK) {
        ADD_ARG (argv, i, "-O");
        if (sparsesuper)
            ADD_ARG (argv, i, "sparse_super");
        else
            ADD_ARG (argv, i, "^sparse_super");
    }
    if (optargs_bitmask & GUESTFS_MKE2FS_UNINITBG_BITMASK) {
        ADD_ARG (argv, i, "-O");
        if (uninitbg)
            ADD_ARG (argv, i, "uninit_bg");
        else
            ADD_ARG (argv, i, "^uninit_bg");
    }

    ADD_ARG (argv, i, device);

    if (optargs_bitmask & GUESTFS_MKE2FS_BLOCKSCOUNT_BITMASK) {
        if (blockscount < 0) {
            reply_with_error ("blockscount must be >= 0");
            return -1;
        }
        snprintf (blockscount_s, sizeof blockscount_s, "%" PRIi64, blockscount);
        ADD_ARG (argv, i, blockscount_s);
    }

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

    return 0;
}
Example #20
0
/* Takes optional arguments, consult optargs_bitmask. */
int
do_mkfs_opts (const char *fstype, const char *device, int blocksize,
              const char *features, int inode, int sectorsize)
{
  const char *argv[MAX_ARGS];
  size_t i = 0;
  char blocksize_str[32];
  char inode_str[32];
  char sectorsize_str[32];
  int r;
  char *err;
  char mke2fs[] = "mke2fs";
  int extfs = 0;

  if (STREQ (fstype, "ext2") || STREQ (fstype, "ext3") ||
      STREQ (fstype, "ext4"))
    extfs = 1;

  /* For ext2/3/4 run the mke2fs program directly.  This is because
   * the mkfs program "eats" some options, in particular the -F
   * option.
   */
  if (extfs) {
    if (e2prog (mke2fs) == -1)
      return -1;
    ADD_ARG (argv, i, mke2fs);
  }
  else
    ADD_ARG (argv, i, "mkfs");

  ADD_ARG (argv, i, "-t");
  ADD_ARG (argv, i, fstype);

  /* Force mke2fs to create a filesystem, even if it thinks it
   * shouldn't (RHBZ#690819).
   */
  if (extfs)
    ADD_ARG (argv, i, "-F");

  /* mkfs.ntfs requires the -Q argument otherwise it writes zeroes
   * to every block and does bad block detection, neither of which
   * are useful behaviour for virtual devices.
   */
  if (STREQ (fstype, "ntfs"))
    ADD_ARG (argv, i, "-Q");

  /* mkfs.reiserfs produces annoying interactive prompts unless you
   * tell it to be quiet.
   * mkfs.jfs is the same
   * mkfs.xfs must force to make xfs filesystem when the device already
   * has a filesystem on it
   */
  if (STREQ (fstype, "reiserfs") || STREQ (fstype, "jfs") ||
      STREQ (fstype, "xfs"))
    ADD_ARG(argv, i, "-f");

  /* For GFS, GFS2, assume a single node. */
  if (STREQ (fstype, "gfs") || STREQ (fstype, "gfs2")) {
    ADD_ARG (argv, i, "-p");
    ADD_ARG (argv, i, "lock_nolock");
    /* The man page says this is default, but it doesn't seem to be: */
    ADD_ARG (argv, i, "-j");
    ADD_ARG (argv, i, "1");
    /* Don't ask questions: */
    ADD_ARG (argv, i, "-O");
  }

  /* Process blocksize parameter if set. */
  if (optargs_bitmask & GUESTFS_MKFS_OPTS_BLOCKSIZE_BITMASK) {
    if (blocksize <= 0 || !is_power_of_2 (blocksize)) {
      reply_with_error ("block size must be > 0 and a power of 2");
      return -1;
    }

    if (STREQ (fstype, "vfat") ||
        STREQ (fstype, "msdos")) {
      /* For VFAT map the blocksize into a cluster size.  However we
       * have to determine the block device sector size in order to do
       * this.
       */
      int sectorsize = do_blockdev_getss (device);
      if (sectorsize == -1)
        return -1;

      int sectors_per_cluster = blocksize / sectorsize;
      if (sectors_per_cluster < 1 || sectors_per_cluster > 128) {
        reply_with_error ("unsupported cluster size for %s filesystem (requested cluster size = %d, sector size = %d, trying sectors per cluster = %d)",
                          fstype, blocksize, sectorsize, sectors_per_cluster);
        return -1;
      }

      snprintf (blocksize_str, sizeof blocksize_str, "%d", sectors_per_cluster);
      ADD_ARG (argv, i, "-s");
      ADD_ARG (argv, i, blocksize_str);
    }
    else if (STREQ (fstype, "ntfs")) {
      /* For NTFS map the blocksize into a cluster size. */
      snprintf (blocksize_str, sizeof blocksize_str, "%d", blocksize);
      ADD_ARG (argv, i, "-c");
      ADD_ARG (argv, i, blocksize_str);
    }
    else {
      /* For all other filesystem types, try the -b option. */
      snprintf (blocksize_str, sizeof blocksize_str, "%d", blocksize);
      ADD_ARG (argv, i, "-b");
      ADD_ARG (argv, i, blocksize_str);
    }
  }

  if (optargs_bitmask & GUESTFS_MKFS_OPTS_FEATURES_BITMASK) {
    ADD_ARG (argv, i, "-O");
    ADD_ARG (argv, i, features);
  }

  if (optargs_bitmask & GUESTFS_MKFS_OPTS_INODE_BITMASK) {
    if (!extfs) {
      reply_with_error ("inode size (-I) can only be set on ext2/3/4 filesystems");
      return -1;
    }

    if (inode <= 0) {
      reply_with_error ("inode size must be larger than zero");
      return -1;
    }

    snprintf (inode_str, sizeof inode_str, "%d", inode);
    ADD_ARG (argv, i, "-I");
    ADD_ARG (argv, i, inode_str);
  }

  if (optargs_bitmask & GUESTFS_MKFS_OPTS_SECTORSIZE_BITMASK) {
    if (!STREQ (fstype, "ufs")) {
      reply_with_error ("sector size (-S) can only be set on ufs filesystems");
      return -1;
    }

    if (sectorsize <= 0) {
      reply_with_error ("sector size must be larger than zero");
      return -1;
    }

    snprintf (sectorsize_str, sizeof sectorsize_str, "%d", sectorsize);
    ADD_ARG (argv, i, "-S");
    ADD_ARG (argv, i, sectorsize_str);
  }

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

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

  free (err);
  return 0;
}
Example #21
0
char *
do_command (char *const *argv)
{
  char *out;
  CLEANUP_FREE char *err = NULL;
  int r;
  CLEANUP_BIND_STATE struct bind_state bind_state = { .mounted = false };
  CLEANUP_RESOLVER_STATE struct resolver_state resolver_state =
    { .mounted = false };

  /* We need a root filesystem mounted to do this. */
  NEED_ROOT (, return NULL);

  /* Conveniently, argv is already a NULL-terminated argv-style array
   * of parameters, so we can pass it straight in to our internal
   * commandv.  We just have to check the list is non-empty.
   */
  if (argv[0] == NULL) {
    reply_with_error ("passed an empty list");
    return NULL;
  }

  if (bind_mount (&bind_state) == -1)
    return NULL;
  if (enable_network) {
    if (set_up_etc_resolv_conf (&resolver_state) == -1)
      return NULL;
  }

  CHROOT_IN;
  r = commandv (&out, &err, (const char * const *) argv);
  CHROOT_OUT;

  free_bind_state (&bind_state);
  free_resolver_state (&resolver_state);

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

  return out;			/* Caller frees. */
}

char **
do_command_lines (char *const *argv)
{
  CLEANUP_FREE char *out = NULL;
  char **lines;

  out = do_command (argv);
  if (out == NULL)
    return NULL;

  lines = split_lines (out);

  if (lines == NULL)
    return NULL;

  return lines;			/* Caller frees. */
}

char *
do_sh (const char *cmd)
{
  const char *argv[] = { "/bin/sh", "-c", cmd, NULL };

  return do_command ((char **) argv);
}

char **
do_sh_lines (const char *cmd)
{
  const char *argv[] = { "/bin/sh", "-c", cmd, NULL };

  return do_command_lines ((char **) argv);
}
Example #22
0
int
do_xfs_admin (const char *device,
              int extunwritten, int imgfile, int v2log,
              int projid32bit,
              int lazycounter, const char *label, const char *uuid)
{
  int r;
  CLEANUP_FREE char *err = NULL;
  const char *argv[MAX_ARGS];
  size_t i = 0;

  ADD_ARG (argv, i, str_xfs_admin);

  /* Optional arguments */
  if (!(optargs_bitmask & GUESTFS_XFS_ADMIN_EXTUNWRITTEN_BITMASK))
    extunwritten = 0;
  if (!(optargs_bitmask & GUESTFS_XFS_ADMIN_IMGFILE_BITMASK))
    imgfile = 0;
  if (!(optargs_bitmask & GUESTFS_XFS_ADMIN_V2LOG_BITMASK))
    v2log = 0;
  if (!(optargs_bitmask & GUESTFS_XFS_ADMIN_PROJID32BIT_BITMASK))
    projid32bit = 0;

  if (extunwritten)
    ADD_ARG (argv, i, "-e");
  if (imgfile)
    ADD_ARG (argv, i, "-f");
  if (v2log)
    ADD_ARG (argv, i, "-j");
  if (projid32bit)
    ADD_ARG (argv, i, "-p");

  if (optargs_bitmask & GUESTFS_XFS_ADMIN_LAZYCOUNTER_BITMASK) {
    if (lazycounter) {
      ADD_ARG (argv, i, "-c");
      ADD_ARG (argv, i, "1");
    } else {
      ADD_ARG (argv, i, "-c");
      ADD_ARG (argv, i, "0");
    }
  }

  if (optargs_bitmask & GUESTFS_XFS_ADMIN_LABEL_BITMASK) {
    if (strlen (label) > XFS_LABEL_MAX) {
      reply_with_error ("%s: xfs labels are limited to %d bytes",
                        label, XFS_LABEL_MAX);
      return -1;
    }

    ADD_ARG (argv, i, "-L");
    ADD_ARG (argv, i, label);
  }

  if (optargs_bitmask & GUESTFS_XFS_ADMIN_UUID_BITMASK) {
    ADD_ARG (argv, i, "-U");
    ADD_ARG (argv, i, uuid);
  }

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

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

  return 0;
}
Example #23
0
/* Takes optional arguments, consult optargs_bitmask. */
int
do_mkfs (const char *fstype, const char *device, int blocksize,
         const char *features, int inode, int sectorsize, const char *label)
{
  const char *argv[MAX_ARGS];
  size_t i = 0;
  char blocksize_str[32];
  char inode_str[32];
  char sectorsize_str[32];
  int r;
  CLEANUP_FREE char *err = NULL;
  int extfs = 0;

  if (fstype_is_extfs (fstype))
    extfs = 1;

  /* For ext2/3/4 run the mke2fs program directly.  This is because
   * the mkfs program "eats" some options, in particular the -F
   * option.
   */
  if (extfs)
    ADD_ARG (argv, i, str_mke2fs);
  else
    ADD_ARG (argv, i, str_mkfs);

  ADD_ARG (argv, i, "-t");
  ADD_ARG (argv, i, fstype);

  /* Force mke2fs to create a filesystem, even if it thinks it
   * shouldn't (RHBZ#690819).
   */
  if (extfs)
    ADD_ARG (argv, i, "-F");

  /* mkfs.ntfs requires the -Q argument otherwise it writes zeroes to
   * every block and does bad block detection, neither of which are
   * useful behaviour for virtual devices.  Also recent versions need
   * to be forced to create filesystems on non-partitions.
   */
  if (STREQ (fstype, "ntfs")) {
    ADD_ARG (argv, i, "-Q");
    ADD_ARG (argv, i, "-F");
  }

  /* mkfs.reiserfs produces annoying interactive prompts unless you
   * tell it to be quiet.
   * mkfs.jfs is the same
   * mkfs.xfs must force to make xfs filesystem when the device already
   * has a filesystem on it
   */
  if (STREQ (fstype, "reiserfs") || STREQ (fstype, "jfs") ||
      STREQ (fstype, "xfs"))
    ADD_ARG (argv, i, "-f");

  /* For GFS, GFS2, assume a single node. */
  if (STREQ (fstype, "gfs") || STREQ (fstype, "gfs2")) {
    ADD_ARG (argv, i, "-p");
    ADD_ARG (argv, i, "lock_nolock");
    /* The man page says this is default, but it doesn't seem to be: */
    ADD_ARG (argv, i, "-j");
    ADD_ARG (argv, i, "1");
    /* Don't ask questions: */
    ADD_ARG (argv, i, "-O");
  }

  /* Force mkfs.fat to create a whole disk filesystem (RHBZ#1039995). */
  if (STREQ (fstype, "fat") || STREQ (fstype, "vfat") ||
      STREQ (fstype, "msdos"))
    ADD_ARG (argv, i, "-I");

  /* Process blocksize parameter if set. */
  if (optargs_bitmask & GUESTFS_MKFS_BLOCKSIZE_BITMASK) {
    if (blocksize <= 0 || !is_power_of_2 (blocksize)) {
      reply_with_error ("block size must be > 0 and a power of 2");
      return -1;
    }

    if (STREQ (fstype, "vfat") ||
        STREQ (fstype, "msdos")) {
      /* For VFAT map the blocksize into a cluster size.  However we
       * have to determine the block device sector size in order to do
       * this.
       */
      int ss = do_blockdev_getss (device);
      if (ss == -1)
        return -1;

      int sectors_per_cluster = blocksize / ss;
      if (sectors_per_cluster < 1 || sectors_per_cluster > 128) {
        reply_with_error ("unsupported cluster size for %s filesystem (requested cluster size = %d, sector size = %d, trying sectors per cluster = %d)",
                          fstype, blocksize, ss, sectors_per_cluster);
        return -1;
      }

      snprintf (blocksize_str, sizeof blocksize_str, "%d", sectors_per_cluster);
      ADD_ARG (argv, i, "-s");
      ADD_ARG (argv, i, blocksize_str);
    }
    else if (STREQ (fstype, "ntfs")) {
      /* For NTFS map the blocksize into a cluster size. */
      snprintf (blocksize_str, sizeof blocksize_str, "%d", blocksize);
      ADD_ARG (argv, i, "-c");
      ADD_ARG (argv, i, blocksize_str);
    }
    else if (STREQ (fstype, "btrfs")) {
      /* For btrfs, blocksize cannot be specified (RHBZ#807905). */
      reply_with_error ("blocksize cannot be set on btrfs filesystems, use 'mkfs-btrfs'");
      return -1;
    }
    else if (STREQ (fstype, "xfs")) {
      /* mkfs -t xfs -b size=<size> (RHBZ#981715). */
      snprintf (blocksize_str, sizeof blocksize_str, "size=%d", blocksize);
      ADD_ARG (argv, i, "-b");
      ADD_ARG (argv, i, blocksize_str);
    }
    else {
      /* For all other filesystem types, try the -b option. */
      snprintf (blocksize_str, sizeof blocksize_str, "%d", blocksize);
      ADD_ARG (argv, i, "-b");
      ADD_ARG (argv, i, blocksize_str);
    }
  }

  if (optargs_bitmask & GUESTFS_MKFS_FEATURES_BITMASK) {
    ADD_ARG (argv, i, "-O");
    ADD_ARG (argv, i, features);
  }

  if (optargs_bitmask & GUESTFS_MKFS_INODE_BITMASK) {
    if (!extfs) {
      reply_with_error ("inode size (-I) can only be set on ext2/3/4 filesystems");
      return -1;
    }

    if (inode <= 0) {
      reply_with_error ("inode size must be larger than zero");
      return -1;
    }

    snprintf (inode_str, sizeof inode_str, "%d", inode);
    ADD_ARG (argv, i, "-I");
    ADD_ARG (argv, i, inode_str);
  }

  if (optargs_bitmask & GUESTFS_MKFS_SECTORSIZE_BITMASK) {
    if (!STREQ (fstype, "ufs")) {
      reply_with_error ("sector size (-S) can only be set on ufs filesystems");
      return -1;
    }

    if (sectorsize <= 0) {
      reply_with_error ("sector size must be larger than zero");
      return -1;
    }

    snprintf (sectorsize_str, sizeof sectorsize_str, "%d", sectorsize);
    ADD_ARG (argv, i, "-S");
    ADD_ARG (argv, i, sectorsize_str);
  }

  if (optargs_bitmask & GUESTFS_MKFS_LABEL_BITMASK) {
    if (extfs) {
      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;
      }

      ADD_ARG (argv, i, "-L");
      ADD_ARG (argv, i, label);
    }
    else if (STREQ (fstype, "fat") || STREQ (fstype, "vfat") ||
             STREQ (fstype, "msdos")) {
      ADD_ARG (argv, i, "-n");
      ADD_ARG (argv, i, label);
    }
    else if (STREQ (fstype, "ntfs")) {
      ADD_ARG (argv, i, "-L");
      ADD_ARG (argv, i, label);
    }
    else if (STREQ (fstype, "xfs")) {
      if (strlen (label) > XFS_LABEL_MAX) {
        reply_with_error ("%s: xfs labels are limited to %d bytes",
                          label, XFS_LABEL_MAX);
        return -1;
      }

      ADD_ARG (argv, i, "-L");
      ADD_ARG (argv, i, label);
    }
    else if (STREQ (fstype, "btrfs")) {
      ADD_ARG (argv, i, "-L");
      ADD_ARG (argv, i, label);
    }
    else {
      reply_with_error ("don't know how to set the label for '%s' filesystems",
                        fstype);
      return -1;
    }
  }

  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: %s", fstype, device, err);
    return -1;
  }

  return 0;
}
Example #24
0
int
do_xfs_growfs (const char *path,
               int datasec, int logsec, int rtsec,
               int64_t datasize, int64_t logsize, int64_t rtsize,
               int64_t rtextsize, int32_t maxpct)
{
  int r;
  CLEANUP_FREE char *buf = NULL, *err = NULL;
  const char *argv[MAX_ARGS];
  char datasize_s[64];
  char logsize_s[64];
  char rtsize_s[64];
  char rtextsize_s[64];
  char maxpct_s[32];
  size_t i = 0;

  buf = sysroot_path (path);
  if (buf == NULL) {
    reply_with_perror ("malloc");
    return -1;
  }

  ADD_ARG (argv, i, str_xfs_growfs);

  /* Optional arguments */
  if (!(optargs_bitmask & GUESTFS_XFS_GROWFS_DATASEC_BITMASK))
    datasec = 0;
  if (!(optargs_bitmask & GUESTFS_XFS_GROWFS_LOGSEC_BITMASK))
    logsec = 0;
  if (!(optargs_bitmask & GUESTFS_XFS_GROWFS_RTSEC_BITMASK))
    rtsec = 0;

  if (datasec)
    ADD_ARG (argv, i, "-d");
  if (logsec)
    ADD_ARG (argv, i, "-l");
  if (rtsec)
    ADD_ARG (argv, i, "-r");

  if (optargs_bitmask & GUESTFS_XFS_GROWFS_DATASIZE_BITMASK) {
    if (datasize < 0) {
      reply_with_error ("datasize must be >= 0");
      return -1;
    }
    snprintf (datasize_s, sizeof datasize_s, "%" PRIi64, datasize);
    ADD_ARG (argv, i, "-D");
    ADD_ARG (argv, i, datasize_s);
  }

  if (optargs_bitmask & GUESTFS_XFS_GROWFS_LOGSIZE_BITMASK) {
    if (logsize < 0) {
      reply_with_error ("logsize must be >= 0");
      return -1;
    }
    snprintf (logsize_s, sizeof logsize_s, "%" PRIi64, logsize);
    ADD_ARG (argv, i, "-L");
    ADD_ARG (argv, i, logsize_s);
  }

  if (optargs_bitmask & GUESTFS_XFS_GROWFS_RTSIZE_BITMASK) {
    if (rtsize < 0) {
      reply_with_error ("rtsize must be >= 0");
      return -1;
    }
    snprintf (rtsize_s, sizeof rtsize_s, "%" PRIi64, rtsize);
    ADD_ARG (argv, i, "-R");
    ADD_ARG (argv, i, rtsize_s);
  }

  if (optargs_bitmask & GUESTFS_XFS_GROWFS_RTEXTSIZE_BITMASK) {
    if (rtextsize < 0) {
      reply_with_error ("rtextsize must be >= 0");
      return -1;
    }
    snprintf (rtextsize_s, sizeof rtextsize_s, "%" PRIi64, rtextsize);
    ADD_ARG (argv, i, "-e");
    ADD_ARG (argv, i, rtextsize_s);
  }

  if (optargs_bitmask & GUESTFS_XFS_GROWFS_MAXPCT_BITMASK) {
    if (maxpct < 0) {
      reply_with_error ("maxpct must be >= 0");
      return -1;
    }
    snprintf (maxpct_s, sizeof maxpct_s, "%" PRIi32, maxpct);
    ADD_ARG (argv, i, "-m");
    ADD_ARG (argv, i, maxpct_s);
  }

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

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

  return 0;
}