1 /* $NetBSD: sftp-client.c,v 1.24 2019/10/12 18:32:22 christos Exp $ */ 2 /* $OpenBSD: sftp-client.c,v 1.135 2019/10/04 04:31:59 djm Exp $ */ 3 /* 4 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* XXX: memleaks */ 20 /* XXX: signed vs unsigned */ 21 /* XXX: remove all logging, only return status codes */ 22 /* XXX: copy between two remote sites */ 23 24 #include "includes.h" 25 __RCSID("$NetBSD: sftp-client.c,v 1.24 2019/10/12 18:32:22 christos Exp $"); 26 27 #include <sys/param.h> /* MIN MAX */ 28 #include <sys/types.h> 29 #include <sys/poll.h> 30 #include <sys/queue.h> 31 #include <sys/stat.h> 32 #include <sys/time.h> 33 #include <sys/statvfs.h> 34 #include <sys/uio.h> 35 36 #include <dirent.h> 37 #include <errno.h> 38 #include <fcntl.h> 39 #include <signal.h> 40 #include <stdarg.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <unistd.h> 45 46 #include "xmalloc.h" 47 #include "ssherr.h" 48 #include "sshbuf.h" 49 #include "log.h" 50 #include "atomicio.h" 51 #include "progressmeter.h" 52 #include "misc.h" 53 #include "utf8.h" 54 55 #include "sftp.h" 56 #include "sftp-common.h" 57 #include "sftp-client.h" 58 59 extern volatile sig_atomic_t interrupted; 60 extern int showprogress; 61 62 /* Minimum amount of data to read at a time */ 63 #define MIN_READ_SIZE 512 64 65 /* Maximum depth to descend in directory trees */ 66 #define MAX_DIR_DEPTH 64 67 68 struct sftp_conn { 69 int fd_in; 70 int fd_out; 71 u_int transfer_buflen; 72 u_int num_requests; 73 u_int version; 74 u_int msg_id; 75 #define SFTP_EXT_POSIX_RENAME 0x00000001 76 #define SFTP_EXT_STATVFS 0x00000002 77 #define SFTP_EXT_FSTATVFS 0x00000004 78 #define SFTP_EXT_HARDLINK 0x00000008 79 #define SFTP_EXT_FSYNC 0x00000010 80 #define SFTP_EXT_LSETSTAT 0x00000020 81 u_int exts; 82 u_int64_t limit_kbps; 83 struct bwlimit bwlimit_in, bwlimit_out; 84 }; 85 86 static u_char * 87 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, 88 const char *errfmt, ...) __attribute__((format(printf, 4, 5))); 89 90 /* ARGSUSED */ 91 static int 92 sftpio(void *_bwlimit, size_t amount) 93 { 94 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit; 95 96 refresh_progress_meter(0); 97 if (bwlimit != NULL) 98 bandwidth_limit(bwlimit, amount); 99 return 0; 100 } 101 102 static void 103 send_msg(struct sftp_conn *conn, struct sshbuf *m) 104 { 105 u_char mlen[4]; 106 struct iovec iov[2]; 107 108 if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH) 109 fatal("Outbound message too long %zu", sshbuf_len(m)); 110 111 /* Send length first */ 112 put_u32(mlen, sshbuf_len(m)); 113 iov[0].iov_base = mlen; 114 iov[0].iov_len = sizeof(mlen); 115 iov[1].iov_base = __UNCONST(sshbuf_ptr(m)); 116 iov[1].iov_len = sshbuf_len(m); 117 118 if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio, 119 conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) != 120 sshbuf_len(m) + sizeof(mlen)) 121 fatal("Couldn't send packet: %s", strerror(errno)); 122 123 sshbuf_reset(m); 124 } 125 126 static void 127 get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial) 128 { 129 u_int msg_len; 130 u_char *p; 131 int r; 132 133 if ((r = sshbuf_reserve(m, 4, &p)) != 0) 134 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 135 if (atomicio6(read, conn->fd_in, p, 4, sftpio, 136 conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) { 137 if (errno == EPIPE || errno == ECONNRESET) 138 fatal("Connection closed"); 139 else 140 fatal("Couldn't read packet: %s", strerror(errno)); 141 } 142 143 if ((r = sshbuf_get_u32(m, &msg_len)) != 0) 144 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 145 if (msg_len > SFTP_MAX_MSG_LENGTH) { 146 do_log2(initial ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_FATAL, 147 "Received message too long %u", msg_len); 148 fatal("Ensure the remote shell produces no output " 149 "for non-interactive sessions."); 150 } 151 152 if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) 153 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 154 if (atomicio6(read, conn->fd_in, p, msg_len, sftpio, 155 conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) 156 != msg_len) { 157 if (errno == EPIPE) 158 fatal("Connection closed"); 159 else 160 fatal("Read packet: %s", strerror(errno)); 161 } 162 } 163 164 static void 165 get_msg(struct sftp_conn *conn, struct sshbuf *m) 166 { 167 get_msg_extended(conn, m, 0); 168 } 169 170 static void 171 send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s, 172 u_int len) 173 { 174 struct sshbuf *msg; 175 int r; 176 177 if ((msg = sshbuf_new()) == NULL) 178 fatal("%s: sshbuf_new failed", __func__); 179 if ((r = sshbuf_put_u8(msg, code)) != 0 || 180 (r = sshbuf_put_u32(msg, id)) != 0 || 181 (r = sshbuf_put_string(msg, s, len)) != 0) 182 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 183 send_msg(conn, msg); 184 debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); 185 sshbuf_free(msg); 186 } 187 188 static void 189 send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, 190 const void *s, u_int len, Attrib *a) 191 { 192 struct sshbuf *msg; 193 int r; 194 195 if ((msg = sshbuf_new()) == NULL) 196 fatal("%s: sshbuf_new failed", __func__); 197 if ((r = sshbuf_put_u8(msg, code)) != 0 || 198 (r = sshbuf_put_u32(msg, id)) != 0 || 199 (r = sshbuf_put_string(msg, s, len)) != 0 || 200 (r = encode_attrib(msg, a)) != 0) 201 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 202 send_msg(conn, msg); 203 debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); 204 sshbuf_free(msg); 205 } 206 207 static u_int 208 get_status(struct sftp_conn *conn, u_int expected_id) 209 { 210 struct sshbuf *msg; 211 u_char type; 212 u_int id, status; 213 int r; 214 215 if ((msg = sshbuf_new()) == NULL) 216 fatal("%s: sshbuf_new failed", __func__); 217 get_msg(conn, msg); 218 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 219 (r = sshbuf_get_u32(msg, &id)) != 0) 220 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 221 222 if (id != expected_id) 223 fatal("ID mismatch (%u != %u)", id, expected_id); 224 if (type != SSH2_FXP_STATUS) 225 fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", 226 SSH2_FXP_STATUS, type); 227 228 if ((r = sshbuf_get_u32(msg, &status)) != 0) 229 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 230 sshbuf_free(msg); 231 232 debug3("SSH2_FXP_STATUS %u", status); 233 234 return status; 235 } 236 237 static u_char * 238 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, 239 const char *errfmt, ...) 240 { 241 struct sshbuf *msg; 242 u_int id, status; 243 u_char type; 244 u_char *handle; 245 char errmsg[256]; 246 va_list args; 247 int r; 248 249 va_start(args, errfmt); 250 if (errfmt != NULL) 251 vsnprintf(errmsg, sizeof(errmsg), errfmt, args); 252 va_end(args); 253 254 if ((msg = sshbuf_new()) == NULL) 255 fatal("%s: sshbuf_new failed", __func__); 256 get_msg(conn, msg); 257 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 258 (r = sshbuf_get_u32(msg, &id)) != 0) 259 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 260 261 if (id != expected_id) 262 fatal("%s: ID mismatch (%u != %u)", 263 errfmt == NULL ? __func__ : errmsg, id, expected_id); 264 if (type == SSH2_FXP_STATUS) { 265 if ((r = sshbuf_get_u32(msg, &status)) != 0) 266 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 267 if (errfmt != NULL) 268 error("%s: %s", errmsg, fx2txt(status)); 269 sshbuf_free(msg); 270 return(NULL); 271 } else if (type != SSH2_FXP_HANDLE) 272 fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u", 273 errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type); 274 275 if ((r = sshbuf_get_string(msg, &handle, len)) != 0) 276 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 277 sshbuf_free(msg); 278 279 return handle; 280 } 281 282 static Attrib * 283 get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) 284 { 285 struct sshbuf *msg; 286 u_int id; 287 u_char type; 288 int r; 289 static Attrib a; 290 291 if ((msg = sshbuf_new()) == NULL) 292 fatal("%s: sshbuf_new failed", __func__); 293 get_msg(conn, msg); 294 295 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 296 (r = sshbuf_get_u32(msg, &id)) != 0) 297 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 298 299 debug3("Received stat reply T:%u I:%u", type, id); 300 if (id != expected_id) 301 fatal("ID mismatch (%u != %u)", id, expected_id); 302 if (type == SSH2_FXP_STATUS) { 303 u_int status; 304 305 if ((r = sshbuf_get_u32(msg, &status)) != 0) 306 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 307 if (quiet) 308 debug("Couldn't stat remote file: %s", fx2txt(status)); 309 else 310 error("Couldn't stat remote file: %s", fx2txt(status)); 311 sshbuf_free(msg); 312 return(NULL); 313 } else if (type != SSH2_FXP_ATTRS) { 314 fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", 315 SSH2_FXP_ATTRS, type); 316 } 317 if ((r = decode_attrib(msg, &a)) != 0) { 318 error("%s: couldn't decode attrib: %s", __func__, ssh_err(r)); 319 sshbuf_free(msg); 320 return NULL; 321 } 322 sshbuf_free(msg); 323 324 return &a; 325 } 326 327 static int 328 get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, 329 u_int expected_id, int quiet) 330 { 331 struct sshbuf *msg; 332 u_char type; 333 u_int id; 334 u_int64_t flag; 335 int r; 336 337 if ((msg = sshbuf_new()) == NULL) 338 fatal("%s: sshbuf_new failed", __func__); 339 get_msg(conn, msg); 340 341 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 342 (r = sshbuf_get_u32(msg, &id)) != 0) 343 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 344 345 debug3("Received statvfs reply T:%u I:%u", type, id); 346 if (id != expected_id) 347 fatal("ID mismatch (%u != %u)", id, expected_id); 348 if (type == SSH2_FXP_STATUS) { 349 u_int status; 350 351 if ((r = sshbuf_get_u32(msg, &status)) != 0) 352 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 353 if (quiet) 354 debug("Couldn't statvfs: %s", fx2txt(status)); 355 else 356 error("Couldn't statvfs: %s", fx2txt(status)); 357 sshbuf_free(msg); 358 return -1; 359 } else if (type != SSH2_FXP_EXTENDED_REPLY) { 360 fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", 361 SSH2_FXP_EXTENDED_REPLY, type); 362 } 363 364 memset(st, 0, sizeof(*st)); 365 if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 || 366 (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 || 367 (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 || 368 (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 || 369 (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 || 370 (r = sshbuf_get_u64(msg, &st->f_files)) != 0 || 371 (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 || 372 (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 || 373 (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 || 374 (r = sshbuf_get_u64(msg, &flag)) != 0 || 375 (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0) 376 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 377 378 st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0; 379 st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0; 380 381 sshbuf_free(msg); 382 383 return 0; 384 } 385 386 struct sftp_conn * 387 do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, 388 u_int64_t limit_kbps) 389 { 390 u_char type; 391 struct sshbuf *msg; 392 struct sftp_conn *ret; 393 int r; 394 395 ret = xcalloc(1, sizeof(*ret)); 396 ret->msg_id = 1; 397 ret->fd_in = fd_in; 398 ret->fd_out = fd_out; 399 ret->transfer_buflen = transfer_buflen; 400 ret->num_requests = num_requests; 401 ret->exts = 0; 402 ret->limit_kbps = 0; 403 404 if ((msg = sshbuf_new()) == NULL) 405 fatal("%s: sshbuf_new failed", __func__); 406 if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 || 407 (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0) 408 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 409 send_msg(ret, msg); 410 411 sshbuf_reset(msg); 412 413 get_msg_extended(ret, msg, 1); 414 415 /* Expecting a VERSION reply */ 416 if ((r = sshbuf_get_u8(msg, &type)) != 0) 417 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 418 if (type != SSH2_FXP_VERSION) { 419 error("Invalid packet back from SSH2_FXP_INIT (type %u)", 420 type); 421 sshbuf_free(msg); 422 free(ret); 423 return(NULL); 424 } 425 if ((r = sshbuf_get_u32(msg, &ret->version)) != 0) 426 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 427 428 debug2("Remote version: %u", ret->version); 429 430 /* Check for extensions */ 431 while (sshbuf_len(msg) > 0) { 432 char *name; 433 u_char *value; 434 size_t vlen; 435 int known = 0; 436 437 if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 || 438 (r = sshbuf_get_string(msg, &value, &vlen)) != 0) 439 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 440 if (strcmp(name, "posix-rename@openssh.com") == 0 && 441 strcmp((char *)value, "1") == 0) { 442 ret->exts |= SFTP_EXT_POSIX_RENAME; 443 known = 1; 444 } else if (strcmp(name, "statvfs@openssh.com") == 0 && 445 strcmp((char *)value, "2") == 0) { 446 ret->exts |= SFTP_EXT_STATVFS; 447 known = 1; 448 } else if (strcmp(name, "fstatvfs@openssh.com") == 0 && 449 strcmp((char *)value, "2") == 0) { 450 ret->exts |= SFTP_EXT_FSTATVFS; 451 known = 1; 452 } else if (strcmp(name, "hardlink@openssh.com") == 0 && 453 strcmp((char *)value, "1") == 0) { 454 ret->exts |= SFTP_EXT_HARDLINK; 455 known = 1; 456 } else if (strcmp(name, "fsync@openssh.com") == 0 && 457 strcmp((char *)value, "1") == 0) { 458 ret->exts |= SFTP_EXT_FSYNC; 459 known = 1; 460 } else if (strcmp(name, "lsetstat@openssh.com") == 0 && 461 strcmp((char *)value, "1") == 0) { 462 ret->exts |= SFTP_EXT_LSETSTAT; 463 known = 1; 464 } 465 if (known) { 466 debug2("Server supports extension \"%s\" revision %s", 467 name, value); 468 } else { 469 debug2("Unrecognised server extension \"%s\"", name); 470 } 471 free(name); 472 free(value); 473 } 474 475 sshbuf_free(msg); 476 477 /* Some filexfer v.0 servers don't support large packets */ 478 if (ret->version == 0) 479 ret->transfer_buflen = MINIMUM(ret->transfer_buflen, 20480); 480 481 ret->limit_kbps = limit_kbps; 482 if (ret->limit_kbps > 0) { 483 bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps, 484 ret->transfer_buflen); 485 bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps, 486 ret->transfer_buflen); 487 } 488 489 return ret; 490 } 491 492 u_int 493 sftp_proto_version(struct sftp_conn *conn) 494 { 495 return conn->version; 496 } 497 498 int 499 do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len) 500 { 501 u_int id, status; 502 struct sshbuf *msg; 503 int r; 504 505 if ((msg = sshbuf_new()) == NULL) 506 fatal("%s: sshbuf_new failed", __func__); 507 508 id = conn->msg_id++; 509 if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 || 510 (r = sshbuf_put_u32(msg, id)) != 0 || 511 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 512 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 513 send_msg(conn, msg); 514 debug3("Sent message SSH2_FXP_CLOSE I:%u", id); 515 516 status = get_status(conn, id); 517 if (status != SSH2_FX_OK) 518 error("Couldn't close file: %s", fx2txt(status)); 519 520 sshbuf_free(msg); 521 522 return status == SSH2_FX_OK ? 0 : -1; 523 } 524 525 526 static int 527 do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, 528 SFTP_DIRENT ***dir) 529 { 530 struct sshbuf *msg; 531 u_int count, id, i, expected_id, ents = 0; 532 size_t handle_len; 533 u_char type, *handle; 534 int status = SSH2_FX_FAILURE; 535 int r; 536 537 if (dir) 538 *dir = NULL; 539 540 id = conn->msg_id++; 541 542 if ((msg = sshbuf_new()) == NULL) 543 fatal("%s: sshbuf_new failed", __func__); 544 if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 || 545 (r = sshbuf_put_u32(msg, id)) != 0 || 546 (r = sshbuf_put_cstring(msg, path)) != 0) 547 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 548 send_msg(conn, msg); 549 550 handle = get_handle(conn, id, &handle_len, 551 "remote readdir(\"%s\")", path); 552 if (handle == NULL) { 553 sshbuf_free(msg); 554 return -1; 555 } 556 557 if (dir) { 558 ents = 0; 559 *dir = xcalloc(1, sizeof(**dir)); 560 (*dir)[0] = NULL; 561 } 562 563 for (; !interrupted;) { 564 id = expected_id = conn->msg_id++; 565 566 debug3("Sending SSH2_FXP_READDIR I:%u", id); 567 568 sshbuf_reset(msg); 569 if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 || 570 (r = sshbuf_put_u32(msg, id)) != 0 || 571 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 572 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 573 send_msg(conn, msg); 574 575 sshbuf_reset(msg); 576 577 get_msg(conn, msg); 578 579 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 580 (r = sshbuf_get_u32(msg, &id)) != 0) 581 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 582 583 debug3("Received reply T:%u I:%u", type, id); 584 585 if (id != expected_id) 586 fatal("ID mismatch (%u != %u)", id, expected_id); 587 588 if (type == SSH2_FXP_STATUS) { 589 u_int rstatus; 590 591 if ((r = sshbuf_get_u32(msg, &rstatus)) != 0) 592 fatal("%s: buffer error: %s", 593 __func__, ssh_err(r)); 594 debug3("Received SSH2_FXP_STATUS %d", rstatus); 595 if (rstatus == SSH2_FX_EOF) 596 break; 597 error("Couldn't read directory: %s", fx2txt(rstatus)); 598 goto out; 599 } else if (type != SSH2_FXP_NAME) 600 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 601 SSH2_FXP_NAME, type); 602 603 if ((r = sshbuf_get_u32(msg, &count)) != 0) 604 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 605 if (count > SSHBUF_SIZE_MAX) 606 fatal("%s: nonsensical number of entries", __func__); 607 if (count == 0) 608 break; 609 debug3("Received %d SSH2_FXP_NAME responses", count); 610 for (i = 0; i < count; i++) { 611 char *filename, *longname; 612 Attrib a; 613 614 if ((r = sshbuf_get_cstring(msg, &filename, 615 NULL)) != 0 || 616 (r = sshbuf_get_cstring(msg, &longname, 617 NULL)) != 0) 618 fatal("%s: buffer error: %s", 619 __func__, ssh_err(r)); 620 if ((r = decode_attrib(msg, &a)) != 0) { 621 error("%s: couldn't decode attrib: %s", 622 __func__, ssh_err(r)); 623 free(filename); 624 free(longname); 625 goto out; 626 } 627 628 if (print_flag) 629 mprintf("%s\n", longname); 630 631 /* 632 * Directory entries should never contain '/' 633 * These can be used to attack recursive ops 634 * (e.g. send '../../../../etc/passwd') 635 */ 636 if (strchr(filename, '/') != NULL) { 637 error("Server sent suspect path \"%s\" " 638 "during readdir of \"%s\"", filename, path); 639 } else if (dir) { 640 *dir = xreallocarray(*dir, ents + 2, sizeof(**dir)); 641 (*dir)[ents] = xcalloc(1, sizeof(***dir)); 642 (*dir)[ents]->filename = xstrdup(filename); 643 (*dir)[ents]->longname = xstrdup(longname); 644 memcpy(&(*dir)[ents]->a, &a, sizeof(a)); 645 (*dir)[++ents] = NULL; 646 } 647 free(filename); 648 free(longname); 649 } 650 } 651 status = 0; 652 653 out: 654 sshbuf_free(msg); 655 do_close(conn, handle, handle_len); 656 free(handle); 657 658 if (status != 0 && dir != NULL) { 659 /* Don't return results on error */ 660 free_sftp_dirents(*dir); 661 *dir = NULL; 662 } else if (interrupted && dir != NULL && *dir != NULL) { 663 /* Don't return partial matches on interrupt */ 664 free_sftp_dirents(*dir); 665 *dir = xcalloc(1, sizeof(**dir)); 666 **dir = NULL; 667 } 668 669 return status == SSH2_FX_OK ? 0 : -1; 670 } 671 672 int 673 do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) 674 { 675 return(do_lsreaddir(conn, path, 0, dir)); 676 } 677 678 void free_sftp_dirents(SFTP_DIRENT **s) 679 { 680 int i; 681 682 if (s == NULL) 683 return; 684 for (i = 0; s[i]; i++) { 685 free(s[i]->filename); 686 free(s[i]->longname); 687 free(s[i]); 688 } 689 free(s); 690 } 691 692 int 693 do_rm(struct sftp_conn *conn, const char *path) 694 { 695 u_int status, id; 696 697 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); 698 699 id = conn->msg_id++; 700 send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path)); 701 status = get_status(conn, id); 702 if (status != SSH2_FX_OK) 703 error("Couldn't delete file: %s", fx2txt(status)); 704 return status == SSH2_FX_OK ? 0 : -1; 705 } 706 707 int 708 do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag) 709 { 710 u_int status, id; 711 712 id = conn->msg_id++; 713 send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path, 714 strlen(path), a); 715 716 status = get_status(conn, id); 717 if (status != SSH2_FX_OK && print_flag) 718 error("Couldn't create directory: %s", fx2txt(status)); 719 720 return status == SSH2_FX_OK ? 0 : -1; 721 } 722 723 int 724 do_rmdir(struct sftp_conn *conn, const char *path) 725 { 726 u_int status, id; 727 728 id = conn->msg_id++; 729 send_string_request(conn, id, SSH2_FXP_RMDIR, path, 730 strlen(path)); 731 732 status = get_status(conn, id); 733 if (status != SSH2_FX_OK) 734 error("Couldn't remove directory: %s", fx2txt(status)); 735 736 return status == SSH2_FX_OK ? 0 : -1; 737 } 738 739 Attrib * 740 do_stat(struct sftp_conn *conn, const char *path, int quiet) 741 { 742 u_int id; 743 744 id = conn->msg_id++; 745 746 send_string_request(conn, id, 747 conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, 748 path, strlen(path)); 749 750 return(get_decode_stat(conn, id, quiet)); 751 } 752 753 Attrib * 754 do_lstat(struct sftp_conn *conn, const char *path, int quiet) 755 { 756 u_int id; 757 758 if (conn->version == 0) { 759 if (quiet) 760 debug("Server version does not support lstat operation"); 761 else 762 logit("Server version does not support lstat operation"); 763 return(do_stat(conn, path, quiet)); 764 } 765 766 id = conn->msg_id++; 767 send_string_request(conn, id, SSH2_FXP_LSTAT, path, 768 strlen(path)); 769 770 return(get_decode_stat(conn, id, quiet)); 771 } 772 773 #ifdef notyet 774 Attrib * 775 do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 776 int quiet) 777 { 778 u_int id; 779 780 id = conn->msg_id++; 781 send_string_request(conn, id, SSH2_FXP_FSTAT, handle, 782 handle_len); 783 784 return(get_decode_stat(conn, id, quiet)); 785 } 786 #endif 787 788 int 789 do_setstat(struct sftp_conn *conn, const char *path, Attrib *a) 790 { 791 u_int status, id; 792 793 id = conn->msg_id++; 794 send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path, 795 strlen(path), a); 796 797 status = get_status(conn, id); 798 if (status != SSH2_FX_OK) 799 error("Couldn't setstat on \"%s\": %s", path, 800 fx2txt(status)); 801 802 return status == SSH2_FX_OK ? 0 : -1; 803 } 804 805 int 806 do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 807 Attrib *a) 808 { 809 u_int status, id; 810 811 id = conn->msg_id++; 812 send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle, 813 handle_len, a); 814 815 status = get_status(conn, id); 816 if (status != SSH2_FX_OK) 817 error("Couldn't fsetstat: %s", fx2txt(status)); 818 819 return status == SSH2_FX_OK ? 0 : -1; 820 } 821 822 char * 823 do_realpath(struct sftp_conn *conn, const char *path) 824 { 825 struct sshbuf *msg; 826 u_int expected_id, count, id; 827 char *filename, *longname; 828 Attrib a; 829 u_char type; 830 int r; 831 832 expected_id = id = conn->msg_id++; 833 send_string_request(conn, id, SSH2_FXP_REALPATH, path, 834 strlen(path)); 835 836 if ((msg = sshbuf_new()) == NULL) 837 fatal("%s: sshbuf_new failed", __func__); 838 839 get_msg(conn, msg); 840 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 841 (r = sshbuf_get_u32(msg, &id)) != 0) 842 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 843 844 if (id != expected_id) 845 fatal("ID mismatch (%u != %u)", id, expected_id); 846 847 if (type == SSH2_FXP_STATUS) { 848 u_int status; 849 850 if ((r = sshbuf_get_u32(msg, &status)) != 0) 851 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 852 error("Couldn't canonicalize: %s", fx2txt(status)); 853 sshbuf_free(msg); 854 return NULL; 855 } else if (type != SSH2_FXP_NAME) 856 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 857 SSH2_FXP_NAME, type); 858 859 if ((r = sshbuf_get_u32(msg, &count)) != 0) 860 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 861 if (count != 1) 862 fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count); 863 864 if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || 865 (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || 866 (r = decode_attrib(msg, &a)) != 0) 867 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 868 869 debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename, 870 (unsigned long)a.size); 871 872 free(longname); 873 874 sshbuf_free(msg); 875 876 return(filename); 877 } 878 879 int 880 do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, 881 int force_legacy) 882 { 883 struct sshbuf *msg; 884 u_int status, id; 885 int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; 886 887 if ((msg = sshbuf_new()) == NULL) 888 fatal("%s: sshbuf_new failed", __func__); 889 890 /* Send rename request */ 891 id = conn->msg_id++; 892 if (use_ext) { 893 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 894 (r = sshbuf_put_u32(msg, id)) != 0 || 895 (r = sshbuf_put_cstring(msg, 896 "posix-rename@openssh.com")) != 0) 897 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 898 } else { 899 if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 || 900 (r = sshbuf_put_u32(msg, id)) != 0) 901 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 902 } 903 if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 || 904 (r = sshbuf_put_cstring(msg, newpath)) != 0) 905 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 906 send_msg(conn, msg); 907 debug3("Sent message %s \"%s\" -> \"%s\"", 908 use_ext ? "posix-rename@openssh.com" : 909 "SSH2_FXP_RENAME", oldpath, newpath); 910 sshbuf_free(msg); 911 912 status = get_status(conn, id); 913 if (status != SSH2_FX_OK) 914 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, 915 newpath, fx2txt(status)); 916 917 return status == SSH2_FX_OK ? 0 : -1; 918 } 919 920 int 921 do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) 922 { 923 struct sshbuf *msg; 924 u_int status, id; 925 int r; 926 927 if ((conn->exts & SFTP_EXT_HARDLINK) == 0) { 928 error("Server does not support hardlink@openssh.com extension"); 929 return -1; 930 } 931 932 if ((msg = sshbuf_new()) == NULL) 933 fatal("%s: sshbuf_new failed", __func__); 934 935 /* Send link request */ 936 id = conn->msg_id++; 937 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 938 (r = sshbuf_put_u32(msg, id)) != 0 || 939 (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 || 940 (r = sshbuf_put_cstring(msg, oldpath)) != 0 || 941 (r = sshbuf_put_cstring(msg, newpath)) != 0) 942 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 943 send_msg(conn, msg); 944 debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"", 945 oldpath, newpath); 946 sshbuf_free(msg); 947 948 status = get_status(conn, id); 949 if (status != SSH2_FX_OK) 950 error("Couldn't link file \"%s\" to \"%s\": %s", oldpath, 951 newpath, fx2txt(status)); 952 953 return status == SSH2_FX_OK ? 0 : -1; 954 } 955 956 int 957 do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) 958 { 959 struct sshbuf *msg; 960 u_int status, id; 961 int r; 962 963 if (conn->version < 3) { 964 error("This server does not support the symlink operation"); 965 return(SSH2_FX_OP_UNSUPPORTED); 966 } 967 968 if ((msg = sshbuf_new()) == NULL) 969 fatal("%s: sshbuf_new failed", __func__); 970 971 /* Send symlink request */ 972 id = conn->msg_id++; 973 if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 || 974 (r = sshbuf_put_u32(msg, id)) != 0 || 975 (r = sshbuf_put_cstring(msg, oldpath)) != 0 || 976 (r = sshbuf_put_cstring(msg, newpath)) != 0) 977 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 978 send_msg(conn, msg); 979 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, 980 newpath); 981 sshbuf_free(msg); 982 983 status = get_status(conn, id); 984 if (status != SSH2_FX_OK) 985 error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, 986 newpath, fx2txt(status)); 987 988 return status == SSH2_FX_OK ? 0 : -1; 989 } 990 991 int 992 do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len) 993 { 994 struct sshbuf *msg; 995 u_int status, id; 996 int r; 997 998 /* Silently return if the extension is not supported */ 999 if ((conn->exts & SFTP_EXT_FSYNC) == 0) 1000 return -1; 1001 1002 /* Send fsync request */ 1003 if ((msg = sshbuf_new()) == NULL) 1004 fatal("%s: sshbuf_new failed", __func__); 1005 id = conn->msg_id++; 1006 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1007 (r = sshbuf_put_u32(msg, id)) != 0 || 1008 (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || 1009 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 1010 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1011 send_msg(conn, msg); 1012 debug3("Sent message fsync@openssh.com I:%u", id); 1013 sshbuf_free(msg); 1014 1015 status = get_status(conn, id); 1016 if (status != SSH2_FX_OK) 1017 error("Couldn't sync file: %s", fx2txt(status)); 1018 1019 return status == SSH2_FX_OK ? 0 : -1; 1020 } 1021 1022 #ifdef notyet 1023 char * 1024 do_readlink(struct sftp_conn *conn, const char *path) 1025 { 1026 struct sshbuf *msg; 1027 u_int expected_id, count, id; 1028 char *filename, *longname; 1029 Attrib a; 1030 u_char type; 1031 int r; 1032 1033 expected_id = id = conn->msg_id++; 1034 send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); 1035 1036 if ((msg = sshbuf_new()) == NULL) 1037 fatal("%s: sshbuf_new failed", __func__); 1038 1039 get_msg(conn, msg); 1040 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1041 (r = sshbuf_get_u32(msg, &id)) != 0) 1042 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1043 1044 if (id != expected_id) 1045 fatal("ID mismatch (%u != %u)", id, expected_id); 1046 1047 if (type == SSH2_FXP_STATUS) { 1048 u_int status; 1049 1050 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1051 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1052 error("Couldn't readlink: %s", fx2txt(status)); 1053 sshbuf_free(msg); 1054 return(NULL); 1055 } else if (type != SSH2_FXP_NAME) 1056 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 1057 SSH2_FXP_NAME, type); 1058 1059 if ((r = sshbuf_get_u32(msg, &count)) != 0) 1060 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1061 if (count != 1) 1062 fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); 1063 1064 if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || 1065 (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || 1066 (r = decode_attrib(msg, &a)) != 0) 1067 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1068 1069 debug3("SSH_FXP_READLINK %s -> %s", path, filename); 1070 1071 free(longname); 1072 1073 sshbuf_free(msg); 1074 1075 return filename; 1076 } 1077 #endif 1078 1079 int 1080 do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, 1081 int quiet) 1082 { 1083 struct sshbuf *msg; 1084 u_int id; 1085 int r; 1086 1087 if ((conn->exts & SFTP_EXT_STATVFS) == 0) { 1088 error("Server does not support statvfs@openssh.com extension"); 1089 return -1; 1090 } 1091 1092 id = conn->msg_id++; 1093 1094 if ((msg = sshbuf_new()) == NULL) 1095 fatal("%s: sshbuf_new failed", __func__); 1096 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1097 (r = sshbuf_put_u32(msg, id)) != 0 || 1098 (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 || 1099 (r = sshbuf_put_cstring(msg, path)) != 0) 1100 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1101 send_msg(conn, msg); 1102 sshbuf_free(msg); 1103 1104 return get_decode_statvfs(conn, st, id, quiet); 1105 } 1106 1107 #ifdef notyet 1108 int 1109 do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 1110 struct sftp_statvfs *st, int quiet) 1111 { 1112 struct sshbuf *msg; 1113 u_int id; 1114 1115 if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) { 1116 error("Server does not support fstatvfs@openssh.com extension"); 1117 return -1; 1118 } 1119 1120 id = conn->msg_id++; 1121 1122 if ((msg = sshbuf_new()) == NULL) 1123 fatal("%s: sshbuf_new failed", __func__); 1124 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1125 (r = sshbuf_put_u32(msg, id)) != 0 || 1126 (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 || 1127 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 1128 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1129 send_msg(conn, msg); 1130 sshbuf_free(msg); 1131 1132 return get_decode_statvfs(conn, st, id, quiet); 1133 } 1134 #endif 1135 1136 int 1137 do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a) 1138 { 1139 struct sshbuf *msg; 1140 u_int status, id; 1141 int r; 1142 1143 if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) { 1144 error("Server does not support lsetstat@openssh.com extension"); 1145 return -1; 1146 } 1147 1148 id = conn->msg_id++; 1149 if ((msg = sshbuf_new()) == NULL) 1150 fatal("%s: sshbuf_new failed", __func__); 1151 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1152 (r = sshbuf_put_u32(msg, id)) != 0 || 1153 (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 || 1154 (r = sshbuf_put_cstring(msg, path)) != 0 || 1155 (r = encode_attrib(msg, a)) != 0) 1156 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1157 send_msg(conn, msg); 1158 sshbuf_free(msg); 1159 1160 status = get_status(conn, id); 1161 if (status != SSH2_FX_OK) 1162 error("Couldn't setstat on \"%s\": %s", path, 1163 fx2txt(status)); 1164 1165 return status == SSH2_FX_OK ? 0 : -1; 1166 } 1167 1168 static void 1169 send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, 1170 u_int len, const u_char *handle, u_int handle_len) 1171 { 1172 struct sshbuf *msg; 1173 int r; 1174 1175 if ((msg = sshbuf_new()) == NULL) 1176 fatal("%s: sshbuf_new failed", __func__); 1177 if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 || 1178 (r = sshbuf_put_u32(msg, id)) != 0 || 1179 (r = sshbuf_put_string(msg, handle, handle_len)) != 0 || 1180 (r = sshbuf_put_u64(msg, offset)) != 0 || 1181 (r = sshbuf_put_u32(msg, len)) != 0) 1182 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1183 send_msg(conn, msg); 1184 sshbuf_free(msg); 1185 } 1186 1187 int 1188 do_download(struct sftp_conn *conn, const char *remote_path, 1189 const char *local_path, Attrib *a, int preserve_flag, int resume_flag, 1190 int fsync_flag) 1191 { 1192 Attrib junk; 1193 struct sshbuf *msg; 1194 u_char *handle; 1195 int local_fd = -1, write_error; 1196 int read_error, write_errno, lmodified = 0, reordered = 0, r; 1197 u_int64_t offset = 0, size, highwater; 1198 u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK; 1199 off_t progress_counter; 1200 size_t handle_len; 1201 struct stat st; 1202 struct request { 1203 u_int id; 1204 size_t len; 1205 u_int64_t offset; 1206 TAILQ_ENTRY(request) tq; 1207 }; 1208 TAILQ_HEAD(reqhead, request) requests; 1209 struct request *req; 1210 u_char type; 1211 1212 status = -1; 1213 TAILQ_INIT(&requests); 1214 1215 if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL) 1216 return -1; 1217 1218 /* Do not preserve set[ug]id here, as we do not preserve ownership */ 1219 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) 1220 mode = a->perm & 0777; 1221 else 1222 mode = 0666; 1223 1224 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && 1225 (!S_ISREG(a->perm))) { 1226 error("Cannot download non-regular file: %s", remote_path); 1227 return(-1); 1228 } 1229 1230 if (a->flags & SSH2_FILEXFER_ATTR_SIZE) 1231 size = a->size; 1232 else 1233 size = 0; 1234 1235 buflen = conn->transfer_buflen; 1236 if ((msg = sshbuf_new()) == NULL) 1237 fatal("%s: sshbuf_new failed", __func__); 1238 1239 attrib_clear(&junk); /* Send empty attributes */ 1240 1241 /* Send open request */ 1242 id = conn->msg_id++; 1243 if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || 1244 (r = sshbuf_put_u32(msg, id)) != 0 || 1245 (r = sshbuf_put_cstring(msg, remote_path)) != 0 || 1246 (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 || 1247 (r = encode_attrib(msg, &junk)) != 0) 1248 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1249 send_msg(conn, msg); 1250 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1251 1252 handle = get_handle(conn, id, &handle_len, 1253 "remote open(\"%s\")", remote_path); 1254 if (handle == NULL) { 1255 sshbuf_free(msg); 1256 return(-1); 1257 } 1258 1259 local_fd = open(local_path, 1260 O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR); 1261 if (local_fd == -1) { 1262 error("Couldn't open local file \"%s\" for writing: %s", 1263 local_path, strerror(errno)); 1264 goto fail; 1265 } 1266 offset = highwater = 0; 1267 if (resume_flag) { 1268 if (fstat(local_fd, &st) == -1) { 1269 error("Unable to stat local file \"%s\": %s", 1270 local_path, strerror(errno)); 1271 goto fail; 1272 } 1273 if (st.st_size < 0) { 1274 error("\"%s\" has negative size", local_path); 1275 goto fail; 1276 } 1277 if ((u_int64_t)st.st_size > size) { 1278 error("Unable to resume download of \"%s\": " 1279 "local file is larger than remote", local_path); 1280 fail: 1281 do_close(conn, handle, handle_len); 1282 sshbuf_free(msg); 1283 free(handle); 1284 if (local_fd != -1) 1285 close(local_fd); 1286 return -1; 1287 } 1288 offset = highwater = st.st_size; 1289 } 1290 1291 /* Read from remote and write to local */ 1292 write_error = read_error = write_errno = num_req = 0; 1293 max_req = 1; 1294 progress_counter = offset; 1295 1296 if (showprogress && size != 0) 1297 start_progress_meter(remote_path, size, &progress_counter); 1298 1299 while (num_req > 0 || max_req > 0) { 1300 u_char *data; 1301 size_t len; 1302 1303 /* 1304 * Simulate EOF on interrupt: stop sending new requests and 1305 * allow outstanding requests to drain gracefully 1306 */ 1307 if (interrupted) { 1308 if (num_req == 0) /* If we haven't started yet... */ 1309 break; 1310 max_req = 0; 1311 } 1312 1313 /* Send some more requests */ 1314 while (num_req < max_req) { 1315 debug3("Request range %llu -> %llu (%d/%d)", 1316 (unsigned long long)offset, 1317 (unsigned long long)offset + buflen - 1, 1318 num_req, max_req); 1319 req = xcalloc(1, sizeof(*req)); 1320 req->id = conn->msg_id++; 1321 req->len = buflen; 1322 req->offset = offset; 1323 offset += buflen; 1324 num_req++; 1325 TAILQ_INSERT_TAIL(&requests, req, tq); 1326 send_read_request(conn, req->id, req->offset, 1327 req->len, handle, handle_len); 1328 } 1329 1330 sshbuf_reset(msg); 1331 get_msg(conn, msg); 1332 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1333 (r = sshbuf_get_u32(msg, &id)) != 0) 1334 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1335 debug3("Received reply T:%u I:%u R:%d", type, id, max_req); 1336 1337 /* Find the request in our queue */ 1338 for (req = TAILQ_FIRST(&requests); 1339 req != NULL && req->id != id; 1340 req = TAILQ_NEXT(req, tq)) 1341 ; 1342 if (req == NULL) 1343 fatal("Unexpected reply %u", id); 1344 1345 switch (type) { 1346 case SSH2_FXP_STATUS: 1347 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1348 fatal("%s: buffer error: %s", 1349 __func__, ssh_err(r)); 1350 if (status != SSH2_FX_EOF) 1351 read_error = 1; 1352 max_req = 0; 1353 TAILQ_REMOVE(&requests, req, tq); 1354 free(req); 1355 num_req--; 1356 break; 1357 case SSH2_FXP_DATA: 1358 if ((r = sshbuf_get_string(msg, &data, &len)) != 0) 1359 fatal("%s: buffer error: %s", 1360 __func__, ssh_err(r)); 1361 debug3("Received data %llu -> %llu", 1362 (unsigned long long)req->offset, 1363 (unsigned long long)req->offset + len - 1); 1364 if (len > req->len) 1365 fatal("Received more data than asked for " 1366 "%zu > %zu", len, req->len); 1367 lmodified = 1; 1368 if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || 1369 atomicio(vwrite, local_fd, data, len) != len) && 1370 !write_error) { 1371 write_errno = errno; 1372 write_error = 1; 1373 max_req = 0; 1374 } 1375 else if (!reordered && req->offset <= highwater) 1376 highwater = req->offset + len; 1377 else if (!reordered && req->offset > highwater) 1378 reordered = 1; 1379 progress_counter += len; 1380 free(data); 1381 1382 if (len == req->len) { 1383 TAILQ_REMOVE(&requests, req, tq); 1384 free(req); 1385 num_req--; 1386 } else { 1387 /* Resend the request for the missing data */ 1388 debug3("Short data block, re-requesting " 1389 "%llu -> %llu (%2d)", 1390 (unsigned long long)req->offset + len, 1391 (unsigned long long)req->offset + 1392 req->len - 1, num_req); 1393 req->id = conn->msg_id++; 1394 req->len -= len; 1395 req->offset += len; 1396 send_read_request(conn, req->id, 1397 req->offset, req->len, handle, handle_len); 1398 /* Reduce the request size */ 1399 if (len < buflen) 1400 buflen = MAXIMUM(MIN_READ_SIZE, len); 1401 } 1402 if (max_req > 0) { /* max_req = 0 iff EOF received */ 1403 if (size > 0 && offset > size) { 1404 /* Only one request at a time 1405 * after the expected EOF */ 1406 debug3("Finish at %llu (%2d)", 1407 (unsigned long long)offset, 1408 num_req); 1409 max_req = 1; 1410 } else if (max_req <= conn->num_requests) { 1411 ++max_req; 1412 } 1413 } 1414 break; 1415 default: 1416 fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", 1417 SSH2_FXP_DATA, type); 1418 } 1419 } 1420 1421 if (showprogress && size) 1422 stop_progress_meter(); 1423 1424 /* Sanity check */ 1425 if (TAILQ_FIRST(&requests) != NULL) 1426 fatal("Transfer complete, but requests still in queue"); 1427 /* Truncate at highest contiguous point to avoid holes on interrupt */ 1428 if (read_error || write_error || interrupted) { 1429 if (reordered && resume_flag) { 1430 error("Unable to resume download of \"%s\": " 1431 "server reordered requests", local_path); 1432 } 1433 debug("truncating at %llu", (unsigned long long)highwater); 1434 if (ftruncate(local_fd, highwater) == -1) 1435 error("ftruncate \"%s\": %s", local_path, 1436 strerror(errno)); 1437 } 1438 if (read_error) { 1439 error("Couldn't read from remote file \"%s\" : %s", 1440 remote_path, fx2txt(status)); 1441 status = -1; 1442 do_close(conn, handle, handle_len); 1443 } else if (write_error) { 1444 error("Couldn't write to \"%s\": %s", local_path, 1445 strerror(write_errno)); 1446 status = SSH2_FX_FAILURE; 1447 do_close(conn, handle, handle_len); 1448 } else { 1449 if (do_close(conn, handle, handle_len) != 0 || interrupted) 1450 status = SSH2_FX_FAILURE; 1451 else 1452 status = SSH2_FX_OK; 1453 /* Override umask and utimes if asked */ 1454 if (preserve_flag && fchmod(local_fd, mode) == -1) 1455 error("Couldn't set mode on \"%s\": %s", local_path, 1456 strerror(errno)); 1457 if (preserve_flag && 1458 (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { 1459 struct timeval tv[2]; 1460 tv[0].tv_sec = a->atime; 1461 tv[1].tv_sec = a->mtime; 1462 tv[0].tv_usec = tv[1].tv_usec = 0; 1463 if (utimes(local_path, tv) == -1) 1464 error("Can't set times on \"%s\": %s", 1465 local_path, strerror(errno)); 1466 } 1467 if (resume_flag && !lmodified) 1468 logit("File \"%s\" was not modified", local_path); 1469 else if (fsync_flag) { 1470 debug("syncing \"%s\"", local_path); 1471 if (fsync(local_fd) == -1) 1472 error("Couldn't sync file \"%s\": %s", 1473 local_path, strerror(errno)); 1474 } 1475 } 1476 close(local_fd); 1477 sshbuf_free(msg); 1478 free(handle); 1479 1480 return status == SSH2_FX_OK ? 0 : -1; 1481 } 1482 1483 static int 1484 download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, 1485 int depth, Attrib *dirattrib, int preserve_flag, int print_flag, 1486 int resume_flag, int fsync_flag) 1487 { 1488 int i, ret = 0; 1489 SFTP_DIRENT **dir_entries; 1490 char *filename, *new_src = NULL, *new_dst = NULL; 1491 mode_t mode = 0777; 1492 1493 if (depth >= MAX_DIR_DEPTH) { 1494 error("Maximum directory depth exceeded: %d levels", depth); 1495 return -1; 1496 } 1497 1498 if (dirattrib == NULL && 1499 (dirattrib = do_stat(conn, src, 1)) == NULL) { 1500 error("Unable to stat remote directory \"%s\"", src); 1501 return -1; 1502 } 1503 if (!S_ISDIR(dirattrib->perm)) { 1504 error("\"%s\" is not a directory", src); 1505 return -1; 1506 } 1507 if (print_flag) 1508 mprintf("Retrieving %s\n", src); 1509 1510 if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) 1511 mode = dirattrib->perm & 01777; 1512 else { 1513 debug("Server did not send permissions for " 1514 "directory \"%s\"", dst); 1515 } 1516 1517 if (mkdir(dst, mode) == -1 && errno != EEXIST) { 1518 error("mkdir %s: %s", dst, strerror(errno)); 1519 return -1; 1520 } 1521 1522 if (do_readdir(conn, src, &dir_entries) == -1) { 1523 error("%s: Failed to get directory contents", src); 1524 return -1; 1525 } 1526 1527 for (i = 0; dir_entries[i] != NULL && !interrupted; i++) { 1528 free(new_dst); 1529 free(new_src); 1530 1531 filename = dir_entries[i]->filename; 1532 new_dst = path_append(dst, filename); 1533 new_src = path_append(src, filename); 1534 1535 if (S_ISDIR(dir_entries[i]->a.perm)) { 1536 if (strcmp(filename, ".") == 0 || 1537 strcmp(filename, "..") == 0) 1538 continue; 1539 if (download_dir_internal(conn, new_src, new_dst, 1540 depth + 1, &(dir_entries[i]->a), preserve_flag, 1541 print_flag, resume_flag, fsync_flag) == -1) 1542 ret = -1; 1543 } else if (S_ISREG(dir_entries[i]->a.perm) ) { 1544 if (do_download(conn, new_src, new_dst, 1545 &(dir_entries[i]->a), preserve_flag, 1546 resume_flag, fsync_flag) == -1) { 1547 error("Download of file %s to %s failed", 1548 new_src, new_dst); 1549 ret = -1; 1550 } 1551 } else 1552 logit("%s: not a regular file\n", new_src); 1553 1554 } 1555 free(new_dst); 1556 free(new_src); 1557 1558 if (preserve_flag) { 1559 if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { 1560 struct timeval tv[2]; 1561 tv[0].tv_sec = dirattrib->atime; 1562 tv[1].tv_sec = dirattrib->mtime; 1563 tv[0].tv_usec = tv[1].tv_usec = 0; 1564 if (utimes(dst, tv) == -1) 1565 error("Can't set times on \"%s\": %s", 1566 dst, strerror(errno)); 1567 } else 1568 debug("Server did not send times for directory " 1569 "\"%s\"", dst); 1570 } 1571 1572 free_sftp_dirents(dir_entries); 1573 1574 return ret; 1575 } 1576 1577 int 1578 download_dir(struct sftp_conn *conn, const char *src, const char *dst, 1579 Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, 1580 int fsync_flag) 1581 { 1582 char *src_canon; 1583 int ret; 1584 1585 if ((src_canon = do_realpath(conn, src)) == NULL) { 1586 error("Unable to canonicalize path \"%s\"", src); 1587 return -1; 1588 } 1589 1590 ret = download_dir_internal(conn, src_canon, dst, 0, 1591 dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag); 1592 free(src_canon); 1593 return ret; 1594 } 1595 1596 int 1597 do_upload(struct sftp_conn *conn, const char *local_path, 1598 const char *remote_path, int preserve_flag, int resume, int fsync_flag) 1599 { 1600 int r, local_fd; 1601 u_int status = SSH2_FX_OK; 1602 u_int id; 1603 u_char type; 1604 off_t offset, progress_counter; 1605 u_char *handle, *data; 1606 struct sshbuf *msg; 1607 struct stat sb; 1608 Attrib a, *c = NULL; 1609 u_int32_t startid; 1610 u_int32_t ackid; 1611 struct outstanding_ack { 1612 u_int id; 1613 u_int len; 1614 off_t offset; 1615 TAILQ_ENTRY(outstanding_ack) tq; 1616 }; 1617 TAILQ_HEAD(ackhead, outstanding_ack) acks; 1618 struct outstanding_ack *ack = NULL; 1619 size_t handle_len; 1620 1621 TAILQ_INIT(&acks); 1622 1623 if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) { 1624 error("Couldn't open local file \"%s\" for reading: %s", 1625 local_path, strerror(errno)); 1626 return(-1); 1627 } 1628 if (fstat(local_fd, &sb) == -1) { 1629 error("Couldn't fstat local file \"%s\": %s", 1630 local_path, strerror(errno)); 1631 close(local_fd); 1632 return(-1); 1633 } 1634 if (!S_ISREG(sb.st_mode)) { 1635 error("%s is not a regular file", local_path); 1636 close(local_fd); 1637 return(-1); 1638 } 1639 stat_to_attrib(&sb, &a); 1640 1641 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 1642 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 1643 a.perm &= 0777; 1644 if (!preserve_flag) 1645 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 1646 1647 if (resume) { 1648 /* Get remote file size if it exists */ 1649 if ((c = do_stat(conn, remote_path, 0)) == NULL) { 1650 close(local_fd); 1651 return -1; 1652 } 1653 1654 if ((off_t)c->size >= sb.st_size) { 1655 error("destination file bigger or same size as " 1656 "source file"); 1657 close(local_fd); 1658 return -1; 1659 } 1660 1661 if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) { 1662 close(local_fd); 1663 return -1; 1664 } 1665 } 1666 1667 if ((msg = sshbuf_new()) == NULL) 1668 fatal("%s: sshbuf_new failed", __func__); 1669 1670 /* Send open request */ 1671 id = conn->msg_id++; 1672 if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || 1673 (r = sshbuf_put_u32(msg, id)) != 0 || 1674 (r = sshbuf_put_cstring(msg, remote_path)) != 0 || 1675 (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| 1676 (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 || 1677 (r = encode_attrib(msg, &a)) != 0) 1678 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1679 send_msg(conn, msg); 1680 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1681 1682 sshbuf_reset(msg); 1683 1684 handle = get_handle(conn, id, &handle_len, 1685 "remote open(\"%s\")", remote_path); 1686 if (handle == NULL) { 1687 close(local_fd); 1688 sshbuf_free(msg); 1689 return -1; 1690 } 1691 1692 startid = ackid = id + 1; 1693 data = xmalloc(conn->transfer_buflen); 1694 1695 /* Read from local and write to remote */ 1696 offset = progress_counter = (resume ? c->size : 0); 1697 if (showprogress) 1698 start_progress_meter(local_path, sb.st_size, 1699 &progress_counter); 1700 1701 for (;;) { 1702 int len; 1703 1704 /* 1705 * Can't use atomicio here because it returns 0 on EOF, 1706 * thus losing the last block of the file. 1707 * Simulate an EOF on interrupt, allowing ACKs from the 1708 * server to drain. 1709 */ 1710 if (interrupted || status != SSH2_FX_OK) 1711 len = 0; 1712 else do 1713 len = read(local_fd, data, conn->transfer_buflen); 1714 while ((len == -1) && (errno == EINTR || errno == EAGAIN)); 1715 1716 if (len == -1) 1717 fatal("Couldn't read from \"%s\": %s", local_path, 1718 strerror(errno)); 1719 1720 if (len != 0) { 1721 ack = xcalloc(1, sizeof(*ack)); 1722 ack->id = ++id; 1723 ack->offset = offset; 1724 ack->len = len; 1725 TAILQ_INSERT_TAIL(&acks, ack, tq); 1726 1727 sshbuf_reset(msg); 1728 if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || 1729 (r = sshbuf_put_u32(msg, ack->id)) != 0 || 1730 (r = sshbuf_put_string(msg, handle, 1731 handle_len)) != 0 || 1732 (r = sshbuf_put_u64(msg, offset)) != 0 || 1733 (r = sshbuf_put_string(msg, data, len)) != 0) 1734 fatal("%s: buffer error: %s", 1735 __func__, ssh_err(r)); 1736 send_msg(conn, msg); 1737 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", 1738 id, (unsigned long long)offset, len); 1739 } else if (TAILQ_FIRST(&acks) == NULL) 1740 break; 1741 1742 if (ack == NULL) 1743 fatal("Unexpected ACK %u", id); 1744 1745 if (id == startid || len == 0 || 1746 id - ackid >= conn->num_requests) { 1747 u_int rid; 1748 1749 sshbuf_reset(msg); 1750 get_msg(conn, msg); 1751 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1752 (r = sshbuf_get_u32(msg, &rid)) != 0) 1753 fatal("%s: buffer error: %s", 1754 __func__, ssh_err(r)); 1755 1756 if (type != SSH2_FXP_STATUS) 1757 fatal("Expected SSH2_FXP_STATUS(%d) packet, " 1758 "got %d", SSH2_FXP_STATUS, type); 1759 1760 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1761 fatal("%s: buffer error: %s", 1762 __func__, ssh_err(r)); 1763 debug3("SSH2_FXP_STATUS %u", status); 1764 1765 /* Find the request in our queue */ 1766 for (ack = TAILQ_FIRST(&acks); 1767 ack != NULL && ack->id != rid; 1768 ack = TAILQ_NEXT(ack, tq)) 1769 ; 1770 if (ack == NULL) 1771 fatal("Can't find request for ID %u", rid); 1772 TAILQ_REMOVE(&acks, ack, tq); 1773 debug3("In write loop, ack for %u %u bytes at %lld", 1774 ack->id, ack->len, (long long)ack->offset); 1775 ++ackid; 1776 progress_counter += ack->len; 1777 free(ack); 1778 } 1779 offset += len; 1780 if (offset < 0) 1781 fatal("%s: offset < 0", __func__); 1782 } 1783 sshbuf_free(msg); 1784 1785 if (showprogress) 1786 stop_progress_meter(); 1787 free(data); 1788 1789 if (status != SSH2_FX_OK) { 1790 error("Couldn't write to remote file \"%s\": %s", 1791 remote_path, fx2txt(status)); 1792 status = SSH2_FX_FAILURE; 1793 } 1794 1795 if (close(local_fd) == -1) { 1796 error("Couldn't close local file \"%s\": %s", local_path, 1797 strerror(errno)); 1798 status = SSH2_FX_FAILURE; 1799 } 1800 1801 /* Override umask and utimes if asked */ 1802 if (preserve_flag) 1803 do_fsetstat(conn, handle, handle_len, &a); 1804 1805 if (fsync_flag) 1806 (void)do_fsync(conn, handle, handle_len); 1807 1808 if (do_close(conn, handle, handle_len) != 0) 1809 status = SSH2_FX_FAILURE; 1810 1811 free(handle); 1812 1813 return status == SSH2_FX_OK ? 0 : -1; 1814 } 1815 1816 static int 1817 upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, 1818 int depth, int preserve_flag, int print_flag, int resume, int fsync_flag) 1819 { 1820 int ret = 0; 1821 DIR *dirp; 1822 struct dirent *dp; 1823 char *filename, *new_src = NULL, *new_dst = NULL; 1824 struct stat sb; 1825 Attrib a, *dirattrib; 1826 1827 if (depth >= MAX_DIR_DEPTH) { 1828 error("Maximum directory depth exceeded: %d levels", depth); 1829 return -1; 1830 } 1831 1832 if (stat(src, &sb) == -1) { 1833 error("Couldn't stat directory \"%s\": %s", 1834 src, strerror(errno)); 1835 return -1; 1836 } 1837 if (!S_ISDIR(sb.st_mode)) { 1838 error("\"%s\" is not a directory", src); 1839 return -1; 1840 } 1841 if (print_flag) 1842 mprintf("Entering %s\n", src); 1843 1844 attrib_clear(&a); 1845 stat_to_attrib(&sb, &a); 1846 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 1847 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 1848 a.perm &= 01777; 1849 if (!preserve_flag) 1850 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 1851 1852 /* 1853 * sftp lacks a portable status value to match errno EEXIST, 1854 * so if we get a failure back then we must check whether 1855 * the path already existed and is a directory. 1856 */ 1857 if (do_mkdir(conn, dst, &a, 0) != 0) { 1858 if ((dirattrib = do_stat(conn, dst, 0)) == NULL) 1859 return -1; 1860 if (!S_ISDIR(dirattrib->perm)) { 1861 error("\"%s\" exists but is not a directory", dst); 1862 return -1; 1863 } 1864 } 1865 1866 if ((dirp = opendir(src)) == NULL) { 1867 error("Failed to open dir \"%s\": %s", src, strerror(errno)); 1868 return -1; 1869 } 1870 1871 while (((dp = readdir(dirp)) != NULL) && !interrupted) { 1872 if (dp->d_ino == 0) 1873 continue; 1874 free(new_dst); 1875 free(new_src); 1876 filename = dp->d_name; 1877 new_dst = path_append(dst, filename); 1878 new_src = path_append(src, filename); 1879 1880 if (lstat(new_src, &sb) == -1) { 1881 logit("%s: lstat failed: %s", filename, 1882 strerror(errno)); 1883 ret = -1; 1884 } else if (S_ISDIR(sb.st_mode)) { 1885 if (strcmp(filename, ".") == 0 || 1886 strcmp(filename, "..") == 0) 1887 continue; 1888 1889 if (upload_dir_internal(conn, new_src, new_dst, 1890 depth + 1, preserve_flag, print_flag, resume, 1891 fsync_flag) == -1) 1892 ret = -1; 1893 } else if (S_ISREG(sb.st_mode)) { 1894 if (do_upload(conn, new_src, new_dst, 1895 preserve_flag, resume, fsync_flag) == -1) { 1896 error("Uploading of file %s to %s failed!", 1897 new_src, new_dst); 1898 ret = -1; 1899 } 1900 } else 1901 logit("%s: not a regular file\n", filename); 1902 } 1903 free(new_dst); 1904 free(new_src); 1905 1906 do_setstat(conn, dst, &a); 1907 1908 (void) closedir(dirp); 1909 return ret; 1910 } 1911 1912 int 1913 upload_dir(struct sftp_conn *conn, const char *src, const char *dst, 1914 int preserve_flag, int print_flag, int resume, int fsync_flag) 1915 { 1916 char *dst_canon; 1917 int ret; 1918 1919 if ((dst_canon = do_realpath(conn, dst)) == NULL) { 1920 error("Unable to canonicalize path \"%s\"", dst); 1921 return -1; 1922 } 1923 1924 ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, 1925 print_flag, resume, fsync_flag); 1926 1927 free(dst_canon); 1928 return ret; 1929 } 1930 1931 char * 1932 path_append(const char *p1, const char *p2) 1933 { 1934 char *ret; 1935 size_t len = strlen(p1) + strlen(p2) + 2; 1936 1937 ret = xmalloc(len); 1938 strlcpy(ret, p1, len); 1939 if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/') 1940 strlcat(ret, "/", len); 1941 strlcat(ret, p2, len); 1942 1943 return(ret); 1944 } 1945 1946