コード例 #1
0
ファイル: tar.c プロジェクト: AlphaStaxLLC/libguestfs
/* Detect if chown(2) is supported on the target directory. */
static int
is_chown_supported (const char *dir)
{
  CLEANUP_FREE char *buf = NULL;
  int fd, r, err, saved_errno;

  /* Create a randomly named file. */
  if (asprintf (&buf, "%s%s/XXXXXXXX.XXX", sysroot, dir) == -1) {
    err = errno;
    r = cancel_receive ();
    errno = err;
    reply_with_perror ("asprintf");
    return -1;
  }
  if (random_name (buf) == -1) {
    err = errno;
    r = cancel_receive ();
    errno = err;
    reply_with_perror ("random_name");
    return -1;
  }

  /* Maybe 'dir' is not a directory or filesystem not writable? */
  fd = open (buf, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0666);
  if (fd == -1) {
    err = errno;
    r = cancel_receive ();
    errno = err;
    reply_with_perror ("%s", dir);
    return -1;
  }

  /* This is the test. */
  r = fchown (fd, 1000, 1000);
  saved_errno = errno;

  /* Make sure the test file is removed. */
  close (fd);
  unlink (buf);

  if (r == -1 && saved_errno == EPERM) {
    /* This means chown is not supported by the filesystem. */
    return 0;
  }

  if (r == -1) {
    /* Some other error? */
    err = errno;
    r = cancel_receive ();
    errno = err;
    reply_with_perror_errno (saved_errno, "unexpected error in fchown");
    return -1;
  }

  /* Else chown is supported. */
  return 1;
}
コード例 #2
0
ファイル: file.c プロジェクト: yumingfei/libguestfs
static char *
pread_fd (int fd, int count, int64_t offset, size_t *size_r,
          const char *display_path)
{
    ssize_t r;
    char *buf;

    if (count < 0) {
        reply_with_error ("count is negative");
        close (fd);
        return NULL;
    }

    if (offset < 0) {
        reply_with_error ("offset is negative");
        close (fd);
        return NULL;
    }

    /* The actual limit on messages is smaller than this.  This check
     * just limits the amount of memory we'll try and allocate in the
     * function.  If the message is larger than the real limit, that
     * will be caught later when we try to serialize the message.
     */
    if (count >= GUESTFS_MESSAGE_MAX) {
        reply_with_error ("%s: count is too large for the protocol, use smaller reads", display_path);
        close (fd);
        return NULL;
    }

    buf = malloc (count);
    if (buf == NULL) {
        reply_with_perror ("malloc");
        close (fd);
        return NULL;
    }

    r = pread (fd, buf, count, offset);
    if (r == -1) {
        reply_with_perror ("pread: %s", display_path);
        close (fd);
        free (buf);
        return NULL;
    }

    if (close (fd) == -1) {
        reply_with_perror ("close: %s", display_path);
        free (buf);
        return NULL;
    }

    /* Mustn't touch *size_r until we are sure that we won't return any
     * error (RHBZ#589039).
     */
    *size_r = r;
    return buf;
}
コード例 #3
0
ファイル: base64.c プロジェクト: FengYang/libguestfs
/* Has one FileIn parameter. */
int
do_base64_in (const char *file)
{
  int err, r;
  FILE *fp;
  CLEANUP_FREE char *cmd = NULL;
  int fd;

  if (asprintf_nowarn (&cmd, "%s -d -i > %R", str_base64, file) == -1) {
    err = errno;
    cancel_receive ();
    errno = err;
    reply_with_perror ("asprintf");
    return -1;
  }

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

  fp = popen (cmd, "w");
  if (fp == NULL) {
    err = errno;
    cancel_receive ();
    errno = err;
    reply_with_perror ("%s", cmd);
    return -1;
  }

  /* The semantics of fwrite are too undefined, so write to the
   * file descriptor directly instead.
   */
  fd = fileno (fp);

  r = receive_file (write_cb, &fd);
  if (r == -1) {		/* write error */
    cancel_receive ();
    reply_with_error ("write error on file: %s", file);
    pclose (fp);
    return -1;
  }
  if (r == -2) {		/* cancellation from library */
    /* This error is ignored by the library since it initiated the
     * cancel.  Nevertheless we must send an error reply here.
     */
    reply_with_error ("file upload cancelled");
    pclose (fp);
    return -1;
  }

  if (pclose (fp) != 0) {
    reply_with_error ("base64 subcommand failed on file: %s", file);
    return -1;
  }

  return 0;
}
コード例 #4
0
ファイル: file.c プロジェクト: yumingfei/libguestfs
int
do_touch (const char *path)
{
    int fd;
    int r;
    struct stat buf;

    /* RHBZ#582484: Restrict touch to regular files.  It's also OK
     * here if the file does not exist, since we will create it.
     *
     * XXX Coverity flags this as a time-of-check to time-of-use race
     * condition, particularly in the libguestfs live case.  Not clear
     * how to fix this yet, since unconditionally opening the file can
     * cause a hang, so you have to somehow check it first before you
     * open it.
     */
    CHROOT_IN;
    r = lstat (path, &buf);
    CHROOT_OUT;

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

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

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

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

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

    return 0;
}
コード例 #5
0
ファイル: inotify.c プロジェクト: will-Do/libguestfs
int
do_inotify_init (int max_events)
{
  FILE *fp;

  NEED_ROOT (, return -1);

  if (max_events < 0) {
    reply_with_error ("max_events < 0");
    return -1;
  }

  if (max_events > 0) {
    fp = fopen (MQE_PATH, "w");
    if (fp == NULL) {
      reply_with_perror (MQE_PATH);
      return -1;
    }
    fprintf (fp, "%d\n", max_events);
    fclose (fp);
  }

  if (inotify_fd >= 0)
    if (do_inotify_close () == -1)
      return -1;

#ifdef HAVE_INOTIFY_INIT1
  inotify_fd = inotify_init1 (IN_NONBLOCK | IN_CLOEXEC);
  if (inotify_fd == -1) {
    reply_with_perror ("inotify_init1");
    return -1;
  }
#else
  inotify_fd = inotify_init ();
  if (inotify_fd == -1) {
    reply_with_perror ("inotify_init");
    return -1;
  }
  if (fcntl (inotify_fd, F_SETFL, O_NONBLOCK) == -1) {
    reply_with_perror ("fcntl: O_NONBLOCK");
    close (inotify_fd);
    inotify_fd = -1;
    return -1;
  }
  if (fcntl (inotify_fd, F_SETFD, FD_CLOEXEC) == -1) {
    reply_with_perror ("fcntl: FD_CLOEXEC");
    close (inotify_fd);
    inotify_fd = -1;
    return -1;
  }
#endif

  return 0;
}
コード例 #6
0
ファイル: stat.c プロジェクト: AlphaStaxLLC/libguestfs
guestfs_int_statns_list *
do_internal_lstatnslist (const char *path, char *const *names)
{
  int path_fd;
  guestfs_int_statns_list *ret;
  size_t i, nr_names;

  nr_names = count_strings (names);

  ret = malloc (sizeof *ret);
  if (!ret) {
    reply_with_perror ("malloc");
    return NULL;
  }
  ret->guestfs_int_statns_list_len = nr_names;
  ret->guestfs_int_statns_list_val =
    calloc (nr_names, sizeof (guestfs_int_statns));
  if (ret->guestfs_int_statns_list_val == NULL) {
    reply_with_perror ("calloc");
    free (ret);
    return NULL;
  }

  CHROOT_IN;
  path_fd = open (path, O_RDONLY|O_DIRECTORY|O_CLOEXEC);
  CHROOT_OUT;

  if (path_fd == -1) {
    reply_with_perror ("%s", path);
    free (ret->guestfs_int_statns_list_val);
    free (ret);
    return NULL;
  }

  for (i = 0; names[i] != NULL; ++i) {
    int r;
    struct stat statbuf;

    r = fstatat (path_fd, names[i], &statbuf, AT_SYMLINK_NOFOLLOW);
    if (r == -1)
      ret->guestfs_int_statns_list_val[i].st_ino = -1;
    else
      stat_to_statns (&ret->guestfs_int_statns_list_val[i], &statbuf);
  }

  if (close (path_fd) == -1) {
    reply_with_perror ("close: %s", path);
    free (ret->guestfs_int_statns_list_val);
    free (ret);
    return NULL;
  }

  return ret;
}
コード例 #7
0
ファイル: file.c プロジェクト: gaowanlong/libguestfs
/* zcat | file */
char *
do_zfile (const char *method, const char *path)
{
  int len;
  const char *zcat;
  char *cmd;
  FILE *fp;
  char line[256];

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

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

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

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

  free (cmd);

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

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

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

  return strdup (line);
}
コード例 #8
0
ファイル: md.c プロジェクト: VladimirTyrin/libguestfs
extern guestfs_int_mdstat_list *
do_md_stat (const char *md)
{
  size_t mdlen;
  FILE *fp;
  CLEANUP_FREE char *line = NULL;
  size_t allocsize = 0;
  ssize_t n;
  guestfs_int_mdstat_list *ret = NULL;

  if (STRPREFIX (md, "/dev/"))
    md += 5;
  mdlen = strlen (md);

  fp = fopen ("/proc/mdstat", "r");
  if (fp == NULL) {
    reply_with_perror ("fopen: %s", "/proc/mdstat");
    return NULL;
  }

  /* Search for a line which begins with "<md> : ". */
  while ((n = getline (&line, &allocsize, fp)) != -1) {
    if (STRPREFIX (line, md) &&
        line[mdlen] == ' ' && line[mdlen+1] == ':' && line[mdlen+2] == ' ') {
      /* Found it. */
      ret = parse_md_stat_line (&line[mdlen+3]);
      if (!ret) {
        fclose (fp);
        return NULL;
      }

      /* Stop parsing the mdstat file after we've found the line
       * we are interested in.
       */
      break;
    }
  }

  if (fclose (fp) == EOF) {
    reply_with_perror ("fclose: %s", "/proc/mdstat");
    xdr_free ((xdrproc_t) xdr_guestfs_int_mdstat_list, (char *) ret);
    return NULL;
  }

  /* Did we find the line? */
  if (!ret) {
    reply_with_error ("%s: MD device not found", md);
    return NULL;
  }

  return ret;
}
コード例 #9
0
ファイル: file.c プロジェクト: gaowanlong/libguestfs
int
do_write_file (const char *path, const char *content, int size)
{
  int fd;

  /* This call is deprecated, and it has a broken interface.  New code
   * should use the 'guestfs_write' call instead.  Because we used an
   * XDR string type, 'content' cannot contain ASCII NUL and 'size'
   * must never be longer than the string.  We must check this to
   * ensure random stuff from XDR or daemon memory isn't written to
   * the file (RHBZ#597135).
   */
  if (size < 0) {
    reply_with_error ("size cannot be negative");
    return -1;
  }

  /* Note content_len must be small because of the limits on protocol
   * message size.
   */
  int content_len = (int) strlen (content);

  if (size == 0)
    size = content_len;
  else if (size > content_len) {
    reply_with_error ("size parameter is larger than string content");
    return -1;
  }

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

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

  if (xwrite (fd, content, size) == -1) {
    reply_with_perror ("write");
    close (fd);
    return -1;
  }

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

  return 0;
}
コード例 #10
0
ファイル: devsparts.c プロジェクト: gaowanlong/libguestfs
static int
add_partitions(const char *device,
               char ***const r, int *const size, int *const alloc)
{
  char devdir[256];

  /* Open the device's directory under /sys/block */
  snprintf (devdir, sizeof devdir, "/sys/block/%s", device);

  DIR *dir = opendir (devdir);
  if (!dir) {
    reply_with_perror ("opendir: %s", devdir);
    free_stringslen (*r, *size);
    return -1;
  }

  /* Look in /sys/block/<device>/ for entries starting with <device>
   * e.g. /sys/block/sda/sda1
   */
  errno = 0;
  struct dirent *d;
  while ((d = readdir (dir)) != NULL) {
    if (STREQLEN (d->d_name, device, strlen (device))) {
      char part[256];
      snprintf (part, sizeof part, "/dev/%s", d->d_name);

      if (add_string (r, size, alloc, part) == -1) {
        closedir (dir);
        return -1;
      }
    }
  }

  /* Check if readdir failed */
  if(0 != errno) {
      reply_with_perror ("readdir: %s", devdir);
      free_stringslen(*r, *size);
      closedir (dir);
      return -1;
  }

  /* Close the directory handle */
  if (closedir (dir) == -1) {
    reply_with_perror ("closedir: /sys/block/%s", device);
    free_stringslen (*r, *size);
    return -1;
  }

  return 0;
}
コード例 #11
0
ファイル: file.c プロジェクト: gaowanlong/libguestfs
int
do_touch (const char *path)
{
  int fd;
  int r;
  struct stat buf;

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

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

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

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

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

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

  return 0;
}
コード例 #12
0
ファイル: fill.c プロジェクト: ArikaChen/libguestfs
int
do_fill (int c, int len, const char *path)
{
  int fd;
  ssize_t r;
  size_t len_sz;
  size_t n;
  char buf[BUFSIZ];

  if (c < 0 || c > 255) {
    reply_with_error ("%d: byte number must be in range 0..255", c);
    return -1;
  }
  memset (buf, c, BUFSIZ);
  if (len < 0) {
    reply_with_error ("%d: length is < 0", len);
    return -1;
  }
  len_sz = (size_t) len;

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

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

  n = 0;
  while (n < len_sz) {
    r = write (fd, buf, len_sz - n < BUFSIZ ? len_sz - n : BUFSIZ);
    if (r == -1) {
      reply_with_perror ("write: %s", path);
      close (fd);
      return -1;
    }
    n += r;
    notify_progress ((uint64_t) n, (uint64_t) len_sz);
  }

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

  return 0;
}
コード例 #13
0
ファイル: debug.c プロジェクト: libguestfs/libguestfs
/* List files in the appliance. */
static char *
debug_ll (const char *subcmd, size_t argc, char *const *const argv)
{
  const size_t len = guestfs_int_count_strings (argv);
  CLEANUP_FREE const char **cargv = NULL;
  size_t i;
  int r;
  char *out;
  CLEANUP_FREE char *err = NULL;

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

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

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

  return out;
}
コード例 #14
0
ファイル: augeas.c プロジェクト: gaowanlong/libguestfs
/* We need to rewrite the root path so it is based at /sysroot. */
int
do_aug_init (const char *root, int flags)
{
#ifdef HAVE_AUGEAS
  char *buf;

  if (aug) {
    aug_close (aug);
    aug = NULL;
  }

  buf = sysroot_path (root);
  if (!buf) {
    reply_with_perror ("malloc");
    return -1;
  }

  aug = aug_init (buf, NULL, flags);
  free (buf);

  if (!aug) {
    reply_with_error ("Augeas initialization failed");
    return -1;
  }

  return 0;
#else
  NOT_AVAILABLE (-1);
#endif
}
コード例 #15
0
ファイル: debug.c プロジェクト: carriercomm/libguestfs
/* Generate lots of debug messages.  Each line of output is 72
 * characters long (plus '\n'), so the total size of the output in
 * bytes is n*73.
 */
static char *
debug_spew (const char *subcmd, size_t argc, char *const *const argv)
{
  size_t i, n;
  char *ret;

  if (argc != 1) {
    reply_with_error ("spew: expecting number of lines <n>");
    return NULL;
  }

  if (sscanf (argv[0], "%zu", &n) != 1) {
    reply_with_error ("spew: could not parse number of lines '%s'", argv[0]);
    return NULL;
  }

  for (i = 0; i < n; ++i)
    fprintf (stderr,
             "abcdefghijklmnopqrstuvwxyz" /* 26 */
             "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* 52 */
             "01234567890123456789" /* 72 */
             "\n");

  ret = strdup ("ok");
  if (!ret) {
    reply_with_perror ("strdup");
    return NULL;
  }

  return ret;
}
コード例 #16
0
ファイル: dir.c プロジェクト: yumingfei/libguestfs
/* This implementation is quick and dirty, and allows people to try
 * to remove parts of the initramfs (eg. "rm -r /..") but if people
 * do stupid stuff, who are we to try to stop them?
 */
int
do_rm_rf (const char *path)
{
  int r;
  char *buf, *err;

  if (STREQ (path, "/")) {
    reply_with_error ("cannot remove root directory");
    return -1;
  }

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

  r = command (NULL, &err, str_rm, "-rf", buf, NULL);
  free (buf);

  /* rm -rf is never supposed to fail.  I/O errors perhaps? */
  if (r == -1) {
    reply_with_error ("%s: %s", path, err);
    free (err);
    return -1;
  }

  free (err);

  return 0;
}
コード例 #17
0
ファイル: lvm.c プロジェクト: limohua/libguestfs
int
do_vgcreate (const char *volgroup, char *const *physvols)
{
  char *err;
  int r, argc, i;
  const char **argv;

  argc = count_strings (physvols) + 3;
  argv = malloc (sizeof (char *) * (argc + 1));
  if (argv == NULL) {
    reply_with_perror ("malloc");
    return -1;
  }
  argv[0] = "lvm";
  argv[1] = "vgcreate";
  argv[2] = volgroup;
  for (i = 3; i <= argc; ++i)
    argv[i] = physvols[i-3];

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

  free (err);
  free (argv);

  udev_settle ();

  return 0;
}
コード例 #18
0
ファイル: parted.c プロジェクト: libguestfs/libguestfs
int
do_part_set_gpt_guid (const char *device, int partnum, const char *guid)
{
  if (partnum <= 0) {
    reply_with_error ("partition number must be >= 1");
    return -1;
  }

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

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

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

  return 0;
}
コード例 #19
0
ファイル: xfs.c プロジェクト: will-Do/libguestfs
guestfs_int_xfsinfo *
do_xfs_info (const char *pathordevice)
{
  int r;
  CLEANUP_FREE char *buf = NULL;
  CLEANUP_FREE char *out = NULL, *err = NULL;
  CLEANUP_FREE_STRING_LIST char **lines = NULL;
  int is_dev;

  is_dev = STREQLEN (pathordevice, "/dev/", 5);
  buf = is_dev ? strdup (pathordevice)
               : sysroot_path (pathordevice);
  if (buf == NULL) {
    reply_with_perror ("malloc");
    return NULL;
  }

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

  lines = split_lines (out);
  if (lines == NULL)
    return NULL;

  return parse_xfs_info (lines);
}
コード例 #20
0
ファイル: parted.c プロジェクト: mdbooth/libguestfs
/* Return the nth field from a string of ':'/';'-delimited strings.
 * Useful for parsing the return value from 'parted -m'.
 */
static char *
get_table_field (const char *line, int n)
{
  const char *p = line;

  while (*p && n > 0) {
    p += strcspn (p, ":;") + 1;
    n--;
  }

  if (n > 0) {
    reply_with_error ("not enough fields in output of parted print command: %s",
                      line);
    return NULL;
  }

  size_t len = strcspn (p, ":;");
  char *q = strndup (p, len);
  if (q == NULL) {
    reply_with_perror ("strndup");
    return NULL;
  }

  return q;
}
コード例 #21
0
ファイル: du.c プロジェクト: DanLipsitt/libguestfs
int64_t
do_du (const char *path)
{
  int r;
  int64_t rv;
  CLEANUP_FREE char *out = NULL, *err = NULL, *buf = NULL;

  /* Make the path relative to /sysroot. */
  buf = sysroot_path (path);
  if (!buf) {
    reply_with_perror ("malloc");
    return -1;
  }

  pulse_mode_start ();

  r = command (&out, &err, str_du, "-s", buf, NULL);
  if (r == -1) {
    pulse_mode_cancel ();
    reply_with_error ("%s: %s", path, err);
    return -1;
  }

  if (sscanf (out, "%"SCNi64, &rv) != 1) {
    pulse_mode_cancel ();
    reply_with_error ("%s: could not read output: %s", path, out);
    return -1;
  }

  pulse_mode_end ();

  return rv;
}
コード例 #22
0
ファイル: debug.c プロジェクト: yumingfei/libguestfs
/* Generate progress notification messages in order to test progress bars. */
static char *
debug_progress (const char *subcmd, size_t argc, char *const *const argv)
{
  if (argc < 1) {
  error:
    reply_with_error ("progress: expecting arg (time in seconds as string)");
    return NULL;
  }

  char *secs_str = argv[0];
  unsigned secs;
  if (sscanf (secs_str, "%u", &secs) != 1)
    goto error;
  if (secs == 0 || secs > 1000000) { /* RHBZ#816839 */
    reply_with_error ("progress: argument is 0, less than 0, or too large");
    return NULL;
  }

  unsigned i;
  unsigned tsecs = secs * 10;   /* 1/10ths of seconds */
  for (i = 1; i <= tsecs; ++i) {
    usleep (100000);
    notify_progress ((uint64_t) i, (uint64_t) tsecs);
  }

  char *ret = strdup ("ok");
  if (ret == NULL) {
    reply_with_perror ("strdup");
    return NULL;
  }

  return ret;
}
コード例 #23
0
ファイル: debug.c プロジェクト: carriercomm/libguestfs
/* Generate progress notification messages in order to test progress bars. */
static char *
debug_progress (const char *subcmd, size_t argc, char *const *const argv)
{
  uint64_t secs, rate = 0;
  char *ret;

  if (argc < 1) {
  error:
    reply_with_error ("progress: expecting one or more args: time in seconds [, rate in microseconds]");
    return NULL;
  }

  if (sscanf (argv[0], "%" SCNu64, &secs) != 1)
    goto error;
  if (secs == 0 || secs > 1000000) { /* RHBZ#816839 */
    reply_with_error ("progress: argument is 0, less than 0, or too large");
    return NULL;
  }

  if (argc >= 2) {
    if (sscanf (argv[1], "%" SCNu64, &rate) != 1)
      goto error;
    if (rate == 0 || rate > 1000000) {
      reply_with_error ("progress: rate is 0 or too large");
      return NULL;
    }
  }

  /* Note the inner loops go to '<= limit' because we want to ensure
   * that the final 100% completed message is set.
   */
  if (rate == 0) {              /* Ordinary rate-limited progress messages. */
    uint64_t tsecs = secs * 10; /* 1/10ths of seconds */
    uint64_t i;

    for (i = 1; i <= tsecs; ++i) {
      usleep (100000);
      notify_progress (i, tsecs);
    }
  }
  else {                        /* Send messages at a given rate. */
    uint64_t usecs = secs * 1000000; /* microseconds */
    uint64_t i;
    struct timeval now;

    for (i = rate; i <= usecs; i += rate) {
      usleep (rate);
      gettimeofday (&now, NULL);
      notify_progress_no_ratelimit (i, usecs, &now);
    }
  }

  ret = strdup ("ok");
  if (ret == NULL) {
    reply_with_perror ("strdup");
    return NULL;
  }

  return ret;
}
コード例 #24
0
ファイル: ext2.c プロジェクト: will-Do/libguestfs
int64_t
do_get_e2generation (const char *filename)
{
    int r;
    CLEANUP_FREE char *buf = NULL, *out = NULL, *err = NULL;
    int64_t ret;

    buf = sysroot_path (filename);
    if (!buf) {
        reply_with_perror ("malloc");
        return -1;
    }

    r = command (&out, &err, str_lsattr, "-dv", "--", buf, NULL);
    if (r == -1) {
        reply_with_error ("%s: %s: %s", "lsattr", filename, err);
        return -1;
    }

    if (sscanf (out, "%" SCNi64, &ret) != 1) {
        reply_with_error ("cannot parse output from '%s' command: %s",
                          "lsattr", out);
        return -1;
    }
    if (ret < 0) {
        reply_with_error ("unexpected negative number from '%s' command: %s",
                          "lsattr", out);
        return -1;
    }

    return ret;
}
コード例 #25
0
ファイル: lvm.c プロジェクト: VladimirTyrin/libguestfs
int
do_vg_activate (int activate, char *const *volgroups)
{
  int r, i, argc;
  CLEANUP_FREE char *err = NULL;
  CLEANUP_FREE const char **argv = NULL;

  argc = count_strings (volgroups) + 4;
  argv = malloc (sizeof (char *) * (argc+1));
  if (argv == NULL) {
    reply_with_perror ("malloc");
    return -1;
  }

  argv[0] = str_lvm;
  argv[1] = "vgchange";
  argv[2] = "-a";
  argv[3] = activate ? "y" : "n";
  for (i = 4; i < argc+1; ++i)
    argv[i] = volgroups[i-4];

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

  udev_settle ();

  return 0;
}
コード例 #26
0
ファイル: scrub.c プロジェクト: AlphaStaxLLC/libguestfs
int
do_scrub_file (const char *file)
{
  CLEANUP_FREE char *buf = NULL;
  CLEANUP_FREE char *err = NULL;
  int r;

  /* Resolve the path to the file, and make the result relative to /sysroot.
   * If it fails, then the file most probably does not exist or "file" is
   * a symlink pointing outside the chroot.
   */
  buf = sysroot_realpath (file);
  if (!buf) {
    reply_with_perror ("malloc");
    return -1;
  }

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

  return 0;
}
コード例 #27
0
ファイル: lvm.c プロジェクト: VladimirTyrin/libguestfs
int
do_vgcreate (const char *volgroup, char *const *physvols)
{
  int r, argc, i;
  CLEANUP_FREE char *err = NULL;
  CLEANUP_FREE const char **argv = NULL;

  argc = count_strings (physvols) + 3;
  argv = malloc (sizeof (char *) * (argc + 1));
  if (argv == NULL) {
    reply_with_perror ("malloc");
    return -1;
  }
  argv[0] = str_lvm;
  argv[1] = "vgcreate";
  argv[2] = volgroup;
  for (i = 3; i < argc+1; ++i)
    argv[i] = physvols[i-3];

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

  udev_settle ();

  return 0;
}
コード例 #28
0
ファイル: xattr.c プロジェクト: msmhrt/libguestfs
char *
do_lgetxattr (const char *path, const char *name, size_t *size_r)
{
  ssize_t r;
  char *buf;
  size_t len;

  CHROOT_IN;
  r = lgetxattr (path, name, NULL, 0);
  CHROOT_OUT;
  if (r == -1) {
    reply_with_perror ("lgetxattr");
    return NULL;
  }

  len = r;

  if (len > XATTR_SIZE_MAX) {
    reply_with_error ("extended attribute is too large");
    return NULL;
  }

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

  CHROOT_IN;
  r = lgetxattr (path, name, buf, len);
  CHROOT_OUT;
  if (r == -1) {
    reply_with_perror ("lgetxattr");
    free (buf);
    return NULL;
  }

  if (len != (size_t) r) {
    reply_with_error ("lgetxattr: unexpected size (%zu/%zd)", len, r);
    free (buf);
    return NULL;
  }

  /* Must set size_r last thing before returning. */
  *size_r = len;
  return buf; /* caller frees */
}
コード例 #29
0
ファイル: fill.c プロジェクト: ArikaChen/libguestfs
int
do_fill_pattern (const char *pattern, int len, const char *path)
{
  size_t patlen = strlen (pattern);

  if (patlen < 1) {
    reply_with_error ("pattern string must be non-empty");
    return -1;
  }

  if (len < 0) {
    reply_with_error ("%d: length is < 0", len);
    return -1;
  }
  size_t len_sz = (size_t) len;

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

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

  /* XXX This implementation won't be very efficient for large files. */
  size_t n = 0;
  while (n < len_sz) {
    size_t wrlen = len_sz - n < patlen ? len_sz - n : patlen;
    if (xwrite (fd, pattern, wrlen) == -1) {
      reply_with_perror ("write: %s", path);
      close (fd);
      return -1;
    }
    n += wrlen;
    notify_progress ((uint64_t) n, (uint64_t) len_sz);
  }

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

  return 0;
}
コード例 #30
0
ファイル: stat.c プロジェクト: gaowanlong/libguestfs
guestfs_int_stat *
do_lstat (const char *path)
{
  int r;
  guestfs_int_stat *ret;
  struct stat statbuf;

  CHROOT_IN;
  r = lstat (path, &statbuf);
  CHROOT_OUT;

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

  ret = malloc (sizeof *ret);
  if (ret == NULL) {
    reply_with_perror ("malloc");
    return NULL;
  }

  ret->dev = statbuf.st_dev;
  ret->ino = statbuf.st_ino;
  ret->mode = statbuf.st_mode;
  ret->nlink = statbuf.st_nlink;
  ret->uid = statbuf.st_uid;
  ret->gid = statbuf.st_gid;
  ret->rdev = statbuf.st_rdev;
  ret->size = statbuf.st_size;
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
  ret->blksize = statbuf.st_blksize;
#else
  ret->blksize = -1;
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
  ret->blocks = statbuf.st_blocks;
#else
  ret->blocks = -1;
#endif
  ret->atime = statbuf.st_atime;
  ret->mtime = statbuf.st_mtime;
  ret->ctime = statbuf.st_ctime;

  return ret;
}