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