コード例 #1
0
ファイル: create.c プロジェクト: NealSCarffery/libguestfs
static int
disk_create_qcow2 (guestfs_h *g, const char *orig_filename, int64_t size,
                   const char *backingfile,
                   const struct guestfs_disk_create_argv *optargs)
{
  CLEANUP_FREE char *filename = NULL;
  const char *backingformat = NULL;
  const char *preallocation = NULL;
  const char *compat = NULL;
  int clustersize = -1;
  CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (optionsv);
  CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
  int r;

  /* If the filename is something like "file:foo" then qemu-img will
   * try to interpret that as "foo" in the file:/// protocol.  To
   * avoid that, if the path is relative prefix it with "./" since
   * qemu-img won't try to interpret such a path.
   */
  if (orig_filename[0] != '/')
    filename = safe_asprintf (g, "./%s", orig_filename);
  else
    filename = safe_strdup (g, orig_filename);

  if (optargs->bitmask & GUESTFS_DISK_CREATE_BACKINGFORMAT_BITMASK) {
    backingformat = optargs->backingformat;
    /* Conservative whitelist.  This can be extended with other
     * valid formats as required.
     */
    if (STRNEQ (backingformat, "raw") &&
        STRNEQ (backingformat, "qcow2") &&
        STRNEQ (backingformat, "vmdk")) {
      error (g, _("invalid value for backingformat parameter '%s'"),
             backingformat);
      return -1;
    }
  }
  if (optargs->bitmask & GUESTFS_DISK_CREATE_PREALLOCATION_BITMASK) {
    if (STREQ (optargs->preallocation, "off") ||
        STREQ (optargs->preallocation, "sparse"))
      preallocation = "off";
    else if (STREQ (optargs->preallocation, "metadata"))
      preallocation = "metadata";
    else if (STREQ (optargs->preallocation, "full"))
      /* Ugh: https://lists.gnu.org/archive/html/qemu-devel/2014-08/msg03863.html */
      preallocation = "falloc";
    else {
      error (g, _("invalid value for preallocation parameter '%s'"),
             preallocation);
      return -1;
    }
  }
  if (optargs->bitmask & GUESTFS_DISK_CREATE_COMPAT_BITMASK) {
    compat = optargs->compat;
    if (STRNEQ (compat, "0.10") && STRNEQ (compat, "1.1")) {
      error (g, _("invalid value for compat parameter '%s'"), compat);
      return -1;
    }
  }
  if (optargs->bitmask & GUESTFS_DISK_CREATE_CLUSTERSIZE_BITMASK) {
    clustersize = optargs->clustersize;
    if (clustersize < 512 || clustersize > 2097152 ||
        !is_power_of_2 ((unsigned) clustersize)) {
      error (g, _("invalid value for clustersize parameter '%d'"),
             clustersize);
      return -1;
    }
  }

  /* Assemble the qemu-img command line. */
  guestfs_int_cmd_add_arg (cmd, "qemu-img");
  guestfs_int_cmd_add_arg (cmd, "create");
  guestfs_int_cmd_add_arg (cmd, "-f");
  guestfs_int_cmd_add_arg (cmd, "qcow2");

  /* -o parameter. */
  if (backingfile) {
    CLEANUP_FREE char *p = qemu_escape_param (g, backingfile);
    guestfs_int_add_sprintf (g, &optionsv, "backing_file=%s", p);
  }
  if (backingformat)
    guestfs_int_add_sprintf (g, &optionsv, "backing_fmt=%s", backingformat);
  if (preallocation)
    guestfs_int_add_sprintf (g, &optionsv, "preallocation=%s", preallocation);
  if (compat)
    guestfs_int_add_sprintf (g, &optionsv, "compat=%s", compat);
  if (clustersize >= 0)
    guestfs_int_add_sprintf (g, &optionsv, "cluster_size=%d", clustersize);
  guestfs_int_end_stringsbuf (g, &optionsv);

  if (optionsv.size > 1) {
    CLEANUP_FREE char *options = guestfs_int_join_strings (",", optionsv.argv);
    guestfs_int_cmd_add_arg (cmd, "-o");
    guestfs_int_cmd_add_arg (cmd, options);
  }

  /* Complete the command line. */
  guestfs_int_cmd_add_arg (cmd, filename);
  if (size >= 0)
    guestfs_int_cmd_add_arg_format (cmd, "%" PRIi64, size);

  r = guestfs_int_cmd_run (cmd);
  if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
    guestfs_int_external_command_failed (g, r, "qemu-img", orig_filename);
    return -1;
  }

  return 0;
}
コード例 #2
0
static int testCompareXMLToArgvFiles(const char *xml,
                                     const char *cmd,
                                     unsigned long long extraFlags,
                                     const char *migrateFrom) {
    char argvData[MAX_FILE];
    char *expectargv = &(argvData[0]);
    char *actualargv = NULL;
    const char **argv = NULL;
    const char **qenv = NULL;
    const char **tmp = NULL;
    int ret = -1, len;
    unsigned long long flags;
    virDomainDefPtr vmdef = NULL;
    virDomainChrDef monitor_chr;
    virConnectPtr conn;

    if (!(conn = virGetConnect()))
        goto fail;

    if (virtTestLoadFile(cmd, &expectargv, MAX_FILE) < 0)
        goto fail;

    if (!(vmdef = virDomainDefParseFile(driver.caps, xml,
                                        VIR_DOMAIN_XML_INACTIVE)))
        goto fail;

    if (extraFlags & QEMUD_CMD_FLAG_DOMID)
        vmdef->id = 6;
    else
        vmdef->id = -1;

    memset(&monitor_chr, 0, sizeof(monitor_chr));
    monitor_chr.type = VIR_DOMAIN_CHR_TYPE_UNIX;
    monitor_chr.data.nix.path = (char *)"/tmp/test-monitor";
    monitor_chr.data.nix.listen = 1;
    if (!(monitor_chr.info.alias = strdup("monitor")))
        goto fail;

    flags = QEMUD_CMD_FLAG_VNC_COLON |
        QEMUD_CMD_FLAG_NO_REBOOT |
        extraFlags;

    if (qemudCanonicalizeMachine(&driver, vmdef) < 0)
        goto fail;

    if (flags & QEMUD_CMD_FLAG_DEVICE) {
        qemuDomainPCIAddressSetPtr pciaddrs;
        if (!(pciaddrs = qemuDomainPCIAddressSetCreate(vmdef)))
            goto fail;

        if (qemuAssignDevicePCISlots(vmdef, pciaddrs) < 0)
            goto fail;

        qemuDomainPCIAddressSetFree(pciaddrs);
    }


    if (qemudBuildCommandLine(conn, &driver,
                              vmdef, &monitor_chr, 0, flags,
                              &argv, &qenv,
                              NULL, NULL, migrateFrom, NULL) < 0)
        goto fail;

    len = 1; /* for trailing newline */
    tmp = qenv;
    while (*tmp) {
        len += strlen(*tmp) + 1;
        tmp++;
    }

    tmp = argv;
    while (*tmp) {
        len += strlen(*tmp) + 1;
        tmp++;
    }
    if ((actualargv = malloc(sizeof(*actualargv)*len)) == NULL)
        goto fail;
    actualargv[0] = '\0';
    tmp = qenv;
    while (*tmp) {
        if (actualargv[0])
            strcat(actualargv, " ");
        strcat(actualargv, *tmp);
        tmp++;
    }
    tmp = argv;
    while (*tmp) {
        if (actualargv[0])
            strcat(actualargv, " ");
        strcat(actualargv, *tmp);
        tmp++;
    }
    strcat(actualargv, "\n");

    if (STRNEQ(expectargv, actualargv)) {
        virtTestDifference(stderr, expectargv, actualargv);
        goto fail;
    }

    ret = 0;

 fail:
    free(actualargv);
    if (argv) {
        tmp = argv;
        while (*tmp) {
            free(*(char**)tmp);
            tmp++;
        }
        free(argv);
    }
    if (qenv) {
        tmp = qenv;
        while (*tmp) {
            free(*(char**)tmp);
            tmp++;
        }
        free(qenv);
    }
    virDomainDefFree(vmdef);
    virUnrefConnect(conn);
    return ret;
}
コード例 #3
0
ファイル: destpaths.c プロジェクト: gaowanlong/libguestfs
char *
complete_dest_paths_generator (const char *text, int state)
{
#ifdef HAVE_LIBREADLINE

  static size_t len, index;
  static struct word *words = NULL;
  static size_t nr_words = 0;
  guestfs_error_handler_cb old_error_cb;
  void *old_error_cb_data;

  /* Temporarily replace the error handler so that messages don't
   * get printed to stderr while we are issuing commands.
   */
#define SAVE_ERROR_CB							\
  old_error_cb = guestfs_get_error_handler (g, &old_error_cb_data);	\
  guestfs_set_error_handler (g, NULL, NULL);

  /* Restore error handler. */
#define RESTORE_ERROR_CB						\
  guestfs_set_error_handler (g, old_error_cb, old_error_cb_data);

  if (!state) {
    char **strs;

    len = strlen (text);
    index = 0;

    if (words) free_words (words, nr_words);

    words = NULL;
    nr_words = 0;

    SAVE_ERROR_CB

/* Silently do nothing if an allocation fails */
#define APPEND_STRS_AND_FREE						\
  do {									\
    if (strs) {								\
      size_t i;								\
      size_t n = count_strings (strs);					\
                                                                        \
      if ( n > 0 && ! xalloc_oversized (nr_words + n, sizeof (struct word))) { \
        struct word *w;							\
        w = realloc (words, sizeof (struct word) * (nr_words + n));	\
                                                                        \
        if (w == NULL) {						\
          free_words (words, nr_words);					\
          words = NULL;							\
          nr_words = 0;							\
        } else {							\
          words = w;							\
          for (i = 0; i < n; ++i) {					\
            words[nr_words].name = strs[i];				\
            words[nr_words].is_dir = 0;					\
            nr_words++;							\
          }								\
        }								\
      }									\
      free (strs);							\
    }									\
  } while (0)

    /* Is it a device? */
    if (len < 5 || STREQLEN (text, "/dev/", 5)) {
      /* Get a list of everything that can possibly begin with /dev/ */
      strs = guestfs_list_devices (g);
      APPEND_STRS_AND_FREE;

      strs = guestfs_list_partitions (g);
      APPEND_STRS_AND_FREE;

      strs = guestfs_lvs (g);
      APPEND_STRS_AND_FREE;

      strs = guestfs_list_dm_devices (g);
      APPEND_STRS_AND_FREE;

      strs = guestfs_list_md_devices (g);
      APPEND_STRS_AND_FREE;
    }

    if (len < 1 || text[0] == '/') {
      /* If we've got a partial path already, we need to list everything
       * in that directory, otherwise list everything in /
       */
      char *p, *dir;
      struct guestfs_dirent_list *dirents;

      p = strrchr (text, '/');
      dir = p && p > text ? strndup (text, p - text) : strdup ("/");
      if (dir) {
        dirents = guestfs_readdir (g, dir);

        /* Prepend directory to names before adding them to the list
         * of words.
         */
        if (dirents) {
          size_t i;

          for (i = 0; i < dirents->len; ++i) {
            int err;

            if (STRNEQ (dirents->val[i].name, ".") &&
                STRNEQ (dirents->val[i].name, "..")) {
              if (STREQ (dir, "/"))
                err = asprintf (&p, "/%s", dirents->val[i].name);
              else
                err = asprintf (&p, "%s/%s", dir, dirents->val[i].name);
              if (err >= 0) {
                if (!xalloc_oversized (nr_words+1, sizeof (struct word))) {
                  struct word *w;

                  w = realloc (words, sizeof (struct word) * (nr_words+1));
                  if (w == NULL) {
                    free_words (words, nr_words);
                    words = NULL;
                    nr_words = 0;
                  }
                  else {
                    words = w;
                    words[nr_words].name = p;
                    words[nr_words].is_dir = dirents->val[i].ftyp == 'd';
                    nr_words++;
                  }
                }
              }
            }
          }

          guestfs_free_dirent_list (dirents);
        }
      }
    }

    /* else ...  In theory we could complete other things here such as VG
     * names.  At the moment we don't do that.
     */

    RESTORE_ERROR_CB
  }
コード例 #4
0
ファイル: initrd.c プロジェクト: AlphaStaxLLC/libguestfs
char *
do_initrd_cat (const char *path, const char *filename, size_t *size_r)
{
  char tmpdir[] = "/tmp/initrd-cat-XXXXXX";
  CLEANUP_FREE char *cmd = NULL;
  struct stat statbuf;
  int fd, r;
  char *ret = NULL;
  CLEANUP_FREE char *fullpath = NULL;

  if (mkdtemp (tmpdir) == NULL) {
    reply_with_perror ("mkdtemp");
    return NULL;
  }

  /* Extract file into temporary directory.  This may create subdirs.
   * It's also possible that this doesn't create anything at all
   * (eg. if the named file does not exist in the cpio archive) --
   * cpio is silent in this case.
   */
  /* "zcat /sysroot/<path> | cpio --quiet -id file", but paths must be quoted */
  if (asprintf_nowarn (&cmd, "cd %Q && zcat %R | cpio --quiet -id %Q",
                       tmpdir, path, filename) == -1) {
    reply_with_perror ("asprintf");
    rmdir (tmpdir);
    return NULL;
  }

  r = system (cmd);
  if (r == -1) {
    reply_with_perror ("command failed: %s", cmd);
    rmdir (tmpdir);
    return NULL;
  }
  if (WEXITSTATUS (r) != 0) {
    reply_with_perror ("command failed with return code %d",
                       WEXITSTATUS (r));
    rmdir (tmpdir);
    return NULL;
  }

  /* Construct the expected name of the extracted file. */
  if (asprintf (&fullpath, "%s/%s", tmpdir, filename) == -1) {
    reply_with_perror ("asprintf");
    rmdir (tmpdir);
    return NULL;
  }

  /* See if we got a file. */
  fd = open (fullpath, O_RDONLY|O_CLOEXEC);
  if (fd == -1) {
    reply_with_perror ("open: %s:%s", path, filename);
    rmdir (tmpdir);
    return NULL;
  }

  /* From this point, we know the file exists, so we require full
   * cleanup.
   */
  if (fstat (fd, &statbuf) == -1) {
    reply_with_perror ("fstat: %s:%s", path, filename);
    goto cleanup;
  }

  /* The actual limit on messages is smaller than this.  This
   * check just limits the amount of memory we'll try and allocate
   * here.  If the message is larger than the real limit, that will
   * be caught later when we try to serialize the message.
   */
  if (statbuf.st_size >= GUESTFS_MESSAGE_MAX) {
    reply_with_error ("%s:%s: file is too large for the protocol",
                      path, filename);
    goto cleanup;
  }

  ret = malloc (statbuf.st_size);
  if (ret == NULL) {
    reply_with_perror ("malloc");
    goto cleanup;
  }

  if (xread (fd, ret, statbuf.st_size) == -1) {
    reply_with_perror ("read: %s:%s", path, filename);
    free (ret);
    ret = NULL;
    goto cleanup;
  }

  if (close (fd) == -1) {
    reply_with_perror ("close: %s:%s", path, filename);
    free (ret);
    ret = NULL;
    goto cleanup;
  }
  fd = -1;

  /* Mustn't touch *size_r until we are sure that we won't return any
   * error (RHBZ#589039).
   */
  *size_r = statbuf.st_size;

 cleanup:
  if (fd >= 0)
    close (fd);

  /* Remove the file. */
  if (unlink (fullpath) == -1) {
    fprintf (stderr, "unlink: %s: %m\n", fullpath);
    /* non-fatal */
  }

  /* Remove the directories up to and including the temp directory. */
  do {
    char *p = strrchr (fullpath, '/');
    if (!p) break;
    *p = '\0';
    if (rmdir (fullpath) == -1) {
      fprintf (stderr, "rmdir: %s: %m\n", fullpath);
      /* non-fatal */
    }
  } while (STRNEQ (fullpath, tmpdir));

  return ret;
}
コード例 #5
0
ファイル: qemuxmlnstest.c プロジェクト: syndicut/libvirt
static int testCompareXMLToArgvFiles(const char *xml,
                                     const char *cmdline,
                                     virBitmapPtr extraFlags,
                                     const char *migrateFrom,
                                     int migrateFd,
                                     bool json,
                                     bool expectError)
{
    char *expectargv = NULL;
    int len;
    char *actualargv = NULL;
    int ret = -1;
    virDomainDefPtr vmdef = NULL;
    virDomainChrSourceDef monitor_chr;
    virConnectPtr conn;
    char *log = NULL;
    char *emulator = NULL;
    virCommandPtr cmd = NULL;

    if (!(conn = virGetConnect()))
        goto fail;

    len = virtTestLoadFile(cmdline, &expectargv);
    if (len < 0)
        goto fail;
    if (len && expectargv[len - 1] == '\n')
        expectargv[len - 1] = '\0';

    if (!(vmdef = virDomainDefParseFile(driver.caps, xml,
                                        QEMU_EXPECTED_VIRT_TYPES,
                                        VIR_DOMAIN_XML_INACTIVE)))
        goto fail;

    /*
     * For test purposes, we may want to fake emulator's output by providing
     * our own script instead of a real emulator. For this to work we need to
     * specify a relative path in <emulator/> element, which, however, is not
     * allowed by RelaxNG schema for domain XML. To work around it we add an
     * extra '/' at the beginning of relative emulator path so that it looks
     * like, e.g., "/./qemu.sh" or "/../emulator/qemu.sh" instead of
     * "./qemu.sh" or "../emulator/qemu.sh" respectively. The following code
     * detects such paths, strips the extra '/' and makes the path absolute.
     */
    if (vmdef->emulator && STRPREFIX(vmdef->emulator, "/.")) {
        if (!(emulator = strdup(vmdef->emulator + 1)))
            goto fail;
        free(vmdef->emulator);
        vmdef->emulator = NULL;
        if (virAsprintf(&vmdef->emulator, "%s/qemuxml2argvdata/%s",
                        abs_srcdir, emulator) < 0)
            goto fail;
    }

    if (qemuCapsGet(extraFlags, QEMU_CAPS_DOMID))
        vmdef->id = 6;
    else
        vmdef->id = -1;

    memset(&monitor_chr, 0, sizeof(monitor_chr));
    monitor_chr.type = VIR_DOMAIN_CHR_TYPE_UNIX;
    monitor_chr.data.nix.path = (char *)"/tmp/test-monitor";
    monitor_chr.data.nix.listen = true;

    qemuCapsSetList(extraFlags,
                    QEMU_CAPS_VNC_COLON,
                    QEMU_CAPS_NO_REBOOT,
                    QEMU_CAPS_LAST);

    if (qemudCanonicalizeMachine(&driver, vmdef) < 0)
        goto fail;

    if (qemuCapsGet(extraFlags, QEMU_CAPS_DEVICE)) {
        qemuDomainPCIAddressSetPtr pciaddrs;
        if (!(pciaddrs = qemuDomainPCIAddressSetCreate(vmdef)))
            goto fail;

        if (qemuAssignDevicePCISlots(vmdef, pciaddrs) < 0)
            goto fail;

        qemuDomainPCIAddressSetFree(pciaddrs);
    }


    free(virtTestLogContentAndReset());
    virResetLastError();

    /* We do not call qemuCapsExtractVersionInfo() before calling
     * qemuBuildCommandLine(), so we should set QEMU_CAPS_PCI_MULTIBUS for
     * x86_64 and i686 architectures here.
     */
    if (STREQLEN(vmdef->os.arch, "x86_64", 6) ||
            STREQLEN(vmdef->os.arch, "i686", 4)) {
        qemuCapsSet(extraFlags, QEMU_CAPS_PCI_MULTIBUS);
    }

    if (qemuAssignDeviceAliases(vmdef, extraFlags) < 0)
        goto fail;

    if (!(cmd = qemuBuildCommandLine(conn, &driver,
                                     vmdef, &monitor_chr, json, extraFlags,
                                     migrateFrom, migrateFd, NULL,
                                     VIR_NETDEV_VPORT_PROFILE_OP_NO_OP)))
        goto fail;

    if (!!virGetLastError() != expectError) {
        if (virTestGetDebug() && (log = virtTestLogContentAndReset()))
            fprintf(stderr, "\n%s", log);
        goto fail;
    }

    if (expectError) {
        /* need to suppress the errors */
        virResetLastError();
    }

    if (!(actualargv = virCommandToString(cmd)))
        goto fail;

    if (emulator) {
        /* Skip the abs_srcdir portion of replacement emulator.  */
        char *start_skip = strstr(actualargv, abs_srcdir);
        char *end_skip = strstr(actualargv, emulator);
        if (!start_skip || !end_skip)
            goto fail;
        memmove(start_skip, end_skip, strlen(end_skip) + 1);
    }

    if (STRNEQ(expectargv, actualargv)) {
        virtTestDifference(stderr, expectargv, actualargv);
        goto fail;
    }

    ret = 0;

fail:
    free(log);
    free(emulator);
    free(expectargv);
    free(actualargv);
    virCommandFree(cmd);
    virDomainDefFree(vmdef);
    virUnrefConnect(conn);
    return ret;
}
コード例 #6
0
/* Align def->disks to def->domain.  Sort the list of def->disks,
 * filling in any missing disks or snapshot state defaults given by
 * the domain, with a fallback to a passed in default.  Convert paths
 * to disk targets for uniformity.  Issue an error and return -1 if
 * any def->disks[n]->name appears more than once or does not map to
 * dom->disks.  If require_match, also require that existing
 * def->disks snapshot states do not override explicit def->dom
 * settings.  */
int
virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr def,
                            int default_snapshot,
                            bool require_match)
{
    int ret = -1;
    virBitmapPtr map = NULL;
    int i;
    int ndisks;
    bool inuse;

    if (!def->dom) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("missing domain in snapshot"));
        goto cleanup;
    }

    if (def->ndisks > def->dom->ndisks) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("too many disk snapshot requests for domain"));
        goto cleanup;
    }

    /* Unlikely to have a guest without disks but technically possible.  */
    if (!def->dom->ndisks) {
        ret = 0;
        goto cleanup;
    }

    if (!(map = virBitmapNew(def->dom->ndisks))) {
        virReportOOMError();
        goto cleanup;
    }

    /* Double check requested disks.  */
    for (i = 0; i < def->ndisks; i++) {
        virDomainSnapshotDiskDefPtr disk = &def->disks[i];
        int idx = virDomainDiskIndexByName(def->dom, disk->name, false);
        int disk_snapshot;

        if (idx < 0) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("no disk named '%s'"), disk->name);
            goto cleanup;
        }
        disk_snapshot = def->dom->disks[idx]->snapshot;

        if (virBitmapGetBit(map, idx, &inuse) < 0 || inuse) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("disk '%s' specified twice"),
                           disk->name);
            goto cleanup;
        }
        ignore_value(virBitmapSetBit(map, idx));
        disk->index = idx;
        if (!disk_snapshot)
            disk_snapshot = default_snapshot;
        if (!disk->snapshot) {
            disk->snapshot = disk_snapshot;
        } else if (disk_snapshot && require_match &&
                   disk->snapshot != disk_snapshot) {
            const char *tmp;

            tmp = virDomainSnapshotLocationTypeToString(disk_snapshot);
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("disk '%s' must use snapshot mode '%s'"),
                           disk->name, tmp);
            goto cleanup;
        }
        if (disk->file &&
            disk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("file '%s' for disk '%s' requires "
                             "use of external snapshot mode"),
                           disk->file, disk->name);
            goto cleanup;
        }
        if (STRNEQ(disk->name, def->dom->disks[idx]->dst)) {
            VIR_FREE(disk->name);
            if (!(disk->name = strdup(def->dom->disks[idx]->dst))) {
                virReportOOMError();
                goto cleanup;
            }
        }
    }

    /* Provide defaults for all remaining disks.  */
    ndisks = def->ndisks;
    if (VIR_EXPAND_N(def->disks, def->ndisks,
                     def->dom->ndisks - def->ndisks) < 0) {
        virReportOOMError();
        goto cleanup;
    }

    for (i = 0; i < def->dom->ndisks; i++) {
        virDomainSnapshotDiskDefPtr disk;

        ignore_value(virBitmapGetBit(map, i, &inuse));
        if (inuse)
            continue;
        disk = &def->disks[ndisks++];
        if (!(disk->name = strdup(def->dom->disks[i]->dst))) {
            virReportOOMError();
            goto cleanup;
        }
        disk->index = i;
        disk->snapshot = def->dom->disks[i]->snapshot;
        if (!disk->snapshot)
            disk->snapshot = default_snapshot;
    }

    qsort(&def->disks[0], def->ndisks, sizeof(def->disks[0]), disksorter);

    /* Generate any default external file names, but only if the
     * backing file is a regular file.  */
    for (i = 0; i < def->ndisks; i++) {
        virDomainSnapshotDiskDefPtr disk = &def->disks[i];

        if (disk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL &&
            !disk->file) {
            const char *original = def->dom->disks[i]->src;
            const char *tmp;
            struct stat sb;

            if (!original) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("cannot generate external snapshot name "
                                 "for disk '%s' without source"),
                               disk->name);
                goto cleanup;
            }
            if (stat(original, &sb) < 0 || !S_ISREG(sb.st_mode)) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("source for disk '%s' is not a regular "
                                 "file; refusing to generate external "
                                 "snapshot name"),
                               disk->name);
                goto cleanup;
            }

            tmp = strrchr(original, '.');
            if (!tmp || strchr(tmp, '/')) {
                ignore_value(virAsprintf(&disk->file, "%s.%s",
                                         original, def->name));
            } else {
                if ((tmp - original) > INT_MAX) {
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("integer overflow"));
                    goto cleanup;
                }
                ignore_value(virAsprintf(&disk->file, "%.*s.%s",
                                         (int) (tmp - original), original,
                                         def->name));
            }
            if (!disk->file) {
                virReportOOMError();
                goto cleanup;
            }
        }
    }

    ret = 0;

cleanup:
    virBitmapFree(map);
    return ret;
}
コード例 #7
0
ファイル: jsontest.c プロジェクト: ISI-apex/libvirt-ARM
static int
testJSONAddRemove(const void *data)
{
    const struct testInfo *info = data;
    virJSONValuePtr json;
    virJSONValuePtr name = NULL;
    char *result = NULL;
    int ret = -1;

    json = virJSONValueFromString(info->doc);
    if (!json) {
        if (virTestGetVerbose())
            fprintf(stderr, "Fail to parse %s\n", info->doc);
        ret = -1;
        goto cleanup;
    }

    switch (virJSONValueObjectRemoveKey(json, "name", &name)) {
    case 1:
        if (!info->pass) {
            if (virTestGetVerbose())
                fprintf(stderr, "should not remove from non-object %s\n",
                        info->doc);
            goto cleanup;
        }
        break;
    case -1:
        if (!info->pass)
            ret = 0;
        else if (virTestGetVerbose())
            fprintf(stderr, "Fail to recognize non-object %s\n", info->doc);
        goto cleanup;
    default:
        if (virTestGetVerbose())
            fprintf(stderr, "unexpected result when removing from %s\n",
                    info->doc);
        goto cleanup;
    }
    if (STRNEQ_NULLABLE(virJSONValueGetString(name), "sample")) {
        if (virTestGetVerbose())
            fprintf(stderr, "unexpected value after removing name: %s\n",
                    NULLSTR(virJSONValueGetString(name)));
        goto cleanup;
    }
    if (virJSONValueObjectRemoveKey(json, "name", NULL)) {
        if (virTestGetVerbose())
            fprintf(stderr, "%s",
                    "unexpected success when removing missing key\n");
        goto cleanup;
    }
    if (virJSONValueObjectAppendString(json, "newname", "foo") < 0) {
        if (virTestGetVerbose())
            fprintf(stderr, "%s", "unexpected failure adding new key\n");
        goto cleanup;
    }
    if (!(result = virJSONValueToString(json, false))) {
        if (virTestGetVerbose())
            fprintf(stderr, "%s", "failed to stringize result\n");
        goto cleanup;
    }
    if (STRNEQ(info->expect, result)) {
        if (virTestGetVerbose())
            virtTestDifference(stderr, info->expect, result);
        goto cleanup;
    }
    ret = 0;

cleanup:
    virJSONValueFree(json);
    virJSONValueFree(name);
    VIR_FREE(result);
    return ret;
}
コード例 #8
0
static int
parallelsLoadNetwork(parallelsConnPtr privconn, virJSONValuePtr jobj)
{
    int ret = -1;
    virNetworkObjPtr net = NULL;
    virNetworkDefPtr def;
    const char *tmp;
    /* MD5_DIGEST_SIZE = VIR_UUID_BUFLEN = 16 */
    unsigned char md5[MD5_DIGEST_SIZE];

    if (VIR_ALLOC(def) < 0)
        goto cleanup;

    if (!(tmp = virJSONValueObjectGetString(jobj, "Network ID"))) {
        parallelsParseError();
        goto cleanup;
    }

    if (VIR_STRDUP(def->name, tmp) < 0)
        goto cleanup;

    /* Network names are unique in Parallels Cloud Server, so we can make
     * a UUID from it */
    md5_buffer(tmp, strlen(tmp), md5);
    memcpy(def->uuid, md5, VIR_UUID_BUFLEN);
    def->uuid_specified = 1;

    if (!(tmp = virJSONValueObjectGetString(jobj, "Type"))) {
        parallelsParseError();
        goto cleanup;
    }

    if (STREQ(tmp, PARALLELS_BRIDGED_NETWORK_TYPE)) {
        def->forward.type = VIR_NETWORK_FORWARD_BRIDGE;

        if (parallelsGetBridgedNetInfo(def, jobj) < 0) {

            /* Only mandatory networks are required to be configured completely */
            if (STRNEQ(def->name, PARALLELS_REQUIRED_BRIDGED_NETWORK))
                ret = 0;

            goto cleanup;
        }
    } else if (STREQ(tmp, PARALLELS_HOSTONLY_NETWORK_TYPE)) {
        def->forward.type = VIR_NETWORK_FORWARD_NONE;

        if (parallelsGetHostOnlyNetInfo(def, def->name) < 0) {

            /* Only mandatory networks are required to be configured completely */
            if (STRNEQ(def->name, PARALLELS_REQUIRED_HOSTONLY_NETWORK))
                ret = 0;

            goto cleanup;
        }
    } else {
        parallelsParseError();
        goto cleanup;
    }

    if (!(net = virNetworkAssignDef(privconn->networks, def, 0)))
        goto cleanup;
    def = NULL;
    net->active = 1;
    net->autostart = 1;
    ret = 0;

 cleanup:
    virNetworkObjEndAPI(&net);
    virNetworkDefFree(def);
    return ret;
}
コード例 #9
0
ファイル: qemuxml2argvtest.c プロジェクト: djs55/libvirt
static int testCompareXMLToArgvFiles(const char *xml,
                                     const char *cmdline,
                                     virQEMUCapsPtr extraFlags,
                                     const char *migrateFrom,
                                     int migrateFd,
                                     virQemuXML2ArgvTestFlags flags)
{
    char *expectargv = NULL;
    int len;
    char *actualargv = NULL;
    int ret = -1;
    virDomainDefPtr vmdef = NULL;
    virDomainChrSourceDef monitor_chr;
    virConnectPtr conn;
    char *log = NULL;
    virCommandPtr cmd = NULL;

    if (!(conn = virGetConnect()))
        goto out;
    conn->secretDriver = &fakeSecretDriver;

    if (!(vmdef = virDomainDefParseFile(xml, driver.caps, driver.xmlopt,
                                        QEMU_EXPECTED_VIRT_TYPES,
                                        VIR_DOMAIN_XML_INACTIVE))) {
        if (flags & FLAG_EXPECT_PARSE_ERROR)
            goto ok;
        goto out;
    }

    if (virQEMUCapsGet(extraFlags, QEMU_CAPS_DOMID))
        vmdef->id = 6;
    else
        vmdef->id = -1;

    memset(&monitor_chr, 0, sizeof(monitor_chr));
    monitor_chr.type = VIR_DOMAIN_CHR_TYPE_UNIX;
    monitor_chr.data.nix.path = (char *)"/tmp/test-monitor";
    monitor_chr.data.nix.listen = true;

    virQEMUCapsSetList(extraFlags,
                       QEMU_CAPS_VNC_COLON,
                       QEMU_CAPS_NO_REBOOT,
                       QEMU_CAPS_NO_ACPI,
                       QEMU_CAPS_LAST);

    if (STREQ(vmdef->os.machine, "pc") &&
        STREQ(vmdef->emulator, "/usr/bin/qemu-system-x86_64")) {
        VIR_FREE(vmdef->os.machine);
        if (VIR_STRDUP(vmdef->os.machine, "pc-0.11") < 0)
            goto out;
    }

    if (virQEMUCapsGet(extraFlags, QEMU_CAPS_DEVICE)) {
        if (qemuDomainAssignAddresses(vmdef, extraFlags, NULL)) {
            if (flags & FLAG_EXPECT_ERROR)
                goto ok;
            goto out;
        }
    }

    log = virtTestLogContentAndReset();
    VIR_FREE(log);
    virResetLastError();

    if (vmdef->os.arch == VIR_ARCH_X86_64 ||
        vmdef->os.arch == VIR_ARCH_I686) {
        virQEMUCapsSet(extraFlags, QEMU_CAPS_PCI_MULTIBUS);
    }

    if (qemuAssignDeviceAliases(vmdef, extraFlags) < 0)
        goto out;

    if (!(cmd = qemuBuildCommandLine(conn, &driver, vmdef, &monitor_chr,
                                     (flags & FLAG_JSON), extraFlags,
                                     migrateFrom, migrateFd, NULL,
                                     VIR_NETDEV_VPORT_PROFILE_OP_NO_OP,
                                     &testCallbacks))) {
        if (flags & FLAG_EXPECT_FAILURE) {
            ret = 0;
            if (virTestGetDebug() > 1)
                fprintf(stderr, "Got expected error: %s\n",
                        virGetLastErrorMessage());
            virResetLastError();
        }
        goto out;
    } else if (flags & FLAG_EXPECT_FAILURE) {
        if (virTestGetDebug())
            fprintf(stderr, "qemuBuildCommandLine should have failed\n");
        goto out;
    }

    if (!!virGetLastError() != !!(flags & FLAG_EXPECT_ERROR)) {
        if (virTestGetDebug() && (log = virtTestLogContentAndReset()))
            fprintf(stderr, "\n%s", log);
        goto out;
    }

    if (!(actualargv = virCommandToString(cmd)))
        goto out;

    len = virtTestLoadFile(cmdline, &expectargv);
    if (len < 0)
        goto out;
    if (len && expectargv[len - 1] == '\n')
        expectargv[len - 1] = '\0';

    if (STRNEQ(expectargv, actualargv)) {
        virtTestDifference(stderr, expectargv, actualargv);
        goto out;
    }

 ok:
    if (flags & FLAG_EXPECT_ERROR) {
        /* need to suppress the errors */
        virResetLastError();
    }

    ret = 0;

out:
    VIR_FREE(log);
    VIR_FREE(expectargv);
    VIR_FREE(actualargv);
    virCommandFree(cmd);
    virDomainDefFree(vmdef);
    virObjectUnref(conn);
    return ret;
}
コード例 #10
0
ファイル: vmware_driver.c プロジェクト: rbu/libvirt
static virDrvOpenStatus
vmwareOpen(virConnectPtr conn,
           virConnectAuthPtr auth ATTRIBUTE_UNUSED,
           int flags ATTRIBUTE_UNUSED)
{
    struct vmware_driver *driver;
    char * vmrun = NULL;

    if (conn->uri == NULL) {
        /* @TODO accept */
        return VIR_DRV_OPEN_DECLINED;
    } else {
        if (conn->uri->scheme == NULL ||
            (STRNEQ(conn->uri->scheme, "vmwareplayer") &&
             STRNEQ(conn->uri->scheme, "vmwarews")))
            return VIR_DRV_OPEN_DECLINED;

        /* If server name is given, its for remote driver */
        if (conn->uri->server != NULL)
            return VIR_DRV_OPEN_DECLINED;

        /* If path isn't /session, then they typoed, so tell them correct path */
        if (conn->uri->path == NULL || STRNEQ(conn->uri->path, "/session")) {
            vmwareError(VIR_ERR_INTERNAL_ERROR,
                        _("unexpected VMware URI path '%s', try vmwareplayer:///session or vmwarews:///session"),
                        NULLSTR(conn->uri->path));
            return VIR_DRV_OPEN_ERROR;
        }
    }

    /* We now know the URI is definitely for this driver, so beyond
     * here, don't return DECLINED, always use ERROR */

    vmrun = virFindFileInPath(VMRUN);

    if (vmrun == NULL) {
        vmwareError(VIR_ERR_INTERNAL_ERROR,
                    _("%s utility is missing"), VMRUN);
        return VIR_DRV_OPEN_ERROR;
    } else {
        VIR_FREE(vmrun);
    }

    if (VIR_ALLOC(driver) < 0) {
        virReportOOMError();
        return VIR_DRV_OPEN_ERROR;
    }

    if (virMutexInit(&driver->lock) < 0)
        goto cleanup;

    driver->type = STRNEQ(conn->uri->scheme, "vmwareplayer") ?
      TYPE_WORKSTATION : TYPE_PLAYER;

    if (virDomainObjListInit(&driver->domains) < 0)
        goto cleanup;

    if (!(driver->caps = vmwareCapsInit()))
        goto cleanup;

    driver->caps->privateDataAllocFunc = vmwareDataAllocFunc;
    driver->caps->privateDataFreeFunc = vmwareDataFreeFunc;

    if (vmwareLoadDomains(driver) < 0)
        goto cleanup;

    if (vmwareExtractVersion(driver) < 0)
        goto cleanup;

    conn->privateData = driver;

    return VIR_DRV_OPEN_SUCCESS;

  cleanup:
    vmwareFreeDriver(driver);
    return VIR_DRV_OPEN_ERROR;
};
コード例 #11
0
static int
SELinuxGenSecurityLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
                        virDomainDefPtr def)
{
    int rc = -1;
    char *mcs = NULL;
    char *scontext = NULL;
    int c1 = 0;
    int c2 = 0;
    context_t ctx = NULL;
    const char *range;

    if ((def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC) &&
        !def->seclabel.baselabel &&
        def->seclabel.model) {
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                               "%s", _("security model already defined for VM"));
        return rc;
    }

    if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
        def->seclabel.label) {
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                               "%s", _("security label already defined for VM"));
        return rc;
    }

    if (def->seclabel.imagelabel) {
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                               "%s", _("security image label already defined for VM"));
        return rc;
    }

    if (def->seclabel.model &&
        STRNEQ(def->seclabel.model, SECURITY_SELINUX_NAME)) {
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                               _("security label model %s is not supported with selinux"),
                               def->seclabel.model);
        return rc;
    }

    switch (def->seclabel.type) {
    case VIR_DOMAIN_SECLABEL_STATIC:
        if (!(ctx = context_new(def->seclabel.label)) ) {
            virReportSystemError(errno,
                                 _("unable to allocate socket security context '%s'"),
                                 def->seclabel.label);
            return rc;
        }

        range = context_range_get(ctx);
        if (!range ||
            !(mcs = strdup(range))) {
            virReportOOMError();
            goto cleanup;
        }
        break;

    case VIR_DOMAIN_SECLABEL_DYNAMIC:
        do {
            c1 = virRandomBits(10);
            c2 = virRandomBits(10);

            if ( c1 == c2 ) {
                if (virAsprintf(&mcs, "s0:c%d", c1) < 0) {
                    virReportOOMError();
                    goto cleanup;
                }
            } else {
                if (c1 > c2) {
                    c1 ^= c2;
                    c2 ^= c1;
                    c1 ^= c2;
                }
                if (virAsprintf(&mcs, "s0:c%d,c%d", c1, c2) < 0) {
                    virReportOOMError();
                    goto cleanup;
                }
            }
        } while (mcsAdd(mcs) == -1);

        def->seclabel.label =
            SELinuxGenNewContext(def->seclabel.baselabel ?
                                 def->seclabel.baselabel :
                                 default_domain_context, mcs);
        if (! def->seclabel.label)  {
            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("cannot generate selinux context for %s"), mcs);
            goto cleanup;
        }
        break;

    case VIR_DOMAIN_SECLABEL_NONE:
        /* no op */
        break;

    default:
        virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                               _("unexpected security label type '%s'"),
                               virDomainSeclabelTypeToString(def->seclabel.type));
        goto cleanup;
    }

    if (!def->seclabel.norelabel) {
        def->seclabel.imagelabel = SELinuxGenNewContext(default_image_context, mcs);
        if (!def->seclabel.imagelabel)  {
            virSecurityReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("cannot generate selinux context for %s"), mcs);
            goto cleanup;
        }
    }

    if (!def->seclabel.model &&
        !(def->seclabel.model = strdup(SECURITY_SELINUX_NAME))) {
        virReportOOMError();
        goto cleanup;
    }

    rc = 0;

cleanup:
    if (rc != 0) {
        if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC)
            VIR_FREE(def->seclabel.label);
        VIR_FREE(def->seclabel.imagelabel);
        if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
            !def->seclabel.baselabel)
            VIR_FREE(def->seclabel.model);
    }

    if (ctx)
        context_free(ctx);
    VIR_FREE(scontext);
    VIR_FREE(mcs);

    VIR_DEBUG("model=%s label=%s imagelabel=%s baselabel=%s",
              NULLSTR(def->seclabel.model),
              NULLSTR(def->seclabel.label),
              NULLSTR(def->seclabel.imagelabel),
              NULLSTR(def->seclabel.baselabel));

    return rc;
}
コード例 #12
0
static virDrvOpenStatus openvzOpen(virConnectPtr conn,
                                   virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                   unsigned int flags)
{
    struct openvz_driver *driver;

    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

    if (conn->uri == NULL) {
        if (!virFileExists("/proc/vz"))
            return VIR_DRV_OPEN_DECLINED;

        if (access("/proc/vz", W_OK) < 0)
            return VIR_DRV_OPEN_DECLINED;

        if (!(conn->uri = virURIParse("openvz:///system")))
            return VIR_DRV_OPEN_ERROR;
    } else {
        /* If scheme isn't 'openvz', then its for another driver */
        if (conn->uri->scheme == NULL ||
            STRNEQ (conn->uri->scheme, "openvz"))
            return VIR_DRV_OPEN_DECLINED;

        /* If server name is given, its for remote driver */
        if (conn->uri->server != NULL)
            return VIR_DRV_OPEN_DECLINED;

        /* If path isn't /system, then they typoed, so tell them correct path */
        if (conn->uri->path == NULL ||
            STRNEQ (conn->uri->path, "/system")) {
            openvzError(VIR_ERR_INTERNAL_ERROR,
                        _("unexpected OpenVZ URI path '%s', try openvz:///system"),
                        conn->uri->path);
            return VIR_DRV_OPEN_ERROR;
        }

        if (!virFileExists("/proc/vz")) {
            openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("OpenVZ control file /proc/vz does not exist"));
            return VIR_DRV_OPEN_ERROR;
        }

        if (access("/proc/vz", W_OK) < 0) {
            openvzError(VIR_ERR_INTERNAL_ERROR, "%s",
                        _("OpenVZ control file /proc/vz is not accessible"));
            return VIR_DRV_OPEN_ERROR;
        }
    }

    /* We now know the URI is definitely for this driver, so beyond
     * here, don't return DECLINED, always use ERROR */

    if (VIR_ALLOC(driver) < 0) {
        virReportOOMError();
        return VIR_DRV_OPEN_ERROR;
    }

    if (virDomainObjListInit(&driver->domains) < 0)
        goto cleanup;

    if (!(driver->caps = openvzCapsInit()))
        goto cleanup;

    if (openvzLoadDomains(driver) < 0)
        goto cleanup;

    if (openvzExtractVersion(driver) < 0)
        goto cleanup;

    conn->privateData = driver;

    return VIR_DRV_OPEN_SUCCESS;

cleanup:
    openvzFreeDriver(driver);
    return VIR_DRV_OPEN_ERROR;
};
コード例 #13
0
static bool
testSELinuxCheckCon(context_t con,
                    const char *user,
                    const char *role,
                    const char *type,
                    int sensMin,
                    int sensMax ATTRIBUTE_UNUSED,
                    int catMin,
                    int catMax)
{
    const char *range;
    char *tmp;
    int gotSens;
    int gotCatOne;
    int gotCatTwo;

    if (STRNEQ(context_user_get(con), user)) {
        fprintf(stderr, "Expect user %s got %s\n",
                user, context_user_get(con));
        return false;
    }
    if (STRNEQ(context_role_get(con), role)) {
        fprintf(stderr, "Expect role %s got %s\n",
                role, context_role_get(con));
        return false;
    }
    if (STRNEQ(context_type_get(con), type)) {
        fprintf(stderr, "Expect type %s got %s\n",
                type, context_type_get(con));
        return false;
    }

    range = context_range_get(con);
    if (range[0] != 's') {
        fprintf(stderr, "Malformed range %s, cannot find sensitivity\n",
                range);
        return false;
    }
    if (virStrToLong_i(range + 1, &tmp, 10, &gotSens) < 0 ||
        !tmp) {
        fprintf(stderr, "Malformed range %s, cannot parse sensitivity\n",
                range + 1);
        return false;
    }
    if (*tmp != ':') {
        fprintf(stderr, "Malformed range %s, too many sensitivity values\n",
                tmp);
        return false;
    }
    tmp++;
    if (*tmp != 'c') {
        fprintf(stderr, "Malformed range %s, cannot find first category\n",
                tmp);
        return false;
    }
    tmp++;
    if (virStrToLong_i(tmp, &tmp, 10, &gotCatOne) < 0) {
        fprintf(stderr, "Malformed range %s, cannot parse category one\n",
                tmp);
        return false;
    }
    if (tmp && *tmp == ',')
        tmp++;
    if (tmp && *tmp == 'c') {
        tmp++;
        if (virStrToLong_i(tmp, &tmp, 10, &gotCatTwo) < 0) {
            fprintf(stderr, "Malformed range %s, cannot parse category two\n",
                    tmp);
            return false;
        }
        if (*tmp != '\0') {
            fprintf(stderr, "Malformed range %s, junk after second category\n",
                    tmp);
            return false;
        }
        if (gotCatOne == gotCatTwo) {
            fprintf(stderr, "Saw category pair %d,%d where cats were equal\n",
                    gotCatOne, gotCatTwo);
            return false;
        }
    } else {
        gotCatTwo = gotCatOne;
    }

    if (gotSens != sensMin) {
        fprintf(stderr, "Sensitivity %d is not equal to min %d\n",
                gotSens, sensMin);
        return false;
    }
    if (gotCatOne < catMin ||
        gotCatOne > catMax) {
        fprintf(stderr, "Category one %d is out of range %d-%d\n",
                gotCatTwo, catMin, catMax);
        return false;
    }
    if (gotCatTwo < catMin ||
        gotCatTwo > catMax) {
        fprintf(stderr, "Category two %d is out of range %d-%d\n",
                gotCatTwo, catMin, catMax);
        return false;
    }

    if (gotCatOne > gotCatTwo) {
        fprintf(stderr, "Category one %d is greater than category two %d\n",
                gotCatOne, gotCatTwo);
        return false;
    }

    return true;
}
コード例 #14
0
ファイル: appliance.c プロジェクト: will-Do/libguestfs
/* Build supermin appliance from supermin_path to $TMPDIR/.guestfs-$UID.
 *
 * Returns:
 * 0 = built
 * -1 = error (aborts launch)
 */
static int
build_supermin_appliance (guestfs_h *g,
                          const char *supermin_path,
                          uid_t uid,
                          char **kernel, char **initrd,
                          char **appliance)
{
  CLEANUP_FREE char *tmpdir = guestfs_get_cachedir (g);
  struct stat statbuf;
  size_t len;

  /* len must be longer than the length of any pathname we can
   * generate in this function.
   */
  len = strlen (tmpdir) + 128;
  char cachedir[len];
  snprintf (cachedir, len, "%s/.guestfs-%ju", tmpdir, (uintmax_t) uid);
  char lockfile[len];
  snprintf (lockfile, len, "%s/lock", cachedir);
  char appliancedir[len];
  snprintf (appliancedir, len, "%s/appliance.d", cachedir);

  ignore_value (mkdir (cachedir, 0755));
  ignore_value (chmod (cachedir, 0755)); /* RHBZ#921292 */

  /* See if the cache directory exists and passes some simple checks
   * to make sure it has not been tampered with.
   */
  if (lstat (cachedir, &statbuf) == -1)
    return 0;
  if (statbuf.st_uid != uid) {
    error (g, _("security: cached appliance %s is not owned by UID %ju"),
           cachedir, (uintmax_t) uid);
    return -1;
  }
  if (!S_ISDIR (statbuf.st_mode)) {
    error (g, _("security: cached appliance %s is not a directory (mode %o)"),
           cachedir, statbuf.st_mode);
    return -1;
  }
  if ((statbuf.st_mode & 0022) != 0) {
    error (g, _("security: cached appliance %s is writable by group or other (mode %o)"),
           cachedir, statbuf.st_mode);
    return -1;
  }

  (void) utimes (cachedir, NULL);
  if (g->verbose)
    guestfs_int_print_timestamped_message (g, "begin building supermin appliance");

  /* Build the appliance if it needs to be built. */
  if (g->verbose)
    guestfs_int_print_timestamped_message (g, "run supermin");

  if (run_supermin_build (g, lockfile, appliancedir, supermin_path) == -1)
    return -1;

  if (g->verbose)
    guestfs_int_print_timestamped_message (g, "finished building supermin appliance");

  /* Return the appliance filenames. */
  *kernel = safe_malloc (g, len);
  *initrd = safe_malloc (g, len);
  *appliance = safe_malloc (g, len);
  snprintf (*kernel, len, "%s/kernel", appliancedir);
  snprintf (*initrd, len, "%s/initrd", appliancedir);
  snprintf (*appliance, len, "%s/root", appliancedir);

  /* Touch the files so they don't get deleted (as they are in /var/tmp). */
  (void) utimes (*kernel, NULL);
  (void) utimes (*initrd, NULL);

  /* Checking backend != "uml" is a big hack.  UML encodes the mtime
   * of the original backing file (in this case, the appliance) in the
   * COW file, and checks it when adding it to the VM.  If there are
   * multiple threads running and one touches the appliance here, it
   * will disturb the mtime and UML will give an error.
   *
   * We can get rid of this hack as soon as UML fixes the
   * ubdN=cow,original parsing bug, since we won't need to run
   * uml_mkcow separately, so there is no possible race.
   *
   * XXX
   */
  if (STRNEQ (g->backend, "uml"))
    (void) utimes (*appliance, NULL);

  return 0;
}
コード例 #15
0
ファイル: qemu_conf.c プロジェクト: candhare/libvirt
int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
                                const char *filename)
{
    virConfPtr conf = NULL;
    virConfValuePtr p;
    int ret = -1;
    size_t i;

    /* Just check the file is readable before opening it, otherwise
     * libvirt emits an error.
     */
    if (access(filename, R_OK) == -1) {
        VIR_INFO("Could not read qemu config file %s", filename);
        return 0;
    }

    if (!(conf = virConfReadFile(filename, 0)))
        goto cleanup;

#define CHECK_TYPE(name, typ)                         \
    if (p && p->type != (typ)) {                      \
        virReportError(VIR_ERR_INTERNAL_ERROR,        \
                       "%s: %s: expected type " #typ, \
                       filename, (name));             \
        goto cleanup;                                 \
    }

#define CHECK_TYPE_ALT(name, type1, type2)                      \
    if (p && (p->type != (type1) && p->type != (type2))) {      \
        virReportError(VIR_ERR_INTERNAL_ERROR,                  \
                       "%s: %s: expected type " #type1,         \
                       filename, (name));                       \
        goto cleanup;                                           \
    }

#define GET_VALUE_LONG(NAME, VAR)                               \
    p = virConfGetValue(conf, NAME);                            \
    CHECK_TYPE_ALT(NAME, VIR_CONF_LONG, VIR_CONF_ULONG);        \
    if (p)                                                      \
        VAR = p->l;

#define GET_VALUE_ULONG(NAME, VAR)    \
    p = virConfGetValue(conf, NAME);  \
    CHECK_TYPE(NAME, VIR_CONF_ULONG); \
    if (p)                            \
        VAR = p->l;

#define GET_VALUE_BOOL(NAME, VAR)     \
    p = virConfGetValue(conf, NAME);  \
    CHECK_TYPE(NAME, VIR_CONF_ULONG); \
    if (p)                            \
        VAR = p->l != 0;

#define GET_VALUE_STR(NAME, VAR)           \
    p = virConfGetValue(conf, NAME);       \
    CHECK_TYPE(NAME, VIR_CONF_STRING);     \
    if (p && p->str) {                     \
        VIR_FREE(VAR);                     \
        if (VIR_STRDUP(VAR, p->str) < 0)   \
            goto cleanup;                  \
    }

    GET_VALUE_BOOL("vnc_auto_unix_socket", cfg->vncAutoUnixSocket);
    GET_VALUE_BOOL("vnc_tls", cfg->vncTLS);
    GET_VALUE_BOOL("vnc_tls_x509_verify", cfg->vncTLSx509verify);
    GET_VALUE_STR("vnc_tls_x509_cert_dir", cfg->vncTLSx509certdir);
    GET_VALUE_STR("vnc_listen", cfg->vncListen);
    GET_VALUE_STR("vnc_password", cfg->vncPassword);
    GET_VALUE_BOOL("vnc_sasl", cfg->vncSASL);
    GET_VALUE_STR("vnc_sasl_dir", cfg->vncSASLdir);
    GET_VALUE_BOOL("vnc_allow_host_audio", cfg->vncAllowHostAudio);
    GET_VALUE_BOOL("nographics_allow_host_audio", cfg->nogfxAllowHostAudio);

    p = virConfGetValue(conf, "security_driver");
    if (p && p->type == VIR_CONF_LIST) {
        size_t len, j;
        virConfValuePtr pp;

        /* Calc length and check items */
        for (len = 0, pp = p->list; pp; len++, pp = pp->next) {
            if (pp->type != VIR_CONF_STRING) {
                virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                               _("security_driver must be a list of strings"));
                goto cleanup;
            }
        }

        if (VIR_ALLOC_N(cfg->securityDriverNames, len + 1) < 0)
            goto cleanup;

        for (i = 0, pp = p->list; pp; i++, pp = pp->next) {
            for (j = 0; j < i; j++) {
                if (STREQ(pp->str, cfg->securityDriverNames[j])) {
                    virReportError(VIR_ERR_CONF_SYNTAX,
                                   _("Duplicate security driver %s"), pp->str);
                    goto cleanup;
                }
            }
            if (VIR_STRDUP(cfg->securityDriverNames[i], pp->str) < 0)
                goto cleanup;
        }
        cfg->securityDriverNames[len] = NULL;
    } else {
        CHECK_TYPE("security_driver", VIR_CONF_STRING);
        if (p && p->str) {
            if (VIR_ALLOC_N(cfg->securityDriverNames, 2) < 0)
                goto cleanup;
            if (VIR_STRDUP(cfg->securityDriverNames[0], p->str) < 0)
                goto cleanup;

            cfg->securityDriverNames[1] = NULL;
        }
    }

    GET_VALUE_BOOL("security_default_confined", cfg->securityDefaultConfined);
    GET_VALUE_BOOL("security_require_confined", cfg->securityRequireConfined);

    GET_VALUE_BOOL("spice_tls", cfg->spiceTLS);
    GET_VALUE_STR("spice_tls_x509_cert_dir", cfg->spiceTLSx509certdir);
    GET_VALUE_BOOL("spice_sasl", cfg->spiceSASL);
    GET_VALUE_STR("spice_sasl_dir", cfg->spiceSASLdir);
    GET_VALUE_STR("spice_listen", cfg->spiceListen);
    GET_VALUE_STR("spice_password", cfg->spicePassword);


    GET_VALUE_ULONG("remote_websocket_port_min", cfg->webSocketPortMin);
    if (cfg->webSocketPortMin < QEMU_WEBSOCKET_PORT_MIN) {
        /* if the port is too low, we can't get the display name
         * to tell to vnc (usually subtract 5700, e.g. localhost:1
         * for port 5701) */
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("%s: remote_websocket_port_min: port must be greater "
                         "than or equal to %d"),
                        filename, QEMU_WEBSOCKET_PORT_MIN);
        goto cleanup;
    }

    GET_VALUE_ULONG("remote_websocket_port_max", cfg->webSocketPortMax);
    if (cfg->webSocketPortMax > QEMU_WEBSOCKET_PORT_MAX ||
        cfg->webSocketPortMax < cfg->webSocketPortMin) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("%s: remote_websocket_port_max: port must be between "
                          "the minimal port and %d"),
                       filename, QEMU_WEBSOCKET_PORT_MAX);
        goto cleanup;
    }

    if (cfg->webSocketPortMin > cfg->webSocketPortMax) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("%s: remote_websocket_port_min: min port must not be "
                          "greater than max port"), filename);
        goto cleanup;
    }

    GET_VALUE_ULONG("remote_display_port_min", cfg->remotePortMin);
    if (cfg->remotePortMin < QEMU_REMOTE_PORT_MIN) {
        /* if the port is too low, we can't get the display name
         * to tell to vnc (usually subtract 5900, e.g. localhost:1
         * for port 5901) */
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("%s: remote_display_port_min: port must be greater "
                         "than or equal to %d"),
                        filename, QEMU_REMOTE_PORT_MIN);
        goto cleanup;
    }

    GET_VALUE_ULONG("remote_display_port_max", cfg->remotePortMax);
    if (cfg->remotePortMax > QEMU_REMOTE_PORT_MAX ||
        cfg->remotePortMax < cfg->remotePortMin) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("%s: remote_display_port_max: port must be between "
                          "the minimal port and %d"),
                       filename, QEMU_REMOTE_PORT_MAX);
        goto cleanup;
    }

    if (cfg->remotePortMin > cfg->remotePortMax) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("%s: remote_display_port_min: min port must not be "
                          "greater than max port"), filename);
        goto cleanup;
    }

    GET_VALUE_ULONG("migration_port_min", cfg->migrationPortMin);
    if (cfg->migrationPortMin <= 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("%s: migration_port_min: port must be greater than 0"),
                        filename);
        goto cleanup;
    }

    GET_VALUE_ULONG("migration_port_max", cfg->migrationPortMax);
    if (cfg->migrationPortMax > 65535 ||
        cfg->migrationPortMax < cfg->migrationPortMin) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("%s: migration_port_max: port must be between "
                          "the minimal port %d and 65535"),
                       filename, cfg->migrationPortMin);
        goto cleanup;
    }

    p = virConfGetValue(conf, "user");
    CHECK_TYPE("user", VIR_CONF_STRING);
    if (p && p->str &&
        virGetUserID(p->str, &cfg->user) < 0)
        goto cleanup;

    p = virConfGetValue(conf, "group");
    CHECK_TYPE("group", VIR_CONF_STRING);
    if (p && p->str &&
        virGetGroupID(p->str, &cfg->group) < 0)
        goto cleanup;

    GET_VALUE_BOOL("dynamic_ownership", cfg->dynamicOwnership);

    p = virConfGetValue(conf, "cgroup_controllers");
    CHECK_TYPE("cgroup_controllers", VIR_CONF_LIST);
    if (p) {
        cfg->cgroupControllers = 0;
        virConfValuePtr pp;
        for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
            int ctl;
            if (pp->type != VIR_CONF_STRING) {
                virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                               _("cgroup_controllers must be a "
                                 "list of strings"));
                goto cleanup;
            }

            if ((ctl = virCgroupControllerTypeFromString(pp->str)) < 0) {
                virReportError(VIR_ERR_CONF_SYNTAX,
                               _("Unknown cgroup controller '%s'"), pp->str);
                goto cleanup;
            }
            cfg->cgroupControllers |= (1 << ctl);
        }
    }

    p = virConfGetValue(conf, "cgroup_device_acl");
    CHECK_TYPE("cgroup_device_acl", VIR_CONF_LIST);
    if (p) {
        int len = 0;
        virConfValuePtr pp;
        for (pp = p->list; pp; pp = pp->next)
            len++;
        if (VIR_ALLOC_N(cfg->cgroupDeviceACL, 1+len) < 0)
            goto cleanup;

        for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
            if (pp->type != VIR_CONF_STRING) {
                virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                               _("cgroup_device_acl must be a "
                                 "list of strings"));
                goto cleanup;
            }
            if (VIR_STRDUP(cfg->cgroupDeviceACL[i], pp->str) < 0)
                goto cleanup;
        }
        cfg->cgroupDeviceACL[i] = NULL;
    }

    GET_VALUE_STR("save_image_format", cfg->saveImageFormat);
    GET_VALUE_STR("dump_image_format", cfg->dumpImageFormat);
    GET_VALUE_STR("snapshot_image_format", cfg->snapshotImageFormat);

    GET_VALUE_STR("auto_dump_path", cfg->autoDumpPath);
    GET_VALUE_BOOL("auto_dump_bypass_cache", cfg->autoDumpBypassCache);
    GET_VALUE_BOOL("auto_start_bypass_cache", cfg->autoStartBypassCache);

    /* Some crazy backcompat. Back in the old days, this was just a pure
     * string. We must continue supporting it. These days however, this may be
     * an array of strings. */
    p = virConfGetValue(conf, "hugetlbfs_mount");
    if (p) {
        /* There already might be something autodetected. Avoid leaking it. */
        while (cfg->nhugetlbfs) {
            cfg->nhugetlbfs--;
            VIR_FREE(cfg->hugetlbfs[cfg->nhugetlbfs].mnt_dir);
        }
        VIR_FREE(cfg->hugetlbfs);

        if (p->type == VIR_CONF_LIST) {
            size_t len = 0;
            virConfValuePtr pp = p->list;

            /* Calc length and check items */
            while (pp) {
                if (pp->type != VIR_CONF_STRING) {
                    virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                                   _("hugetlbfs_mount must be a list of strings"));
                    goto cleanup;
                }
                len++;
                pp = pp->next;
            }

            if (len && VIR_ALLOC_N(cfg->hugetlbfs, len) < 0)
                goto cleanup;
            cfg->nhugetlbfs = len;

            pp = p->list;
            len = 0;
            while (pp) {
                if (virQEMUDriverConfigHugeTLBFSInit(&cfg->hugetlbfs[len],
                                                     pp->str, !len) < 0)
                    goto cleanup;
                len++;
                pp = pp->next;
            }
        } else {
            CHECK_TYPE("hugetlbfs_mount", VIR_CONF_STRING);
            if (STRNEQ(p->str, "")) {
                if (VIR_ALLOC_N(cfg->hugetlbfs, 1) < 0)
                    goto cleanup;
                cfg->nhugetlbfs = 1;
                if (virQEMUDriverConfigHugeTLBFSInit(&cfg->hugetlbfs[0],
                                                     p->str, true) < 0)
                    goto cleanup;
            }
        }
    }

    GET_VALUE_STR("bridge_helper", cfg->bridgeHelperName);

    GET_VALUE_BOOL("mac_filter", cfg->macFilter);

    GET_VALUE_BOOL("relaxed_acs_check", cfg->relaxedACS);
    GET_VALUE_BOOL("clear_emulator_capabilities", cfg->clearEmulatorCapabilities);
    GET_VALUE_BOOL("allow_disk_format_probing", cfg->allowDiskFormatProbing);
    GET_VALUE_BOOL("set_process_name", cfg->setProcessName);
    GET_VALUE_ULONG("max_processes", cfg->maxProcesses);
    GET_VALUE_ULONG("max_files", cfg->maxFiles);

    GET_VALUE_STR("lock_manager", cfg->lockManagerName);

    GET_VALUE_ULONG("max_queued", cfg->maxQueuedJobs);

    GET_VALUE_LONG("keepalive_interval", cfg->keepAliveInterval);
    GET_VALUE_ULONG("keepalive_count", cfg->keepAliveCount);

    GET_VALUE_LONG("seccomp_sandbox", cfg->seccompSandbox);

    GET_VALUE_STR("migration_host", cfg->migrateHost);
    virStringStripIPv6Brackets(cfg->migrateHost);
    if (cfg->migrateHost &&
        (STRPREFIX(cfg->migrateHost, "localhost") ||
         virSocketAddrIsNumericLocalhost(cfg->migrateHost))) {
        virReportError(VIR_ERR_CONF_SYNTAX,
                       _("migration_host must not be the address of"
                         " the local machine: %s"),
                       cfg->migrateHost);
        goto cleanup;
    }

    GET_VALUE_STR("migration_address", cfg->migrationAddress);
    virStringStripIPv6Brackets(cfg->migrationAddress);
    if (cfg->migrationAddress &&
        (STRPREFIX(cfg->migrationAddress, "localhost") ||
         virSocketAddrIsNumericLocalhost(cfg->migrationAddress))) {
        virReportError(VIR_ERR_CONF_SYNTAX,
                       _("migration_address must not be the address of"
                         " the local machine: %s"),
                       cfg->migrationAddress);
        goto cleanup;
    }

    GET_VALUE_BOOL("log_timestamp", cfg->logTimestamp);

    if ((p = virConfGetValue(conf, "nvram"))) {
        size_t len;
        virConfValuePtr pp;

        CHECK_TYPE("nvram", VIR_CONF_LIST);

        while (cfg->nloader) {
            VIR_FREE(cfg->loader[cfg->nloader - 1]);
            VIR_FREE(cfg->nvram[cfg->nloader - 1]);
            cfg->nloader--;
        }
        VIR_FREE(cfg->loader);
        VIR_FREE(cfg->nvram);

        /* Calc length and check items */
        for (len = 0, pp = p->list; pp; len++, pp = pp->next) {
            if (pp->type != VIR_CONF_STRING) {
                virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                               _("nvram must be a list of strings"));
                goto cleanup;
            }
        }

        if (len &&
            (VIR_ALLOC_N(cfg->loader, len) < 0 ||
             VIR_ALLOC_N(cfg->nvram, len) < 0))
            goto cleanup;
        cfg->nloader = len;

        for (i = 0, pp = p->list; pp; i++, pp = pp->next) {
            if (virQEMUDriverConfigNVRAMParse(pp->str,
                                              &cfg->loader[i],
                                              &cfg->nvram[i]) < 0)
                goto cleanup;
        }
    }

    ret = 0;

 cleanup:
    virConfFree(conf);
    return ret;
}
コード例 #16
0
/* virNetDevVPortProfileMerge() - merge the attributes in mods into
 * orig. If anything that is set in mods has already been set in orig
 * *and doesn't match*, log an error and return -1, otherwise return 0.
 */
static int
virNetDevVPortProfileMerge(virNetDevVPortProfilePtr orig,
                           virNetDevVPortProfilePtr mods)
{
    enum virNetDevVPortProfile otype;

    if (!orig || !mods)
        return 0;

    otype = orig->virtPortType;

    if (mods->virtPortType != VIR_NETDEV_VPORT_PROFILE_NONE) {
        if (otype != VIR_NETDEV_VPORT_PROFILE_NONE &&
            otype != mods->virtPortType) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("attempt to merge virtualports "
                             "with mismatched types (%s and %s)"),
                           virNetDevVPortTypeToString(otype),
                           virNetDevVPortTypeToString(mods->virtPortType));
            return -1;
        }
        otype = orig->virtPortType = mods->virtPortType;
    }

    if (mods->managerID_specified &&
        (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        if (orig->managerID_specified &&
            (orig->managerID != mods->managerID)) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("attempt to merge virtualports "
                             "with mismatched managerids (%d and %d)"),
                           orig->managerID, mods->managerID);
            return -1;
        }
        orig->managerID = mods->managerID;
        orig->managerID_specified = true;
    }

    if (mods->typeID_specified &&
        (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        if (orig->typeID_specified &&
            (orig->typeID != mods->typeID)) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("attempt to merge virtualports "
                             "with mismatched typeids (%d and %d)"),
                           orig->typeID, mods->typeID);
            return -1;
        }
        orig->typeID = mods->typeID;
        orig->typeID_specified = true;
    }

    if (mods->typeIDVersion_specified &&
        (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        if (orig->typeIDVersion_specified &&
            (orig->typeIDVersion != mods->typeIDVersion)) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("attempt to merge virtualports with "
                             "mismatched typeidversions (%d and %d)"),
                           orig->typeIDVersion, mods->typeIDVersion);
            return -1;
        }
        orig->typeIDVersion = mods->typeIDVersion;
        orig->typeIDVersion_specified = true;
    }

    if (mods->instanceID_specified &&
        (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        if (orig->instanceID_specified &&
            memcmp(orig->instanceID, mods->instanceID,
                   sizeof(orig->instanceID))) {
            char origuuid[VIR_UUID_STRING_BUFLEN];
            char modsuuid[VIR_UUID_STRING_BUFLEN];

            virReportError(VIR_ERR_XML_ERROR,
                           _("attempt to merge virtualports with "
                             "mismatched instanceids ('%s' and '%s')"),
                           virUUIDFormat(orig->instanceID, origuuid),
                           virUUIDFormat(mods->instanceID, modsuuid));
            return -1;
        }
        memcpy(orig->instanceID, mods->instanceID, sizeof(orig->instanceID));
        orig->instanceID_specified = true;
    }

    if (mods->interfaceID_specified &&
        (otype == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        if (orig->interfaceID_specified &&
            memcmp(orig->interfaceID, mods->interfaceID,
                   sizeof(orig->interfaceID))) {
            char origuuid[VIR_UUID_STRING_BUFLEN];
            char modsuuid[VIR_UUID_STRING_BUFLEN];

            virReportError(VIR_ERR_XML_ERROR,
                           _("attempt to merge virtualports with "
                             "mismatched interfaceids ('%s' and '%s')"),
                           virUUIDFormat(orig->interfaceID, origuuid),
                           virUUIDFormat(mods->interfaceID, modsuuid));
            return -1;
        }
        memcpy(orig->interfaceID, mods->interfaceID, sizeof(orig->interfaceID));
        orig->interfaceID_specified = true;
    }

    if (mods->profileID[0] &&
        (otype == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
         otype == VIR_NETDEV_VPORT_PROFILE_8021QBH ||
         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        if (orig->profileID[0] &&
            STRNEQ(orig->profileID, mods->profileID)) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("attempt to merge virtualports with "
                             "mismatched profileids ('%s' and '%s')"),
                           orig->profileID, mods->profileID);
            return -1;
        }
        if (virStrcpyStatic(orig->profileID, mods->profileID) == NULL) {
            /* this should never happen - it indicates mods->profileID
             * isn't properly null terminated. */
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("corrupted profileid string"));
            return -1;
        }
    }
    return 0;
}
コード例 #17
0
ファイル: libvirt-admin.c プロジェクト: carriercomm/libvirt
static char *
getSocketPath(const char *name)
{
    char *rundir = virGetUserRuntimeDirectory();
    char *sock_path = NULL;
    size_t i = 0;
    virURIPtr uri = NULL;

    if (name) {
        if (!(uri = virURIParse(name)))
            goto error;

        if (STRNEQ(uri->scheme, "admin") ||
            uri->server || uri->user || uri->fragment) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Invalid connection name '%s'"), name);
            goto error;
        }

        for (i = 0; i < uri->paramsCount; i++) {
            virURIParamPtr param = &uri->params[i];

            if (STREQ(param->name, "socket")) {
                VIR_FREE(sock_path);
                if (VIR_STRDUP(sock_path, param->value) < 0)
                    goto error;
            } else {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("Unknown URI parameter '%s'"), param->name);
                goto error;
            }
        }
    }

    if (!sock_path) {
        if (!uri || !uri->path || STREQ(uri->path, "/system")) {
            if (VIR_STRDUP(sock_path, LIBVIRTD_ADMIN_UNIX_SOCKET) < 0)
                goto error;
        } else if (STREQ_NULLABLE(uri->path, "/session")) {
            if (!rundir)
                goto error;

            if (virAsprintf(&sock_path,
                            "%s%s", rundir, LIBVIRTD_ADMIN_SOCK_NAME) < 0)
                goto error;
        } else {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Invalid URI path '%s'"), uri->path);
            goto error;
        }
    }

 cleanup:
    VIR_FREE(rundir);
    virURIFree(uri);
    return sock_path;

 error:
    VIR_FREE(sock_path);
    goto cleanup;
}
コード例 #18
0
ファイル: uri.c プロジェクト: noxdafox/libguestfs
static int
parse (const char *arg, char **path_ret, char **protocol_ret,
       char ***server_ret, char **username_ret, char **password_ret)
{
  CLEANUP_XMLFREEURI xmlURIPtr uri = NULL;
  CLEANUP_FREE char *socket = NULL;
  char *path;

  uri = xmlParseURI (arg);
  if (!uri) {
    fprintf (stderr, _("%s: --add: could not parse URI '%s'\n"),
             getprogname (), arg);
    return -1;
  }

  /* Note we don't do much checking of the parsed URI, since the
   * underlying function 'guestfs_add_drive_opts' will check for us.
   * So just the basics here.
   */
  if (uri->scheme == NULL || STREQ (uri->scheme, "")) {
    /* Probably can never happen. */
    fprintf (stderr, _("%s: %s: scheme of URI is NULL or empty\n"),
             getprogname (), arg);
    return -1;
  }

  socket = query_get (uri, "socket");

  if (uri->server && STRNEQ (uri->server, "") && socket) {
    fprintf (stderr, _("%s: %s: cannot both a server name and a socket query parameter\n"),
             getprogname (), arg);
    return -1;
  }

  /* Is this needed? XXX
  if (socket && socket[0] != '/') {
    fprintf (stderr, _("%s: --add %s: socket query parameter must be an absolute path\n"),
             getprogname (), arg);
    return -1;
  }
  */

  *protocol_ret = strdup (uri->scheme);
  if (*protocol_ret == NULL) {
    perror ("strdup: protocol");
    return -1;
  }

  if (make_server (uri, socket, server_ret) == -1) {
    free (*protocol_ret);
    return -1;
  }

  *password_ret = NULL;
  *username_ret = NULL;
  if (uri->user && STRNEQ (uri->user, "")) {
    char *p = strchr (uri->user, ':');
    if (p != NULL) {
      if (STRNEQ (p+1, "")) {
        *password_ret = strdup (p+1);
        if (*password_ret == NULL) {
          perror ("strdup: password");
          free (*protocol_ret);
          guestfs_int_free_string_list (*server_ret);
          return -1;
        }
      }
      *p = '\0';
    }
    *username_ret = strdup (uri->user);
    if (*username_ret == NULL) {
      perror ("strdup: username");
      free (*password_ret);
      free (*protocol_ret);
      guestfs_int_free_string_list (*server_ret);
      return -1;
    }
  }

  /* We may have to adjust the path depending on the protocol.  For
   * example ceph/rbd URIs look like rbd:///pool/disk, but the
   * exportname expected will be "pool/disk".  Here, uri->path will be
   * "/pool/disk" so we have to knock off the leading '/' character.
   */
  path = uri->path;
  if (path && path[0] == '/' &&
      (STREQ (uri->scheme, "gluster") ||
       STREQ (uri->scheme, "iscsi") ||
       STREQ (uri->scheme, "rbd") ||
       STREQ (uri->scheme, "sheepdog")))
    path++;

  *path_ret = strdup (path ? path : "");
  if (*path_ret == NULL) {
    perror ("strdup: path");
    free (*protocol_ret);
    guestfs_int_free_string_list (*server_ret);
    free (*username_ret);
    free (*password_ret);
    return -1;
  }

  return 0;
}
コード例 #19
0
ファイル: rc.c プロジェクト: yumingfei/libguestfs
/* Remote control server. */
void
rc_listen (void)
{
  char sockpath[128];
  pid_t pid;
  struct sockaddr_un addr;
  int sock, s;
  size_t i;
  FILE *fp;
  XDR xdr, xdr2;
  guestfish_hello hello;
  guestfish_call call;
  guestfish_reply reply;
  char **argv;
  size_t argc;

  memset (&hello, 0, sizeof hello);
  memset (&call, 0, sizeof call);

  pid = fork ();
  if (pid == -1) {
    perror ("fork");
    exit (EXIT_FAILURE);
  }

  if (pid > 0) {
    /* Parent process. */

    if (!remote_control_csh)
      printf ("GUESTFISH_PID=%d; export GUESTFISH_PID\n", pid);
    else
      printf ("setenv GUESTFISH_PID %d\n", pid);

    fflush (stdout);
    _exit (0);
  }

  /* Child process.
   *
   * Create the listening socket for accepting commands.
   *
   * Unfortunately there is a small but unavoidable race here.  We
   * don't know the PID until after we've forked, so we cannot be
   * sure the socket is created from the point of view of the parent
   * (if the child is very slow).
   */
  pid = getpid ();
  create_sockpath (pid, sockpath, sizeof sockpath, &addr);

  sock = socket (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
  if (sock == -1) {
    perror ("socket");
    exit (EXIT_FAILURE);
  }
  unlink (sockpath);
  if (bind (sock, (struct sockaddr *) &addr, sizeof addr) == -1) {
    perror (sockpath);
    exit (EXIT_FAILURE);
  }
  if (listen (sock, 4) == -1) {
    perror ("listen");
    exit (EXIT_FAILURE);
  }

  /* Read commands and execute them. */
  while (!quit) {
    /* Before waiting, close stdout and substitute /dev/null.  This is
     * necessary so that eval `guestfish --listen` doesn't block
     * forever.
     */
    close_stdout ();

    s = accept4 (sock, NULL, NULL, SOCK_CLOEXEC);
    if (s == -1)
      perror ("accept");
    else {
      receive_stdout(s);

      fp = fdopen (s, "r+");
      xdrstdio_create (&xdr, fp, XDR_DECODE);

      if (!xdr_guestfish_hello (&xdr, &hello)) {
        fprintf (stderr, _("guestfish: protocol error: could not read 'hello' message\n"));
        goto error;
      }

      if (STRNEQ (hello.vers, PACKAGE_VERSION)) {
        fprintf (stderr, _("guestfish: protocol error: version mismatch, server version '%s' does not match client version '%s'.  The two versions must match exactly.\n"),
                 PACKAGE_VERSION,
                 hello.vers);
        xdr_free ((xdrproc_t) xdr_guestfish_hello, (char *) &hello);
        goto error;
      }
      xdr_free ((xdrproc_t) xdr_guestfish_hello, (char *) &hello);

      while (xdr_guestfish_call (&xdr, &call)) {
        /* We have to extend and NULL-terminate the argv array. */
        argc = call.args.args_len;
        argv = realloc (call.args.args_val, (argc+1) * sizeof (char *));
        if (argv == NULL) {
          perror ("realloc");
          exit (EXIT_FAILURE);
        }
        call.args.args_val = argv;
        argv[argc] = NULL;

        if (verbose) {
          fprintf (stderr, "guestfish(%d): %s", pid, call.cmd);
          for (i = 0; i < argc; ++i)
            fprintf (stderr, " %s", argv[i]);
          fprintf (stderr, "\n");
        }

        /* Run the command. */
        reply.r = issue_command (call.cmd, argv, NULL, 0);

        xdr_free ((xdrproc_t) xdr_guestfish_call, (char *) &call);

        /* RHBZ#802389: If the command is quit, close the handle right
         * away.  Note that the main while loop will exit preventing
         * 'g' from being reused.
         */
        if (quit) {
          guestfs_close (g);
          g = NULL;
        }

        /* Send the reply. */
        xdrstdio_create (&xdr2, fp, XDR_ENCODE);
        (void) xdr_guestfish_reply (&xdr2, &reply);
        xdr_destroy (&xdr2);

        /* Exit on error? */
        if (call.exit_on_error && reply.r == -1) {
          unlink (sockpath);
          exit (EXIT_FAILURE);
        }
      }

    error:
      xdr_destroy (&xdr);	/* NB. This doesn't close 'fp'. */
      fclose (fp);		/* Closes the underlying socket 's'. */
    }
  }

  unlink (sockpath);
  close (sock);

  /* This returns to 'fish.c', where it jumps to global cleanups and exits. */
}
コード例 #20
0
int
main (int argc, char *argv[])
{
  guestfs_h *g;
  struct guestfs_internal_mountable *mountable;
  const char *devices[] = { "/dev/VG/LV", NULL };
  const char *feature[] = { "btrfs", NULL };

  g = guestfs_create ();
  if (g == NULL) {
    perror ("could not create handle");
    exit (EXIT_FAILURE);
  }

  if (guestfs_add_drive_scratch (g, 1024*1024*1024, -1) == -1) {
  error:
    guestfs_close (g);
    exit (EXIT_FAILURE);
  }

  if (guestfs_launch (g) == -1) goto error;

  if (!guestfs_feature_available (g, (char **) feature)) {
    printf ("skipping test because btrfs is not available\n");
    guestfs_close (g);
    exit (77);
  }

  if (!guestfs_filesystem_available (g, "btrfs")) {
    printf ("skipping test because btrfs filesystem is not available\n");
    guestfs_close (g);
    exit (77);
  }

  if (guestfs_part_disk (g, "/dev/sda", "mbr") == -1) goto error;

  if (guestfs_pvcreate (g, "/dev/sda1") == -1) goto error;

  const char *pvs[] = { "/dev/sda1", NULL };
  if (guestfs_vgcreate (g, "VG", (char **) pvs) == -1) goto error;

  if (guestfs_lvcreate (g, "LV", "VG", 900) == -1) goto error;

  if (guestfs_mkfs_btrfs (g, (char * const *)devices, -1) == -1) goto error;

  if (guestfs_mount (g, "/dev/VG/LV", "/") == -1) goto error;

  if (guestfs_btrfs_subvolume_create (g, "/sv") == -1) goto error;

  mountable = guestfs_internal_parse_mountable (g, "/dev/VG/LV");
  if (mountable == NULL) goto error;

  if (mountable->im_type != MOUNTABLE_DEVICE ||
      STRNEQ ("/dev/VG/LV", mountable->im_device))
  {
    fprintf (stderr, "incorrectly parsed /dev/VG/LV: im_device=%s\n",
             mountable->im_device);
    goto error;
  }

  guestfs_free_internal_mountable (mountable);

  mountable = guestfs_internal_parse_mountable (g, "btrfsvol:/dev/VG/LV/sv");
  if (mountable == NULL) goto error;

  if (mountable->im_type != MOUNTABLE_BTRFSVOL ||
      STRNEQ ("/dev/VG/LV", mountable->im_device) ||
      STRNEQ ("sv", mountable->im_volume))
  {
    fprintf (stderr, "incorrectly parsed /dev/VG/LV/sv: im_device=%s, im_volume=%s\n",
             mountable->im_device, mountable->im_volume);
    goto error;
  }
  guestfs_free_internal_mountable (mountable);

  guestfs_close (g);

  exit (EXIT_SUCCESS);
}
コード例 #21
0
ファイル: cpu_generic.c プロジェクト: ansisatteka/libvirt-ovs
static virCPUDefPtr
genericBaseline(virCPUDefPtr *cpus,
                unsigned int ncpus,
                const char **models,
                unsigned int nmodels)
{
    virCPUDefPtr cpu = NULL;
    virCPUFeatureDefPtr features = NULL;
    unsigned int nfeatures;
    unsigned int count;
    unsigned int i, j;

    if (models) {
        bool found = false;
        for (i = 0; i < nmodels; i++) {
            if (STREQ(cpus[0]->model, models[i])) {
                found = true;
                break;
            }
        }
        if (!found) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    _("CPU model '%s' is not support by hypervisor"),
                    cpus[0]->model);
            goto error;
        }
    }

    if (VIR_ALLOC(cpu) < 0 ||
        !(cpu->arch = strdup(cpus[0]->arch)) ||
        !(cpu->model = strdup(cpus[0]->model)) ||
        VIR_ALLOC_N(features, cpus[0]->nfeatures) < 0)
        goto no_memory;

    cpu->type = VIR_CPU_TYPE_HOST;

    count = nfeatures = cpus[0]->nfeatures;
    for (i = 0; i < nfeatures; i++)
        features[i].name = cpus[0]->features[i].name;

    for (i = 1; i < ncpus; i++) {
        virHashTablePtr hash;

        if (STRNEQ(cpu->arch, cpus[i]->arch)) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    _("CPUs have incompatible architectures: '%s' != '%s'"),
                    cpu->arch, cpus[i]->arch);
            goto error;
        }

        if (STRNEQ(cpu->model, cpus[i]->model)) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    _("CPU models don't match: '%s' != '%s'"),
                    cpu->model, cpus[i]->model);
            goto error;
        }

        if (!(hash = genericHashFeatures(cpus[i])))
            goto no_memory;

        for (j = 0; j < nfeatures; j++) {
            if (features[j].name &&
                !virHashLookup(hash, features[j].name)) {
                features[j].name = NULL;
                count--;
            }
        }

        virHashFree(hash);
    }

    if (VIR_ALLOC_N(cpu->features, count) < 0)
        goto no_memory;
    cpu->nfeatures = count;

    j = 0;
    for (i = 0; i < nfeatures; i++) {
        if (!features[i].name)
            continue;

        if (!(cpu->features[j++].name = strdup(features[i].name)))
            goto no_memory;
    }

cleanup:
    VIR_FREE(features);

    return cpu;

no_memory:
    virReportOOMError();
error:
    virCPUDefFree(cpu);
    cpu = NULL;
    goto cleanup;
}
コード例 #22
0
ファイル: ext2.c プロジェクト: will-Do/libguestfs
/* 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;
}
コード例 #23
0
bool
virCPUDefIsEqual(virCPUDefPtr src,
                 virCPUDefPtr dst)
{
    bool identical = false;
    int i;

    if (!src && !dst)
        return true;

    if ((src && !dst) || (!src && dst)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Target CPU does not match source"));
        goto cleanup;
    }

    if (src->type != dst->type) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Target CPU type %s does not match source %s"),
                       virCPUTypeToString(dst->type),
                       virCPUTypeToString(src->type));
        goto cleanup;
    }

    if (src->mode != dst->mode) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Target CPU mode %s does not match source %s"),
                       virCPUModeTypeToString(dst->mode),
                       virCPUModeTypeToString(src->mode));
        goto cleanup;
    }

    if (STRNEQ_NULLABLE(src->arch, dst->arch)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Target CPU arch %s does not match source %s"),
                       NULLSTR(dst->arch), NULLSTR(src->arch));
        goto cleanup;
    }

    if (STRNEQ_NULLABLE(src->model, dst->model)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Target CPU model %s does not match source %s"),
                       NULLSTR(dst->model), NULLSTR(src->model));
        goto cleanup;
    }

    if (STRNEQ_NULLABLE(src->vendor, dst->vendor)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Target CPU vendor %s does not match source %s"),
                       NULLSTR(dst->vendor), NULLSTR(src->vendor));
        goto cleanup;
    }

    if (STRNEQ_NULLABLE(src->vendor_id, dst->vendor_id)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Target CPU model %s does not match source %s"),
                       NULLSTR(dst->vendor_id), NULLSTR(src->vendor_id));
        goto cleanup;
    }

    if (src->sockets != dst->sockets) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Target CPU sockets %d does not match source %d"),
                       dst->sockets, src->sockets);
        goto cleanup;
    }

    if (src->cores != dst->cores) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Target CPU cores %d does not match source %d"),
                       dst->cores, src->cores);
        goto cleanup;
    }

    if (src->threads != dst->threads) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Target CPU threads %d does not match source %d"),
                       dst->threads, src->threads);
        goto cleanup;
    }

    if (src->nfeatures != dst->nfeatures) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("Target CPU feature count %zu does not match source %zu"),
                       dst->nfeatures, src->nfeatures);
        goto cleanup;
    }

    for (i = 0 ; i < src->nfeatures ; i++) {
        if (STRNEQ(src->features[i].name, dst->features[i].name)) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Target CPU feature %s does not match source %s"),
                           dst->features[i].name, src->features[i].name);
            goto cleanup;
        }

        if (src->features[i].policy != dst->features[i].policy) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Target CPU feature policy %s does not match source %s"),
                           virCPUFeaturePolicyTypeToString(dst->features[i].policy),
                           virCPUFeaturePolicyTypeToString(src->features[i].policy));
            goto cleanup;
        }
    }

    identical = true;

cleanup:
    return identical;
}
コード例 #24
0
ファイル: openvz_conf.c プロジェクト: noxdafox/libvirt
int openvzLoadDomains(struct openvz_driver *driver)
{
    int veid, ret;
    char *status;
    char uuidstr[VIR_UUID_STRING_BUFLEN];
    virDomainObjPtr dom = NULL;
    virDomainDefPtr def = NULL;
    char *temp = NULL;
    char *outbuf = NULL;
    char *line;
    virCommandPtr cmd = NULL;
    unsigned int vcpus = 0;

    if (openvzAssignUUIDs() < 0)
        return -1;

    cmd = virCommandNewArgList(VZLIST, "-a", "-ovpsid,status", "-H", NULL);
    virCommandSetOutputBuffer(cmd, &outbuf);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    line = outbuf;
    while (line[0] != '\0') {
        unsigned int flags = 0;
        if (virStrToLong_i(line, &status, 10, &veid) < 0 ||
            *status++ != ' ' ||
            (line = strchr(status, '\n')) == NULL) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Failed to parse vzlist output"));
            goto cleanup;
        }
        *line++ = '\0';

        if (!(def = virDomainDefNew()))
            goto cleanup;

        def->virtType = VIR_DOMAIN_VIRT_OPENVZ;

        if (STREQ(status, "stopped"))
            def->id = -1;
        else
            def->id = veid;
        if (virAsprintf(&def->name, "%i", veid) < 0)
            goto cleanup;

        openvzGetVPSUUID(veid, uuidstr, sizeof(uuidstr));
        ret = virUUIDParse(uuidstr, def->uuid);

        if (ret == -1) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("UUID in config file malformed"));
            goto cleanup;
        }

        def->os.type = VIR_DOMAIN_OSTYPE_EXE;
        if (VIR_STRDUP(def->os.init, "/sbin/init") < 0)
            goto cleanup;

        ret = openvzReadVPSConfigParam(veid, "CPUS", &temp);
        if (ret < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not read config for container %d"),
                           veid);
            goto cleanup;
        } else if (ret > 0) {
            vcpus = strtoI(temp);
        }

        if (ret == 0 || vcpus == 0)
            vcpus = openvzGetNodeCPUs();

        def->maxvcpus = vcpus;
        def->vcpus = vcpus;

        /* XXX load rest of VM config data .... */

        openvzReadNetworkConf(def, veid);
        openvzReadFSConf(def, veid);
        openvzReadMemConf(def, veid);

        virUUIDFormat(def->uuid, uuidstr);
        flags = VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE;
        if (STRNEQ(status, "stopped"))
            flags |= VIR_DOMAIN_OBJ_LIST_ADD_LIVE;

        if (!(dom = virDomainObjListAdd(driver->domains,
                                        def,
                                        driver->xmlopt,
                                        flags,
                                        NULL)))
            goto cleanup;

        if (STREQ(status, "stopped")) {
            virDomainObjSetState(dom, VIR_DOMAIN_SHUTOFF,
                                 VIR_DOMAIN_SHUTOFF_UNKNOWN);
            dom->pid = -1;
        } else {
            virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
                                 VIR_DOMAIN_RUNNING_UNKNOWN);
            dom->pid = veid;
        }
        /* XXX OpenVZ doesn't appear to have concept of a transient domain */
        dom->persistent = 1;

        virObjectUnlock(dom);
        dom = NULL;
        def = NULL;
    }

    virCommandFree(cmd);
    VIR_FREE(temp);
    VIR_FREE(outbuf);

    return 0;

 cleanup:
    virCommandFree(cmd);
    VIR_FREE(temp);
    VIR_FREE(outbuf);
    virObjectUnref(dom);
    virDomainDefFree(def);
    return -1;
}
コード例 #25
0
ファイル: virstoragetest.c プロジェクト: i-ninth/libvirt
static int
testStorageChain(const void *args)
{
    const struct testChainData *data = args;
    int ret = -1;
    virStorageFileMetadataPtr meta;
    virStorageFileMetadataPtr elt;
    size_t i = 0;

    meta = virStorageFileGetMetadata(data->start, data->format, -1, -1,
                                     (data->flags & ALLOW_PROBE) != 0);
    if (!meta) {
        if (data->flags & EXP_FAIL) {
            virResetLastError();
            ret = 0;
        }
        goto cleanup;
    } else if (data->flags & EXP_FAIL) {
        fprintf(stderr, "call should have failed\n");
        goto cleanup;
    }
    if (data->flags & EXP_WARN) {
        if (!virGetLastError()) {
            fprintf(stderr, "call should have warned\n");
            goto cleanup;
        }
        virResetLastError();
    } else if (virGetLastError()) {
        fprintf(stderr, "call should not have warned\n");
        goto cleanup;
    }

    elt = meta;
    while (elt) {
        char *expect = NULL;
        char *actual = NULL;

        if (i == data->nfiles) {
            fprintf(stderr, "probed chain was too long\n");
            goto cleanup;
        }

        if (virAsprintf(&expect,
                        "store:%s\nraw:%s\ndirectory:%s\nother:%d %d %lld %d",
                        NULLSTR(data->files[i]->expBackingStore),
                        NULLSTR(data->files[i]->expBackingStoreRaw),
                        NULLSTR(data->files[i]->expDirectory),
                        data->files[i]->expFormat,
                        data->files[i]->expIsFile,
                        data->files[i]->expCapacity,
                        data->files[i]->expEncrypted) < 0 ||
            virAsprintf(&actual,
                        "store:%s\nraw:%s\ndirectory:%s\nother:%d %d %lld %d",
                        NULLSTR(elt->backingStore),
                        NULLSTR(elt->backingStoreRaw),
                        NULLSTR(elt->directory),
                        elt->backingStoreFormat, elt->backingStoreIsFile,
                        elt->capacity, !!elt->encryption) < 0) {
            VIR_FREE(expect);
            VIR_FREE(actual);
            goto cleanup;
        }
        if (STRNEQ(expect, actual)) {
            virtTestDifference(stderr, expect, actual);
            VIR_FREE(expect);
            VIR_FREE(actual);
            goto cleanup;
        }
        VIR_FREE(expect);
        VIR_FREE(actual);
        elt = elt->backingMeta;
        i++;
    }
    if (i != data->nfiles) {
        fprintf(stderr, "probed chain was too short\n");
        goto cleanup;
    }

    ret = 0;
 cleanup:
    virStorageFileFreeMetadata(meta);
    return ret;
}
コード例 #26
0
ファイル: storage_backend_disk.c プロジェクト: emaste/libvirt
static int
virStorageBackendDiskMakeDataVol(virStoragePoolObjPtr pool,
                                 char **const groups,
                                 virStorageVolDefPtr vol)
{
    char *tmp, *devpath;

    if (vol == NULL) {
        if (VIR_ALLOC(vol) < 0) {
            virReportOOMError();
            return -1;
        }

        if (VIR_REALLOC_N(pool->volumes.objs,
                          pool->volumes.count+1) < 0) {
            virReportOOMError();
            virStorageVolDefFree(vol);
            return -1;
        }
        pool->volumes.objs[pool->volumes.count++] = vol;

        /* Prepended path will be same for all partitions, so we can
         * strip the path to form a reasonable pool-unique name
         */
        tmp = strrchr(groups[0], '/');
        if ((vol->name = strdup(tmp ? tmp + 1 : groups[0])) == NULL) {
            virReportOOMError();
            return -1;
        }
    }

    if (vol->target.path == NULL) {
        if ((devpath = strdup(groups[0])) == NULL) {
            virReportOOMError();
            return -1;
        }

        /* Now figure out the stable path
         *
         * XXX this method is O(N) because it scans the pool target
         * dir every time its run. Should figure out a more efficient
         * way of doing this...
         */
        vol->target.path = virStorageBackendStablePath(pool, devpath, true);
        VIR_FREE(devpath);
        if (vol->target.path == NULL)
            return -1;
    }

    if (vol->key == NULL) {
        /* XXX base off a unique key of the underlying disk */
        if ((vol->key = strdup(vol->target.path)) == NULL) {
            virReportOOMError();
            return -1;
        }
    }

    if (vol->source.extents == NULL) {
        if (VIR_ALLOC(vol->source.extents) < 0) {
            virReportOOMError();
            return -1;
        }
        vol->source.nextent = 1;

        if (virStrToLong_ull(groups[3], NULL, 10,
                             &vol->source.extents[0].start) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("cannot parse device start location"));
            return -1;
        }

        if (virStrToLong_ull(groups[4], NULL, 10,
                             &vol->source.extents[0].end) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("cannot parse device end location"));
            return -1;
        }

        if ((vol->source.extents[0].path =
             strdup(pool->def->source.devices[0].path)) == NULL) {
            virReportOOMError();
            return -1;
        }
    }

    /* Refresh allocation/capacity/perms */
    if (virStorageBackendUpdateVolInfo(vol, 1) < 0)
        return -1;

    /* set partition type */
    if (STREQ(groups[1], "normal"))
       vol->target.type = VIR_STORAGE_VOL_DISK_TYPE_PRIMARY;
    else if (STREQ(groups[1], "logical"))
       vol->target.type = VIR_STORAGE_VOL_DISK_TYPE_LOGICAL;
    else if (STREQ(groups[1], "extended"))
       vol->target.type = VIR_STORAGE_VOL_DISK_TYPE_EXTENDED;
    else
       vol->target.type = VIR_STORAGE_VOL_DISK_TYPE_NONE;

    vol->type = VIR_STORAGE_VOL_BLOCK;

    /* The above gets allocation wrong for
     * extended partitions, so overwrite it */
    vol->allocation = vol->capacity =
        (vol->source.extents[0].end - vol->source.extents[0].start);

    if (STRNEQ(groups[2], "metadata"))
        pool->def->allocation += vol->allocation;
    if (vol->source.extents[0].end > pool->def->capacity)
        pool->def->capacity = vol->source.extents[0].end;

    return 0;
}
コード例 #27
0
ファイル: qemuxml2xmltest.c プロジェクト: candhare/libvirt
static int
testCompareStatusXMLToXMLFiles(const void *opaque)
{
    const struct testInfo *data = opaque;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    xmlDocPtr xml = NULL;
    virDomainObjPtr obj = NULL;
    char *expect = NULL;
    char *actual = NULL;
    char *source = NULL;
    int ret = -1;
    int keepBlanksDefault = xmlKeepBlanksDefault(0);

    /* construct faked source status XML */
    virBufferAdd(&buf, testStatusXMLPrefix, -1);
    virBufferAdjustIndent(&buf, 2);
    virBufferAddStr(&buf, data->inFile);
    virBufferAdjustIndent(&buf, -2);
    virBufferAdd(&buf, testStatusXMLSuffix, -1);

    if (!(source = virBufferContentAndReset(&buf))) {
        fprintf(stderr, "Failed to create the source XML");
        goto cleanup;
    }

    /* construct the expect string */
    virBufferAdd(&buf, testStatusXMLPrefix, -1);
    virBufferAdjustIndent(&buf, 2);
    virBufferAddStr(&buf, data->outActiveFile);
    virBufferAdjustIndent(&buf, -2);
    virBufferAdd(&buf, testStatusXMLSuffix, -1);

    if (!(expect = virBufferContentAndReset(&buf))) {
        fprintf(stderr, "Failed to create the expect XML");
        goto cleanup;
    }

    /* parse the fake source status XML */
    if (!(xml = virXMLParseString(source, "(domain_status_test_XML)")) ||
        !(obj = virDomainObjParseNode(xml, xmlDocGetRootElement(xml),
                                      driver.caps, driver.xmlopt,
                                      VIR_DOMAIN_DEF_PARSE_STATUS |
                                      VIR_DOMAIN_DEF_PARSE_ACTUAL_NET |
                                      VIR_DOMAIN_DEF_PARSE_PCI_ORIG_STATES |
                                      VIR_DOMAIN_DEF_PARSE_CLOCK_ADJUST))) {
        fprintf(stderr, "Failed to parse domain status XML:\n%s", source);
        goto cleanup;
    }

    /* format it back */
    if (!(actual = virDomainObjFormat(driver.xmlopt, obj,
                                      VIR_DOMAIN_DEF_FORMAT_SECURE))) {
        fprintf(stderr, "Failed to format domain status XML");
        goto cleanup;
    }

    if (STRNEQ(actual, expect)) {
        virtTestDifferenceFull(stderr,
                               expect, data->outActiveName,
                               actual, data->inName);
        goto cleanup;
    }

    ret = 0;

 cleanup:
    xmlKeepBlanksDefault(keepBlanksDefault);
    xmlFreeDoc(xml);
    virObjectUnref(obj);
    VIR_FREE(expect);
    VIR_FREE(actual);
    VIR_FREE(source);
    return ret;
}
コード例 #28
0
ファイル: qemuargv2xmltest.c プロジェクト: qhjindev/libvirt
static int testCompareXMLToArgvFiles(const char *xml,
                                     const char *cmdfile,
                                     virQemuXML2ArgvTestFlags flags)
{
    char *expectxml = NULL;
    char *actualxml = NULL;
    char *cmd = NULL;
    char *log = NULL;
    int ret = -1;
    virDomainDefPtr vmdef = NULL;

    if (virtTestLoadFile(cmdfile, &cmd) < 0)
        goto fail;
    if (virtTestLoadFile(xml, &expectxml) < 0)
        goto fail;

    if (!(vmdef = qemuParseCommandLineString(driver.caps, driver.xmlopt,
                                             cmd, NULL, NULL, NULL)))
        goto fail;

    if (!virtTestOOMActive()) {
        if ((log = virtTestLogContentAndReset()) == NULL)
            goto fail;
        if (flags & FLAG_EXPECT_WARNING) {
            if (*log) {
                VIR_TEST_DEBUG("Got expected warning from "
                            "qemuParseCommandLineString:\n%s",
                            log);
            } else {
                VIR_TEST_DEBUG("qemuParseCommandLineString "
                        "should have logged a warning\n");
                goto fail;
            }
        } else { /* didn't expect a warning */
            if (*log) {
                VIR_TEST_DEBUG("Got unexpected warning from "
                            "qemuParseCommandLineString:\n%s",
                            log);
                goto fail;
            }
        }
    }

    if (!virDomainDefCheckABIStability(vmdef, vmdef)) {
        VIR_TEST_DEBUG("ABI stability check failed on %s", xml);
        goto fail;
    }

    if (!(actualxml = virDomainDefFormat(vmdef, driver.caps, 0)))
        goto fail;

    if (blankProblemElements(expectxml) < 0 ||
        blankProblemElements(actualxml) < 0)
        goto fail;

    if (STRNEQ(expectxml, actualxml)) {
        virtTestDifference(stderr, expectxml, actualxml);
        goto fail;
    }

    ret = 0;

 fail:
    VIR_FREE(expectxml);
    VIR_FREE(actualxml);
    VIR_FREE(cmd);
    VIR_FREE(log);
    virDomainDefFree(vmdef);
    return ret;
}
コード例 #29
0
ファイル: gdb_interface.c プロジェクト: huodianzhong/crash
/*
 *  The gdb target_xfer_memory() has a hook installed to re-route
 *  all memory accesses back here; reads of 1 or 4 bytes come primarily
 *  from text disassembly requests, and are diverted to the text cache.
 */
int 
gdb_readmem_callback(ulong addr, void *buf, int len, int write)
{ 
	char locbuf[SIZEOF_32BIT], *p1;
	uint32_t *p2;
	int memtype;

	if (write)
		return FALSE;

	if (pc->cur_req->flags & GNU_NO_READMEM)
		return TRUE;

	if (pc->curcmd_flags & MEMTYPE_UVADDR)
		memtype = UVADDR;
	else if (pc->curcmd_flags & MEMTYPE_FILEADDR)
		memtype = FILEADDR;
	else if (!IS_KVADDR(addr)) {
		if (STREQ(pc->curcmd, "gdb") && 
		    STRNEQ(pc->cur_req->buf, "x/")) {
			memtype = UVADDR;
		} else {
			if (CRASHDEBUG(1))
			        console("gdb_readmem_callback: %lx %d FAILED\n",
					addr, len);
			return FALSE;
		}
	} else
		memtype = KVADDR;

	if (CRASHDEBUG(1))
		console("gdb_readmem_callback[%d]: %lx %d\n", 
			memtype, addr, len);

	if (memtype == FILEADDR)
		return(readmem(pc->curcmd_private, memtype, buf, len,
                	"gdb_readmem_callback", RETURN_ON_ERROR));
	
	switch (len)
	{
	case SIZEOF_8BIT:
		p1 = (char *)buf;
		if ((memtype == KVADDR) && 
		    text_value_cache_byte(addr, (unsigned char *)p1)) 
			return TRUE;

		if (!readmem(addr, memtype, locbuf, SIZEOF_32BIT,
		    "gdb_readmem_callback", RETURN_ON_ERROR)) 
			return FALSE;

		*p1 = locbuf[0];
		if (memtype == KVADDR) {
			p2 = (uint32_t *)locbuf;
			text_value_cache(addr, *p2, 0);
		}
		return TRUE;

	case SIZEOF_32BIT:
		if ((memtype == KVADDR) && text_value_cache(addr, 0, buf)) 
			return TRUE;

		if (!readmem(addr, memtype, buf, SIZEOF_32BIT, 
		    "gdb_readmem callback", RETURN_ON_ERROR))
			return FALSE;

		if (memtype == KVADDR)
			text_value_cache(addr, 
				(uint32_t)*((uint32_t *)buf), NULL);
		return TRUE;
	}

	return(readmem(addr, memtype, buf, len,
                "gdb_readmem_callback", RETURN_ON_ERROR));

}
コード例 #30
0
ファイル: fdd.c プロジェクト: mdmoo1978/dxp
/** @brief Find the requested firmware in the specified FDD file.
 *
 */
FDD_STATIC boolean_t xiaFddFindFirmware(const char *filename, const char *ftype,
                                        double ptmin, double ptmax,
                                        unsigned int nother, char **others,
                                        const char *mode, FILE **fp,
                                        boolean_t *exact,
                                        char rawFilename[MAXFILENAME_LEN])
/* Returns TRUE_ if the file was found FALSE_ otherwise                */
/* const char *filename;     Input: name of the file that is the fdd        */
/* const char *ftype;      Input: firmware type to retrieve           */
/* double ptmin;        Input: min peaking time for this firmware       */
/* double ptmax;        Input: max peaking time for this firmware       */
/* unsigned short nother;     Input: number of elements in the array of other specifiers */
/* const char **others;      Input: array of stings contianing firmware options    */
/* const char *mode;       Input: what mode to open the FDD file        */
/* FILE **fp;         Output: pointer to the file, if found        */
/* boolean_t *exact;       Output: was this an exact match to the types?     */
{

    char newFile[MAXFILENAME_LEN];

    char *cstatus = NULL;

    boolean_t found = FALSE_;

    int status;

    unsigned int i;
    unsigned int j;
    unsigned int nmatch;

    /* local variable used to decrement the number of type matches */
    unsigned short nkey;

    /* Min and max ptime read from fdd */
    double fddmin;
    double fddmax;


    ASSERT(filename != NULL);



    *fp = dxp_find_file(filename, mode, newFile);

    if (!*fp) {
        sprintf(info_string,"Error finding the FDD file: %s", filename);
        xiaFddLogError("xiaFddFindFirmware", info_string, XIA_OPEN_FILE);
        return FALSE_;
    }

    rewind(*fp);

    /* Skip past anything that doesn't equal the first section line. */
    do {
        cstatus = fdd_md_fgets(line, XIA_LINE_LEN, *fp);
    } while (!STRNEQ(line, section));

    /* Skip over the original filename entry */
    cstatus = fdd_md_fgets(rawFilename, XIA_LINE_LEN, *fp);

    fdd__StringChomp(rawFilename);

    sprintf(info_string, "rawFilename = %s", rawFilename);
    xiaFddLogDebug("xiaFddFindFirmware", info_string);

    /* Located the FDD file, now start the search */
    cstatus = fdd_md_fgets(line, XIA_LINE_LEN, *fp);

    while ((!found)&&(cstatus!=NULL)) {
        /* Second line contains the firmware type, strip off delimiters */
        token = strtok(line, delim);

        if (STREQ(token, ftype)) {
            sprintf(info_string, "Matched token: '%s'", token);
            xiaFddLogDebug("xiaFddFindFirmware", info_string);

            /* Read in the number of keywords */
            cstatus = fdd_md_fgets(line, XIA_LINE_LEN, *fp);
            nkey = (unsigned short) strtol(line, NULL, 10);

            /* Reset the number of matches */
            nmatch = nother;
            for (i=0; i < nkey; i++) {
                /* Read in the keywords and check for matches */
                cstatus = fdd_md_fgets(line, XIA_LINE_LEN, *fp);
                /* Strip off spaces and endline characters */
                token = strtok(line, delim);
                for (j = 0; j < nother; j++) {
                    if STREQ(token,others[j]) {
                        nmatch--;
                        break;
                    }
                }
                if (nmatch==0) {
                    found = TRUE_;
                    if (nkey == nother) *exact = TRUE_;
                    break;
                }
            }
            /* case of no other keywords */
            if (nkey == 0) {
                found = TRUE_;
                *exact = TRUE_;
            }
        } else {