# SFTP Protocol v6 Quick reference tables <style> .markdown-body table { font-size: 1.2rem; margin: auto; width: fit-content; } .markdown-body td { font-family: monospace; } </style> # &sect;4.3: Packet types |name |value |hex | |----------------------|-----:|---:| |SSH_FXP_INIT |1 |0x01| |SSH_FXP_VERSION |2 |0x02| |SSH_FXP_OPEN |3 |0x03| |SSH_FXP_CLOSE |4 |0x04| |SSH_FXP_READ |5 |0x05| |SSH_FXP_WRITE |6 |0x06| |SSH_FXP_LSTAT |7 |0x07| |SSH_FXP_FSTAT |8 |0x08| |SSH_FXP_SETSTAT |9 |0x09| |SSH_FXP_FSETSTAT |10 |0x0A| |SSH_FXP_OPENDIR |11 |0x0B| |SSH_FXP_READDIR |12 |0x0C| |SSH_FXP_REMOVE |13 |0x0D| |SSH_FXP_MKDIR |14 |0x0E| |SSH_FXP_RMDIR |15 |0x0F| |SSH_FXP_REALPATH |16 |0x10| |SSH_FXP_STAT |17 |0x11| |SSH_FXP_RENAME |18 |0x12| |SSH_FXP_READLINK |19 |0x13| |\-\-\- |20 |0x14| |SSH_FXP_LINK |21 |0x15| |SSH_FXP_BLOCK |22 |0x16| |SSH_FXP_UNBLOCK |23 |0x17| | | | | |SSH_FXP_STATUS |101 |0x65| |SSH_FXP_HANDLE |102 |0x66| |SSH_FXP_DATA |103 |0x67| |SSH_FXP_NAME |104 |0x68| |SSH_FXP_ATTRS |105 |0x69| | | | | |SSH_FXP_EXTENDED |200 |0xC8| |SSH_FXP_EXTENDED_REPLY|201 |0xC9| # &sect;7: File attributes | `SSH_FILEXFER...` | hex | |------------------------|---------:| |~_ATTR_SIZE | 0x0001| |\-\-\- (deprecated) | 0x0002| |~_ATTR_PERMISSIONS | 0x0004| |~_ATTR_ACCESSTIME | 0x0008| |~_ATTR_CREATETIME | 0x0010| |~_ATTR_MODIFYTIME | 0x0020| |~_ATTR_ACL | 0x0040| |~_ATTR_OWNERGROUP | 0x0080| |~_ATTR_SUBSECOND_TIMES | 0x0100| |~_ATTR_BITS | 0x0200| |~_ATTR_ALLOCATION_SIZE | 0x0400| |~_ATTR_TEXT_HINT | 0x0800| |~_ATTR_MIME_TYPE | 0x1000| |~_ATTR_LINK_COUNT | 0x2000| |~_ATTR_UNTRANSLATED_NAME| 0x4000| |~_ATTR_CTIME | 0x8000| |~_ATTR_EXTENDED |0x80000000| ## Support table |type |attr |supported by |mask | |--------|------------------------|------------------|---------:| |uint32 |valid-attribute-flags | (always present) | | |byte |type | (always present) | | |uint64 |size |SIZE | 0x0001| |uint64 |allocation-size |ALLOCATION | 0x0400| |string |owner |OWNERGROUP | 0x0080| |string |group |OWNERGROUP | 0x0080| |uint32 |permissions |PERMISSIONS | 0x0004| |int64 |atime |MODIFIED | 0x0008| |uint32 |atime-nseconds |SUBSECOND_TIMES | 0x0108| |int64 |createtime |CREATETIME | 0x0010| |uint32 |createtime-nseconds |SUBSECOND_TIMES | 0x0110| |int64 |mtime |ACMODTIME | 0x0020| |uint32 |mtime-nseconds |SUBSECOND_TIMES | 0x0120| |int64 |ctime |CTIME | 0x8000| |uint32 |ctime-nseconds |SUBSECOND_TIMES | 0x8010| |string |acl |ACL | 0x0040| |uint32 |attrib-bits |BITS | 0x0200| |uint32 |attrib-bits-valid |BITS | 0x0200| |byte |text-hint |TEXT_HINT | 0x0800| |string |mime-type |MIME_TYPE | 0x1000| |uint32 |link-count |LINK_COUNT | 0x2000| |string |untranslated-name |UNTRANSLATED_NAME | 0x4000| |uint32 |extended-count |EXTENDED |0x80000000| <br> **supported by** field means that the field only presents if `valid-attribute-flags` has the bit set indicated by `SSH_FILEXFER_...`, as shown in the **mask** column for reference. Otherwise, the field is skipped. **Note on owner/group information**: In SFTP v3, owners and groups were reported by uid/gid. v6 no longer supports the flag `SSH_FILEXFER_UIDGID`, and can only report owner or group by names. Refer to the spec of v6: > 0x00000002 was used in a previous version of this protocol. It is now a reserved value and MUST NOT appear in the mask. Some future version of this protocol may reuse this value. ... where 0x00000002 is actually the `SSH_FILEXFER_UIDGID` in SFTP v3. To be compatible with most interfaces (POSIX?), v6 clients must come up a way mapping those strings back to ids. **Nanosecond fields**: Special cases are `*-nseconds` where one also requires the presence of flag supporting its timestamp (in seconds). The specification did not make it clear enough, and some client might exhabit nonsensical behavior. As a side note, the flags [Green End SFTP Server](https://www.greenend.org.uk/rjk/sftpserver/) supply to its client for SFTP v6 is `0xA3AD`. # &sect;7.2 File types |`SSH_FILEXFER_TYPE...`|value|st_mode |hex |meaning | |----------------------|----:|--------|-------:|----------------| |~_REGULAR | 1|S_IFREG | 0x8000|regular file | |~_DIRECTORY | 2|S_IFDIR | 0x4000|directory | |~_SYMLINK | 3|S_IFLNK | 0xA000|symbolic link | |~_SPECIAL | 4| (N/A) | | | |~_UNKNOWN | 5| (N/A) | | | |~_SOCKET | 6|S_IFSOCK| 0xC000|socket | |~_CHAR_DEVICE | 7|S_IFCHR | 0x2000|character device| |~_BLOCK_DEVICE | 8|S_IFBLK | 0x6000|block device | |~_FIFO | 9|S_IFIFO | 0x1000|FIFO | <br> The enums of `st_mode` are referred from [the manpage](https://man7.org/linux/man-pages/man3/stat.3type.html). As a small hack, GE stores the entire `st_mode` of an inode in the `permissions` field, so you don't have to map it if you know the server is a GE one. # &sect;7.9 File attrib-bits (WIP) |`SSH_FILEXFER_ATTR_FLAGS...`|value| |----------------------------|----:| |~_READONLY |0x0001| |~_SYSTEM |0x0002| |~_HIDDEN |0x0004| |~_CASE_INSENSITIVE |0x0008| |~_ARCHIVE |0x0010| |~_ENCRYPTED |0x0020| |~_COMPRESSED |0x0040| |~_SPARSE |0x0080| |~_APPEND_ONLY |0x0100| |~_IMMUTABLE |0x0200| |~_SYNC |0x0400| |~_TRANSLATION_ERR |0x0800| # &sect;8.3 Rename flag (WIP) SSH_FXF_RENAME_OVERWRITE 0x00000001 SSH_FXF_RENAME_ATOMIC 0x00000002 SSH_FXF_RENAME_NATIVE 0x00000004 # &sect;9.1 Response status code (WIP) SSH_FX_OK 0 SSH_FX_EOF 1 SSH_FX_NO_SUCH_FILE 2 SSH_FX_PERMISSION_DENIED 3 SSH_FX_FAILURE 4 SSH_FX_BAD_MESSAGE 5 SSH_FX_NO_CONNECTION 6 SSH_FX_CONNECTION_LOST 7 SSH_FX_OP_UNSUPPORTED 8 SSH_FX_INVALID_HANDLE 9 SSH_FX_NO_SUCH_PATH 10 SSH_FX_FILE_ALREADY_EXISTS 11 SSH_FX_WRITE_PROTECT 12 SSH_FX_NO_MEDIA 13 SSH_FX_NO_SPACE_ON_FILESYSTEM 14 SSH_FX_QUOTA_EXCEEDED 15 SSH_FX_UNKNOWN_PRINCIPAL 16 SSH_FX_LOCK_CONFLICT 17 SSH_FX_DIR_NOT_EMPTY 18 SSH_FX_NOT_A_DIRECTORY 19 SSH_FX_INVALID_FILENAME 20 SSH_FX_LINK_LOOP 21 SSH_FX_CANNOT_DELETE 22 SSH_FX_INVALID_PARAMETER 23 SSH_FX_FILE_IS_A_DIRECTORY 24 SSH_FX_BYTE_RANGE_LOCK_CONFLICT 25 SSH_FX_BYTE_RANGE_LOCK_REFUSED 26 SSH_FX_DELETE_PENDING 27 SSH_FX_FILE_CORRUPT 28 SSH_FX_OWNER_INVALID 29 SSH_FX_GROUP_INVALID 30 SSH_FX_NO_MATCHING_BYTE_RANGE_LOCK 31