Pino Toscano
2014-Aug-29 14:47 UTC
[Libguestfs] [PATCH 1/2] fish: edit: factor out download and reupload phases
Share some code between edit_file_editor and edit_file_perl; mostly code
motion, with no actual behaviour change.
---
fish/file-edit.c | 143 +++++++++++++++++++++++--------------------------------
1 file changed, 60 insertions(+), 83 deletions(-)
diff --git a/fish/file-edit.c b/fish/file-edit.c
index ff36ac2..74cb89b 100644
--- a/fish/file-edit.c
+++ b/fish/file-edit.c
@@ -35,6 +35,9 @@
#include "guestfs-internal-frontend.h"
+static int do_download (guestfs_h *g, const char *filename, char **tempfile);
+static int do_upload (guestfs_h *g, const char *filename, const char *tempfile,
+ const char *backup_extension);
static char *generate_random_name (const char *filename);
static char *generate_backup_name (const char *filename,
const char *backup_extension);
@@ -43,38 +46,15 @@ int
edit_file_editor (guestfs_h *g, const char *filename, const char *editor,
const char *backup_extension, int verbose)
{
- CLEANUP_FREE char *tmpdir = guestfs_get_tmpdir (g);
CLEANUP_UNLINK_FREE char *tmpfilename = NULL;
- char buf[256];
- CLEANUP_FREE char *newname = NULL;
CLEANUP_FREE char *cmd = NULL;
struct stat oldstat, newstat;
- int r, fd;
+ int r;
struct utimbuf times;
/* 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);
+ if (do_download (g, filename, &tmpfilename) == -1)
return -1;
- }
-
- if (close (fd) == -1) {
- perror (tmpfilename);
- return -1;
- }
/* Set the time back a few seconds on the original file. This is so
* that if the user is very fast at editing, or if EDITOR is an
@@ -125,38 +105,7 @@ edit_file_editor (guestfs_h *g, const char *filename, const
char *editor,
oldstat.st_size == newstat.st_size)
return 1;
- /* 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;
-
- /* Backup or overwrite the file. */
- if (backup_extension) {
- CLEANUP_FREE char *backupname = NULL;
-
- backupname = generate_backup_name (filename, backup_extension);
- if (backupname == NULL)
- return -1;
-
- if (guestfs_mv (g, filename, backupname) == -1)
- return -1;
- }
- if (guestfs_mv (g, newname, filename) == -1)
+ if (do_upload (g, filename, tmpfilename, backup_extension) == -1)
return -1;
return 0;
@@ -166,37 +115,14 @@ int
edit_file_perl (guestfs_h *g, const char *filename, const char *perl_expr,
const char *backup_extension, int verbose)
{
- CLEANUP_FREE char *tmpdir = guestfs_get_tmpdir (g);
CLEANUP_UNLINK_FREE char *tmpfilename = NULL;
- char buf[256];
- CLEANUP_FREE char *newname = NULL;
CLEANUP_FREE char *cmd = NULL;
CLEANUP_FREE char *outfile = NULL;
- int r, fd;
+ int r;
/* Download the file and write it to a temporary. */
- if (asprintf (&tmpfilename, "%s/libguestfsXXXXXX", tmpdir) ==
-1) {
- perror ("asprintf");
+ if (do_download (g, filename, &tmpfilename) == -1)
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;
- }
if (asprintf (&outfile, "%s.out", tmpfilename) == -1) {
perror ("asprintf");
@@ -238,6 +164,57 @@ edit_file_perl (guestfs_h *g, const char *filename, const
char *perl_expr,
return -1;
}
+ if (do_upload (g, filename, tmpfilename, backup_extension) == -1)
+ return -1;
+
+ return 0;
+}
+
+static int
+do_download (guestfs_h *g, const char *filename, char **tempfile)
+{
+ CLEANUP_FREE char *tmpdir = guestfs_get_tmpdir (g);
+ CLEANUP_UNLINK_FREE char *tmpfilename = NULL;
+ char buf[256];
+ int 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;
+ }
+
+ /* Hand over the temporary file. */
+ *tempfile = tmpfilename;
+ tmpfilename = NULL;
+
+ return 0;
+}
+
+static int
+do_upload (guestfs_h *g, const char *filename, const char *tempfile,
+ const char *backup_extension)
+{
+ CLEANUP_FREE char *newname = NULL;
+
/* 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
@@ -248,7 +225,7 @@ edit_file_perl (guestfs_h *g, const char *filename, const
char *perl_expr,
return -1;
/* Write new content. */
- if (guestfs_upload (g, tmpfilename, newname) == -1)
+ if (guestfs_upload (g, tempfile, newname) == -1)
return -1;
/* Set the permissions, UID, GID and SELinux context of the new
--
1.9.3
Pino Toscano
2014-Aug-29 14:47 UTC
[Libguestfs] [PATCH 2/2] fish: edit: centralize the EDITOR handling
Allow null as value for the editor parameter of edit_file_editor, which
will then get it from the EDITOR envvar (falling back on vi).
This is basically code motion from the two edit_file_editor users to it.
---
edit/edit.c | 12 +++---------
fish/edit.c | 7 ++-----
fish/file-edit.c | 6 ++++++
fish/file-edit.h | 3 +++
4 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/edit/edit.c b/edit/edit.c
index f1c3b91..821f280 100644
--- a/edit/edit.c
+++ b/edit/edit.c
@@ -333,15 +333,9 @@ edit (const char *filename, const char *root)
if (perl_expr != NULL) {
r = edit_file_perl (g, filename, perl_expr, backup_extension, verbose);
- } else {
- const char *editor;
-
- editor = getenv ("EDITOR");
- if (editor == NULL)
- editor = "vi";
-
- r = edit_file_editor (g, filename, editor, backup_extension, verbose);
- }
+ } else
+ r = edit_file_editor (g, filename, NULL /* use $EDITOR */,
+ backup_extension, verbose);
switch (r) {
case -1:
diff --git a/fish/edit.c b/fish/edit.c
index 0f41a88..013306e 100644
--- a/fish/edit.c
+++ b/fish/edit.c
@@ -47,11 +47,8 @@ run_edit (const char *cmd, size_t argc, char *argv[])
editor = "vi";
else if (STRCASEEQ (cmd, "emacs"))
editor = "emacs -nw";
- else {
- editor = getenv ("EDITOR");
- if (editor == NULL)
- editor = "vi"; /* could be cruel here and choose ed(1) */
- }
+ else
+ editor = NULL; /* use $EDITOR */
/* Handle 'win:...' prefix. */
remotefilename = win_prefix (argv[0]);
diff --git a/fish/file-edit.c b/fish/file-edit.c
index 74cb89b..e6d25f5 100644
--- a/fish/file-edit.c
+++ b/fish/file-edit.c
@@ -52,6 +52,12 @@ edit_file_editor (guestfs_h *g, const char *filename, const
char *editor,
int r;
struct utimbuf times;
+ if (editor == NULL) {
+ editor = getenv ("EDITOR");
+ if (editor == NULL)
+ editor = "vi";
+ }
+
/* Download the file and write it to a temporary. */
if (do_download (g, filename, &tmpfilename) == -1)
return -1;
diff --git a/fish/file-edit.h b/fish/file-edit.h
index 3f8b95e..1635254 100644
--- a/fish/file-edit.h
+++ b/fish/file-edit.h
@@ -25,6 +25,9 @@
* Edit 'filename' using the specified 'editor' application.
* If 'backup_extension' is not null, then a copy of 'filename'
is saved
* with 'backup_extension' appended to its file name.
+ * If 'editor' is null, then the EDITOR environment variable
+ * will be queried for the editor application, leaving "vi" as
fallback
+ * if not set.
*
* Returns -1 for failure, 0 on success, 1 if the editor did not change
* the file (e.g. the user closed the editor without saving).
--
1.9.3
Richard W.M. Jones
2014-Sep-01 08:06 UTC
[Libguestfs] [PATCH 1/2] fish: edit: factor out download and reupload phases
ACK series. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-top is 'top' for virtual machines. Tiny program with many powerful monitoring features, net stats, disk stats, logging, etc. http://people.redhat.com/~rjones/virt-top