Beispiel #1
0
static int
do_fusermount (guestfs_h *g, const char *localmountpoint, int error_fd)
{
  pid_t pid;
  int status;

  pid = fork ();
  if (pid == -1) {
    perrorf (g, "fork");
    return -1;
  }

  if (pid == 0) {               /* child */
    /* Ensure stdout and stderr point to the error_fd. */
    dup2 (error_fd, STDOUT_FILENO);
    dup2 (error_fd, STDERR_FILENO);
    close (error_fd);
    execlp ("fusermount", "fusermount", "-u", localmountpoint, NULL);
    perror ("exec: fusermount");
    _exit (EXIT_FAILURE);
  }

  /* Parent. */
  if (waitpid (pid, &status, 0) == -1) {
    perrorf (g, "waitpid");
    return -1;
  }

  if (!WIFEXITED (status) || WEXITSTATUS (status) != EXIT_SUCCESS)
    return 0;                   /* it failed to unmount the mountpoint */

  return 1;                     /* unmount was successful */
}
Beispiel #2
0
static int
rlc_insert (guestfs_h *g,
            const char *path, const char *name, time_t now,
            char *link)
{
  struct rlc_entry *entry;
  size_t len;

  entry = malloc (sizeof *entry);
  if (entry == NULL) {
    perrorf (g, "malloc");
    return -1;
  }

  len = strlen (path) + strlen (name) + 2;
  entry->c.pathname = malloc (len);
  if (entry->c.pathname == NULL) {
    perrorf (g, "malloc");
    free (entry);
    return -1;
  }
  if (STREQ (path, "/"))
    snprintf (entry->c.pathname, len, "/%s", name);
  else
    snprintf (entry->c.pathname, len, "%s/%s", path, name);

  entry->link = link;

  entry->c.timeout = now + g->ml_dir_cache_timeout;

  return gen_replace (g, g->rlc_ht, (struct entry_common *) entry, rlc_free);
}
Beispiel #3
0
int filecopy(FILE *in, FILE *out, char *outname, size_t insiz)
{
	char buffer[BSIZ];
	size_t nread, total = 0;
	int ret = 0, lastprogress = 0;

	while((nread = fread(buffer, sizeof buffer[0], BSIZ, in)) > 0){
		if(fwrite(buffer, sizeof buffer[0], nread, out) <= 0){
			perrorf("fwrite()");
			ret = 1;
			goto bail;
		}
		if(++lastprogress > PROGRESS_COUNT){
			progress(outname, total += nread, insiz);
			lastprogress = 0;
		}
	}

	progressdone(outname, insiz);

	if(ferror(in)){
		perrorf("fread()");
		ret = 1;
	}
bail:
	return ret;
}
Beispiel #4
0
char *
guestfs_impl_read_file (guestfs_h *g, const char *path, size_t *size_r)
{
  int fd = -1;
  size_t size;
  CLEANUP_UNLINK_FREE char *tmpfile = NULL;
  char *ret = NULL;
  struct stat statbuf;

  tmpfile = guestfs_int_make_temp_path (g, "cat", NULL);
  if (tmpfile == NULL)
    goto err;

  if (guestfs_download (g, path, tmpfile) == -1)
    goto err;

  fd = open (tmpfile, O_RDONLY|O_CLOEXEC);
  if (fd == -1) {
    perrorf (g, "open: %s", tmpfile);
    goto err;
  }

  /* Read the whole file into memory. */
  if (fstat (fd, &statbuf) == -1) {
    perrorf (g, "stat: %s", tmpfile);
    goto err;
  }

  /* Don't use safe_malloc, because we want to return an errno to the caller. */
  size = statbuf.st_size;
  ret = malloc (size + 1);
  if (!ret) {
    perrorf (g, "malloc: %zu bytes", size + 1);
    goto err;
  }

  if (full_read (fd, ret, size) != size) {
    perrorf (g, "full-read: %s: %zu bytes", tmpfile, size + 1);
    goto err;
  }

  ret[size] = '\0';

  if (close (fd) == -1) {
    perrorf (g, "close: %s", tmpfile);
    goto err;
  }

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

 err:
  free (ret);
  if (fd >= 0)
    close (fd);
  return NULL;
}
Beispiel #5
0
/* We need to make all tmpdir paths absolute because lots of places in
 * the code assume this.  Do it at the time we set the path or read
 * the environment variable (RHBZ#882417).
 */
static int
set_abs_path (guestfs_h *g, const char *tmpdir, char **tmpdir_ret)
{
  char *ret;
  struct stat statbuf;

  /* Free the old path, and set it to NULL so that if we fail below
   * we don't end up with a pointer to freed memory.
   */
  free (*tmpdir_ret);
  *tmpdir_ret = NULL;

  if (tmpdir == NULL)
    return 0;

  ret = realpath (tmpdir, NULL);
  if (ret == NULL) {
    perrorf (g, _("failed to set temporary directory: %s"), tmpdir);
    return -1;
  }

  if (stat (ret, &statbuf) == -1) {
    perrorf (g, _("failed to set temporary directory: %s"), tmpdir);
    return -1;
  }

  if (!S_ISDIR (statbuf.st_mode)) {
    error (g, _("temporary directory '%s' is not a directory"), tmpdir);
    return -1;
  }

  *tmpdir_ret = ret;
  return 0;
}
Beispiel #6
0
static struct guestfs_xattr_list *
copy_xattr_list (guestfs_h *g, const struct guestfs_xattr *first, size_t num)
{
  struct guestfs_xattr_list *xattrs;
  size_t i;

  xattrs = malloc (sizeof *xattrs);
  if (xattrs == NULL) {
    perrorf (g, "malloc");
    return NULL;
  }

  xattrs->len = num;
  xattrs->val = malloc (num * sizeof (struct guestfs_xattr));
  if (xattrs->val == NULL) {
    perrorf (g, "malloc");
    free (xattrs);
    return NULL;
  }

  for (i = 0; i < num; ++i) {
    xattrs->val[i].attrname = strdup (first[i].attrname);
    xattrs->val[i].attrval_len = first[i].attrval_len;
    xattrs->val[i].attrval = malloc (first[i].attrval_len);
    memcpy (xattrs->val[i].attrval, first[i].attrval, first[i].attrval_len);
  }

  return xattrs;
}
Beispiel #7
0
static int
lazy_make_tmpdir (guestfs_h *g, char *(*getdir) (guestfs_h *g), char **dest)
{
  if (!*dest) {
    CLEANUP_FREE char *tmpdir = getdir (g);
    char *tmppath = safe_asprintf (g, "%s/libguestfsXXXXXX", tmpdir);
    if (mkdtemp (tmppath) == NULL) {
      perrorf (g, _("%s: cannot create temporary directory"), tmppath);
      free (tmppath);
      return -1;
    }
    /* Allow qemu (which may be running as qemu.qemu) to read in this
     * temporary directory; we are storing either sockets, or temporary
     * disks which qemu needs to access to.  (RHBZ#610880).
     * We do this only for root, as for normal users qemu will be run
     * under the same user.
     */
    if (geteuid () == 0 && chmod (tmppath, 0755) == -1) {
      perrorf (g, "chmod: %s", tmppath);
      free (tmppath);
      return -1;
    }
    *dest = tmppath;
  }
  return 0;
}
Beispiel #8
0
/* Create a new socket connection, connected.
 *
 * As above, but the caller passes us a connected daemon_sock
 * and promises not to call accept_connection.
 */
struct connection *
guestfs_int_new_conn_socket_connected (guestfs_h *g,
                                     int daemon_sock,
                                     int console_sock)
{
  struct connection_socket *conn;

  assert (daemon_sock >= 0);

  if (fcntl (daemon_sock, F_SETFL, O_NONBLOCK) == -1) {
    perrorf (g, "new_conn_socket_connected: fcntl");
    return NULL;
  }

  if (console_sock >= 0) {
    if (fcntl (console_sock, F_SETFL, O_NONBLOCK) == -1) {
      perrorf (g, "new_conn_socket_connected: fcntl");
      return NULL;
    }
  }

  conn = safe_malloc (g, sizeof *conn);

  /* Set the operations. */
  conn->ops = &ops;

  /* Set the internal state. */
  conn->console_sock = console_sock;
  conn->daemon_sock = daemon_sock;
  conn->daemon_accept_sock = -1;

  return (struct connection *) conn;
}
Beispiel #9
0
static int
write_or_append (guestfs_h *g, const char *path,
                 const char *content, size_t size,
                 int append)
{
  CLEANUP_UNLINK_FREE char *tmpfile = NULL;
  int fd = -1;
  int64_t filesize;

  /* If the content is small enough, use guestfs_internal_write{,_append}
   * since that call is more efficient.
   */
  if (size <= 2*1024*1024)
    return
      (!append ? guestfs_internal_write : guestfs_internal_write_append)
      (g, path, content, size);

  if (guestfs_int_lazy_make_tmpdir (g) == -1)
    goto err;

  /* Write the content out to a temporary file. */
  tmpfile = safe_asprintf (g, "%s/write%d", g->tmpdir, ++g->unique);

  fd = open (tmpfile, O_WRONLY|O_CREAT|O_NOCTTY|O_CLOEXEC, 0600);
  if (fd == -1) {
    perrorf (g, "open: %s", tmpfile);
    goto err;
  }

  if (full_write (fd, content, size) != size) {
    perrorf (g, "write: %s", tmpfile);
    goto err;
  }

  if (close (fd) == -1) {
    perrorf (g, "close: %s", tmpfile);
    goto err;
  }
  fd = -1;

  if (!append) {
    if (guestfs_upload (g, tmpfile, path) == -1)
      goto err;
  }
  else {
    /* XXX Should have an 'upload-append' call to make this atomic. */
    filesize = guestfs_filesize (g, path);
    if (filesize == -1)
      goto err;
    if (guestfs_upload_offset (g, tmpfile, path, filesize) == -1)
      goto err;
  }

  return 0;

 err:
  if (fd >= 0)
    close (fd);
  return -1;
}
Beispiel #10
0
/* Download a guest file to a local temporary file.  The file is
 * cached in the temporary directory, and is not downloaded again.
 *
 * The name of the temporary (downloaded) file is returned.  The
 * caller must free the pointer, but does *not* need to delete the
 * temporary file.  It will be deleted when the handle is closed.
 *
 * Refuse to download the guest file if it is larger than max_size.
 * On this and other errors, NULL is returned.
 *
 * There is actually one cache per 'struct inspect_fs *' in order
 * to handle the case of multiple roots.
 */
char *
guestfs___download_to_tmp (guestfs_h *g, struct inspect_fs *fs,
                           const char *filename,
                           const char *basename, uint64_t max_size)
{
    char *r;
    int fd;
    char devfd[32];
    int64_t size;

    /* Make the basename unique by prefixing it with the fs number.
     * This also ensures there is one cache per filesystem.
     */
    if (asprintf (&r, "%s/%td-%s", g->tmpdir, fs - g->fses, basename) == -1) {
        perrorf (g, "asprintf");
        return NULL;
    }

    /* If the file has already been downloaded, return. */
    if (access (r, R_OK) == 0)
        return r;

    /* Check size of remote file. */
    size = guestfs_filesize (g, filename);
    if (size == -1)
        /* guestfs_filesize failed and has already set error in handle */
        goto error;
    if ((uint64_t) size > max_size) {
        error (g, _("size of %s is unreasonably large (%" PRIi64 " bytes)"),
               filename, size);
        goto error;
    }

    fd = open (r, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY|O_CLOEXEC, 0600);
    if (fd == -1) {
        perrorf (g, "open: %s", r);
        goto error;
    }

    snprintf (devfd, sizeof devfd, "/dev/fd/%d", fd);

    if (guestfs_download (g, filename, devfd) == -1) {
        unlink (r);
        close (fd);
        goto error;
    }

    if (close (fd) == -1) {
        perrorf (g, "close: %s", r);
        unlink (r);
        goto error;
    }

    return r;

error:
    free (r);
    return NULL;
}
Beispiel #11
0
/* Send a file.
 * Returns:
 *   0 OK
 *   -1 error
 *   -2 daemon cancelled (we must read the error message)
 */
int
guestfs___send_file (guestfs_h *g, const char *filename)
{
  char buf[GUESTFS_MAX_CHUNK_SIZE];
  int fd, r = 0, err;

  g->user_cancel = 0;

  fd = open (filename, O_RDONLY|O_CLOEXEC);
  if (fd == -1) {
    perrorf (g, "open: %s", filename);
    send_file_cancellation (g);
    return -1;
  }

  fadvise_sequential (fd);

  /* Send file in chunked encoding. */
  while (!g->user_cancel) {
    r = read (fd, buf, sizeof buf);
    if (r == -1 && (errno == EINTR || errno == EAGAIN))
      continue;
    if (r <= 0) break;
    err = send_file_data (g, buf, r);
    if (err < 0) {
      if (err == -2)		/* daemon sent cancellation */
        send_file_cancellation (g);
      close (fd);
      return err;
    }
  }

  if (r == -1) {
    perrorf (g, "read: %s", filename);
    send_file_cancellation (g);
    close (fd);
    return -1;
  }

  if (g->user_cancel) {
    error (g, _("operation cancelled by user"));
    g->last_errnum = EINTR;
    send_file_cancellation (g);
    close (fd);
    return -1;
  }

  /* End of file, but before we send that, we need to close
   * the file and check for errors.
   */
  if (close (fd) == -1) {
    perrorf (g, "close: %s", filename);
    send_file_cancellation (g);
    return -1;
  }

  return send_file_complete (g);
}
Beispiel #12
0
/**
 * Fallback method of getting the umask using fork.
 */
static int
get_umask_from_fork (guestfs_h *g)
{
  pid_t pid;
  int fd[2], r;
  int mask;
  int status;

  r = pipe2 (fd, O_CLOEXEC);
  if (r == -1) {
    perrorf (g, "pipe2");
    return -1;
  }

  pid = fork ();
  if (pid == -1) {
    perrorf (g, "fork");
    close (fd[0]);
    close (fd[1]);
    return -1;
  }
  if (pid == 0) {
    /* The child process must ONLY call async-safe functions. */
    close (fd[0]);

    /* umask can't fail. */
    mask = umask (0);

    if (write (fd[1], &mask, sizeof mask) != sizeof mask)
      _exit (EXIT_FAILURE);
    if (close (fd[1]) == -1)
      _exit (EXIT_FAILURE);

    _exit (EXIT_SUCCESS);
  }

  /* Parent. */
  close (fd[1]);

  /* Read the umask. */
  if (read (fd[0], &mask, sizeof mask) != sizeof mask) {
    perrorf (g, "read");
    close (fd[0]);
    guestfs_int_waitpid_noerror (pid);
    return -1;
  }
  close (fd[0]);

  if (guestfs_int_waitpid (g, pid, &status, "umask") == -1)
    return -1;
  else if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) {
    guestfs_int_external_command_failed (g, status, "umask", NULL);
    return -1;
  }

  return mask;
}
Beispiel #13
0
int copy(char *dest, char *src)
{
	FILE *in, *out;
	int ret;
	char *actualdest = dest;

	if(samefile(dest, src)){
		eprintf("`%s' and `%s' are the same file", dest, src);
		return 1;
	}

	if(!(in = fopen(src, "r"))){
		perrorf("open (for read): `%s'", src);
		return 1;
	}

	/* TODO: make dir if it doesn't exist */
	if(!(out = fopen(dest, "w"))){
		if(errno == EISDIR){
			char *srcbase = strrchr(src, '/');

			if(!srcbase)
				srcbase = src;

			actualdest = alloca(strlen(dest) + strlen(srcbase) + 2);
			sprintf(actualdest, "%s/%s", dest, srcbase);

			if(samefile(actualdest, src)){
				eprintf("`%s' and `%s' are the same file", actualdest, src);
				fclose(in);
				return 1;
			}

			out = fopen(actualdest, "w");
			if(!out){
				perrorf("open (for write): `%s'", actualdest);
				fclose(in);
				return 1;
			}
		}else{
			perrorf("open (for write): `%s'", dest);
			fclose(in);
			return 1;
		}
	}

	ret = filecopy(in, out, actualdest, filelen(src));

	fclose(in);
	fclose(out);

	if(!i_am_cp && remove(src))
		perrorf("non-fatal: remove: `%s'", src);

	return ret;
}
Beispiel #14
0
static int
read_osinfo_db_three_levels (guestfs_h *g, const char *directory)
{
  DIR *dir;
  int r;

  dir = opendir (directory);
  if (!dir) {
    debug (g, "osinfo: %s: %s", directory, strerror (errno));
    return 0; /* This is not an error: RHBZ#948324. */
  }

  debug (g, "osinfo: loading 3-level-directories database from %s", directory);

  for (;;) {
    struct dirent *d;
    CLEANUP_FREE char *pathname = NULL;
    struct stat sb;

    errno = 0;
    d = readdir (dir);
    if (!d) break;

    pathname = safe_asprintf (g, "%s/%s", directory, d->d_name);

    /* Iterate only on directories. */
    if (stat (pathname, &sb) == 0 && S_ISDIR (sb.st_mode)) {
      r = read_osinfo_db_directory (g, pathname);
      if (r == -1)
        goto error;
    }
  }

  /* Check for failure in readdir. */
  if (errno != 0) {
    perrorf (g, "readdir: %s", directory);
    goto error;
  }

  /* Close the directory handle. */
  r = closedir (dir);
  dir = NULL;
  if (r == -1) {
    perrorf (g, "closedir: %s", directory);
    goto error;
  }

  return 1;

 error:
  if (dir)
    closedir (dir);

  return -1;
}
Beispiel #15
0
/* Read the whole file into a memory buffer and return it.  The file
 * should be a regular, local, trusted file.
 */
static int
read_whole_file (guestfs_h *g, const char *filename,
                 char **data_r, size_t *size_r)
{
  int fd;
  char *data;
  off_t size;
  off_t n;
  ssize_t r;
  struct stat statbuf;

  fd = open (filename, O_RDONLY|O_CLOEXEC);
  if (fd == -1) {
    perrorf (g, "open: %s", filename);
    return -1;
  }

  if (fstat (fd, &statbuf) == -1) {
    perrorf (g, "stat: %s", filename);
    close (fd);
    return -1;
  }

  size = statbuf.st_size;
  data = safe_malloc (g, size);

  n = 0;
  while (n < size) {
    r = read (fd, &data[n], size - n);
    if (r == -1) {
      perrorf (g, "read: %s", filename);
      free (data);
      close (fd);
      return -1;
    }
    if (r == 0) {
      error (g, _("read: %s: unexpected end of file"), filename);
      free (data);
      close (fd);
      return -1;
    }
    n += r;
  }

  if (close (fd) == -1) {
    perrorf (g, "close: %s", filename);
    free (data);
    return -1;
  }

  *data_r = data;
  *size_r = size;

  return 0;
}
Beispiel #16
0
static int
read_osinfo_db_directory (guestfs_h *g, const char *directory)
{
  DIR *dir;
  int r;

  dir = opendir (directory);
  if (!dir) {
    debug (g, "osinfo: %s: %s", directory, strerror (errno));
    return 0; /* This is not an error: RHBZ#948324. */
  }

  for (;;) {
    struct dirent *d;

    errno = 0;
    d = readdir (dir);
    if (!d) break;

    if (STRSUFFIX (d->d_name, ".xml")) {
      CLEANUP_FREE char *pathname = NULL;

      pathname = safe_asprintf (g, "%s/%s", directory, d->d_name);
      r = read_osinfo_db_xml (g, pathname);
      if (r == -1)
        goto error;
    }
  }

  /* Check for failure in readdir. */
  if (errno != 0) {
    perrorf (g, "readdir: %s", directory);
    goto error;
  }

  /* Close the directory handle. */
  r = closedir (dir);
  dir = NULL;
  if (r == -1) {
    perrorf (g, "closedir: %s", directory);
    goto error;
  }

  return 1;

 error:
  if (dir)
    closedir (dir);

  return -1;
}
Beispiel #17
0
static int
run_qemu_img_info (guestfs_h *g, const char *filename,
                   cmd_stdout_callback fn, void *data)
{
  char *abs_filename = NULL;
  char *safe_filename = NULL;
  struct command *cmd;
  int r;

  if (guestfs___lazy_make_tmpdir (g) == -1)
    return -1;

  safe_filename = safe_asprintf (g, "%s/format.%d", g->tmpdir, ++g->unique);

  /* 'filename' must be an absolute path so we can link to it. */
  abs_filename = realpath (filename, NULL);
  if (abs_filename == NULL) {
    perrorf (g, "realpath");
    goto error;
  }

  if (symlink (abs_filename, safe_filename) == -1) {
    perrorf (g, "symlink");
    goto error;
  }

  cmd = guestfs___new_command (g);
  guestfs___cmd_add_arg (cmd, "qemu-img");
  guestfs___cmd_add_arg (cmd, "info");
  guestfs___cmd_add_arg (cmd, safe_filename);
  guestfs___cmd_set_stdout_callback (cmd, fn, data, 0);
  r = guestfs___cmd_run (cmd);
  guestfs___cmd_close (cmd);
  if (r == -1)
    goto error;
  if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) {
    error (g, _("qemu-img: %s: child process failed"), filename);
    goto error;
  }

  free (safe_filename);
  free (abs_filename);
  return 0;

 error:
  free (safe_filename);
  free (abs_filename);

  return -1;
}
Beispiel #18
0
void set_nonblocking(int fd) {
  int flags = 0;

  flags = fcntl(fd, F_GETFL, 0);
  if (flags == -1) {
    perrorf("fcntl(fd=%d)", fd);
    abort();
  }

  if (-1 == fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
    perrorf("fcntl(fd=%d)", fd);
    abort();
  }
}
Beispiel #19
0
int init_files()
{
	snprintf(dir, PATH_LEN, "%s:%s", host, port);
	if(mkdir(dir, 0700)){
		if(errno == EEXIST){
			fprintf(stderr, "not overwriting %s\n", dir);
			return 2;
		}else{
			perror("mkdir()");
			return 1;
		}
		/* unreachable */
	}

	snprintf(file_input,   PATH_LEN, "%s/%s", dir, "in");
	snprintf(file_cmd,     PATH_LEN, "%s/%s", dir, "cmd");

	snprintf(file_output,  PATH_LEN, "%s/%s", dir, "out");
	snprintf(file_info,    PATH_LEN, "%s/%s", dir, "server");
	snprintf(file_clients, PATH_LEN, "%s/%s", dir, "clients");
	snprintf(file_err,     PATH_LEN, "%s/%s", dir, "err");


	if(mkfifo(file_input, 0600) == -1 && errno != EEXIST){
		perrorf("mkfifo(): %s: ", file_input);
		return 1; /* ya */
	}
	if(mkfifo(file_cmd, 0600) == -1 && errno != EEXIST){
		perrorf("mkfifo(): %s: ", file_cmd);
		goto bail;
	}

	if((fd_input = open(file_input, O_RDONLY | O_NONBLOCK, 0600)) == -1){
		perrorf("open(): %s: ", file_input);
		goto bail;
	}
	if((fd_cmd = open(file_cmd, O_RDONLY | O_NONBLOCK, 0600)) == -1){
		perrorf("open(): %s: ", file_cmd);
		close(fd_input);
		goto bail;
	}

	return 0;
bail:
	remove(file_input);
	remove(file_cmd);
	return 1;
}
Beispiel #20
0
int nand_info(struct cmd_param *params)
{
	struct chip_param_io chip_params;
	int fd = -1, ret = 0;
	int block_size;
	off_t chip_size, media_size;
	const char *dev;

	if ((dev = param_get_string(params, "dev")) == NULL) {
		fprintf(stderr, "Please supply 'dev' parameter, eg. "
		    "'dev=/dev/gnand0'\n");
		return (1);
	}

	if ((fd = g_open(dev, 1)) == -1) {
		perrorf("Cannot open %s", dev);
		return (1);
	}

	if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) {
		perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)");
		ret = 1;
		goto out;
	}

	if (ioctl(fd, DIOCGMEDIASIZE, &media_size) == -1) {
		perrorf("Cannot ioctl(DIOCGMEDIASIZE)");
		ret = 1;
		goto out;
	}

	block_size = chip_params.page_size * chip_params.pages_per_block;
	chip_size = block_size * chip_params.blocks;

	printf("Device:\t\t\t%s\n", dev);
	printf("Page size:\t\t%d bytes\n", chip_params.page_size);
	printf("Block size:\t\t%d bytes (%d KB)\n", block_size,
	    block_size / 1024);
	printf("OOB size per page:\t%d bytes\n", chip_params.oob_size);
	printf("Chip size:\t\t%jd MB\n", (uintmax_t)(chip_size / 1024 / 1024));
	printf("Slice size:\t\t%jd MB\n",
	    (uintmax_t)(media_size / 1024 / 1024));

out:
	g_close(fd);

	return (ret);
}
Beispiel #21
0
/**
 * For Linux E<ge> 4.7 get the umask from F</proc/self/status>.
 *
 * On failure this returns C<-1>.  However if we could not open the
 * F</proc> file or find the C<Umask> entry in it, return C<-2> which
 * causes the fallback path to run.
 */
static int
get_umask_from_proc (guestfs_h *g)
{
  CLEANUP_FCLOSE FILE *fp = NULL;
  CLEANUP_FREE char *line = NULL;
  size_t allocsize = 0;
  ssize_t len;
  unsigned int mask;
  bool found = false;

  fp = fopen ("/proc/self/status", "r");
  if (fp == NULL) {
    if (errno == ENOENT || errno == ENOTDIR)
      return -2;                /* fallback */
    perrorf (g, "open: /proc/self/status");
    return -1;
  }

  while ((len = getline (&line, &allocsize, fp)) != -1) {
    if (len > 0 && line[len-1] == '\n')
      line[--len] = '\0';

    /* Looking for: "Umask:  0022" */
    if (sscanf (line, "Umask: %o", &mask) == 1) {
      found = true;
      break;
    }
  }

  if (!found)
    return -2;                  /* fallback */

  return (int) mask;
}
Beispiel #22
0
static int
can_read_data (guestfs_h *g, struct connection *connv)
{
  struct connection_socket *conn = (struct connection_socket *) connv;
  struct pollfd fd;
  int r;

  if (conn->daemon_sock == -1) {
    error (g, _("can_read_data: socket not connected"));
    return -1;
  }

  fd.fd = conn->daemon_sock;
  fd.events = POLLIN;
  fd.revents = 0;

 again:
  r = poll (&fd, 1, 0);
  if (r == -1) {
    if (errno == EINTR || errno == EAGAIN)
      goto again;
    perrorf (g, "can_read_data: poll");
    return -1;
  }

  return (fd.revents & POLLIN) != 0 ? 1 : 0;
}
bool compress(char *param, void *conf)
{
    clientConfig *c=(clientConfig*)conf;
    int i=0;
    char buffer[MSGSIZE];
    char archive[MSGSIZE];

    /* direxists -> makesubdir*/

    for(i=0;i<MSGSIZE;i++)
        buffer[i]=0;

    sendCommand(CMD_COMPRESS, NULL, &(c->sock));

    if (recvCommand(buffer, &(c->sock)) != CMD_SEND)
    {
        printf("* compress \"%s\" failed. no file sent or server error\n",param);

        return false;
    }

    sendCommand(CMD_ACK, NULL, &(c->sock));
    printf("* downloading remote archive \"%s\"\n",buffer);

    pullfile(buffer, &(c->sock));

    strcpy(archive,param);
    addSlash(archive);
    strcat(archive,buffer);
    printf("* moving file \"%s\" to %s\n",buffer,archive);
    if (rename(buffer,archive)<0)
        perrorf("rename()");

    return true;
}
Beispiel #24
0
static int
disk_create_raw_block (guestfs_h *g, const char *filename)
{
  int fd;

  fd = open (filename, O_WRONLY|O_NOCTTY|O_CLOEXEC, 0666);
  if (fd == -1) {
    perrorf (g, _("cannot open block device: %s"), filename);
    return -1;
  }

  /* Just discard blocks, if possible.  However don't try too hard. */
#if defined(BLKGETSIZE64) && defined(BLKDISCARD)
  uint64_t size;
  uint64_t range[2];

  if (ioctl (fd, BLKGETSIZE64, &size) == 0) {
    range[0] = 0;
    range[1] = size;
    if (ioctl (fd, BLKDISCARD, range) == 0)
      debug (g, "disk_create: %s: BLKDISCARD failed on this device: %m",
             filename);
  }
#endif

  close (fd);

  return 0;
}
Beispiel #25
0
int dircopy(char *base, char *src[], int nsrc)
{
	char *dest = NULL;
	int baselen = strlen(base) + 1; /* +1 for '/' */
	int i, destlen = 0, ret = 0;
#define BAIL() do{ ret = 1; goto bail; } while(0)

	for(i = 0; i < nsrc; i++){
		int newlen = baselen + strlen(src[i]) + 1;

		if(destlen < newlen){
			char *tmp = realloc(dest, newlen);
			if(!tmp){
				perrorf("realloc()");
				BAIL();
			}
			dest = tmp;
		}

		if(*src[i] != '/')
			sprintf(dest, "%s/%s", base, src[i]);
		else
			strcpy(dest, src[i]);

		if(copy(dest, src[i]))
			BAIL();
	}

bail:
	free(dest);

	return ret;
}
Beispiel #26
0
int
guestfs__mount_local_run (guestfs_h *g)
{
  int r, mounted;

  gl_lock_lock (mount_local_lock);
  mounted = g->localmountpoint != NULL;
  gl_lock_unlock (mount_local_lock);

  if (!mounted) {
    error (g, _("you must call guestfs_mount_local first"));
    return -1;
  }

  debug (g, "%s: entering fuse_loop", __func__);

  /* Enter the main loop. */
  r = fuse_loop (g->fuse);
  if (r != 0)
    perrorf (g, _("fuse_loop: %s"), g->localmountpoint);

  debug (g, "%s: leaving fuse_loop", __func__);

  guestfs___free_fuse (g);
  gl_lock_lock (mount_local_lock);
  g->localmountpoint = NULL;
  gl_lock_unlock (mount_local_lock);

  /* By inspection, I found that fuse_loop only returns 0 or -1, but
   * don't rely on this in future.
   */
  return r == 0 ? 0 : -1;
}
Beispiel #27
0
/* This is called if conn->console_sock becomes ready to read while we
 * are doing one of the connection operations above.  It reads and
 * deals with the log message.
 *
 * Returns:
 *   1 = log message(s) were handled successfully
 *   0 = connection to appliance closed
 *  -1 = error
 */
static int
handle_log_message (guestfs_h *g,
                    struct connection_socket *conn)
{
  char buf[BUFSIZ];
  ssize_t n;

  /* Carried over from ancient proto.c code.  The comment there was:
   *
   *   "QEMU's console emulates a 16550A serial port.  The real 16550A
   *   device has a small FIFO buffer (16 bytes) which means here we
   *   see lots of small reads of 1-16 bytes in length, usually single
   *   bytes.  Sleeping here for a very brief period groups reads
   *   together (so we usually get a few lines of output at once) and
   *   improves overall throughput, as well as making the event
   *   interface a bit more sane for callers.  With a virtio-serial
   *   based console (not yet implemented) we may be able to remove
   *   this.  XXX"
   */
  usleep (1000);

  n = read (conn->console_sock, buf, sizeof buf);
  if (n == 0)
    return 0;

  if (n == -1) {
    if (errno == EINTR || errno == EAGAIN)
      return 1; /* not an error */

    perrorf (g, _("error reading console messages from the appliance"));
    return -1;
  }

  /* It's an actual log message, send it upwards. */
  guestfs_int_log_message_callback (g, buf, n);

#ifdef VALGRIND_DAEMON
  /* Find the canary printed by appliance/init if valgrinding of the
   * daemon fails, and exit abruptly.  Note this is only used in
   * developer builds, and should never be enabled in ordinary/
   * production builds.
   */
  if (g->verbose) {
    const char *valgrind_canary = "DAEMON VALGRIND FAILED";

    if (memmem (buf, n, valgrind_canary, strlen (valgrind_canary)) != NULL) {
      fprintf (stderr,
               "Detected valgrind failure in the daemon!  Exiting with exit code 119.\n"
               "See log messages printed above.\n"
               "Note: This happens because libguestfs was configured with\n"
               "'--enable-valgrind-daemon' which should not be used in production builds.\n");
      exit (119);
    }
  }
#endif

  return 1;
}
Beispiel #28
0
int lewp()
{
	struct pollfd pfd[2];
	static char buffer[MAX_LINE_LEN], *nl;
	int nread;

	pfd[0].fd     = fd_input;
	pfd[1].fd     = fd_cmd;
	pfd[0].events = pfd[1].events = POLLIN;

	while(!finito){
		if(comm_recv(&commt, &commcallback)){
			outputf(file_err, "comm_recv() failed: %s\n", comm_lasterr(&commt));
			return 1;
		}

		switch(poll(pfd, 2, FIFO_POLL_WAIT)){
			case 0:
				/* notan happan */
				continue;
			case -1:
				perrorf("%s", "poll()");
				return 1;
		}

#define READ(fd) \
			nread = read(fd, buffer, MAX_LINE_LEN); \
	 \
			switch(nread){ \
				case -1: \
					perrorf("%s", "read()"); \
					return 1; \
				case 0: \
					break; \
				default: \
					buffer[nread-1] = '\0'; \
					if((nl = strchr(buffer, '\n'))) \
						*nl = '\0'; \
			}

#define BIT(x, b) (((x) & (b)) == (b))
		if(BIT(pfd[0].revents, POLLIN)){
			READ(pfd[0].fd);
			if(nread > 0)
				/* message */
				comm_sendmessage(&commt, buffer);
		}

		if(BIT(pfd[1].revents, POLLIN)){
			READ(pfd[1].fd);
			if(nread > 0)
				proc_cmd(buffer);
		}
	}
	return 0;
}
bool quit(char *param, void *conf)
{
    clientConfig *c=(clientConfig*)conf;
    if (close(c->sock) < 0)
        perrorf("close()");
    else
        printf("* socket closed, bye...\n");

    exit(0);
    return false;
}
Beispiel #30
0
int
guestfs_impl_copy_in (guestfs_h *g, const char *localpath, const char *remotedir)
{
  CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g);
  int fd;
  int r;
  char fdbuf[64];
  size_t buf_len = strlen (localpath) + 1;
  char buf[buf_len];
  const char *dirname, *basename;

  int remote_is_dir = guestfs_is_dir (g, remotedir);
  if (remote_is_dir == -1)
    return -1;

  if (!remote_is_dir) {
    error (g, _("target '%s' is not a directory"), remotedir);
    return -1;
  }

  if (split_path (g, buf, buf_len, localpath, &dirname, &basename) == -1)
    return -1;

  guestfs_int_cmd_add_arg (cmd, "tar");
  if (dirname) {
    guestfs_int_cmd_add_arg (cmd, "-C");
    guestfs_int_cmd_add_arg (cmd, dirname);
  }
  guestfs_int_cmd_add_arg (cmd, "-cf");
  guestfs_int_cmd_add_arg (cmd, "-");
  guestfs_int_cmd_add_arg (cmd, basename);

  r = guestfs_int_cmd_run_async (cmd, NULL, NULL, &fd, NULL);
  if (r == -1)
    return -1;

  snprintf (fdbuf, sizeof fdbuf, "/dev/fd/%d", fd);

  r = guestfs_tar_in (g, fdbuf, remotedir);

  if (close (fd) == -1) {
    perrorf (g, "close (tar subprocess)");
    return -1;
  }

  r = guestfs_int_cmd_wait (cmd);
  if (r == -1)
    return -1;
  if (!(WIFEXITED (r) && WEXITSTATUS (r) == 0))
    return -1;

  return 0;
}