summaryrefslogtreecommitdiff
path: root/sftp-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'sftp-client.c')
-rw-r--r--sftp-client.c259
1 files changed, 160 insertions, 99 deletions
diff --git a/sftp-client.c b/sftp-client.c
index 9dab47780..caa384b4e 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp-client.c,v 1.92 2010/07/19 03:16:33 djm Exp $ */ 1/* $OpenBSD: sftp-client.c,v 1.94 2010/12/04 00:18:01 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -75,15 +75,28 @@ struct sftp_conn {
75#define SFTP_EXT_POSIX_RENAME 0x00000001 75#define SFTP_EXT_POSIX_RENAME 0x00000001
76#define SFTP_EXT_STATVFS 0x00000002 76#define SFTP_EXT_STATVFS 0x00000002
77#define SFTP_EXT_FSTATVFS 0x00000004 77#define SFTP_EXT_FSTATVFS 0x00000004
78#define SFTP_EXT_HARDLINK 0x00000008
78 u_int exts; 79 u_int exts;
80 u_int64_t limit_kbps;
81 struct bwlimit bwlimit_in, bwlimit_out;
79}; 82};
80 83
81static char * 84static char *
82get_handle(int fd, u_int expected_id, u_int *len, const char *errfmt, ...) 85get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len,
83 __attribute__((format(printf, 4, 5))); 86 const char *errfmt, ...) __attribute__((format(printf, 4, 5)));
87
88/* ARGSUSED */
89static int
90sftpio(void *_bwlimit, size_t amount)
91{
92 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
93
94 bandwidth_limit(bwlimit, amount);
95 return 0;
96}
84 97
85static void 98static void
86send_msg(int fd, Buffer *m) 99send_msg(struct sftp_conn *conn, Buffer *m)
87{ 100{
88 u_char mlen[4]; 101 u_char mlen[4];
89 struct iovec iov[2]; 102 struct iovec iov[2];
@@ -98,19 +111,22 @@ send_msg(int fd, Buffer *m)
98 iov[1].iov_base = buffer_ptr(m); 111 iov[1].iov_base = buffer_ptr(m);
99 iov[1].iov_len = buffer_len(m); 112 iov[1].iov_len = buffer_len(m);
100 113
101 if (atomiciov(writev, fd, iov, 2) != buffer_len(m) + sizeof(mlen)) 114 if (atomiciov6(writev, conn->fd_out, iov, 2,
115 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) !=
116 buffer_len(m) + sizeof(mlen))
102 fatal("Couldn't send packet: %s", strerror(errno)); 117 fatal("Couldn't send packet: %s", strerror(errno));
103 118
104 buffer_clear(m); 119 buffer_clear(m);
105} 120}
106 121
107static void 122static void
108get_msg(int fd, Buffer *m) 123get_msg(struct sftp_conn *conn, Buffer *m)
109{ 124{
110 u_int msg_len; 125 u_int msg_len;
111 126
112 buffer_append_space(m, 4); 127 buffer_append_space(m, 4);
113 if (atomicio(read, fd, buffer_ptr(m), 4) != 4) { 128 if (atomicio6(read, conn->fd_in, buffer_ptr(m), 4,
129 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) {
114 if (errno == EPIPE) 130 if (errno == EPIPE)
115 fatal("Connection closed"); 131 fatal("Connection closed");
116 else 132 else
@@ -122,7 +138,9 @@ get_msg(int fd, Buffer *m)
122 fatal("Received message too long %u", msg_len); 138 fatal("Received message too long %u", msg_len);
123 139
124 buffer_append_space(m, msg_len); 140 buffer_append_space(m, msg_len);
125 if (atomicio(read, fd, buffer_ptr(m), msg_len) != msg_len) { 141 if (atomicio6(read, conn->fd_in, buffer_ptr(m), msg_len,
142 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in)
143 != msg_len) {
126 if (errno == EPIPE) 144 if (errno == EPIPE)
127 fatal("Connection closed"); 145 fatal("Connection closed");
128 else 146 else
@@ -131,7 +149,7 @@ get_msg(int fd, Buffer *m)
131} 149}
132 150
133static void 151static void
134send_string_request(int fd, u_int id, u_int code, char *s, 152send_string_request(struct sftp_conn *conn, u_int id, u_int code, char *s,
135 u_int len) 153 u_int len)
136{ 154{
137 Buffer msg; 155 Buffer msg;
@@ -140,14 +158,14 @@ send_string_request(int fd, u_int id, u_int code, char *s,
140 buffer_put_char(&msg, code); 158 buffer_put_char(&msg, code);
141 buffer_put_int(&msg, id); 159 buffer_put_int(&msg, id);
142 buffer_put_string(&msg, s, len); 160 buffer_put_string(&msg, s, len);
143 send_msg(fd, &msg); 161 send_msg(conn, &msg);
144 debug3("Sent message fd %d T:%u I:%u", fd, code, id); 162 debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
145 buffer_free(&msg); 163 buffer_free(&msg);
146} 164}
147 165
148static void 166static void
149send_string_attrs_request(int fd, u_int id, u_int code, char *s, 167send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code,
150 u_int len, Attrib *a) 168 char *s, u_int len, Attrib *a)
151{ 169{
152 Buffer msg; 170 Buffer msg;
153 171
@@ -156,19 +174,19 @@ send_string_attrs_request(int fd, u_int id, u_int code, char *s,
156 buffer_put_int(&msg, id); 174 buffer_put_int(&msg, id);
157 buffer_put_string(&msg, s, len); 175 buffer_put_string(&msg, s, len);
158 encode_attrib(&msg, a); 176 encode_attrib(&msg, a);
159 send_msg(fd, &msg); 177 send_msg(conn, &msg);
160 debug3("Sent message fd %d T:%u I:%u", fd, code, id); 178 debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
161 buffer_free(&msg); 179 buffer_free(&msg);
162} 180}
163 181
164static u_int 182static u_int
165get_status(int fd, u_int expected_id) 183get_status(struct sftp_conn *conn, u_int expected_id)
166{ 184{
167 Buffer msg; 185 Buffer msg;
168 u_int type, id, status; 186 u_int type, id, status;
169 187
170 buffer_init(&msg); 188 buffer_init(&msg);
171 get_msg(fd, &msg); 189 get_msg(conn, &msg);
172 type = buffer_get_char(&msg); 190 type = buffer_get_char(&msg);
173 id = buffer_get_int(&msg); 191 id = buffer_get_int(&msg);
174 192
@@ -183,11 +201,12 @@ get_status(int fd, u_int expected_id)
183 201
184 debug3("SSH2_FXP_STATUS %u", status); 202 debug3("SSH2_FXP_STATUS %u", status);
185 203
186 return(status); 204 return status;
187} 205}
188 206
189static char * 207static char *
190get_handle(int fd, u_int expected_id, u_int *len, const char *errfmt, ...) 208get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len,
209 const char *errfmt, ...)
191{ 210{
192 Buffer msg; 211 Buffer msg;
193 u_int type, id; 212 u_int type, id;
@@ -201,7 +220,7 @@ get_handle(int fd, u_int expected_id, u_int *len, const char *errfmt, ...)
201 va_end(args); 220 va_end(args);
202 221
203 buffer_init(&msg); 222 buffer_init(&msg);
204 get_msg(fd, &msg); 223 get_msg(conn, &msg);
205 type = buffer_get_char(&msg); 224 type = buffer_get_char(&msg);
206 id = buffer_get_int(&msg); 225 id = buffer_get_int(&msg);
207 226
@@ -225,14 +244,14 @@ get_handle(int fd, u_int expected_id, u_int *len, const char *errfmt, ...)
225} 244}
226 245
227static Attrib * 246static Attrib *
228get_decode_stat(int fd, u_int expected_id, int quiet) 247get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
229{ 248{
230 Buffer msg; 249 Buffer msg;
231 u_int type, id; 250 u_int type, id;
232 Attrib *a; 251 Attrib *a;
233 252
234 buffer_init(&msg); 253 buffer_init(&msg);
235 get_msg(fd, &msg); 254 get_msg(conn, &msg);
236 255
237 type = buffer_get_char(&msg); 256 type = buffer_get_char(&msg);
238 id = buffer_get_int(&msg); 257 id = buffer_get_int(&msg);
@@ -260,14 +279,14 @@ get_decode_stat(int fd, u_int expected_id, int quiet)
260} 279}
261 280
262static int 281static int
263get_decode_statvfs(int fd, struct sftp_statvfs *st, u_int expected_id, 282get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
264 int quiet) 283 u_int expected_id, int quiet)
265{ 284{
266 Buffer msg; 285 Buffer msg;
267 u_int type, id, flag; 286 u_int type, id, flag;
268 287
269 buffer_init(&msg); 288 buffer_init(&msg);
270 get_msg(fd, &msg); 289 get_msg(conn, &msg);
271 290
272 type = buffer_get_char(&msg); 291 type = buffer_get_char(&msg);
273 id = buffer_get_int(&msg); 292 id = buffer_get_int(&msg);
@@ -311,21 +330,29 @@ get_decode_statvfs(int fd, struct sftp_statvfs *st, u_int expected_id,
311} 330}
312 331
313struct sftp_conn * 332struct sftp_conn *
314do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests) 333do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
334 u_int64_t limit_kbps)
315{ 335{
316 u_int type, exts = 0; 336 u_int type;
317 int version;
318 Buffer msg; 337 Buffer msg;
319 struct sftp_conn *ret; 338 struct sftp_conn *ret;
320 339
340 ret = xmalloc(sizeof(*ret));
341 ret->fd_in = fd_in;
342 ret->fd_out = fd_out;
343 ret->transfer_buflen = transfer_buflen;
344 ret->num_requests = num_requests;
345 ret->exts = 0;
346 ret->limit_kbps = 0;
347
321 buffer_init(&msg); 348 buffer_init(&msg);
322 buffer_put_char(&msg, SSH2_FXP_INIT); 349 buffer_put_char(&msg, SSH2_FXP_INIT);
323 buffer_put_int(&msg, SSH2_FILEXFER_VERSION); 350 buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
324 send_msg(fd_out, &msg); 351 send_msg(ret, &msg);
325 352
326 buffer_clear(&msg); 353 buffer_clear(&msg);
327 354
328 get_msg(fd_in, &msg); 355 get_msg(ret, &msg);
329 356
330 /* Expecting a VERSION reply */ 357 /* Expecting a VERSION reply */
331 if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) { 358 if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) {
@@ -334,9 +361,9 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
334 buffer_free(&msg); 361 buffer_free(&msg);
335 return(NULL); 362 return(NULL);
336 } 363 }
337 version = buffer_get_int(&msg); 364 ret->version = buffer_get_int(&msg);
338 365
339 debug2("Remote version: %d", version); 366 debug2("Remote version: %u", ret->version);
340 367
341 /* Check for extensions */ 368 /* Check for extensions */
342 while (buffer_len(&msg) > 0) { 369 while (buffer_len(&msg) > 0) {
@@ -346,15 +373,19 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
346 373
347 if (strcmp(name, "posix-rename@openssh.com") == 0 && 374 if (strcmp(name, "posix-rename@openssh.com") == 0 &&
348 strcmp(value, "1") == 0) { 375 strcmp(value, "1") == 0) {
349 exts |= SFTP_EXT_POSIX_RENAME; 376 ret->exts |= SFTP_EXT_POSIX_RENAME;
350 known = 1; 377 known = 1;
351 } else if (strcmp(name, "statvfs@openssh.com") == 0 && 378 } else if (strcmp(name, "statvfs@openssh.com") == 0 &&
352 strcmp(value, "2") == 0) { 379 strcmp(value, "2") == 0) {
353 exts |= SFTP_EXT_STATVFS; 380 ret->exts |= SFTP_EXT_STATVFS;
354 known = 1; 381 known = 1;
355 } if (strcmp(name, "fstatvfs@openssh.com") == 0 && 382 } else if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
356 strcmp(value, "2") == 0) { 383 strcmp(value, "2") == 0) {
357 exts |= SFTP_EXT_FSTATVFS; 384 ret->exts |= SFTP_EXT_FSTATVFS;
385 known = 1;
386 } else if (strcmp(name, "hardlink@openssh.com") == 0 &&
387 strcmp(value, "1") == 0) {
388 ret->exts |= SFTP_EXT_HARDLINK;
358 known = 1; 389 known = 1;
359 } 390 }
360 if (known) { 391 if (known) {
@@ -369,26 +400,25 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
369 400
370 buffer_free(&msg); 401 buffer_free(&msg);
371 402
372 ret = xmalloc(sizeof(*ret));
373 ret->fd_in = fd_in;
374 ret->fd_out = fd_out;
375 ret->transfer_buflen = transfer_buflen;
376 ret->num_requests = num_requests;
377 ret->version = version;
378 ret->msg_id = 1;
379 ret->exts = exts;
380
381 /* Some filexfer v.0 servers don't support large packets */ 403 /* Some filexfer v.0 servers don't support large packets */
382 if (version == 0) 404 if (ret->version == 0)
383 ret->transfer_buflen = MIN(ret->transfer_buflen, 20480); 405 ret->transfer_buflen = MIN(ret->transfer_buflen, 20480);
384 406
385 return(ret); 407 ret->limit_kbps = limit_kbps;
408 if (ret->limit_kbps > 0) {
409 bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps,
410 ret->transfer_buflen);
411 bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps,
412 ret->transfer_buflen);
413 }
414
415 return ret;
386} 416}
387 417
388u_int 418u_int
389sftp_proto_version(struct sftp_conn *conn) 419sftp_proto_version(struct sftp_conn *conn)
390{ 420{
391 return(conn->version); 421 return conn->version;
392} 422}
393 423
394int 424int
@@ -403,16 +433,16 @@ do_close(struct sftp_conn *conn, char *handle, u_int handle_len)
403 buffer_put_char(&msg, SSH2_FXP_CLOSE); 433 buffer_put_char(&msg, SSH2_FXP_CLOSE);
404 buffer_put_int(&msg, id); 434 buffer_put_int(&msg, id);
405 buffer_put_string(&msg, handle, handle_len); 435 buffer_put_string(&msg, handle, handle_len);
406 send_msg(conn->fd_out, &msg); 436 send_msg(conn, &msg);
407 debug3("Sent message SSH2_FXP_CLOSE I:%u", id); 437 debug3("Sent message SSH2_FXP_CLOSE I:%u", id);
408 438
409 status = get_status(conn->fd_in, id); 439 status = get_status(conn, id);
410 if (status != SSH2_FX_OK) 440 if (status != SSH2_FX_OK)
411 error("Couldn't close file: %s", fx2txt(status)); 441 error("Couldn't close file: %s", fx2txt(status));
412 442
413 buffer_free(&msg); 443 buffer_free(&msg);
414 444
415 return(status); 445 return status;
416} 446}
417 447
418 448
@@ -430,14 +460,14 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
430 buffer_put_char(&msg, SSH2_FXP_OPENDIR); 460 buffer_put_char(&msg, SSH2_FXP_OPENDIR);
431 buffer_put_int(&msg, id); 461 buffer_put_int(&msg, id);
432 buffer_put_cstring(&msg, path); 462 buffer_put_cstring(&msg, path);
433 send_msg(conn->fd_out, &msg); 463 send_msg(conn, &msg);
434 464
435 buffer_clear(&msg); 465 buffer_clear(&msg);
436 466
437 handle = get_handle(conn->fd_in, id, &handle_len, 467 handle = get_handle(conn, id, &handle_len,
438 "remote readdir(\"%s\")", path); 468 "remote readdir(\"%s\")", path);
439 if (handle == NULL) 469 if (handle == NULL)
440 return(-1); 470 return -1;
441 471
442 if (dir) { 472 if (dir) {
443 ents = 0; 473 ents = 0;
@@ -454,11 +484,11 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
454 buffer_put_char(&msg, SSH2_FXP_READDIR); 484 buffer_put_char(&msg, SSH2_FXP_READDIR);
455 buffer_put_int(&msg, id); 485 buffer_put_int(&msg, id);
456 buffer_put_string(&msg, handle, handle_len); 486 buffer_put_string(&msg, handle, handle_len);
457 send_msg(conn->fd_out, &msg); 487 send_msg(conn, &msg);
458 488
459 buffer_clear(&msg); 489 buffer_clear(&msg);
460 490
461 get_msg(conn->fd_in, &msg); 491 get_msg(conn, &msg);
462 492
463 type = buffer_get_char(&msg); 493 type = buffer_get_char(&msg);
464 id = buffer_get_int(&msg); 494 id = buffer_get_int(&msg);
@@ -537,7 +567,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
537 **dir = NULL; 567 **dir = NULL;
538 } 568 }
539 569
540 return(0); 570 return 0;
541} 571}
542 572
543int 573int
@@ -566,9 +596,8 @@ do_rm(struct sftp_conn *conn, char *path)
566 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); 596 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
567 597
568 id = conn->msg_id++; 598 id = conn->msg_id++;
569 send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path, 599 send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path));
570 strlen(path)); 600 status = get_status(conn, id);
571 status = get_status(conn->fd_in, id);
572 if (status != SSH2_FX_OK) 601 if (status != SSH2_FX_OK)
573 error("Couldn't delete file: %s", fx2txt(status)); 602 error("Couldn't delete file: %s", fx2txt(status));
574 return(status); 603 return(status);
@@ -580,10 +609,10 @@ do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int printflag)
580 u_int status, id; 609 u_int status, id;
581 610
582 id = conn->msg_id++; 611 id = conn->msg_id++;
583 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_MKDIR, path, 612 send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path,
584 strlen(path), a); 613 strlen(path), a);
585 614
586 status = get_status(conn->fd_in, id); 615 status = get_status(conn, id);
587 if (status != SSH2_FX_OK && printflag) 616 if (status != SSH2_FX_OK && printflag)
588 error("Couldn't create directory: %s", fx2txt(status)); 617 error("Couldn't create directory: %s", fx2txt(status));
589 618
@@ -596,10 +625,10 @@ do_rmdir(struct sftp_conn *conn, char *path)
596 u_int status, id; 625 u_int status, id;
597 626
598 id = conn->msg_id++; 627 id = conn->msg_id++;
599 send_string_request(conn->fd_out, id, SSH2_FXP_RMDIR, path, 628 send_string_request(conn, id, SSH2_FXP_RMDIR, path,
600 strlen(path)); 629 strlen(path));
601 630
602 status = get_status(conn->fd_in, id); 631 status = get_status(conn, id);
603 if (status != SSH2_FX_OK) 632 if (status != SSH2_FX_OK)
604 error("Couldn't remove directory: %s", fx2txt(status)); 633 error("Couldn't remove directory: %s", fx2txt(status));
605 634
@@ -613,11 +642,11 @@ do_stat(struct sftp_conn *conn, char *path, int quiet)
613 642
614 id = conn->msg_id++; 643 id = conn->msg_id++;
615 644
616 send_string_request(conn->fd_out, id, 645 send_string_request(conn, id,
617 conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, 646 conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
618 path, strlen(path)); 647 path, strlen(path));
619 648
620 return(get_decode_stat(conn->fd_in, id, quiet)); 649 return(get_decode_stat(conn, id, quiet));
621} 650}
622 651
623Attrib * 652Attrib *
@@ -634,10 +663,10 @@ do_lstat(struct sftp_conn *conn, char *path, int quiet)
634 } 663 }
635 664
636 id = conn->msg_id++; 665 id = conn->msg_id++;
637 send_string_request(conn->fd_out, id, SSH2_FXP_LSTAT, path, 666 send_string_request(conn, id, SSH2_FXP_LSTAT, path,
638 strlen(path)); 667 strlen(path));
639 668
640 return(get_decode_stat(conn->fd_in, id, quiet)); 669 return(get_decode_stat(conn, id, quiet));
641} 670}
642 671
643#ifdef notyet 672#ifdef notyet
@@ -647,10 +676,10 @@ do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet)
647 u_int id; 676 u_int id;
648 677
649 id = conn->msg_id++; 678 id = conn->msg_id++;
650 send_string_request(conn->fd_out, id, SSH2_FXP_FSTAT, handle, 679 send_string_request(conn, id, SSH2_FXP_FSTAT, handle,
651 handle_len); 680 handle_len);
652 681
653 return(get_decode_stat(conn->fd_in, id, quiet)); 682 return(get_decode_stat(conn, id, quiet));
654} 683}
655#endif 684#endif
656 685
@@ -660,10 +689,10 @@ do_setstat(struct sftp_conn *conn, char *path, Attrib *a)
660 u_int status, id; 689 u_int status, id;
661 690
662 id = conn->msg_id++; 691 id = conn->msg_id++;
663 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_SETSTAT, path, 692 send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path,
664 strlen(path), a); 693 strlen(path), a);
665 694
666 status = get_status(conn->fd_in, id); 695 status = get_status(conn, id);
667 if (status != SSH2_FX_OK) 696 if (status != SSH2_FX_OK)
668 error("Couldn't setstat on \"%s\": %s", path, 697 error("Couldn't setstat on \"%s\": %s", path,
669 fx2txt(status)); 698 fx2txt(status));
@@ -678,10 +707,10 @@ do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len,
678 u_int status, id; 707 u_int status, id;
679 708
680 id = conn->msg_id++; 709 id = conn->msg_id++;
681 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_FSETSTAT, handle, 710 send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle,
682 handle_len, a); 711 handle_len, a);
683 712
684 status = get_status(conn->fd_in, id); 713 status = get_status(conn, id);
685 if (status != SSH2_FX_OK) 714 if (status != SSH2_FX_OK)
686 error("Couldn't fsetstat: %s", fx2txt(status)); 715 error("Couldn't fsetstat: %s", fx2txt(status));
687 716
@@ -697,12 +726,12 @@ do_realpath(struct sftp_conn *conn, char *path)
697 Attrib *a; 726 Attrib *a;
698 727
699 expected_id = id = conn->msg_id++; 728 expected_id = id = conn->msg_id++;
700 send_string_request(conn->fd_out, id, SSH2_FXP_REALPATH, path, 729 send_string_request(conn, id, SSH2_FXP_REALPATH, path,
701 strlen(path)); 730 strlen(path));
702 731
703 buffer_init(&msg); 732 buffer_init(&msg);
704 733
705 get_msg(conn->fd_in, &msg); 734 get_msg(conn, &msg);
706 type = buffer_get_char(&msg); 735 type = buffer_get_char(&msg);
707 id = buffer_get_int(&msg); 736 id = buffer_get_int(&msg);
708 737
@@ -756,13 +785,13 @@ do_rename(struct sftp_conn *conn, char *oldpath, char *newpath)
756 } 785 }
757 buffer_put_cstring(&msg, oldpath); 786 buffer_put_cstring(&msg, oldpath);
758 buffer_put_cstring(&msg, newpath); 787 buffer_put_cstring(&msg, newpath);
759 send_msg(conn->fd_out, &msg); 788 send_msg(conn, &msg);
760 debug3("Sent message %s \"%s\" -> \"%s\"", 789 debug3("Sent message %s \"%s\" -> \"%s\"",
761 (conn->exts & SFTP_EXT_POSIX_RENAME) ? "posix-rename@openssh.com" : 790 (conn->exts & SFTP_EXT_POSIX_RENAME) ? "posix-rename@openssh.com" :
762 "SSH2_FXP_RENAME", oldpath, newpath); 791 "SSH2_FXP_RENAME", oldpath, newpath);
763 buffer_free(&msg); 792 buffer_free(&msg);
764 793
765 status = get_status(conn->fd_in, id); 794 status = get_status(conn, id);
766 if (status != SSH2_FX_OK) 795 if (status != SSH2_FX_OK)
767 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, 796 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
768 newpath, fx2txt(status)); 797 newpath, fx2txt(status));
@@ -771,6 +800,39 @@ do_rename(struct sftp_conn *conn, char *oldpath, char *newpath)
771} 800}
772 801
773int 802int
803do_hardlink(struct sftp_conn *conn, char *oldpath, char *newpath)
804{
805 Buffer msg;
806 u_int status, id;
807
808 buffer_init(&msg);
809
810 /* Send link request */
811 id = conn->msg_id++;
812 if ((conn->exts & SFTP_EXT_HARDLINK) == 0) {
813 error("Server does not support hardlink@openssh.com extension");
814 return -1;
815 }
816
817 buffer_put_char(&msg, SSH2_FXP_EXTENDED);
818 buffer_put_int(&msg, id);
819 buffer_put_cstring(&msg, "hardlink@openssh.com");
820 buffer_put_cstring(&msg, oldpath);
821 buffer_put_cstring(&msg, newpath);
822 send_msg(conn, &msg);
823 debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"",
824 oldpath, newpath);
825 buffer_free(&msg);
826
827 status = get_status(conn, id);
828 if (status != SSH2_FX_OK)
829 error("Couldn't link file \"%s\" to \"%s\": %s", oldpath,
830 newpath, fx2txt(status));
831
832 return(status);
833}
834
835int
774do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) 836do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath)
775{ 837{
776 Buffer msg; 838 Buffer msg;
@@ -789,12 +851,12 @@ do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath)
789 buffer_put_int(&msg, id); 851 buffer_put_int(&msg, id);
790 buffer_put_cstring(&msg, oldpath); 852 buffer_put_cstring(&msg, oldpath);
791 buffer_put_cstring(&msg, newpath); 853 buffer_put_cstring(&msg, newpath);
792 send_msg(conn->fd_out, &msg); 854 send_msg(conn, &msg);
793 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, 855 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
794 newpath); 856 newpath);
795 buffer_free(&msg); 857 buffer_free(&msg);
796 858
797 status = get_status(conn->fd_in, id); 859 status = get_status(conn, id);
798 if (status != SSH2_FX_OK) 860 if (status != SSH2_FX_OK)
799 error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, 861 error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath,
800 newpath, fx2txt(status)); 862 newpath, fx2txt(status));
@@ -812,12 +874,11 @@ do_readlink(struct sftp_conn *conn, char *path)
812 Attrib *a; 874 Attrib *a;
813 875
814 expected_id = id = conn->msg_id++; 876 expected_id = id = conn->msg_id++;
815 send_string_request(conn->fd_out, id, SSH2_FXP_READLINK, path, 877 send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path));
816 strlen(path));
817 878
818 buffer_init(&msg); 879 buffer_init(&msg);
819 880
820 get_msg(conn->fd_in, &msg); 881 get_msg(conn, &msg);
821 type = buffer_get_char(&msg); 882 type = buffer_get_char(&msg);
822 id = buffer_get_int(&msg); 883 id = buffer_get_int(&msg);
823 884
@@ -871,10 +932,10 @@ do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
871 buffer_put_int(&msg, id); 932 buffer_put_int(&msg, id);
872 buffer_put_cstring(&msg, "statvfs@openssh.com"); 933 buffer_put_cstring(&msg, "statvfs@openssh.com");
873 buffer_put_cstring(&msg, path); 934 buffer_put_cstring(&msg, path);
874 send_msg(conn->fd_out, &msg); 935 send_msg(conn, &msg);
875 buffer_free(&msg); 936 buffer_free(&msg);
876 937
877 return get_decode_statvfs(conn->fd_in, st, id, quiet); 938 return get_decode_statvfs(conn, st, id, quiet);
878} 939}
879 940
880#ifdef notyet 941#ifdef notyet
@@ -898,16 +959,16 @@ do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len,
898 buffer_put_int(&msg, id); 959 buffer_put_int(&msg, id);
899 buffer_put_cstring(&msg, "fstatvfs@openssh.com"); 960 buffer_put_cstring(&msg, "fstatvfs@openssh.com");
900 buffer_put_string(&msg, handle, handle_len); 961 buffer_put_string(&msg, handle, handle_len);
901 send_msg(conn->fd_out, &msg); 962 send_msg(conn, &msg);
902 buffer_free(&msg); 963 buffer_free(&msg);
903 964
904 return get_decode_statvfs(conn->fd_in, st, id, quiet); 965 return get_decode_statvfs(conn, st, id, quiet);
905} 966}
906#endif 967#endif
907 968
908static void 969static void
909send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len, 970send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
910 char *handle, u_int handle_len) 971 u_int len, char *handle, u_int handle_len)
911{ 972{
912 Buffer msg; 973 Buffer msg;
913 974
@@ -918,7 +979,7 @@ send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
918 buffer_put_string(&msg, handle, handle_len); 979 buffer_put_string(&msg, handle, handle_len);
919 buffer_put_int64(&msg, offset); 980 buffer_put_int64(&msg, offset);
920 buffer_put_int(&msg, len); 981 buffer_put_int(&msg, len);
921 send_msg(fd_out, &msg); 982 send_msg(conn, &msg);
922 buffer_free(&msg); 983 buffer_free(&msg);
923} 984}
924 985
@@ -976,10 +1037,10 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
976 buffer_put_int(&msg, SSH2_FXF_READ); 1037 buffer_put_int(&msg, SSH2_FXF_READ);
977 attrib_clear(&junk); /* Send empty attributes */ 1038 attrib_clear(&junk); /* Send empty attributes */
978 encode_attrib(&msg, &junk); 1039 encode_attrib(&msg, &junk);
979 send_msg(conn->fd_out, &msg); 1040 send_msg(conn, &msg);
980 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1041 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
981 1042
982 handle = get_handle(conn->fd_in, id, &handle_len, 1043 handle = get_handle(conn, id, &handle_len,
983 "remote open(\"%s\")", remote_path); 1044 "remote open(\"%s\")", remote_path);
984 if (handle == NULL) { 1045 if (handle == NULL) {
985 buffer_free(&msg); 1046 buffer_free(&msg);
@@ -1032,12 +1093,12 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
1032 offset += buflen; 1093 offset += buflen;
1033 num_req++; 1094 num_req++;
1034 TAILQ_INSERT_TAIL(&requests, req, tq); 1095 TAILQ_INSERT_TAIL(&requests, req, tq);
1035 send_read_request(conn->fd_out, req->id, req->offset, 1096 send_read_request(conn, req->id, req->offset,
1036 req->len, handle, handle_len); 1097 req->len, handle, handle_len);
1037 } 1098 }
1038 1099
1039 buffer_clear(&msg); 1100 buffer_clear(&msg);
1040 get_msg(conn->fd_in, &msg); 1101 get_msg(conn, &msg);
1041 type = buffer_get_char(&msg); 1102 type = buffer_get_char(&msg);
1042 id = buffer_get_int(&msg); 1103 id = buffer_get_int(&msg);
1043 debug3("Received reply T:%u I:%u R:%d", type, id, max_req); 1104 debug3("Received reply T:%u I:%u R:%d", type, id, max_req);
@@ -1092,7 +1153,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
1092 req->id = conn->msg_id++; 1153 req->id = conn->msg_id++;
1093 req->len -= len; 1154 req->len -= len;
1094 req->offset += len; 1155 req->offset += len;
1095 send_read_request(conn->fd_out, req->id, 1156 send_read_request(conn, req->id,
1096 req->offset, req->len, handle, handle_len); 1157 req->offset, req->len, handle, handle_len);
1097 /* Reduce the request size */ 1158 /* Reduce the request size */
1098 if (len < buflen) 1159 if (len < buflen)
@@ -1327,12 +1388,12 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1327 buffer_put_cstring(&msg, remote_path); 1388 buffer_put_cstring(&msg, remote_path);
1328 buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); 1389 buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC);
1329 encode_attrib(&msg, &a); 1390 encode_attrib(&msg, &a);
1330 send_msg(conn->fd_out, &msg); 1391 send_msg(conn, &msg);
1331 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1392 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
1332 1393
1333 buffer_clear(&msg); 1394 buffer_clear(&msg);
1334 1395
1335 handle = get_handle(conn->fd_in, id, &handle_len, 1396 handle = get_handle(conn, id, &handle_len,
1336 "remote open(\"%s\")", remote_path); 1397 "remote open(\"%s\")", remote_path);
1337 if (handle == NULL) { 1398 if (handle == NULL) {
1338 close(local_fd); 1399 close(local_fd);
@@ -1381,7 +1442,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1381 buffer_put_string(&msg, handle, handle_len); 1442 buffer_put_string(&msg, handle, handle_len);
1382 buffer_put_int64(&msg, offset); 1443 buffer_put_int64(&msg, offset);
1383 buffer_put_string(&msg, data, len); 1444 buffer_put_string(&msg, data, len);
1384 send_msg(conn->fd_out, &msg); 1445 send_msg(conn, &msg);
1385 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", 1446 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
1386 id, (unsigned long long)offset, len); 1447 id, (unsigned long long)offset, len);
1387 } else if (TAILQ_FIRST(&acks) == NULL) 1448 } else if (TAILQ_FIRST(&acks) == NULL)
@@ -1395,7 +1456,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1395 u_int r_id; 1456 u_int r_id;
1396 1457
1397 buffer_clear(&msg); 1458 buffer_clear(&msg);
1398 get_msg(conn->fd_in, &msg); 1459 get_msg(conn, &msg);
1399 type = buffer_get_char(&msg); 1460 type = buffer_get_char(&msg);
1400 r_id = buffer_get_int(&msg); 1461 r_id = buffer_get_int(&msg);
1401 1462