1 /* $OpenBSD: sftp-client.c,v 1.133 2019/01/24 16:52:17 dtucker 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 sshbuf_free(msg); 635 return -1; 636 } 637 638 if (print_flag) 639 mprintf("%s\n", longname); 640 641 /* 642 * Directory entries should never contain '/' 643 * These can be used to attack recursive ops 644 * (e.g. send '../../../../etc/passwd') 645 */ 646 if (strpbrk(filename, SFTP_DIRECTORY_CHARS) != NULL) { 647 error("Server sent suspect path \"%s\" " 648 "during readdir of \"%s\"", filename, path); 649 } else if (dir) { 650 *dir = xreallocarray(*dir, ents + 2, sizeof(**dir)); 651 (*dir)[ents] = xcalloc(1, sizeof(***dir)); 652 (*dir)[ents]->filename = xstrdup(filename); 653 (*dir)[ents]->longname = xstrdup(longname); 654 memcpy(&(*dir)[ents]->a, &a, sizeof(a)); 655 (*dir)[++ents] = NULL; 656 } 657 free(filename); 658 free(longname); 659 } 660 } 661 status = 0; 662 663 out: 664 sshbuf_free(msg); 665 do_close(conn, handle, handle_len); 666 free(handle); 667 668 if (status != 0 && dir != NULL) { 669 /* Don't return results on error */ 670 free_sftp_dirents(*dir); 671 *dir = NULL; 672 } else if (interrupted && dir != NULL && *dir != NULL) { 673 /* Don't return partial matches on interrupt */ 674 free_sftp_dirents(*dir); 675 *dir = xcalloc(1, sizeof(**dir)); 676 **dir = NULL; 677 } 678 679 return status == SSH2_FX_OK ? 0 : -1; 680 } 681 682 int 683 do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) 684 { 685 return(do_lsreaddir(conn, path, 0, dir)); 686 } 687 688 void free_sftp_dirents(SFTP_DIRENT **s) 689 { 690 int i; 691 692 if (s == NULL) 693 return; 694 for (i = 0; s[i]; i++) { 695 free(s[i]->filename); 696 free(s[i]->longname); 697 free(s[i]); 698 } 699 free(s); 700 } 701 702 int 703 do_rm(struct sftp_conn *conn, const char *path) 704 { 705 u_int status, id; 706 707 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); 708 709 id = conn->msg_id++; 710 send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path)); 711 status = get_status(conn, id); 712 if (status != SSH2_FX_OK) 713 error("Couldn't delete file: %s", fx2txt(status)); 714 return status == SSH2_FX_OK ? 0 : -1; 715 } 716 717 int 718 do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag) 719 { 720 u_int status, id; 721 722 id = conn->msg_id++; 723 send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path, 724 strlen(path), a); 725 726 status = get_status(conn, id); 727 if (status != SSH2_FX_OK && print_flag) 728 error("Couldn't create directory: %s", fx2txt(status)); 729 730 return status == SSH2_FX_OK ? 0 : -1; 731 } 732 733 int 734 do_rmdir(struct sftp_conn *conn, const char *path) 735 { 736 u_int status, id; 737 738 id = conn->msg_id++; 739 send_string_request(conn, id, SSH2_FXP_RMDIR, path, 740 strlen(path)); 741 742 status = get_status(conn, id); 743 if (status != SSH2_FX_OK) 744 error("Couldn't remove directory: %s", fx2txt(status)); 745 746 return status == SSH2_FX_OK ? 0 : -1; 747 } 748 749 Attrib * 750 do_stat(struct sftp_conn *conn, const char *path, int quiet) 751 { 752 u_int id; 753 754 id = conn->msg_id++; 755 756 send_string_request(conn, id, 757 conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, 758 path, strlen(path)); 759 760 return(get_decode_stat(conn, id, quiet)); 761 } 762 763 Attrib * 764 do_lstat(struct sftp_conn *conn, const char *path, int quiet) 765 { 766 u_int id; 767 768 if (conn->version == 0) { 769 if (quiet) 770 debug("Server version does not support lstat operation"); 771 else 772 logit("Server version does not support lstat operation"); 773 return(do_stat(conn, path, quiet)); 774 } 775 776 id = conn->msg_id++; 777 send_string_request(conn, id, SSH2_FXP_LSTAT, path, 778 strlen(path)); 779 780 return(get_decode_stat(conn, id, quiet)); 781 } 782 783 #ifdef notyet 784 Attrib * 785 do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 786 int quiet) 787 { 788 u_int id; 789 790 id = conn->msg_id++; 791 send_string_request(conn, id, SSH2_FXP_FSTAT, handle, 792 handle_len); 793 794 return(get_decode_stat(conn, id, quiet)); 795 } 796 #endif 797 798 int 799 do_setstat(struct sftp_conn *conn, const char *path, Attrib *a) 800 { 801 u_int status, id; 802 803 id = conn->msg_id++; 804 send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path, 805 strlen(path), a); 806 807 status = get_status(conn, id); 808 if (status != SSH2_FX_OK) 809 error("Couldn't setstat on \"%s\": %s", path, 810 fx2txt(status)); 811 812 return status == SSH2_FX_OK ? 0 : -1; 813 } 814 815 int 816 do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 817 Attrib *a) 818 { 819 u_int status, id; 820 821 id = conn->msg_id++; 822 send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle, 823 handle_len, a); 824 825 status = get_status(conn, id); 826 if (status != SSH2_FX_OK) 827 error("Couldn't fsetstat: %s", fx2txt(status)); 828 829 return status == SSH2_FX_OK ? 0 : -1; 830 } 831 832 char * 833 do_realpath(struct sftp_conn *conn, const char *path) 834 { 835 struct sshbuf *msg; 836 u_int expected_id, count, id; 837 char *filename, *longname; 838 Attrib a; 839 u_char type; 840 int r; 841 842 expected_id = id = conn->msg_id++; 843 send_string_request(conn, id, SSH2_FXP_REALPATH, path, 844 strlen(path)); 845 846 if ((msg = sshbuf_new()) == NULL) 847 fatal("%s: sshbuf_new failed", __func__); 848 849 get_msg(conn, msg); 850 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 851 (r = sshbuf_get_u32(msg, &id)) != 0) 852 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 853 854 if (id != expected_id) 855 fatal("ID mismatch (%u != %u)", id, expected_id); 856 857 if (type == SSH2_FXP_STATUS) { 858 u_int status; 859 860 if ((r = sshbuf_get_u32(msg, &status)) != 0) 861 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 862 error("Couldn't canonicalize: %s", fx2txt(status)); 863 sshbuf_free(msg); 864 return NULL; 865 } else if (type != SSH2_FXP_NAME) 866 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 867 SSH2_FXP_NAME, type); 868 869 if ((r = sshbuf_get_u32(msg, &count)) != 0) 870 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 871 if (count != 1) 872 fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count); 873 874 if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || 875 (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || 876 (r = decode_attrib(msg, &a)) != 0) 877 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 878 879 debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename, 880 (unsigned long)a.size); 881 882 free(longname); 883 884 sshbuf_free(msg); 885 886 return(filename); 887 } 888 889 int 890 do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, 891 int force_legacy) 892 { 893 struct sshbuf *msg; 894 u_int status, id; 895 int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; 896 897 if ((msg = sshbuf_new()) == NULL) 898 fatal("%s: sshbuf_new failed", __func__); 899 900 /* Send rename request */ 901 id = conn->msg_id++; 902 if (use_ext) { 903 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 904 (r = sshbuf_put_u32(msg, id)) != 0 || 905 (r = sshbuf_put_cstring(msg, 906 "posix-rename@openssh.com")) != 0) 907 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 908 } else { 909 if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 || 910 (r = sshbuf_put_u32(msg, id)) != 0) 911 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 912 } 913 if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 || 914 (r = sshbuf_put_cstring(msg, newpath)) != 0) 915 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 916 send_msg(conn, msg); 917 debug3("Sent message %s \"%s\" -> \"%s\"", 918 use_ext ? "posix-rename@openssh.com" : 919 "SSH2_FXP_RENAME", oldpath, newpath); 920 sshbuf_free(msg); 921 922 status = get_status(conn, id); 923 if (status != SSH2_FX_OK) 924 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, 925 newpath, fx2txt(status)); 926 927 return status == SSH2_FX_OK ? 0 : -1; 928 } 929 930 int 931 do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) 932 { 933 struct sshbuf *msg; 934 u_int status, id; 935 int r; 936 937 if ((conn->exts & SFTP_EXT_HARDLINK) == 0) { 938 error("Server does not support hardlink@openssh.com extension"); 939 return -1; 940 } 941 942 if ((msg = sshbuf_new()) == NULL) 943 fatal("%s: sshbuf_new failed", __func__); 944 945 /* Send link request */ 946 id = conn->msg_id++; 947 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 948 (r = sshbuf_put_u32(msg, id)) != 0 || 949 (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 || 950 (r = sshbuf_put_cstring(msg, oldpath)) != 0 || 951 (r = sshbuf_put_cstring(msg, newpath)) != 0) 952 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 953 send_msg(conn, msg); 954 debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"", 955 oldpath, newpath); 956 sshbuf_free(msg); 957 958 status = get_status(conn, id); 959 if (status != SSH2_FX_OK) 960 error("Couldn't link file \"%s\" to \"%s\": %s", oldpath, 961 newpath, fx2txt(status)); 962 963 return status == SSH2_FX_OK ? 0 : -1; 964 } 965 966 int 967 do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) 968 { 969 struct sshbuf *msg; 970 u_int status, id; 971 int r; 972 973 if (conn->version < 3) { 974 error("This server does not support the symlink operation"); 975 return(SSH2_FX_OP_UNSUPPORTED); 976 } 977 978 if ((msg = sshbuf_new()) == NULL) 979 fatal("%s: sshbuf_new failed", __func__); 980 981 /* Send symlink request */ 982 id = conn->msg_id++; 983 if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 || 984 (r = sshbuf_put_u32(msg, id)) != 0 || 985 (r = sshbuf_put_cstring(msg, oldpath)) != 0 || 986 (r = sshbuf_put_cstring(msg, newpath)) != 0) 987 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 988 send_msg(conn, msg); 989 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, 990 newpath); 991 sshbuf_free(msg); 992 993 status = get_status(conn, id); 994 if (status != SSH2_FX_OK) 995 error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, 996 newpath, fx2txt(status)); 997 998 return status == SSH2_FX_OK ? 0 : -1; 999 } 1000 1001 int 1002 do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len) 1003 { 1004 struct sshbuf *msg; 1005 u_int status, id; 1006 int r; 1007 1008 /* Silently return if the extension is not supported */ 1009 if ((conn->exts & SFTP_EXT_FSYNC) == 0) 1010 return -1; 1011 1012 /* Send fsync request */ 1013 if ((msg = sshbuf_new()) == NULL) 1014 fatal("%s: sshbuf_new failed", __func__); 1015 id = conn->msg_id++; 1016 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1017 (r = sshbuf_put_u32(msg, id)) != 0 || 1018 (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || 1019 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 1020 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1021 send_msg(conn, msg); 1022 debug3("Sent message fsync@openssh.com I:%u", id); 1023 sshbuf_free(msg); 1024 1025 status = get_status(conn, id); 1026 if (status != SSH2_FX_OK) 1027 error("Couldn't sync file: %s", fx2txt(status)); 1028 1029 return status == SSH2_FX_OK ? 0 : -1; 1030 } 1031 1032 #ifdef notyet 1033 char * 1034 do_readlink(struct sftp_conn *conn, const char *path) 1035 { 1036 struct sshbuf *msg; 1037 u_int expected_id, count, id; 1038 char *filename, *longname; 1039 Attrib a; 1040 u_char type; 1041 int r; 1042 1043 expected_id = id = conn->msg_id++; 1044 send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); 1045 1046 if ((msg = sshbuf_new()) == NULL) 1047 fatal("%s: sshbuf_new failed", __func__); 1048 1049 get_msg(conn, msg); 1050 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1051 (r = sshbuf_get_u32(msg, &id)) != 0) 1052 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1053 1054 if (id != expected_id) 1055 fatal("ID mismatch (%u != %u)", id, expected_id); 1056 1057 if (type == SSH2_FXP_STATUS) { 1058 u_int status; 1059 1060 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1061 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1062 error("Couldn't readlink: %s", fx2txt(status)); 1063 sshbuf_free(msg); 1064 return(NULL); 1065 } else if (type != SSH2_FXP_NAME) 1066 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 1067 SSH2_FXP_NAME, type); 1068 1069 if ((r = sshbuf_get_u32(msg, &count)) != 0) 1070 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1071 if (count != 1) 1072 fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); 1073 1074 if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || 1075 (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || 1076 (r = decode_attrib(msg, &a)) != 0) 1077 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1078 1079 debug3("SSH_FXP_READLINK %s -> %s", path, filename); 1080 1081 free(longname); 1082 1083 sshbuf_free(msg); 1084 1085 return filename; 1086 } 1087 #endif 1088 1089 int 1090 do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, 1091 int quiet) 1092 { 1093 struct sshbuf *msg; 1094 u_int id; 1095 int r; 1096 1097 if ((conn->exts & SFTP_EXT_STATVFS) == 0) { 1098 error("Server does not support statvfs@openssh.com extension"); 1099 return -1; 1100 } 1101 1102 id = conn->msg_id++; 1103 1104 if ((msg = sshbuf_new()) == NULL) 1105 fatal("%s: sshbuf_new failed", __func__); 1106 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1107 (r = sshbuf_put_u32(msg, id)) != 0 || 1108 (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 || 1109 (r = sshbuf_put_cstring(msg, path)) != 0) 1110 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1111 send_msg(conn, msg); 1112 sshbuf_free(msg); 1113 1114 return get_decode_statvfs(conn, st, id, quiet); 1115 } 1116 1117 #ifdef notyet 1118 int 1119 do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 1120 struct sftp_statvfs *st, int quiet) 1121 { 1122 struct sshbuf *msg; 1123 u_int id; 1124 1125 if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) { 1126 error("Server does not support fstatvfs@openssh.com extension"); 1127 return -1; 1128 } 1129 1130 id = conn->msg_id++; 1131 1132 if ((msg = sshbuf_new()) == NULL) 1133 fatal("%s: sshbuf_new failed", __func__); 1134 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1135 (r = sshbuf_put_u32(msg, id)) != 0 || 1136 (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 || 1137 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 1138 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1139 send_msg(conn, msg); 1140 sshbuf_free(msg); 1141 1142 return get_decode_statvfs(conn, st, id, quiet); 1143 } 1144 #endif 1145 1146 int 1147 do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a) 1148 { 1149 struct sshbuf *msg; 1150 u_int status, id; 1151 int r; 1152 1153 if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) { 1154 error("Server does not support lsetstat@openssh.com extension"); 1155 return -1; 1156 } 1157 1158 id = conn->msg_id++; 1159 if ((msg = sshbuf_new()) == NULL) 1160 fatal("%s: sshbuf_new failed", __func__); 1161 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1162 (r = sshbuf_put_u32(msg, id)) != 0 || 1163 (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 || 1164 (r = sshbuf_put_cstring(msg, path)) != 0 || 1165 (r = encode_attrib(msg, a)) != 0) 1166 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1167 send_msg(conn, msg); 1168 sshbuf_free(msg); 1169 1170 status = get_status(conn, id); 1171 if (status != SSH2_FX_OK) 1172 error("Couldn't setstat on \"%s\": %s", path, 1173 fx2txt(status)); 1174 1175 return status == SSH2_FX_OK ? 0 : -1; 1176 } 1177 1178 static void 1179 send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, 1180 u_int len, const u_char *handle, u_int handle_len) 1181 { 1182 struct sshbuf *msg; 1183 int r; 1184 1185 if ((msg = sshbuf_new()) == NULL) 1186 fatal("%s: sshbuf_new failed", __func__); 1187 if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 || 1188 (r = sshbuf_put_u32(msg, id)) != 0 || 1189 (r = sshbuf_put_string(msg, handle, handle_len)) != 0 || 1190 (r = sshbuf_put_u64(msg, offset)) != 0 || 1191 (r = sshbuf_put_u32(msg, len)) != 0) 1192 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1193 send_msg(conn, msg); 1194 sshbuf_free(msg); 1195 } 1196 1197 int 1198 do_download(struct sftp_conn *conn, const char *remote_path, 1199 const char *local_path, Attrib *a, int preserve_flag, int resume_flag, 1200 int fsync_flag) 1201 { 1202 Attrib junk; 1203 struct sshbuf *msg; 1204 u_char *handle; 1205 int local_fd = -1, write_error; 1206 int read_error, write_errno, reordered = 0, r; 1207 u_int64_t offset = 0, size, highwater; 1208 u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK; 1209 off_t progress_counter; 1210 size_t handle_len; 1211 struct stat st; 1212 struct request { 1213 u_int id; 1214 size_t len; 1215 u_int64_t offset; 1216 TAILQ_ENTRY(request) tq; 1217 }; 1218 TAILQ_HEAD(reqhead, request) requests; 1219 struct request *req; 1220 u_char type; 1221 1222 TAILQ_INIT(&requests); 1223 1224 if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL) 1225 return -1; 1226 1227 /* Do not preserve set[ug]id here, as we do not preserve ownership */ 1228 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) 1229 mode = a->perm & 0777; 1230 else 1231 mode = 0666; 1232 1233 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && 1234 (!S_ISREG(a->perm))) { 1235 error("Cannot download non-regular file: %s", remote_path); 1236 return(-1); 1237 } 1238 1239 if (a->flags & SSH2_FILEXFER_ATTR_SIZE) 1240 size = a->size; 1241 else 1242 size = 0; 1243 1244 buflen = conn->transfer_buflen; 1245 if ((msg = sshbuf_new()) == NULL) 1246 fatal("%s: sshbuf_new failed", __func__); 1247 1248 attrib_clear(&junk); /* Send empty attributes */ 1249 1250 /* Send open request */ 1251 id = conn->msg_id++; 1252 if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || 1253 (r = sshbuf_put_u32(msg, id)) != 0 || 1254 (r = sshbuf_put_cstring(msg, remote_path)) != 0 || 1255 (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 || 1256 (r = encode_attrib(msg, &junk)) != 0) 1257 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1258 send_msg(conn, msg); 1259 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1260 1261 handle = get_handle(conn, id, &handle_len, 1262 "remote open(\"%s\")", remote_path); 1263 if (handle == NULL) { 1264 sshbuf_free(msg); 1265 return(-1); 1266 } 1267 1268 local_fd = open(local_path, 1269 O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR); 1270 if (local_fd == -1) { 1271 error("Couldn't open local file \"%s\" for writing: %s", 1272 local_path, strerror(errno)); 1273 goto fail; 1274 } 1275 offset = highwater = 0; 1276 if (resume_flag) { 1277 if (fstat(local_fd, &st) == -1) { 1278 error("Unable to stat local file \"%s\": %s", 1279 local_path, strerror(errno)); 1280 goto fail; 1281 } 1282 if (st.st_size < 0) { 1283 error("\"%s\" has negative size", local_path); 1284 goto fail; 1285 } 1286 if ((u_int64_t)st.st_size > size) { 1287 error("Unable to resume download of \"%s\": " 1288 "local file is larger than remote", local_path); 1289 fail: 1290 do_close(conn, handle, handle_len); 1291 sshbuf_free(msg); 1292 free(handle); 1293 if (local_fd != -1) 1294 close(local_fd); 1295 return -1; 1296 } 1297 offset = highwater = st.st_size; 1298 } 1299 1300 /* Read from remote and write to local */ 1301 write_error = read_error = write_errno = num_req = 0; 1302 max_req = 1; 1303 progress_counter = offset; 1304 1305 if (showprogress && size != 0) 1306 start_progress_meter(remote_path, size, &progress_counter); 1307 1308 while (num_req > 0 || max_req > 0) { 1309 u_char *data; 1310 size_t len; 1311 1312 /* 1313 * Simulate EOF on interrupt: stop sending new requests and 1314 * allow outstanding requests to drain gracefully 1315 */ 1316 if (interrupted) { 1317 if (num_req == 0) /* If we haven't started yet... */ 1318 break; 1319 max_req = 0; 1320 } 1321 1322 /* Send some more requests */ 1323 while (num_req < max_req) { 1324 debug3("Request range %llu -> %llu (%d/%d)", 1325 (unsigned long long)offset, 1326 (unsigned long long)offset + buflen - 1, 1327 num_req, max_req); 1328 req = xcalloc(1, sizeof(*req)); 1329 req->id = conn->msg_id++; 1330 req->len = buflen; 1331 req->offset = offset; 1332 offset += buflen; 1333 num_req++; 1334 TAILQ_INSERT_TAIL(&requests, req, tq); 1335 send_read_request(conn, req->id, req->offset, 1336 req->len, handle, handle_len); 1337 } 1338 1339 sshbuf_reset(msg); 1340 get_msg(conn, msg); 1341 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1342 (r = sshbuf_get_u32(msg, &id)) != 0) 1343 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1344 debug3("Received reply T:%u I:%u R:%d", type, id, max_req); 1345 1346 /* Find the request in our queue */ 1347 for (req = TAILQ_FIRST(&requests); 1348 req != NULL && req->id != id; 1349 req = TAILQ_NEXT(req, tq)) 1350 ; 1351 if (req == NULL) 1352 fatal("Unexpected reply %u", id); 1353 1354 switch (type) { 1355 case SSH2_FXP_STATUS: 1356 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1357 fatal("%s: buffer error: %s", 1358 __func__, ssh_err(r)); 1359 if (status != SSH2_FX_EOF) 1360 read_error = 1; 1361 max_req = 0; 1362 TAILQ_REMOVE(&requests, req, tq); 1363 free(req); 1364 num_req--; 1365 break; 1366 case SSH2_FXP_DATA: 1367 if ((r = sshbuf_get_string(msg, &data, &len)) != 0) 1368 fatal("%s: buffer error: %s", 1369 __func__, ssh_err(r)); 1370 debug3("Received data %llu -> %llu", 1371 (unsigned long long)req->offset, 1372 (unsigned long long)req->offset + len - 1); 1373 if (len > req->len) 1374 fatal("Received more data than asked for " 1375 "%zu > %zu", len, req->len); 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 (fsync_flag) { 1480 debug("syncing \"%s\"", local_path); 1481 if (fsync(local_fd) == -1) 1482 error("Couldn't sync file \"%s\": %s", 1483 local_path, strerror(errno)); 1484 } 1485 } 1486 close(local_fd); 1487 sshbuf_free(msg); 1488 free(handle); 1489 1490 return status == SSH2_FX_OK ? 0 : -1; 1491 } 1492 1493 static int 1494 download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, 1495 int depth, Attrib *dirattrib, int preserve_flag, int print_flag, 1496 int resume_flag, int fsync_flag) 1497 { 1498 int i, ret = 0; 1499 SFTP_DIRENT **dir_entries; 1500 char *filename, *new_src = NULL, *new_dst = NULL; 1501 mode_t mode = 0777; 1502 1503 if (depth >= MAX_DIR_DEPTH) { 1504 error("Maximum directory depth exceeded: %d levels", depth); 1505 return -1; 1506 } 1507 1508 if (dirattrib == NULL && 1509 (dirattrib = do_stat(conn, src, 1)) == NULL) { 1510 error("Unable to stat remote directory \"%s\"", src); 1511 return -1; 1512 } 1513 if (!S_ISDIR(dirattrib->perm)) { 1514 error("\"%s\" is not a directory", src); 1515 return -1; 1516 } 1517 if (print_flag) 1518 mprintf("Retrieving %s\n", src); 1519 1520 if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) 1521 mode = dirattrib->perm & 01777; 1522 else { 1523 debug("Server did not send permissions for " 1524 "directory \"%s\"", dst); 1525 } 1526 1527 if (mkdir(dst, mode) == -1 && errno != EEXIST) { 1528 error("mkdir %s: %s", dst, strerror(errno)); 1529 return -1; 1530 } 1531 1532 if (do_readdir(conn, src, &dir_entries) == -1) { 1533 error("%s: Failed to get directory contents", src); 1534 return -1; 1535 } 1536 1537 for (i = 0; dir_entries[i] != NULL && !interrupted; i++) { 1538 free(new_dst); 1539 free(new_src); 1540 1541 filename = dir_entries[i]->filename; 1542 new_dst = path_append(dst, filename); 1543 new_src = path_append(src, filename); 1544 1545 if (S_ISDIR(dir_entries[i]->a.perm)) { 1546 if (strcmp(filename, ".") == 0 || 1547 strcmp(filename, "..") == 0) 1548 continue; 1549 if (download_dir_internal(conn, new_src, new_dst, 1550 depth + 1, &(dir_entries[i]->a), preserve_flag, 1551 print_flag, resume_flag, fsync_flag) == -1) 1552 ret = -1; 1553 } else if (S_ISREG(dir_entries[i]->a.perm) ) { 1554 if (do_download(conn, new_src, new_dst, 1555 &(dir_entries[i]->a), preserve_flag, 1556 resume_flag, fsync_flag) == -1) { 1557 error("Download of file %s to %s failed", 1558 new_src, new_dst); 1559 ret = -1; 1560 } 1561 } else 1562 logit("%s: not a regular file\n", new_src); 1563 1564 } 1565 free(new_dst); 1566 free(new_src); 1567 1568 if (preserve_flag) { 1569 if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { 1570 struct timeval tv[2]; 1571 tv[0].tv_sec = dirattrib->atime; 1572 tv[1].tv_sec = dirattrib->mtime; 1573 tv[0].tv_usec = tv[1].tv_usec = 0; 1574 if (utimes(dst, tv) == -1) 1575 error("Can't set times on \"%s\": %s", 1576 dst, strerror(errno)); 1577 } else 1578 debug("Server did not send times for directory " 1579 "\"%s\"", dst); 1580 } 1581 1582 free_sftp_dirents(dir_entries); 1583 1584 return ret; 1585 } 1586 1587 int 1588 download_dir(struct sftp_conn *conn, const char *src, const char *dst, 1589 Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, 1590 int fsync_flag) 1591 { 1592 char *src_canon; 1593 int ret; 1594 1595 if ((src_canon = do_realpath(conn, src)) == NULL) { 1596 error("Unable to canonicalize path \"%s\"", src); 1597 return -1; 1598 } 1599 1600 ret = download_dir_internal(conn, src_canon, dst, 0, 1601 dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag); 1602 free(src_canon); 1603 return ret; 1604 } 1605 1606 int 1607 do_upload(struct sftp_conn *conn, const char *local_path, 1608 const char *remote_path, int preserve_flag, int resume, int fsync_flag) 1609 { 1610 int r, local_fd; 1611 u_int status = SSH2_FX_OK; 1612 u_int id; 1613 u_char type; 1614 off_t offset, progress_counter; 1615 u_char *handle, *data; 1616 struct sshbuf *msg; 1617 struct stat sb; 1618 Attrib a, *c = NULL; 1619 u_int32_t startid; 1620 u_int32_t ackid; 1621 struct outstanding_ack { 1622 u_int id; 1623 u_int len; 1624 off_t offset; 1625 TAILQ_ENTRY(outstanding_ack) tq; 1626 }; 1627 TAILQ_HEAD(ackhead, outstanding_ack) acks; 1628 struct outstanding_ack *ack = NULL; 1629 size_t handle_len; 1630 1631 TAILQ_INIT(&acks); 1632 1633 if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) { 1634 error("Couldn't open local file \"%s\" for reading: %s", 1635 local_path, strerror(errno)); 1636 return(-1); 1637 } 1638 if (fstat(local_fd, &sb) == -1) { 1639 error("Couldn't fstat local file \"%s\": %s", 1640 local_path, strerror(errno)); 1641 close(local_fd); 1642 return(-1); 1643 } 1644 if (!S_ISREG(sb.st_mode)) { 1645 error("%s is not a regular file", local_path); 1646 close(local_fd); 1647 return(-1); 1648 } 1649 stat_to_attrib(&sb, &a); 1650 1651 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 1652 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 1653 a.perm &= 0777; 1654 if (!preserve_flag) 1655 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 1656 1657 if (resume) { 1658 /* Get remote file size if it exists */ 1659 if ((c = do_stat(conn, remote_path, 0)) == NULL) { 1660 close(local_fd); 1661 return -1; 1662 } 1663 1664 if ((off_t)c->size >= sb.st_size) { 1665 error("destination file bigger or same size as " 1666 "source file"); 1667 close(local_fd); 1668 return -1; 1669 } 1670 1671 if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) { 1672 close(local_fd); 1673 return -1; 1674 } 1675 } 1676 1677 if ((msg = sshbuf_new()) == NULL) 1678 fatal("%s: sshbuf_new failed", __func__); 1679 1680 /* Send open request */ 1681 id = conn->msg_id++; 1682 if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || 1683 (r = sshbuf_put_u32(msg, id)) != 0 || 1684 (r = sshbuf_put_cstring(msg, remote_path)) != 0 || 1685 (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| 1686 (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 || 1687 (r = encode_attrib(msg, &a)) != 0) 1688 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 1689 send_msg(conn, msg); 1690 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1691 1692 sshbuf_reset(msg); 1693 1694 handle = get_handle(conn, id, &handle_len, 1695 "remote open(\"%s\")", remote_path); 1696 if (handle == NULL) { 1697 close(local_fd); 1698 sshbuf_free(msg); 1699 return -1; 1700 } 1701 1702 startid = ackid = id + 1; 1703 data = xmalloc(conn->transfer_buflen); 1704 1705 /* Read from local and write to remote */ 1706 offset = progress_counter = (resume ? c->size : 0); 1707 if (showprogress) 1708 start_progress_meter(local_path, sb.st_size, 1709 &progress_counter); 1710 1711 for (;;) { 1712 int len; 1713 1714 /* 1715 * Can't use atomicio here because it returns 0 on EOF, 1716 * thus losing the last block of the file. 1717 * Simulate an EOF on interrupt, allowing ACKs from the 1718 * server to drain. 1719 */ 1720 if (interrupted || status != SSH2_FX_OK) 1721 len = 0; 1722 else do 1723 len = read(local_fd, data, conn->transfer_buflen); 1724 while ((len == -1) && 1725 (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); 1726 1727 if (len == -1) 1728 fatal("Couldn't read from \"%s\": %s", local_path, 1729 strerror(errno)); 1730 1731 if (len != 0) { 1732 ack = xcalloc(1, sizeof(*ack)); 1733 ack->id = ++id; 1734 ack->offset = offset; 1735 ack->len = len; 1736 TAILQ_INSERT_TAIL(&acks, ack, tq); 1737 1738 sshbuf_reset(msg); 1739 if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || 1740 (r = sshbuf_put_u32(msg, ack->id)) != 0 || 1741 (r = sshbuf_put_string(msg, handle, 1742 handle_len)) != 0 || 1743 (r = sshbuf_put_u64(msg, offset)) != 0 || 1744 (r = sshbuf_put_string(msg, data, len)) != 0) 1745 fatal("%s: buffer error: %s", 1746 __func__, ssh_err(r)); 1747 send_msg(conn, msg); 1748 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", 1749 id, (unsigned long long)offset, len); 1750 } else if (TAILQ_FIRST(&acks) == NULL) 1751 break; 1752 1753 if (ack == NULL) 1754 fatal("Unexpected ACK %u", id); 1755 1756 if (id == startid || len == 0 || 1757 id - ackid >= conn->num_requests) { 1758 u_int rid; 1759 1760 sshbuf_reset(msg); 1761 get_msg(conn, msg); 1762 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1763 (r = sshbuf_get_u32(msg, &rid)) != 0) 1764 fatal("%s: buffer error: %s", 1765 __func__, ssh_err(r)); 1766 1767 if (type != SSH2_FXP_STATUS) 1768 fatal("Expected SSH2_FXP_STATUS(%d) packet, " 1769 "got %d", SSH2_FXP_STATUS, type); 1770 1771 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1772 fatal("%s: buffer error: %s", 1773 __func__, ssh_err(r)); 1774 debug3("SSH2_FXP_STATUS %u", status); 1775 1776 /* Find the request in our queue */ 1777 for (ack = TAILQ_FIRST(&acks); 1778 ack != NULL && ack->id != rid; 1779 ack = TAILQ_NEXT(ack, tq)) 1780 ; 1781 if (ack == NULL) 1782 fatal("Can't find request for ID %u", rid); 1783 TAILQ_REMOVE(&acks, ack, tq); 1784 debug3("In write loop, ack for %u %u bytes at %lld", 1785 ack->id, ack->len, (long long)ack->offset); 1786 ++ackid; 1787 progress_counter += ack->len; 1788 free(ack); 1789 } 1790 offset += len; 1791 if (offset < 0) 1792 fatal("%s: offset < 0", __func__); 1793 } 1794 sshbuf_free(msg); 1795 1796 if (showprogress) 1797 stop_progress_meter(); 1798 free(data); 1799 1800 if (status != SSH2_FX_OK) { 1801 error("Couldn't write to remote file \"%s\": %s", 1802 remote_path, fx2txt(status)); 1803 status = SSH2_FX_FAILURE; 1804 } 1805 1806 if (close(local_fd) == -1) { 1807 error("Couldn't close local file \"%s\": %s", local_path, 1808 strerror(errno)); 1809 status = SSH2_FX_FAILURE; 1810 } 1811 1812 /* Override umask and utimes if asked */ 1813 if (preserve_flag) 1814 do_fsetstat(conn, handle, handle_len, &a); 1815 1816 if (fsync_flag) 1817 (void)do_fsync(conn, handle, handle_len); 1818 1819 if (do_close(conn, handle, handle_len) != 0) 1820 status = SSH2_FX_FAILURE; 1821 1822 free(handle); 1823 1824 return status == SSH2_FX_OK ? 0 : -1; 1825 } 1826 1827 static int 1828 upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, 1829 int depth, int preserve_flag, int print_flag, int resume, int fsync_flag) 1830 { 1831 int ret = 0; 1832 DIR *dirp; 1833 struct dirent *dp; 1834 char *filename, *new_src = NULL, *new_dst = NULL; 1835 struct stat sb; 1836 Attrib a, *dirattrib; 1837 1838 if (depth >= MAX_DIR_DEPTH) { 1839 error("Maximum directory depth exceeded: %d levels", depth); 1840 return -1; 1841 } 1842 1843 if (stat(src, &sb) == -1) { 1844 error("Couldn't stat directory \"%s\": %s", 1845 src, strerror(errno)); 1846 return -1; 1847 } 1848 if (!S_ISDIR(sb.st_mode)) { 1849 error("\"%s\" is not a directory", src); 1850 return -1; 1851 } 1852 if (print_flag) 1853 mprintf("Entering %s\n", src); 1854 1855 attrib_clear(&a); 1856 stat_to_attrib(&sb, &a); 1857 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 1858 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 1859 a.perm &= 01777; 1860 if (!preserve_flag) 1861 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 1862 1863 /* 1864 * sftp lacks a portable status value to match errno EEXIST, 1865 * so if we get a failure back then we must check whether 1866 * the path already existed and is a directory. 1867 */ 1868 if (do_mkdir(conn, dst, &a, 0) != 0) { 1869 if ((dirattrib = do_stat(conn, dst, 0)) == NULL) 1870 return -1; 1871 if (!S_ISDIR(dirattrib->perm)) { 1872 error("\"%s\" exists but is not a directory", dst); 1873 return -1; 1874 } 1875 } 1876 1877 if ((dirp = opendir(src)) == NULL) { 1878 error("Failed to open dir \"%s\": %s", src, strerror(errno)); 1879 return -1; 1880 } 1881 1882 while (((dp = readdir(dirp)) != NULL) && !interrupted) { 1883 if (dp->d_ino == 0) 1884 continue; 1885 free(new_dst); 1886 free(new_src); 1887 filename = dp->d_name; 1888 new_dst = path_append(dst, filename); 1889 new_src = path_append(src, filename); 1890 1891 if (lstat(new_src, &sb) == -1) { 1892 logit("%s: lstat failed: %s", filename, 1893 strerror(errno)); 1894 ret = -1; 1895 } else if (S_ISDIR(sb.st_mode)) { 1896 if (strcmp(filename, ".") == 0 || 1897 strcmp(filename, "..") == 0) 1898 continue; 1899 1900 if (upload_dir_internal(conn, new_src, new_dst, 1901 depth + 1, preserve_flag, print_flag, resume, 1902 fsync_flag) == -1) 1903 ret = -1; 1904 } else if (S_ISREG(sb.st_mode)) { 1905 if (do_upload(conn, new_src, new_dst, 1906 preserve_flag, resume, fsync_flag) == -1) { 1907 error("Uploading of file %s to %s failed!", 1908 new_src, new_dst); 1909 ret = -1; 1910 } 1911 } else 1912 logit("%s: not a regular file\n", filename); 1913 } 1914 free(new_dst); 1915 free(new_src); 1916 1917 do_setstat(conn, dst, &a); 1918 1919 (void) closedir(dirp); 1920 return ret; 1921 } 1922 1923 int 1924 upload_dir(struct sftp_conn *conn, const char *src, const char *dst, 1925 int preserve_flag, int print_flag, int resume, int fsync_flag) 1926 { 1927 char *dst_canon; 1928 int ret; 1929 1930 if ((dst_canon = do_realpath(conn, dst)) == NULL) { 1931 error("Unable to canonicalize path \"%s\"", dst); 1932 return -1; 1933 } 1934 1935 ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, 1936 print_flag, resume, fsync_flag); 1937 1938 free(dst_canon); 1939 return ret; 1940 } 1941 1942 char * 1943 path_append(const char *p1, const char *p2) 1944 { 1945 char *ret; 1946 size_t len = strlen(p1) + strlen(p2) + 2; 1947 1948 ret = xmalloc(len); 1949 strlcpy(ret, p1, len); 1950 if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/') 1951 strlcat(ret, "/", len); 1952 strlcat(ret, p2, len); 1953 1954 return(ret); 1955 } 1956 1957