Hardlink support in sshfs
OpenSSH 5.7 adds hardlink support to the sftp protocol:
sftp(1)/sftp-server(8): add a protocol extension to support a hard link operation. It is available through the “ln” command in the client. The old “ln” behaviour of creating a symlink is available using its “-s” option or through the preexisting “symlink” command
This is awesome as I can use that to make rdup work (better) with sshfs.
I’ve created a patch to add hardlink support to sshfs. See below. I also created packages for ubuntu:
- 64 bit: sshfs_2.2-1build1_amd64.deb
- 32 bit: sshfs_2.2-1build1_i386.deb
The patched sshfs reverts to the older behavior of creating a symlink in older OpenSSH setups.
Patch⌗
diff -ur sshfs-fuse-2.2/sshfs.c sshfs-fuse-2.2-hardlink/sshfs.c
--- sshfs-fuse-2.2/sshfs.c 2008-10-20 14:10:09.000000000 +0200
+++ sshfs-fuse-2.2-hardlink/sshfs.c 2011-02-19 13:50:39.815845053 +0100
@@ -105,6 +105,7 @@
#define SSH2_FXE_STATVFS_ST_RDONLY 0x00000001
#define SSH2_FXE_STATVFS_ST_NOSUID 0x00000002
+#define SFTP_EXT_HARDLINK "hardlink@openssh.com"
#define SFTP_EXT_POSIX_RENAME "posix-rename@openssh.com"
#define SFTP_EXT_STATVFS "statvfs@openssh.com"
@@ -219,6 +220,7 @@
char *password;
int ext_posix_rename;
int ext_statvfs;
+ int ext_hardlink;
/* statistics */
uint64_t bytes_sent;
@@ -1358,6 +1360,10 @@
if (strcmp(ext, SFTP_EXT_STATVFS) == 0 &&
strcmp(extdata, "2") == 0)
sshfs.ext_statvfs = 1;
+ if (strcmp(ext, SFTP_EXT_HARDLINK) == 0 &&
+ strcmp(extdata, "1") == 0) {
+ sshfs.ext_hardlink = 1;
+ }
} while (buf2.len < buf2.size);
}
return 0;
@@ -2015,6 +2021,19 @@
return err;
}
+static int sshfs_ext_hardlink(const char *from, const char *to)
+{
+ int err;
+ struct buffer buf;
+ buf_init(&buf, 0);
+ buf_add_string(&buf, SFTP_EXT_HARDLINK);
+ buf_add_path(&buf, from);
+ buf_add_path(&buf, to);
+ err = sftp_request(SSH_FXP_EXTENDED, &buf, SSH_FXP_STATUS, NULL);
+ buf_free(&buf);
+ return err;
+}
+
static void random_string(char *str, int length)
{
int i;
@@ -2023,6 +2042,19 @@
*str = '\0';
}
+static int sshfs_link(const char *from, const char *to)
+{
+ int err;
+ if (sshfs.ext_hardlink) {
+ err = sshfs_ext_hardlink(from, to);
+ } else {
+ /* fall back to old behavoir */
+ err = sshfs_symlink(from, to);
+ }
+
+ return err;
+}
+
static int sshfs_rename(const char *from, const char *to)
{
int err;
@@ -2801,6 +2833,7 @@
.readlink = sshfs_readlink,
.mknod = sshfs_mknod,
.mkdir = sshfs_mkdir,
+ .link = sshfs_link,
.symlink = sshfs_symlink,
.unlink = sshfs_unlink,
.rmdir = sshfs_rmdir,
Read other posts