[Libguestfs] [PATCH 05/13] fish: isolate file editing (w/ editor) code in own file

Pino Toscano ptoscano at redhat.com
Thu Aug 28 13:21:08 UTC 2014


Move the implementation of file editing using editor to an own file, so
that can be shared by different tools.

Mostly code motion.
---
 fish/Makefile.am |   2 +
 fish/edit.c      | 125 ++-----------------------------------------
 fish/file-edit.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fish/file-edit.h |  32 +++++++++++
 po/POTFILES      |   1 +
 5 files changed, 198 insertions(+), 120 deletions(-)
 create mode 100644 fish/file-edit.c
 create mode 100644 fish/file-edit.h

diff --git a/fish/Makefile.am b/fish/Makefile.am
index c02f703..d28a94b 100644
--- a/fish/Makefile.am
+++ b/fish/Makefile.am
@@ -87,6 +87,8 @@ guestfish_SOURCES = \
 	echo.c \
 	edit.c \
 	events.c \
+	file-edit.c \
+	file-edit.h \
 	fish.c \
 	fish.h \
 	glob.c \
diff --git a/fish/edit.c b/fish/edit.c
index bd02f4b..5b851e7 100644
--- a/fish/edit.c
+++ b/fish/edit.c
@@ -22,29 +22,20 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include <fcntl.h>
 #include <inttypes.h>
 #include <libintl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <assert.h>
 
 #include "fish.h"
-
-static char *generate_random_name (const char *filename);
+#include "file-edit.h"
 
 /* guestfish edit command, suggested by Ján Ondrej, implemented by RWMJ */
 
 int
 run_edit (const char *cmd, size_t argc, char *argv[])
 {
-  CLEANUP_FREE char *tmpdir = guestfs_get_tmpdir (g);
-  CLEANUP_UNLINK_FREE char *filename = NULL;
-  char buf[256];
   const char *editor;
-  CLEANUP_FREE char *remotefilename = NULL, *newname = NULL;
-  struct stat oldstat, newstat;
-  int r, fd;
+  CLEANUP_FREE char *remotefilename = NULL;
+  int r;
 
   if (argc != 1) {
     fprintf (stderr, _("use '%s filename' to edit a file\n"), cmd);
@@ -67,113 +58,7 @@ run_edit (const char *cmd, size_t argc, char *argv[])
   if (remotefilename == NULL)
     return -1;
 
-  /* Download the file and write it to a temporary. */
-  if (asprintf (&filename, "%s/guestfishXXXXXX", tmpdir) == -1) {
-    perror ("asprintf");
-    return -1;
-  }
-
-  fd = mkstemp (filename);
-  if (fd == -1) {
-    perror ("mkstemp");
-    return -1;
-  }
-
-  snprintf (buf, sizeof buf, "/dev/fd/%d", fd);
-
-  if (guestfs_download (g, remotefilename, buf) == -1) {
-    close (fd);
-    return -1;
-  }
-
-  if (close (fd) == -1) {
-    perror (filename);
-    return -1;
-  }
-
-  /* Get the old stat. */
-  if (stat (filename, &oldstat) == -1) {
-    perror (filename);
-    return -1;
-  }
-
-  /* Edit it. */
-  /* XXX Safe? */
-  snprintf (buf, sizeof buf, "%s %s", editor, filename);
-
-  r = system (buf);
-  if (r != 0) {
-    perror (buf);
-    return -1;
-  }
-
-  /* Get the new stat. */
-  if (stat (filename, &newstat) == -1) {
-    perror (filename);
-    return -1;
-  }
-
-  /* Changed? */
-  if (oldstat.st_ctime == newstat.st_ctime &&
-      oldstat.st_size == newstat.st_size)
-    return 0;
-
-  /* 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 (remotefilename);
-  if (!newname)
-    return -1;
-
-  /* Write new content. */
-  if (guestfs_upload (g, filename, newname) == -1)
-    return -1;
-
-  /* Set the permissions, UID, GID and SELinux context of the new
-   * file to match the old file (RHBZ#788641).
-   */
-  if (guestfs_copy_attributes (g, remotefilename, newname,
-      GUESTFS_COPY_ATTRIBUTES_ALL, 1, -1) == -1)
-    return -1;
-
-  if (guestfs_mv (g, newname, remotefilename) == -1)
-    return -1;
-
-  return 0;
-}
-
-static char
-random_char (void)
-{
-  char c[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-  return c[random () % (sizeof c - 1)];
-}
-
-static char *
-generate_random_name (const char *filename)
-{
-  char *ret, *p;
-  size_t i;
-
-  ret = malloc (strlen (filename) + 16);
-  if (!ret) {
-    perror ("malloc");
-    return NULL;
-  }
-  strcpy (ret, filename);
-
-  p = strrchr (ret, '/');
-  assert (p);
-  p++;
-
-  /* Because of "+ 16" above, there should be enough space in the
-   * output buffer to write 8 random characters here.
-   */
-  for (i = 0; i < 8; ++i)
-    *p++ = random_char ();
-  *p++ = '\0';
+  r = edit_file_editor (g, remotefilename, editor);
 
-  return ret; /* caller will free */
+  return r;
 }
diff --git a/fish/file-edit.c b/fish/file-edit.c
new file mode 100644
index 0000000..ec707a9
--- /dev/null
+++ b/fish/file-edit.c
@@ -0,0 +1,158 @@
+/* libguestfs - shared file editing
+ * Copyright (C) 2009-2014 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include "file-edit.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <locale.h>
+#include <langinfo.h>
+#include <libintl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <assert.h>
+
+#include "guestfs-internal-frontend.h"
+
+static char *generate_random_name (const char *filename);
+
+int
+edit_file_editor (guestfs_h *g, const char *filename, const char *editor)
+{
+  CLEANUP_FREE char *tmpdir = guestfs_get_tmpdir (g);
+  CLEANUP_UNLINK_FREE char *tmpfilename = NULL;
+  char buf[256];
+  CLEANUP_FREE char *newname = NULL;
+  struct stat oldstat, newstat;
+  int r, fd;
+
+  /* Download the file and write it to a temporary. */
+  if (asprintf (&tmpfilename, "%s/libguestfsXXXXXX", tmpdir) == -1) {
+    perror ("asprintf");
+    return -1;
+  }
+
+  fd = mkstemp (tmpfilename);
+  if (fd == -1) {
+    perror ("mkstemp");
+    return -1;
+  }
+
+  snprintf (buf, sizeof buf, "/dev/fd/%d", fd);
+
+  if (guestfs_download (g, filename, buf) == -1) {
+    close (fd);
+    return -1;
+  }
+
+  if (close (fd) == -1) {
+    perror (tmpfilename);
+    return -1;
+  }
+
+  /* Get the old stat. */
+  if (stat (tmpfilename, &oldstat) == -1) {
+    perror (tmpfilename);
+    return -1;
+  }
+
+  /* Edit it. */
+  /* XXX Safe? */
+  snprintf (buf, sizeof buf, "%s %s", editor, filename);
+
+  r = system (buf);
+  if (r != 0) {
+    perror (buf);
+    return -1;
+  }
+
+  /* Get the new stat. */
+  if (stat (tmpfilename, &newstat) == -1) {
+    perror (tmpfilename);
+    return -1;
+  }
+
+  /* Changed? */
+  if (oldstat.st_ctime == newstat.st_ctime &&
+      oldstat.st_size == newstat.st_size)
+    return 0;
+
+  /* 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 (!newname)
+    return -1;
+
+  /* Write new content. */
+  if (guestfs_upload (g, tmpfilename, newname) == -1)
+    return -1;
+
+  /* Set the permissions, UID, GID and SELinux context of the new
+   * file to match the old file (RHBZ#788641).
+   */
+  if (guestfs_copy_attributes (g, filename, newname,
+      GUESTFS_COPY_ATTRIBUTES_ALL, 1, -1) == -1)
+    return -1;
+
+  if (guestfs_mv (g, newname, filename) == -1)
+    return -1;
+
+  return 0;
+}
+
+static char
+random_char (void)
+{
+  const char c[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+  return c[random () % (sizeof c - 1)];
+}
+
+static char *
+generate_random_name (const char *filename)
+{
+  char *ret, *p;
+  size_t i;
+
+  ret = malloc (strlen (filename) + 16);
+  if (!ret) {
+    perror ("malloc");
+    return NULL;
+  }
+  strcpy (ret, filename);
+
+  p = strrchr (ret, '/');
+  assert (p);
+  p++;
+
+  /* Because of "+ 16" above, there should be enough space in the
+   * output buffer to write 8 random characters here.
+   */
+  for (i = 0; i < 8; ++i)
+    *p++ = random_char ();
+  *p++ = '\0';
+
+  return ret; /* caller will free */
+}
diff --git a/fish/file-edit.h b/fish/file-edit.h
new file mode 100644
index 0000000..eff1c7d
--- /dev/null
+++ b/fish/file-edit.h
@@ -0,0 +1,32 @@
+/* libguestfs - shared file editing
+ * Copyright (C) 2009-2014 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef FISH_FILE_EDIT_H
+#define FISH_FILE_EDIT_H
+
+#include <guestfs.h>
+
+/**
+ * Edit 'filename' using the specified 'editor' application.
+ *
+ * Returns -1 for failure, 0 otherwise.
+ */
+extern int edit_file_editor (guestfs_h *g, const char *filename,
+                             const char *editor);
+
+#endif
diff --git a/po/POTFILES b/po/POTFILES
index d40cf9b..a31cc88 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -135,6 +135,7 @@ fish/echo.c
 fish/edit.c
 fish/event-names.c
 fish/events.c
+fish/file-edit.c
 fish/fish.c
 fish/glob.c
 fish/help.c
-- 
1.9.3




More information about the Libguestfs mailing list