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@xxxxxxxxxxx" 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@xxxxxxxxxxx")) != 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); _______________________________________________ openssh-unix-dev mailing list openssh-unix-dev@xxxxxxxxxxx https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev