[PATCH-resend] Implement SSH2_FXF_APPEND

Ross Lagerwall rosslagerwall at gmail.com
Tue Oct 15 07:52:42 EST 2013


Hi,

I submitted this a few weeks ago but here it is again since I got no
response.  If there is somewhere else I should send this, please tell
me.

This patch implements SSH2_FXF_APPEND in the sftp server.  It is a
fairly trivial patch and applies against the proper OpenSSH and the
Portable edition.  I would argue that it is important for OpenSSH to
implement SSH2_FXF_APPEND since it is in the spec and clients who expect
it to work find that their files are overwritten rather than appended
to.

I opened a bug for it:
https://bugzilla.mindrot.org/show_bug.cgi?id=2159

Some relevant links:
http://marc.info/?l=openssh-unix-dev&m=138053388830753&w=2
http://marc.info/?l=openssh-unix-dev&m=123798287811788
http://marc.info/?l=openssh-unix-dev&m=111093206900604
https://bugzilla.gnome.org/show_bug.cgi?id=608910

Thanks
-- 
Ross Lagerwall
-------------- next part --------------
Index: sftp-server.c
===================================================================
RCS file: /cvs/openssh/sftp-server.c,v
retrieving revision 1.114
diff -u -p -r1.114 sftp-server.c
--- sftp-server.c	1 Jun 2013 21:31:19 -0000	1.114
+++ sftp-server.c	30 Sep 2013 08:16:57 -0000
@@ -130,6 +130,8 @@ flags_from_portable(int pflags)
 	} else if (pflags & SSH2_FXF_WRITE) {
 		flags = O_WRONLY;
 	}
+	if (pflags & SSH2_FXF_APPEND)
+		flags |= O_APPEND;
 	if (pflags & SSH2_FXF_CREAT)
 		flags |= O_CREAT;
 	if (pflags & SSH2_FXF_TRUNC)
@@ -156,6 +158,8 @@ string_from_portable(int pflags)
 		PAPPEND("READ")
 	if (pflags & SSH2_FXF_WRITE)
 		PAPPEND("WRITE")
+	if (pflags & SSH2_FXF_APPEND)
+		PAPPEND("APPEND")
 	if (pflags & SSH2_FXF_CREAT)
 		PAPPEND("CREATE")
 	if (pflags & SSH2_FXF_TRUNC)
@@ -179,6 +183,7 @@ struct Handle {
 	int use;
 	DIR *dirp;
 	int fd;
+	int flags;
 	char *name;
 	u_int64_t bytes_read, bytes_write;
 	int next_unused;
@@ -202,7 +207,7 @@ static void handle_unused(int i)
 }
 
 static int
-handle_new(int use, const char *name, int fd, DIR *dirp)
+handle_new(int use, const char *name, int fd, int flags, DIR *dirp)
 {
 	int i;
 
@@ -220,6 +225,7 @@ handle_new(int use, const char *name, in
 	handles[i].use = use;
 	handles[i].dirp = dirp;
 	handles[i].fd = fd;
+	handles[i].flags = flags;
 	handles[i].name = xstrdup(name);
 	handles[i].bytes_read = handles[i].bytes_write = 0;
 
@@ -282,6 +288,14 @@ handle_to_fd(int handle)
 	return -1;
 }
 
+static int
+handle_to_flags(int handle)
+{
+	if (handle_is_ok(handle, HANDLE_FILE))
+		return handles[handle].flags;
+	return -1;
+}
+
 static void
 handle_update_read(int handle, ssize_t bytes)
 {
@@ -567,7 +581,7 @@ process_open(void)
 		if (fd < 0) {
 			status = errno_to_portable(errno);
 		} else {
-			handle = handle_new(HANDLE_FILE, name, fd, NULL);
+			handle = handle_new(HANDLE_FILE, name, fd, flags, NULL);
 			if (handle < 0) {
 				close(fd);
 			} else {
@@ -660,7 +674,8 @@ process_write(void)
 	else if (readonly)
 		status = SSH2_FX_PERMISSION_DENIED;
 	else {
-		if (lseek(fd, off, SEEK_SET) < 0) {
+		if (!(handle_to_flags(handle) & O_APPEND) &&
+				lseek(fd, off, SEEK_SET) < 0) {
 			status = errno_to_portable(errno);
 			error("process_write: seek failed");
 		} else {
@@ -893,7 +908,7 @@ process_opendir(void)
 	if (dirp == NULL) {
 		status = errno_to_portable(errno);
 	} else {
-		handle = handle_new(HANDLE_DIR, path, 0, dirp);
+		handle = handle_new(HANDLE_DIR, path, 0, 0, dirp);
 		if (handle < 0) {
 			closedir(dirp);
 		} else {


More information about the openssh-unix-dev mailing list