Pino Toscano
2014-Sep-01  09:54 UTC
[Libguestfs] [PATCH] fish: edit: write to the real file name
When saving, resolve the path of the file being edited and use that as
real target to write to. Otherwise, if the file name is a symlink then
it will be replaced by a regular file with the new content, leaving the
old file untouched.
Extend test-edit.sh to check for this situation.
---
 fish/file-edit.c  | 15 ++++++++++++++-
 fish/test-edit.sh | 12 +++++++++++-
 2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/fish/file-edit.c b/fish/file-edit.c
index e6d25f5..dd2272b 100644
--- a/fish/file-edit.c
+++ b/fish/file-edit.c
@@ -216,11 +216,24 @@ do_download (guestfs_h *g, const char *filename, char
**tempfile)
 }
 
 static int
-do_upload (guestfs_h *g, const char *filename, const char *tempfile,
+do_upload (guestfs_h *g, const char *fn, const char *tempfile,
            const char *backup_extension)
 {
+  CLEANUP_FREE char *filename = NULL;
   CLEANUP_FREE char *newname = NULL;
 
+  /* Resolve the file name and write to the actual target, since
+   * that is the file it was opened earlier; otherwise, if it is
+   * a symlink it will be overwritten by a regular file with the
+   * new content.
+   *
+   * Theoretically realpath should work, but just check again
+   * to be safe.
+   */
+  filename = guestfs_realpath (g, fn);
+  if (filename == NULL)
+    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
diff --git a/fish/test-edit.sh b/fish/test-edit.sh
index 34bfc9d..9d7ab9d 100755
--- a/fish/test-edit.sh
+++ b/fish/test-edit.sh
@@ -43,6 +43,12 @@ cat /file.txt
 stat /file.txt | grep mode:
 stat /file.txt | grep uid:
 stat /file.txt | grep gid:
+echo =========+write /file-2.txt "symlink test\n"
+ln-s /file-2.txt /symlink-2.txt
+edit /symlink-2.txt
+is-symlink /symlink-2.txt
+cat /symlink-2.txt
 EOF
 )
 
@@ -51,7 +57,11 @@ second line of text
 
 mode: 33152
 uid: 10
-gid: 11" ]; then
+gid: 11
+=========+true
+symlink test
+second line of text" ]; then
     echo "$0: error: output of guestfish after edit command did not match
expected output"
     echo "$output"
     exit 1
-- 
1.9.3
Richard W.M. Jones
2014-Sep-01  11:21 UTC
[Libguestfs] [PATCH] fish: edit: write to the real file name
On Mon, Sep 01, 2014 at 11:54:08AM +0200, Pino Toscano wrote:> When saving, resolve the path of the file being edited and use that as > real target to write to. Otherwise, if the file name is a symlink then > it will be replaced by a regular file with the new content, leaving the > old file untouched. > > Extend test-edit.sh to check for this situation. > --- > fish/file-edit.c | 15 ++++++++++++++- > fish/test-edit.sh | 12 +++++++++++- > 2 files changed, 25 insertions(+), 2 deletions(-) > > diff --git a/fish/file-edit.c b/fish/file-edit.c > index e6d25f5..dd2272b 100644 > --- a/fish/file-edit.c > +++ b/fish/file-edit.c > @@ -216,11 +216,24 @@ do_download (guestfs_h *g, const char *filename, char **tempfile) > } > > static int > -do_upload (guestfs_h *g, const char *filename, const char *tempfile, > +do_upload (guestfs_h *g, const char *fn, const char *tempfile, > const char *backup_extension) > { > + CLEANUP_FREE char *filename = NULL; > CLEANUP_FREE char *newname = NULL; > > + /* Resolve the file name and write to the actual target, since > + * that is the file it was opened earlier; otherwise, if it is > + * a symlink it will be overwritten by a regular file with the > + * new content. > + * > + * Theoretically realpath should work, but just check again > + * to be safe. > + */ > + filename = guestfs_realpath (g, fn); > + if (filename == NULL) > + 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 > diff --git a/fish/test-edit.sh b/fish/test-edit.sh > index 34bfc9d..9d7ab9d 100755 > --- a/fish/test-edit.sh > +++ b/fish/test-edit.sh > @@ -43,6 +43,12 @@ cat /file.txt > stat /file.txt | grep mode: > stat /file.txt | grep uid: > stat /file.txt | grep gid: > +echo =========> +write /file-2.txt "symlink test\n" > +ln-s /file-2.txt /symlink-2.txt > +edit /symlink-2.txt > +is-symlink /symlink-2.txt > +cat /symlink-2.txt > EOF > ) > > @@ -51,7 +57,11 @@ second line of text > > mode: 33152 > uid: 10 > -gid: 11" ]; then > +gid: 11 > +=========> +true > +symlink test > +second line of text" ]; then > echo "$0: error: output of guestfish after edit command did not match expected output" > echo "$output" > exit 1 > -- > 1.9.3ACK. 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