summaryrefslogtreecommitdiffstats
path: root/fish/edit.c
diff options
context:
space:
mode:
authorRichard W.M. Jones <[email protected]>2012-02-10 10:12:45 +0000
committerRichard W.M. Jones <[email protected]>2012-02-10 11:27:13 +0000
commitddae5abf80f65fc149eec253f14f073d397b49c2 (patch)
tree1fb3f7e40c31592d34a5c18c7cbb37b76e24cd6c /fish/edit.c
parentca80e4490463d646de4504fc2bcb4e4a722bedb8 (diff)
downloadlibguestfs-ddae5abf80f65fc149eec253f14f073d397b49c2.tar.gz
libguestfs-ddae5abf80f65fc149eec253f14f073d397b49c2.tar.xz
libguestfs-ddae5abf80f65fc149eec253f14f073d397b49c2.zip
fish: In edit command, upload to a new file.
If the upload fails, this means we don't leave a partially written file. Also add a test for the edit command.
Diffstat (limited to 'fish/edit.c')
-rw-r--r--fish/edit.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/fish/edit.c b/fish/edit.c
index e0204b0b..908a3a3a 100644
--- a/fish/edit.c
+++ b/fish/edit.c
@@ -26,9 +26,12 @@
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <assert.h>
#include "fish.h"
+static char *generate_random_name (const char *filename);
+
/* guestfish edit command, suggested by Ján Ondrej, implemented by RWMJ */
int
@@ -37,7 +40,7 @@ run_edit (const char *cmd, size_t argc, char *argv[])
TMP_TEMPLATE_ON_STACK (filename);
char buf[256];
const char *editor;
- char *remotefilename;
+ char *remotefilename, *newname;
struct stat oldstat, newstat;
int r, fd;
@@ -111,14 +114,29 @@ run_edit (const char *cmd, size_t argc, char *argv[])
return 0;
}
- /* Write new content. */
- if (guestfs_upload (g, filename, remotefilename) == -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 (remotefilename);
+ if (!newname)
goto error2;
+ /* Write new content. */
+ if (guestfs_upload (g, filename, newname) == -1)
+ goto error3;
+
+ if (guestfs_mv (g, newname, remotefilename) == -1)
+ goto error3;
+
+ free (newname);
unlink (filename);
free (remotefilename);
return 0;
+ error3:
+ free (newname);
error2:
unlink (filename);
error1:
@@ -126,3 +144,37 @@ run_edit (const char *cmd, size_t argc, char *argv[])
error0:
return -1;
}
+
+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';
+
+ return ret; /* caller will free */
+}
OSZAR »