Re: [PATCH] Adds support for SSH_FXP_LINK request to sftp-server and

This is a discussion on Re: [PATCH] Adds support for SSH_FXP_LINK request to sftp-server and within the OpenSSH Development forums, part of the Networking and Network Related category; --===============2137883816== Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="Pk/CTwBz1VvfPIDp" Content-...


Go Back   Usenet Forums > Networking and Network Related > OpenSSH Development

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 05-14-2007
Peter Collingbourne
 
Posts: n/a
Default Re: [PATCH] Adds support for SSH_FXP_LINK request to sftp-server and


--===============2137883816==
Content-Type: multipart/signed; micalg=pgp-sha1;
protocol="application/pgp-signature"; boundary="Pk/CTwBz1VvfPIDp"
Content-Disposition: inline


--Pk/CTwBz1VvfPIDp
Content-Type: multipart/mixed; boundary="HxQt9wRz9wbL5Edg"
Content-Disposition: inline


--HxQt9wRz9wbL5Edg
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Tue, May 08, 2007 at 06:09:22PM +0100, Peter Collingbourne wrote:
> On Tue, May 08, 2007 at 05:13:39PM +0200, Daniele Calore wrote:
> > - Solutions:
> > 1- Upgrade define SSH2_FILEXFER_VERSION to 4 ???
> > (and also update the check)

>
> If we do this then perhaps it should go to 7 (I assume the version
> numbers correspond to drafts?) But then we may not be completely
> compliant with 7 yet. Of course if the check fails we should revert
> to sending a SYMLINK request (if version >=3D 3), but only if sym =3D
> 1. This is because only the hardlink request requires the oldpath to
> be normalised, and sending a normalised oldpath for a symlink request
> would lead to problems.
>=20
> This behaviour would cause compatibility problems if the bare 'ln'
> command is issued to a new client connected to an old server, not
> to mention the fact that the behaviour of ln has changed anyway.
> Perhaps the best course of action would be to change the -s flag to
> an -h flag, with the default being softlinks? Of course this would
> be inconsistent with the ln(1) command.


I am attaching a patch which incorporates some of my above suggestions.
According to draft 7 and all future drafts, the current version of
the filexfer protocol is 6, which is the version number I am using
in my patch. I would like feedback on whether an -s flag or an -h
flag would be best for the ln command of the sftp client.

Thanks,
--=20
Peter

--HxQt9wRz9wbL5Edg
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="openssh-sftp-hardlink-pcvs-v3.patch"
Content-Transfer-Encoding: quoted-printable

diff -ur openssh.orig/sftp.1 openssh/sftp.1
--- openssh.orig/sftp.1 2006-01-20 00:31:47.000000000 +0000
+++ openssh/sftp.1 2007-05-14 20:56:49.000000000 +0100
@@ -321,11 +321,17 @@
.It Ic lmkdir Ar path
Create local directory specified by
.Ar path .
-.It Ic ln Ar oldpath Ar newpath
-Create a symbolic link from
+.It Xo Ic ln
+.Op Fl s
+.Ar oldpath Ar newpath
+.Xc
+Create a hard link from
.Ar oldpath
to
-.Ar newpath .
+.Ar newpath ,
+or a symbolic link if the
+.Fl s
+flag is specified.
.It Ic lpwd
Print local working directory.
.It Xo Ic ls
diff -ur openssh.orig/sftp.c openssh/sftp.c
--- openssh.orig/sftp.c 2007-01-05 05:30:41.000000000 +0000
+++ openssh/sftp.c 2007-05-14 20:48:38.000000000 +0100
@@ -122,6 +122,7 @@
#define I_SYMLINK 21
#define I_VERSION 22
#define I_PROGRESS 23
+#define I_LINK 24
=20
struct CMD {
const char *c;
@@ -144,7 +145,7 @@
{ "lchdir", I_LCHDIR },
{ "lls", I_LLS },
{ "lmkdir", I_LMKDIR },
- { "ln", I_SYMLINK },
+ { "ln", I_LINK },
{ "lpwd", I_LPWD },
{ "ls", I_LS },
{ "lumask", I_LUMASK },
@@ -202,7 +203,7 @@
printf("help Display this help text\n");
printf("get remote-path [local-path] Download file\n");
printf("lls [ls-options [path]] Display local directory listing\n");
- printf("ln oldpath newpath Symlink remote file\n");
+ printf("ln [-s] oldpath newpath (Sym)link remote file\n");
printf("lmkdir path Create local directory\n");
printf("lpwd Print local working directory\n");
printf("ls [path] Display remote directory listing\n"=
);
@@ -369,6 +370,29 @@
}
=20
static int
+parse_link_flags(const char **cpp, int *sflag)
+{
+ const char *cp =3D *cpp;
+
+ /* Check for flags */
+ if (cp[0] =3D=3D '-' && cp[1] && strchr(WHITESPACE, cp[2])) {
+ switch (cp[1]) {
+ case 's':
+ case 'S':
+ *sflag =3D 1;
+ break;
+ default:
+ error("Invalid flag -%c", cp[1]);
+ return(-1);
+ }
+ cp +=3D 2;
+ *cpp =3D cp + strspn(cp, WHITESPACE);
+ }
+
+ return(0);
+}
+
+static int
parse_ls_flags(const char **cpp, int *lflag)
{
const char *cp =3D *cpp;
@@ -867,7 +891,7 @@
}
=20
static int
-parse_args(const char **cpp, int *pflag, int *lflag, int *iflag,
+parse_args(const char **cpp, int *pflag, int *lflag, int *sflag, int *ifla=
g,
unsigned long *n_arg, char **path1, char **path2)
{
const char *cmd, *cp =3D *cpp;
@@ -915,7 +939,7 @@
}
=20
/* Get arguments and parse flags */
- *lflag =3D *pflag =3D *n_arg =3D 0;
+ *sflag =3D *lflag =3D *pflag =3D *n_arg =3D 0;
*path1 =3D *path2 =3D NULL;
switch (cmdnum) {
case I_GET:
@@ -934,6 +958,9 @@
if (get_pathname(&cp, path2))
return(-1);
break;
+ case I_LINK:
+ if (parse_link_flags(&cp, sflag))
+ return(-1);
case I_RENAME:
case I_SYMLINK:
if (get_pathname(&cp, path1))
@@ -1027,7 +1054,7 @@
int err_abort)
{
char *path1, *path2, *tmp;
- int pflag, lflag, iflag, cmdnum, i;
+ int pflag, lflag, sflag, iflag, cmdnum, i;
unsigned long n_arg;
Attrib a, *aa;
char path_buf[MAXPATHLEN];
@@ -1035,7 +1062,7 @@
glob_t g;
=20
path1 =3D path2 =3D NULL;
- cmdnum =3D parse_args(&cmd, &pflag, &lflag, &iflag, &n_arg,
+ cmdnum =3D parse_args(&cmd, &pflag, &lflag, &sflag, &iflag, &n_arg,
&path1, &path2);
=20
if (iflag !=3D 0)
@@ -1067,6 +1094,13 @@
path2 =3D make_absolute(path2, *pwd);
err =3D do_symlink(conn, path1, path2);
break;
+ case I_LINK:
+ if (!sflag) {
+ path1 =3D make_absolute(path1, *pwd);
+ }
+ path2 =3D make_absolute(path2, *pwd);
+ err =3D do_link(conn, path1, path2, sflag);
+ break;
case I_RM:
path1 =3D make_absolute(path1, *pwd);
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
diff -ur openssh.orig/sftp-client.c openssh/sftp-client.c
--- openssh.orig/sftp-client.c 2007-02-19 11:13:39.000000000 +0000
+++ openssh/sftp-client.c 2007-05-14 20:48:38.000000000 +0100
@@ -686,6 +686,47 @@
return(status);
}
=20
+int
+do_link(struct sftp_conn *conn, char *oldpath, char *newpath, int sym)
+{
+ Buffer msg;
+ u_int status, id;
+
+ if (conn->version >=3D 3 && conn->version < 6 && sym) {
+ /*
+ * For backwards-compatibility, send a symlink request
+ * if possible and server does not support link request.
+ */
+ return(do_symlink(conn, oldpath, newpath));
+ }
+
+ if (conn->version < 6) {
+ error("This server does not support the link operation");
+ return(SSH2_FX_OP_UNSUPPORTED);
+ }
+
+ buffer_init(&msg);
+
+ /* Send link request */
+ id =3D conn->msg_id++;
+ buffer_put_char(&msg, SSH2_FXP_LINK);
+ buffer_put_int(&msg, id);
+ buffer_put_cstring(&msg, newpath);
+ buffer_put_cstring(&msg, oldpath);
+ buffer_put_char(&msg, sym);
+ send_msg(conn->fd_out, &msg);
+ debug3("Sent message SSH2_FXP_LINK \"%s\" -> \"%s\" (sym=3D%d)", oldpath,
+ newpath, sym);
+ buffer_free(&msg);
+
+ status =3D get_status(conn->fd_in, id);
+ if (status !=3D SSH2_FX_OK)
+ error("Couldn't link file \"%s\" to \"%s\": %s", oldpath,
+ newpath, fx2txt(status));
+
+ return(status);
+}
+
char *
do_readlink(struct sftp_conn *conn, char *path)
{
diff -ur openssh.orig/sftp-client.h openssh/sftp-client.h
--- openssh.orig/sftp-client.h 2005-05-26 03:05:49.000000000 +0100
+++ openssh/sftp-client.h 2007-05-14 20:48:38.000000000 +0100
@@ -76,9 +76,12 @@
/* Rename 'oldpath' to 'newpath' */
int do_rename(struct sftp_conn *, char *, char *);
=20
-/* Rename 'oldpath' to 'newpath' */
+/* Symlink 'oldpath' to 'newpath' */
int do_symlink(struct sftp_conn *, char *, char *);
=20
+/* Link 'oldpath' to 'newpath', with a symlink if 'sflag' is set */
+int do_link(struct sftp_conn *, char *, char *, int);
+
/* Return target of symlink 'path' - caller must free result */
char *do_readlink(struct sftp_conn *, char *);
=20
diff -ur openssh.orig/sftp.h openssh/sftp.h
--- openssh.orig/sftp.h 2006-03-26 04:30:02.000000000 +0100
+++ openssh/sftp.h 2007-05-14 20:48:38.000000000 +0100
@@ -29,7 +29,7 @@
*/
=20
/* version */
-#define SSH2_FILEXFER_VERSION 3
+#define SSH2_FILEXFER_VERSION 6
=20
/* client to server */
#define SSH2_FXP_INIT 1
@@ -52,6 +52,7 @@
#define SSH2_FXP_RENAME 18
#define SSH2_FXP_READLINK 19
#define SSH2_FXP_SYMLINK 20
+#define SSH2_FXP_LINK 21
=20
/* server to client */
#define SSH2_FXP_VERSION 2
diff -ur openssh.orig/sftp-server.c openssh/sftp-server.c
--- openssh.orig/sftp-server.c 2007-01-05 05:31:03.000000000 +0000
+++ openssh/sftp-server.c 2007-05-14 20:53:37.000000000 +0100
@@ -48,6 +48,7 @@
/* helper */
#define get_int64() buffer_get_int64(&iqueue);
#define get_int() buffer_get_int(&iqueue);
+#define get_char() buffer_get_char(&iqueue);
#define get_string(lenp) buffer_get_string(&iqueue, lenp);
=20
/* Our verbosity */
@@ -1070,6 +1071,32 @@
}
=20
static void
+process_link(void)
+{
+ u_int32_t id;
+ char *oldpath, *newpath;
+ u_int sym;
+ int ret, status;
+
+ id =3D get_int();
+ newpath =3D get_string(NULL);
+ oldpath =3D get_string(NULL);
+ sym =3D get_char();
+ debug3("request %u: link", id);
+ logit("link old \"%s\" new \"%s\" sym %u", oldpath, newpath, sym);
+ /* this will fail if 'newpath' exists */
+ if (sym) {
+ ret =3D symlink(oldpath, newpath);
+ } else {
+ ret =3D link(oldpath, newpath);
+ }
+ status =3D (ret =3D=3D -1) ? errno_to_portable(errno) : SSH2_FX_OK;
+ send_status(id, status);
+ xfree(oldpath);
+ xfree(newpath);
+}
+
+static void
process_extended(void)
{
u_int32_t id;
@@ -1165,6 +1192,9 @@
case SSH2_FXP_SYMLINK:
process_symlink();
break;
+ case SSH2_FXP_LINK:
+ process_link();
+ break;
case SSH2_FXP_EXTENDED:
process_extended();
break;

--HxQt9wRz9wbL5Edg--

--Pk/CTwBz1VvfPIDp
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)

iD8DBQFGSMLfXDqn6DSH7HERAoUtAJ40wxPs5wRKtniaKi9Sd1 CarYOUaQCfakHb
b3Gw83zLRs3QmjV6zkle68s=
=brzp
-----END PGP SIGNATURE-----

--Pk/CTwBz1VvfPIDp--

--===============2137883816==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
http://lists.mindrot.org/mailman/lis...enssh-unix-dev

--===============2137883816==--
Reply With Quote
Reply
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT +1. The time now is 08:42 AM.


Powered by vBulletin® Version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO 3.0.0