[PATCH] Link count attribute extension

Rian Hunter rian at thelig.ht
Thu Jun 2 12:17:55 AEST 2016


Hello,

This patch adds client and server support for transmitting the st_nlink field
across SSH2_FXP_NAME and SSH2_FXP_ATTRS responses.

Please let me know if there anything I can do to improve this patch. I am
not subscribed to list so please CC me.

Index: sftp-common.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/sftp-common.c,v
retrieving revision 1.28
diff -u -r1.28 sftp-common.c
--- sftp-common.c	20 Jan 2015 23:14:00 -0000	1.28
+++ sftp-common.c	2 Jun 2016 01:32:02 -0000
@@ -56,6 +56,8 @@
 	a->perm = 0;
 	a->atime = 0;
 	a->mtime = 0;
+	a->has_nlink = 0;
+	a->nlink = 0;
 }
 
 /* Convert from struct stat to filexfer attribs */
@@ -74,6 +76,9 @@
 	a->flags |= SSH2_FILEXFER_ATTR_ACMODTIME;
 	a->atime = st->st_atime;
 	a->mtime = st->st_mtime;
+	a->flags |= SSH2_FILEXFER_ATTR_EXTENDED;
+	a->has_nlink = 1;
+	a->nlink = st->st_nlink;
 }
 
 /* Convert from filexfer attribs to struct stat */
@@ -94,6 +99,11 @@
 		st->st_atime = a->atime;
 		st->st_mtime = a->mtime;
 	}
+	if (a->flags & SSH2_FILEXFER_ATTR_EXTENDED) {
+		if (a->has_nlink) {
+			st->st_nlink = a->nlink;
+		}
+	}
 }
 
 /* Decode attributes in buffer */
@@ -138,6 +148,15 @@
 				return r;
 			debug3("Got file attribute \"%.100s\" len %zu",
 			    type, dlen);
+			if (strcmp(type, SFTP_EXT_ATTR_LINK_COUNT) == 0) {
+				if (dlen < 8) {
+					return SSH_ERR_MESSAGE_INCOMPLETE;
+					free(type);
+					free(data);
+				}
+				a->has_nlink = 1;
+				a->nlink = PEEK_U64(data);
+			}
 			free(type);
 			free(data);
 		}
@@ -170,6 +189,24 @@
 		if ((r = sshbuf_put_u32(b, a->atime)) != 0 ||
 		    (r = sshbuf_put_u32(b, a->mtime)) != 0)
 			return r;
+	}
+	if (a->flags & SSH2_FILEXFER_ATTR_EXTENDED) {
+		u_int32_t count = 0;
+		if (a->has_nlink) {
+			count += 1;
+		}
+
+		if (count) {
+			if ((r = sshbuf_put_u32(b, count)) != 0)
+				return r;
+
+			if (a->has_nlink) {
+				if ((r = sshbuf_put_cstring(b, SFTP_EXT_ATTR_LINK_COUNT)) != 0 ||
+				    (r = sshbuf_put_u32(b, 8)) != 0 ||
+				    (r = sshbuf_put_u64(b, a->nlink)))
+					return r;
+			}
+		}
 	}
 	return 0;
 }
Index: sftp-common.h
===================================================================
RCS file: /cvs/src/usr.bin/ssh/sftp-common.h,v
retrieving revision 1.12
diff -u -r1.12 sftp-common.h
--- sftp-common.h	14 Jan 2015 13:54:13 -0000	1.12
+++ sftp-common.h	2 Jun 2016 01:32:02 -0000
@@ -40,6 +40,8 @@
 	u_int32_t	perm;
 	u_int32_t	atime;
 	u_int32_t	mtime;
+	u_int32_t	has_nlink;
+	u_int64_t	nlink;
 };
 
 void	 attrib_clear(Attrib *);
@@ -50,3 +52,5 @@
 char	*ls_file(const char *, const struct stat *, int, int);
 
 const char *fx2txt(int);
+
+#define SFTP_EXT_ATTR_LINK_COUNT "attr-link-count at openssh.com"
Index: sftp-server.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/sftp-server.c,v
retrieving revision 1.109
diff -u -r1.109 sftp-server.c
--- sftp-server.c	15 Feb 2016 09:47:49 -0000	1.109
+++ sftp-server.c	2 Jun 2016 01:32:02 -0000
@@ -659,6 +659,9 @@
 	    (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
 	    /* fsync extension */
 	    (r = sshbuf_put_cstring(msg, "fsync at openssh.com")) != 0 ||
+	    (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
+	    /* attr link count extension */
+	    (r = sshbuf_put_cstring(msg, SFTP_EXT_ATTR_LINK_COUNT)) != 0 ||
 	    (r = sshbuf_put_cstring(msg, "1")) != 0) /* version */
 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 	send_msg(msg);


More information about the openssh-unix-dev mailing list