diff --git a/fish/file-edit.c b/fish/file-edit.c index e6d25f5ab..dd2272bba 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 34bfc9dc3..9d7ab9d7b 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