Esempio n. 1
0
static void
edit (const char *filename, const char *root)
{
  CLEANUP_FREE char *filename_to_free = NULL;
  int r;

  /* Windows?  Special handling is required. */
  if (root != NULL && is_windows (g, root)) {
    filename = filename_to_free = windows_path (g, root, filename,
                                                0 /* not read only */);
    if (filename == NULL)
      exit (EXIT_FAILURE);
  }

  if (perl_expr != NULL) {
    r = edit_file_perl (g, filename, perl_expr, backup_extension, verbose);
  } else
    r = edit_file_editor (g, filename, NULL /* use $EDITOR */,
                          backup_extension, verbose);

  switch (r) {
  case -1:
    exit (EXIT_FAILURE);
  case 1:
    printf ("File not changed.\n");
    break;
  default:
    /* Success. */
    break;
  }
}
Esempio n. 2
0
static void
edit (const char *filename, const char *root)
{
  char *filename_to_free = NULL;
  const char *tmpdir = guestfs_tmpdir ();
  char tmpfile[strlen (tmpdir) + 32];
  sprintf (tmpfile, "%s/virteditXXXXXX", tmpdir);
  int fd;
  char fdbuf[32];
  char *upload_from = NULL;
  char *newname = NULL;
  char *backupname = NULL;

  /* Windows?  Special handling is required. */
  if (is_windows (g, root))
    filename = filename_to_free = windows_path (g, root, filename);

  /* Download the file to a temporary. */
  fd = mkstemp (tmpfile);
  if (fd == -1) {
    perror ("mkstemp");
    exit (EXIT_FAILURE);
  }

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

  if (guestfs_download (g, filename, fdbuf) == -1)
    goto error;

  if (close (fd) == -1) {
    perror (tmpfile);
    goto error;
  }

  if (!perl_expr)
    upload_from = edit_interactively (tmpfile);
  else
    upload_from = edit_non_interactively (tmpfile);

  /* We don't always need to upload: upload_from could be NULL because
   * the user closed the editor without changing the file.
   */
  if (upload_from) {
    /* Upload to a new file in the same directory, so if it fails we
     * don't end up with a partially written file.  Give the new file
     * a completely random name so we have only a tiny chance of
     * overwriting some existing file.
     */
    newname = generate_random_name (filename);

    if (guestfs_upload (g, upload_from, newname) == -1)
      goto error;

    /* Backup or overwrite the file. */
    if (backup_extension) {
      backupname = generate_backup_name (filename);
      if (guestfs_mv (g, filename, backupname) == -1)
        goto error;
    }
    if (guestfs_mv (g, newname, filename) == -1)
      goto error;
  }

  unlink (tmpfile);
  free (filename_to_free);
  free (upload_from);
  free (newname);
  free (backupname);
  return;

 error:
  unlink (tmpfile);
  exit (EXIT_FAILURE);
}
Esempio n. 3
0
int
main (int argc, char *argv[])
{
  /* Set global program name that is not polluted with libtool artifacts.  */
  set_program_name (argv[0]);

  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEBASEDIR);
  textdomain (PACKAGE);

  enum { HELP_OPTION = CHAR_MAX + 1 };

  static const char *options = "a:c:d:vVx";
  static const struct option long_options[] = {
    { "add", 1, 0, 'a' },
    { "connect", 1, 0, 'c' },
    { "domain", 1, 0, 'd' },
    { "echo-keys", 0, 0, 0 },
    { "format", 2, 0, 0 },
    { "help", 0, 0, HELP_OPTION },
    { "keys-from-stdin", 0, 0, 0 },
    { "verbose", 0, 0, 'v' },
    { "version", 0, 0, 'V' },
    { 0, 0, 0, 0 }
  };
  struct drv *drvs = NULL;
  struct drv *drv;
  const char *format = NULL;
  int c;
  int option_index;

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

  argv[0] = bad_cast (program_name);

  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, "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, "format")) {
        if (!optarg || STREQ (optarg, ""))
          format = NULL;
        else
          format = optarg;
      } 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 'v':
      OPTION_v;
      break;

    case 'V':
      OPTION_V;
      break;

    case 'x':
      OPTION_x;
      break;

    case HELP_OPTION:
      usage (EXIT_SUCCESS);

    default:
      usage (EXIT_FAILURE);
    }
  }

  /* Old-style syntax?  There were no -a or -d options in the old
   * virt-cat which is how we detect this.
   */
  if (drvs == NULL) {
    /* argc - 1 because last parameter is the single filename. */
    while (optind < argc - 1) {
      if (strchr (argv[optind], '/') ||
          access (argv[optind], F_OK) == 0) { /* simulate -a option */
        drv = calloc (1, sizeof (struct drv));
        if (!drv) {
          perror ("malloc");
          exit (EXIT_FAILURE);
        }
        drv->type = drv_a;
        drv->a.filename = argv[optind];
        drv->next = drvs;
        drvs = drv;
      } else {                  /* simulate -d option */
        drv = calloc (1, sizeof (struct drv));
        if (!drv) {
          perror ("malloc");
          exit (EXIT_FAILURE);
        }
        drv->type = drv_d;
        drv->d.guest = argv[optind];
        drv->next = drvs;
        drvs = drv;
      }

      optind++;
    }
  }

  /* These are really constants, but they have to be variables for the
   * options parsing code.  Assert here that they have known-good
   * values.
   */
  assert (read_only == 1);
  assert (inspector == 1);
  assert (live == 0);

  /* User must specify at least one filename on the command line. */
  if (optind >= argc || argc - optind < 1)
    usage (EXIT_FAILURE);

  /* User must have specified some drives. */
  if (drvs == NULL)
    usage (EXIT_FAILURE);

  /* Add drives, inspect and mount.  Note that inspector is always true,
   * and there is no -m option.
   */
  add_drives (drvs, 'a');

  if (guestfs_launch (g) == -1)
    exit (EXIT_FAILURE);

  inspect_mount ();

  /* Free up data structures, no longer needed after this point. */
  free_drives (drvs);

  unsigned errors = 0;
  int windows;
  char *root, **roots;

  /* Get root mountpoint.  See: fish/inspect.c:inspect_mount */
  roots = guestfs_inspect_get_roots (g);
  assert (roots);
  assert (roots[0] != NULL);
  assert (roots[1] == NULL);
  root = roots[0];
  free (roots);

  /* Windows?  Special handling is required. */
  windows = is_windows (g, root);

  for (; optind < argc; optind++) {
    char *filename_to_free = NULL;
    const char *filename = argv[optind];

    if (windows) {
      filename = filename_to_free = windows_path (g, root, filename);
      if (filename == NULL) {
        errors++;
        continue;
      }
    }

    if (guestfs_download (g, filename, "/dev/stdout") == -1)
      errors++;

    free (filename_to_free);
  }

  free (root);

  guestfs_close (g);

  exit (errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}