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