Ejemplo n.º 1
0
static void
try_df (const char *name, const char *uuid,
        const char *dev, int offset)
{
  struct guestfs_statvfs *stat = NULL;
  guestfs_error_handler_cb old_error_cb;
  void *old_error_data;

  if (verbose)
    fprintf (stderr, "try_df %s %s %d\n", name, dev, offset);

  /* Try mounting and stating the device.  This might reasonably fail,
   * so don't show errors.
   */
  old_error_cb = guestfs_get_error_handler (g, &old_error_data);
  guestfs_set_error_handler (g, NULL, NULL);

  if (guestfs_mount_ro (g, dev, "/") == 0) {
    stat = guestfs_statvfs (g, "/");
    guestfs_umount_all (g);
  }

  guestfs_set_error_handler (g, old_error_cb, old_error_data);

  if (stat) {
    print_stat (name, uuid, dev, offset, stat);
    guestfs_free_statvfs (stat);
  }
}
Ejemplo n.º 2
0
int
run_supported (const char *cmd, size_t argc, char *argv[])
{
  char **groups;

  /* As a side-effect this also checks that we've called 'launch'. */
  groups = guestfs_available_all_groups (g);
  if (groups == NULL)
    return -1;

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

  /* Work out the max string length of any group name. */
  size_t i;
  size_t len = 0;
  for (i = 0; groups[i] != NULL; ++i) {
    size_t l = strlen (groups[i]);
    if (l > len)
      len = l;
  }

  for (i = 0; groups[i] != NULL; ++i) {
    size_t l = strlen (groups[i]);
    size_t j;
    for (j = 0; j < len-l; ++j)
      putchar (' ');
    printf ("%s", groups[i]);
    putchar (' ');

    char *gg[] = { groups[i], NULL };
    int r = guestfs_available (g, gg);
    if (r == 0)
      printf ("%s", _("yes"));
    else
      printf ("%s", _("no"));
    putchar ('\n');
  }

  /* Free groups list. */
  for (i = 0; groups[i] != NULL; ++i)
    free (groups[i]);
  free (groups);

  /* Restore error handler. */
  guestfs_set_error_handler (g, old_error_cb, old_error_cb_data);

  return 0;
}
Ejemplo n.º 3
0
/* Guestfs.create */
CAMLprim value
ocaml_guestfs_create (void)
{
  CAMLparam0 ();
  CAMLlocal1 (gv);
  guestfs_h *g;
  value *v;

  g = guestfs_create ();
  if (g == NULL)
    caml_failwith ("failed to create guestfs handle");

  guestfs_set_error_handler (g, NULL, NULL);

  gv = Val_guestfs (g);

  /* Store the OCaml handle into the C handle.  This is only so we can
   * map the C handle to the OCaml handle in event_callback_wrapper.
   */
  v = guestfs_safe_malloc (g, sizeof *v);
  *v = gv;
  /* XXX This global root is generational, but we cannot rely on every
   * user having the OCaml 3.11 version which supports this.
   */
  caml_register_global_root (v);
  guestfs_set_private (g, "_ocaml_g", v);

  CAMLreturn (gv);
}
Ejemplo n.º 4
0
/* Guestfs.create */
value
ocaml_guestfs_create (value environmentv, value close_on_exitv, value unitv)
{
  CAMLparam3 (environmentv, close_on_exitv, unitv);
  CAMLlocal1 (gv);
  unsigned flags = 0;
  guestfs_h *g;

  if (environmentv != Val_int (0) &&
      !Bool_val (Field (environmentv, 0)))
    flags |= GUESTFS_CREATE_NO_ENVIRONMENT;

  if (close_on_exitv != Val_int (0) &&
      !Bool_val (Field (close_on_exitv, 0)))
    flags |= GUESTFS_CREATE_NO_CLOSE_ON_EXIT;

  g = guestfs_create_flags (flags);
  if (g == NULL)
    caml_failwith ("failed to create guestfs handle");

  guestfs_set_error_handler (g, NULL, NULL);

  gv = Val_guestfs (g);

  CAMLreturn (gv);
}
Ejemplo n.º 5
0
void
guestfs_push_error_handler (guestfs_h *g,
                            guestfs_error_handler_cb cb, void *data)
{
  struct error_cb_stack *old_stack;

  old_stack = g->error_cb_stack;
  g->error_cb_stack = safe_malloc (g, sizeof (struct error_cb_stack));
  g->error_cb_stack->next = old_stack;
  g->error_cb_stack->error_cb = g->error_cb;
  g->error_cb_stack->error_cb_data = g->error_cb_data;

  guestfs_set_error_handler (g, cb, data);
}
Ejemplo n.º 6
0
JNIEXPORT jlong JNICALL
Java_com_redhat_et_libguestfs_GuestFS__1create (JNIEnv *env,
                                                jobject obj_unused, jint flags)
{
  guestfs_h *g;

  g = guestfs_create_flags ((int) flags);
  if (g == NULL) {
    throw_exception (env, "GuestFS.create: failed to allocate handle");
    return 0;
  }
  guestfs_set_error_handler (g, NULL, NULL);
  return (jlong) (long) g;
}
Ejemplo n.º 7
0
void
guestfs_pop_error_handler (guestfs_h *g)
{
  struct error_cb_stack *next_stack;

  if (g->error_cb_stack) {
    next_stack = g->error_cb_stack->next;
    guestfs_set_error_handler (g, g->error_cb_stack->error_cb,
                               g->error_cb_stack->error_cb_data);
    free (g->error_cb_stack);
    g->error_cb_stack = next_stack;
  }
  else
    guestfs___init_error_handler (g);
}
Ejemplo n.º 8
0
PyObject *
py_guestfs_create (PyObject *self, PyObject *args)
{
  guestfs_h *g;

  g = guestfs_create ();
  if (g == NULL) {
    PyErr_SetString (PyExc_RuntimeError,
                     "guestfs.create: failed to allocate handle");
    return NULL;
  }
  guestfs_set_error_handler (g, NULL, NULL);
  /* This can return NULL, but in that case put_handle will have
   * set the Python error string.
   */
  return put_handle (g);
}
Ejemplo n.º 9
0
/* Guestfs.create */
value
ocaml_guestfs_create (value environmentv, value close_on_exitv, value unitv)
{
  CAMLparam3 (environmentv, close_on_exitv, unitv);
  CAMLlocal1 (gv);
  unsigned flags = 0;
  guestfs_h *g;
  value *v;

  if (environmentv != Val_int (0) &&
      !Bool_val (Field (environmentv, 0)))
    flags |= GUESTFS_CREATE_NO_ENVIRONMENT;

  if (close_on_exitv != Val_int (0) &&
      !Bool_val (Field (close_on_exitv, 0)))
    flags |= GUESTFS_CREATE_NO_CLOSE_ON_EXIT;

  g = guestfs_create_flags (flags);
  if (g == NULL)
    caml_failwith ("failed to create guestfs handle");

  guestfs_set_error_handler (g, NULL, NULL);

  gv = Val_guestfs (g);

  /* Store the OCaml handle into the C handle.  This is only so we can
   * map the C handle to the OCaml handle in event_callback_wrapper.
   */
  v = guestfs_int_safe_malloc (g, sizeof *v);
  *v = gv;
  /* XXX This global root is generational, but we cannot rely on every
   * user having the OCaml 3.11 version which supports this.
   */
  caml_register_global_root (v);
  guestfs_set_private (g, "_ocaml_g", v);

  CAMLreturn (gv);
}
Ejemplo n.º 10
0
int
main (int argc, char *argv[])
{
  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEBASEDIR);
  textdomain (PACKAGE);

  parse_config ();

  enum { HELP_OPTION = CHAR_MAX + 1 };

  /* The command line arguments are broadly compatible with (a subset
   * of) guestfish.  Thus we have to deal mainly with -a, -m and --ro.
   */
  static const char *options = "a:c:d:im:no:rv?Vwx";
  static const struct option long_options[] = {
    { "add", 1, 0, 'a' },
    { "connect", 1, 0, 'c' },
    { "dir-cache-timeout", 1, 0, 0 },
    { "domain", 1, 0, 'd' },
    { "echo-keys", 0, 0, 0 },
    { "format", 2, 0, 0 },
    { "fuse-help", 0, 0, 0 },
    { "help", 0, 0, HELP_OPTION },
    { "inspector", 0, 0, 'i' },
    { "keys-from-stdin", 0, 0, 0 },
    { "live", 0, 0, 0 },
    { "mount", 1, 0, 'm' },
    { "no-sync", 0, 0, 'n' },
    { "option", 1, 0, 'o' },
    { "ro", 0, 0, 'r' },
    { "rw", 0, 0, 'w' },
    { "selinux", 0, 0, 0 },
    { "trace", 0, 0, 'x' },
    { "verbose", 0, 0, 'v' },
    { "version", 0, 0, 'V' },
    { 0, 0, 0, 0 }
  };

  struct drv *drvs = NULL;
  struct drv *drv;
  struct mp *mps = NULL;
  struct mp *mp;
  char *p;
  const char *format = NULL;
  int c, r;
  int option_index;
  struct sigaction sa;

  int fuse_argc = 0;
  const char **fuse_argv = NULL;

#define ADD_FUSE_ARG(str)                                               \
  do {                                                                  \
    fuse_argc ++;                                                       \
    fuse_argv = realloc (fuse_argv, (1+fuse_argc) * sizeof (char *));   \
    if (!fuse_argv) {                                                   \
      perror ("realloc");                                               \
      exit (EXIT_FAILURE);                                                         \
    }                                                                   \
    fuse_argv[fuse_argc-1] = (str);                                     \
    fuse_argv[fuse_argc] = NULL;                                        \
  } while (0)

  /* LC_ALL=C is required so we can parse error messages. */
  setenv ("LC_ALL", "C", 1);

  /* Set global program name that is not polluted with libtool artifacts.  */
  set_program_name (argv[0]);

  memset (&sa, 0, sizeof sa);
  sa.sa_handler = SIG_IGN;
  sa.sa_flags = SA_RESTART;
  sigaction (SIGPIPE, &sa, NULL);

  /* Various initialization. */
  init_dir_caches ();

  g = guestfs_create ();
  if (g == NULL) {
    fprintf (stderr, _("guestfs_create: failed to create handle\n"));
    exit (EXIT_FAILURE);
  }

  guestfs_set_recovery_proc (g, 0);

  ADD_FUSE_ARG (program_name);
  /* MUST be single-threaded.  You cannot have two threads accessing the
   * same libguestfs handle, and opening more than one handle is likely
   * to be very expensive.
   */
  ADD_FUSE_ARG ("-s");

  for (;;) {
    c = getopt_long (argc, argv, options, long_options, &option_index);
    if (c == -1) break;

    switch (c) {
    case 0:			/* options which are long only */
      if (STREQ (long_options[option_index].name, "dir-cache-timeout"))
        dir_cache_timeout = atoi (optarg);
      else if (STREQ (long_options[option_index].name, "fuse-help"))
        fuse_help ();
      else if (STREQ (long_options[option_index].name, "selinux"))
        guestfs_set_selinux (g, 1);
      else if (STREQ (long_options[option_index].name, "format")) {
        if (!optarg || STREQ (optarg, ""))
          format = NULL;
        else
          format = optarg;
      } else if (STREQ (long_options[option_index].name, "keys-from-stdin")) {
        keys_from_stdin = 1;
      } else if (STREQ (long_options[option_index].name, "echo-keys")) {
        echo_keys = 1;
      } else if (STREQ (long_options[option_index].name, "live")) {
        live = 1;
      } else {
        fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
                 program_name, long_options[option_index].name, option_index);
        exit (EXIT_FAILURE);
      }
      break;

    case 'a':
      OPTION_a;
      break;

    case 'c':
      OPTION_c;
      break;

    case 'd':
      OPTION_d;
      break;

    case 'i':
      OPTION_i;
      break;

    case 'm':
      OPTION_m;
      break;

    case 'n':
      OPTION_n;
      break;

    case 'o':
      ADD_FUSE_ARG ("-o");
      ADD_FUSE_ARG (optarg);
      break;

    case 'r':
      OPTION_r;
      break;

    case 'v':
      OPTION_v;
      break;

    case 'V':
      OPTION_V;
      break;

    case 'w':
      OPTION_w;
      break;

    case 'x':
      OPTION_x;
      ADD_FUSE_ARG ("-f");
      guestfs_set_recovery_proc (g, 1);
      trace_calls = 1;
      break;

    case HELP_OPTION:
      usage (EXIT_SUCCESS);

    default:
      usage (EXIT_FAILURE);
    }
  }

  /* Check we have the right options. */
  if (!live) {
    if (!drvs || !(mps || inspector)) {
      fprintf (stderr,
               _("%s: must have at least one -a/-d and at least one -m/-i option\n"),
               program_name);
      exit (EXIT_FAILURE);
    }
  } else {
    size_t count_d = 0, count_other = 0;
    struct drv *drv;

    if (read_only) {
      fprintf (stderr,
               _("%s: --live is not compatible with --ro option\n"),
               program_name);
      exit (EXIT_FAILURE);
    }

    if (inspector) {
      fprintf (stderr,
               _("%s: --live is not compatible with -i option\n"),
               program_name);
      exit (EXIT_FAILURE);
    }

    /* --live: make sure there was one -d option and no -a options */
    for (drv = drvs; drv; drv = drv->next) {
      if (drv->type == drv_d)
        count_d++;
      else
        count_other++;
    }

    if (count_d != 1) {
      fprintf (stderr,
               _("%s: with --live, you must use exactly one -d option\n"),
               program_name);
      exit (EXIT_FAILURE);
    }

    if (count_other != 0) {
      fprintf (stderr,
               _("%s: --live is not compatible with -a option\n"),
               program_name);
      exit (EXIT_FAILURE);
    }
  }

  /* We'd better have a mountpoint. */
  if (optind+1 != argc) {
    fprintf (stderr,
             _("%s: you must specify a mountpoint in the host filesystem\n"),
             program_name);
    exit (EXIT_FAILURE);
  }

  /* Do the guest drives and mountpoints. */
  add_drives (drvs, 'a');
  if (guestfs_launch (g) == -1)
    exit (EXIT_FAILURE);
  if (inspector)
    inspect_mount ();
  mount_mps (mps);

  free_drives (drvs);
  free_mps (mps);

  /* FUSE example does this, not clear if it's necessary, but ... */
  if (guestfs_umask (g, 0) == -1)
    exit (EXIT_FAILURE);

  /* At the last minute, remove the libguestfs error handler.  In code
   * above this point, the default error handler has been used which
   * sends all errors to stderr.  Now before entering FUSE itself we
   * want to silence errors so we can convert them (see error()
   * function above).
   */
  guestfs_set_error_handler (g, NULL, NULL);

  /* Finish off FUSE args. */
  ADD_FUSE_ARG (argv[optind]);

  /*
    It says about the line containing the for-statement:
    error: assuming signed overflow does not occur when simplifying conditional to constant [-Wstrict-overflow]

  if (verbose) {
    fprintf (stderr, "guestmount: invoking FUSE with args [");
    for (i = 0; i < fuse_argc; ++i) {
      if (i > 0) fprintf (stderr, ", ");
      fprintf (stderr, "%s", fuse_argv[i]);
    }
    fprintf (stderr, "]\n");
  }
  */

  r = fuse_main (fuse_argc, (char **) fuse_argv, &fg_operations, NULL);

  /* Cleanup. */
  guestfs_close (g);
  free_dir_caches ();

  exit (r == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
Ejemplo n.º 11
0
int
run_reopen (const char *cmd, size_t argc, char *argv[])
{
  guestfs_h *g2;
  int r;
  const char *p;
  guestfs_error_handler_cb cb;
  void *cb_data;

  if (argc > 0) {
    fprintf (stderr, _("'reopen' command takes no parameters\n"));
    return -1;
  }

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

  /* Open the new handle first, so we can copy the settings from the
   * old one to the new one, and also so if it fails we still have an
   * open handle.
   */
  g2 = guestfs_create ();
  if (g2 == NULL) {
    fprintf (stderr, _("reopen: guestfs_create: failed to create handle\n"));
    return -1;
  }

  /* Now copy some of the settings from the old handle.  The settings
   * we copy are those which are set by guestfish itself.
   */
  cb = guestfs_get_error_handler (g, &cb_data);
  guestfs_set_error_handler (g2, cb, cb_data);

  r = guestfs_get_verbose (g);
  if (r >= 0)
    guestfs_set_verbose (g2, r);

  r = guestfs_get_trace (g);
  if (r >= 0)
    guestfs_set_trace (g2, r);

  r = guestfs_get_autosync (g);
  if (r >= 0)
    guestfs_set_autosync (g2, r);

  p = guestfs_get_path (g);
  if (p)
    guestfs_set_path (g2, p);

  r = guestfs_get_pgroup (g);
  if (r >= 0)
    guestfs_set_pgroup (g2, r);

  if (progress_bars)
    guestfs_set_event_callback (g2, progress_callback,
                                GUESTFS_EVENT_PROGRESS, 0, NULL);

  /* Close the original handle. */
  guestfs_close (g);
  g = g2;

  /* We don't bother copying event handlers over to the new handle,
   * but we have to reset the list because they were registered
   * against the old handle.
   */
  free_event_handlers ();
  init_event_handlers ();

  return 0;
}