1 /* $OpenBSD: sftp-client.c,v 1.154 2021/08/09 23:47:44 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 #ifdef HAVE_POLL_H 41 #include <poll.h> 42 #else 43 # ifdef HAVE_SYS_POLL_H 44 # include <sys/poll.h> 45 # endif 46 #endif 47 #include <fcntl.h> 48 #include <signal.h> 49 #include <stdarg.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <string.h> 53 #include <unistd.h> 54 55 #include "xmalloc.h" 56 #include "ssherr.h" 57 #include "sshbuf.h" 58 #include "log.h" 59 #include "atomicio.h" 60 #include "progressmeter.h" 61 #include "misc.h" 62 #include "utf8.h" 63 64 #include "sftp.h" 65 #include "sftp-common.h" 66 #include "sftp-client.h" 67 68 extern volatile sig_atomic_t interrupted; 69 extern int showprogress; 70 71 /* Default size of buffer for up/download */ 72 #define DEFAULT_COPY_BUFLEN 32768 73 74 /* Default number of concurrent outstanding requests */ 75 #define DEFAULT_NUM_REQUESTS 64 76 77 /* Minimum amount of data to read at a time */ 78 #define MIN_READ_SIZE 512 79 80 /* Maximum depth to descend in directory trees */ 81 #define MAX_DIR_DEPTH 64 82 83 /* Directory separator characters */ 84 #ifdef HAVE_CYGWIN 85 # define SFTP_DIRECTORY_CHARS "/\\" 86 #else /* HAVE_CYGWIN */ 87 # define SFTP_DIRECTORY_CHARS "/" 88 #endif /* HAVE_CYGWIN */ 89 90 struct sftp_conn { 91 int fd_in; 92 int fd_out; 93 u_int download_buflen; 94 u_int upload_buflen; 95 u_int num_requests; 96 u_int version; 97 u_int msg_id; 98 #define SFTP_EXT_POSIX_RENAME 0x00000001 99 #define SFTP_EXT_STATVFS 0x00000002 100 #define SFTP_EXT_FSTATVFS 0x00000004 101 #define SFTP_EXT_HARDLINK 0x00000008 102 #define SFTP_EXT_FSYNC 0x00000010 103 #define SFTP_EXT_LSETSTAT 0x00000020 104 #define SFTP_EXT_LIMITS 0x00000040 105 #define SFTP_EXT_PATH_EXPAND 0x00000080 106 u_int exts; 107 u_int64_t limit_kbps; 108 struct bwlimit bwlimit_in, bwlimit_out; 109 }; 110 111 /* Tracks in-progress requests during file transfers */ 112 struct request { 113 u_int id; 114 size_t len; 115 u_int64_t offset; 116 TAILQ_ENTRY(request) tq; 117 }; 118 TAILQ_HEAD(requests, request); 119 120 static u_char * 121 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, 122 const char *errfmt, ...) __attribute__((format(printf, 4, 5))); 123 124 static struct request * 125 request_enqueue(struct requests *requests, u_int id, size_t len, 126 uint64_t offset) 127 { 128 struct request *req; 129 130 req = xcalloc(1, sizeof(*req)); 131 req->id = id; 132 req->len = len; 133 req->offset = offset; 134 TAILQ_INSERT_TAIL(requests, req, tq); 135 return req; 136 } 137 138 static struct request * 139 request_find(struct requests *requests, u_int id) 140 { 141 struct request *req; 142 143 for (req = TAILQ_FIRST(requests); 144 req != NULL && req->id != id; 145 req = TAILQ_NEXT(req, tq)) 146 ; 147 return req; 148 } 149 150 /* ARGSUSED */ 151 static int 152 sftpio(void *_bwlimit, size_t amount) 153 { 154 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit; 155 156 refresh_progress_meter(0); 157 if (bwlimit != NULL) 158 bandwidth_limit(bwlimit, amount); 159 return 0; 160 } 161 162 static void 163 send_msg(struct sftp_conn *conn, struct sshbuf *m) 164 { 165 u_char mlen[4]; 166 struct iovec iov[2]; 167 168 if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH) 169 fatal("Outbound message too long %zu", sshbuf_len(m)); 170 171 /* Send length first */ 172 put_u32(mlen, sshbuf_len(m)); 173 iov[0].iov_base = mlen; 174 iov[0].iov_len = sizeof(mlen); 175 iov[1].iov_base = (u_char *)sshbuf_ptr(m); 176 iov[1].iov_len = sshbuf_len(m); 177 178 if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio, 179 conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) != 180 sshbuf_len(m) + sizeof(mlen)) 181 fatal("Couldn't send packet: %s", strerror(errno)); 182 183 sshbuf_reset(m); 184 } 185 186 static void 187 get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial) 188 { 189 u_int msg_len; 190 u_char *p; 191 int r; 192 193 sshbuf_reset(m); 194 if ((r = sshbuf_reserve(m, 4, &p)) != 0) 195 fatal_fr(r, "reserve"); 196 if (atomicio6(read, conn->fd_in, p, 4, sftpio, 197 conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) { 198 if (errno == EPIPE || errno == ECONNRESET) 199 fatal("Connection closed"); 200 else 201 fatal("Couldn't read packet: %s", strerror(errno)); 202 } 203 204 if ((r = sshbuf_get_u32(m, &msg_len)) != 0) 205 fatal_fr(r, "sshbuf_get_u32"); 206 if (msg_len > SFTP_MAX_MSG_LENGTH) { 207 do_log2(initial ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_FATAL, 208 "Received message too long %u", msg_len); 209 fatal("Ensure the remote shell produces no output " 210 "for non-interactive sessions."); 211 } 212 213 if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) 214 fatal_fr(r, "reserve"); 215 if (atomicio6(read, conn->fd_in, p, msg_len, sftpio, 216 conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) 217 != msg_len) { 218 if (errno == EPIPE) 219 fatal("Connection closed"); 220 else 221 fatal("Read packet: %s", strerror(errno)); 222 } 223 } 224 225 static void 226 get_msg(struct sftp_conn *conn, struct sshbuf *m) 227 { 228 get_msg_extended(conn, m, 0); 229 } 230 231 static void 232 send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s, 233 u_int len) 234 { 235 struct sshbuf *msg; 236 int r; 237 238 if ((msg = sshbuf_new()) == NULL) 239 fatal_f("sshbuf_new failed"); 240 if ((r = sshbuf_put_u8(msg, code)) != 0 || 241 (r = sshbuf_put_u32(msg, id)) != 0 || 242 (r = sshbuf_put_string(msg, s, len)) != 0) 243 fatal_fr(r, "compose"); 244 send_msg(conn, msg); 245 debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); 246 sshbuf_free(msg); 247 } 248 249 static void 250 send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, 251 const void *s, u_int len, Attrib *a) 252 { 253 struct sshbuf *msg; 254 int r; 255 256 if ((msg = sshbuf_new()) == NULL) 257 fatal_f("sshbuf_new failed"); 258 if ((r = sshbuf_put_u8(msg, code)) != 0 || 259 (r = sshbuf_put_u32(msg, id)) != 0 || 260 (r = sshbuf_put_string(msg, s, len)) != 0 || 261 (r = encode_attrib(msg, a)) != 0) 262 fatal_fr(r, "compose"); 263 send_msg(conn, msg); 264 debug3("Sent message fd %d T:%u I:%u F:0x%04x M:%05o", 265 conn->fd_out, code, id, a->flags, a->perm); 266 sshbuf_free(msg); 267 } 268 269 static u_int 270 get_status(struct sftp_conn *conn, u_int expected_id) 271 { 272 struct sshbuf *msg; 273 u_char type; 274 u_int id, status; 275 int r; 276 277 if ((msg = sshbuf_new()) == NULL) 278 fatal_f("sshbuf_new failed"); 279 get_msg(conn, msg); 280 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 281 (r = sshbuf_get_u32(msg, &id)) != 0) 282 fatal_fr(r, "compose"); 283 284 if (id != expected_id) 285 fatal("ID mismatch (%u != %u)", id, expected_id); 286 if (type != SSH2_FXP_STATUS) 287 fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", 288 SSH2_FXP_STATUS, type); 289 290 if ((r = sshbuf_get_u32(msg, &status)) != 0) 291 fatal_fr(r, "parse"); 292 sshbuf_free(msg); 293 294 debug3("SSH2_FXP_STATUS %u", status); 295 296 return status; 297 } 298 299 static u_char * 300 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, 301 const char *errfmt, ...) 302 { 303 struct sshbuf *msg; 304 u_int id, status; 305 u_char type; 306 u_char *handle; 307 char errmsg[256]; 308 va_list args; 309 int r; 310 311 va_start(args, errfmt); 312 if (errfmt != NULL) 313 vsnprintf(errmsg, sizeof(errmsg), errfmt, args); 314 va_end(args); 315 316 if ((msg = sshbuf_new()) == NULL) 317 fatal_f("sshbuf_new failed"); 318 get_msg(conn, msg); 319 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 320 (r = sshbuf_get_u32(msg, &id)) != 0) 321 fatal_fr(r, "parse"); 322 323 if (id != expected_id) 324 fatal("%s: ID mismatch (%u != %u)", 325 errfmt == NULL ? __func__ : errmsg, id, expected_id); 326 if (type == SSH2_FXP_STATUS) { 327 if ((r = sshbuf_get_u32(msg, &status)) != 0) 328 fatal_fr(r, "parse status"); 329 if (errfmt != NULL) 330 error("%s: %s", errmsg, fx2txt(status)); 331 sshbuf_free(msg); 332 return(NULL); 333 } else if (type != SSH2_FXP_HANDLE) 334 fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u", 335 errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type); 336 337 if ((r = sshbuf_get_string(msg, &handle, len)) != 0) 338 fatal_fr(r, "parse handle"); 339 sshbuf_free(msg); 340 341 return handle; 342 } 343 344 /* XXX returing &static is error-prone. Refactor to fill *Attrib argument */ 345 static Attrib * 346 get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) 347 { 348 struct sshbuf *msg; 349 u_int id; 350 u_char type; 351 int r; 352 static Attrib a; 353 354 if ((msg = sshbuf_new()) == NULL) 355 fatal_f("sshbuf_new failed"); 356 get_msg(conn, msg); 357 358 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 359 (r = sshbuf_get_u32(msg, &id)) != 0) 360 fatal_fr(r, "parse"); 361 362 if (id != expected_id) 363 fatal("ID mismatch (%u != %u)", id, expected_id); 364 if (type == SSH2_FXP_STATUS) { 365 u_int status; 366 367 if ((r = sshbuf_get_u32(msg, &status)) != 0) 368 fatal_fr(r, "parse status"); 369 if (quiet) 370 debug("Couldn't stat remote file: %s", fx2txt(status)); 371 else 372 error("Couldn't stat remote file: %s", fx2txt(status)); 373 sshbuf_free(msg); 374 return(NULL); 375 } else if (type != SSH2_FXP_ATTRS) { 376 fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", 377 SSH2_FXP_ATTRS, type); 378 } 379 if ((r = decode_attrib(msg, &a)) != 0) { 380 error_fr(r, "decode_attrib"); 381 sshbuf_free(msg); 382 return NULL; 383 } 384 debug3("Recevied stat reply T:%u I:%u F:0x%04x M:%05o", 385 type, id, a.flags, a.perm); 386 sshbuf_free(msg); 387 388 return &a; 389 } 390 391 static int 392 get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, 393 u_int expected_id, int quiet) 394 { 395 struct sshbuf *msg; 396 u_char type; 397 u_int id; 398 u_int64_t flag; 399 int r; 400 401 if ((msg = sshbuf_new()) == NULL) 402 fatal_f("sshbuf_new failed"); 403 get_msg(conn, msg); 404 405 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 406 (r = sshbuf_get_u32(msg, &id)) != 0) 407 fatal_fr(r, "parse"); 408 409 debug3("Received statvfs reply T:%u I:%u", type, id); 410 if (id != expected_id) 411 fatal("ID mismatch (%u != %u)", id, expected_id); 412 if (type == SSH2_FXP_STATUS) { 413 u_int status; 414 415 if ((r = sshbuf_get_u32(msg, &status)) != 0) 416 fatal_fr(r, "parse status"); 417 if (quiet) 418 debug("Couldn't statvfs: %s", fx2txt(status)); 419 else 420 error("Couldn't statvfs: %s", fx2txt(status)); 421 sshbuf_free(msg); 422 return -1; 423 } else if (type != SSH2_FXP_EXTENDED_REPLY) { 424 fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", 425 SSH2_FXP_EXTENDED_REPLY, type); 426 } 427 428 memset(st, 0, sizeof(*st)); 429 if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 || 430 (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 || 431 (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 || 432 (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 || 433 (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 || 434 (r = sshbuf_get_u64(msg, &st->f_files)) != 0 || 435 (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 || 436 (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 || 437 (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 || 438 (r = sshbuf_get_u64(msg, &flag)) != 0 || 439 (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0) 440 fatal_fr(r, "parse statvfs"); 441 442 st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0; 443 st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0; 444 445 sshbuf_free(msg); 446 447 return 0; 448 } 449 450 struct sftp_conn * 451 do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, 452 u_int64_t limit_kbps) 453 { 454 u_char type; 455 struct sshbuf *msg; 456 struct sftp_conn *ret; 457 int r; 458 459 ret = xcalloc(1, sizeof(*ret)); 460 ret->msg_id = 1; 461 ret->fd_in = fd_in; 462 ret->fd_out = fd_out; 463 ret->download_buflen = ret->upload_buflen = 464 transfer_buflen ? transfer_buflen : DEFAULT_COPY_BUFLEN; 465 ret->num_requests = 466 num_requests ? num_requests : DEFAULT_NUM_REQUESTS; 467 ret->exts = 0; 468 ret->limit_kbps = 0; 469 470 if ((msg = sshbuf_new()) == NULL) 471 fatal_f("sshbuf_new failed"); 472 if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 || 473 (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0) 474 fatal_fr(r, "parse"); 475 476 send_msg(ret, msg); 477 478 get_msg_extended(ret, msg, 1); 479 480 /* Expecting a VERSION reply */ 481 if ((r = sshbuf_get_u8(msg, &type)) != 0) 482 fatal_fr(r, "parse type"); 483 if (type != SSH2_FXP_VERSION) { 484 error("Invalid packet back from SSH2_FXP_INIT (type %u)", 485 type); 486 sshbuf_free(msg); 487 free(ret); 488 return(NULL); 489 } 490 if ((r = sshbuf_get_u32(msg, &ret->version)) != 0) 491 fatal_fr(r, "parse version"); 492 493 debug2("Remote version: %u", ret->version); 494 495 /* Check for extensions */ 496 while (sshbuf_len(msg) > 0) { 497 char *name; 498 u_char *value; 499 size_t vlen; 500 int known = 0; 501 502 if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 || 503 (r = sshbuf_get_string(msg, &value, &vlen)) != 0) 504 fatal_fr(r, "parse extension"); 505 if (strcmp(name, "posix-rename@openssh.com") == 0 && 506 strcmp((char *)value, "1") == 0) { 507 ret->exts |= SFTP_EXT_POSIX_RENAME; 508 known = 1; 509 } else if (strcmp(name, "statvfs@openssh.com") == 0 && 510 strcmp((char *)value, "2") == 0) { 511 ret->exts |= SFTP_EXT_STATVFS; 512 known = 1; 513 } else if (strcmp(name, "fstatvfs@openssh.com") == 0 && 514 strcmp((char *)value, "2") == 0) { 515 ret->exts |= SFTP_EXT_FSTATVFS; 516 known = 1; 517 } else if (strcmp(name, "hardlink@openssh.com") == 0 && 518 strcmp((char *)value, "1") == 0) { 519 ret->exts |= SFTP_EXT_HARDLINK; 520 known = 1; 521 } else if (strcmp(name, "fsync@openssh.com") == 0 && 522 strcmp((char *)value, "1") == 0) { 523 ret->exts |= SFTP_EXT_FSYNC; 524 known = 1; 525 } else if (strcmp(name, "lsetstat@openssh.com") == 0 && 526 strcmp((char *)value, "1") == 0) { 527 ret->exts |= SFTP_EXT_LSETSTAT; 528 known = 1; 529 } else if (strcmp(name, "limits@openssh.com") == 0 && 530 strcmp((char *)value, "1") == 0) { 531 ret->exts |= SFTP_EXT_LIMITS; 532 known = 1; 533 } else if (strcmp(name, "expand-path@openssh.com") == 0 && 534 strcmp((char *)value, "1") == 0) { 535 ret->exts |= SFTP_EXT_PATH_EXPAND; 536 known = 1; 537 } 538 if (known) { 539 debug2("Server supports extension \"%s\" revision %s", 540 name, value); 541 } else { 542 debug2("Unrecognised server extension \"%s\"", name); 543 } 544 free(name); 545 free(value); 546 } 547 548 sshbuf_free(msg); 549 550 /* Query the server for its limits */ 551 if (ret->exts & SFTP_EXT_LIMITS) { 552 struct sftp_limits limits; 553 if (do_limits(ret, &limits) != 0) 554 fatal_f("limits failed"); 555 556 /* If the caller did not specify, find a good value */ 557 if (transfer_buflen == 0) { 558 ret->download_buflen = limits.read_length; 559 ret->upload_buflen = limits.write_length; 560 debug("Using server download size %u", ret->download_buflen); 561 debug("Using server upload size %u", ret->upload_buflen); 562 } 563 564 /* Use the server limit to scale down our value only */ 565 if (num_requests == 0 && limits.open_handles) { 566 ret->num_requests = 567 MINIMUM(DEFAULT_NUM_REQUESTS, limits.open_handles); 568 debug("Server handle limit %llu; using %u", 569 (unsigned long long)limits.open_handles, 570 ret->num_requests); 571 } 572 } 573 574 /* Some filexfer v.0 servers don't support large packets */ 575 if (ret->version == 0) { 576 ret->download_buflen = MINIMUM(ret->download_buflen, 20480); 577 ret->upload_buflen = MINIMUM(ret->upload_buflen, 20480); 578 } 579 580 ret->limit_kbps = limit_kbps; 581 if (ret->limit_kbps > 0) { 582 bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps, 583 ret->download_buflen); 584 bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps, 585 ret->upload_buflen); 586 } 587 588 return ret; 589 } 590 591 u_int 592 sftp_proto_version(struct sftp_conn *conn) 593 { 594 return conn->version; 595 } 596 597 int 598 do_limits(struct sftp_conn *conn, struct sftp_limits *limits) 599 { 600 u_int id, msg_id; 601 u_char type; 602 struct sshbuf *msg; 603 int r; 604 605 if ((conn->exts & SFTP_EXT_LIMITS) == 0) { 606 error("Server does not support limits@openssh.com extension"); 607 return -1; 608 } 609 610 if ((msg = sshbuf_new()) == NULL) 611 fatal_f("sshbuf_new failed"); 612 613 id = conn->msg_id++; 614 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 615 (r = sshbuf_put_u32(msg, id)) != 0 || 616 (r = sshbuf_put_cstring(msg, "limits@openssh.com")) != 0) 617 fatal_fr(r, "compose"); 618 send_msg(conn, msg); 619 debug3("Sent message limits@openssh.com I:%u", id); 620 621 get_msg(conn, msg); 622 623 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 624 (r = sshbuf_get_u32(msg, &msg_id)) != 0) 625 fatal_fr(r, "parse"); 626 627 debug3("Received limits reply T:%u I:%u", type, msg_id); 628 if (id != msg_id) 629 fatal("ID mismatch (%u != %u)", msg_id, id); 630 if (type != SSH2_FXP_EXTENDED_REPLY) { 631 debug_f("expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", 632 SSH2_FXP_EXTENDED_REPLY, type); 633 /* Disable the limits extension */ 634 conn->exts &= ~SFTP_EXT_LIMITS; 635 sshbuf_free(msg); 636 return 0; 637 } 638 639 memset(limits, 0, sizeof(*limits)); 640 if ((r = sshbuf_get_u64(msg, &limits->packet_length)) != 0 || 641 (r = sshbuf_get_u64(msg, &limits->read_length)) != 0 || 642 (r = sshbuf_get_u64(msg, &limits->write_length)) != 0 || 643 (r = sshbuf_get_u64(msg, &limits->open_handles)) != 0) 644 fatal_fr(r, "parse limits"); 645 646 sshbuf_free(msg); 647 648 return 0; 649 } 650 651 int 652 do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len) 653 { 654 u_int id, status; 655 struct sshbuf *msg; 656 int r; 657 658 if ((msg = sshbuf_new()) == NULL) 659 fatal_f("sshbuf_new failed"); 660 661 id = conn->msg_id++; 662 if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 || 663 (r = sshbuf_put_u32(msg, id)) != 0 || 664 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 665 fatal_fr(r, "parse"); 666 send_msg(conn, msg); 667 debug3("Sent message SSH2_FXP_CLOSE I:%u", id); 668 669 status = get_status(conn, id); 670 if (status != SSH2_FX_OK) 671 error("Couldn't close file: %s", fx2txt(status)); 672 673 sshbuf_free(msg); 674 675 return status == SSH2_FX_OK ? 0 : -1; 676 } 677 678 679 static int 680 do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, 681 SFTP_DIRENT ***dir) 682 { 683 struct sshbuf *msg; 684 u_int count, id, i, expected_id, ents = 0; 685 size_t handle_len; 686 u_char type, *handle; 687 int status = SSH2_FX_FAILURE; 688 int r; 689 690 if (dir) 691 *dir = NULL; 692 693 id = conn->msg_id++; 694 695 if ((msg = sshbuf_new()) == NULL) 696 fatal_f("sshbuf_new failed"); 697 if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 || 698 (r = sshbuf_put_u32(msg, id)) != 0 || 699 (r = sshbuf_put_cstring(msg, path)) != 0) 700 fatal_fr(r, "compose OPENDIR"); 701 send_msg(conn, msg); 702 703 handle = get_handle(conn, id, &handle_len, 704 "remote readdir(\"%s\")", path); 705 if (handle == NULL) { 706 sshbuf_free(msg); 707 return -1; 708 } 709 710 if (dir) { 711 ents = 0; 712 *dir = xcalloc(1, sizeof(**dir)); 713 (*dir)[0] = NULL; 714 } 715 716 for (; !interrupted;) { 717 id = expected_id = conn->msg_id++; 718 719 debug3("Sending SSH2_FXP_READDIR I:%u", id); 720 721 sshbuf_reset(msg); 722 if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 || 723 (r = sshbuf_put_u32(msg, id)) != 0 || 724 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 725 fatal_fr(r, "compose READDIR"); 726 send_msg(conn, msg); 727 728 sshbuf_reset(msg); 729 730 get_msg(conn, msg); 731 732 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 733 (r = sshbuf_get_u32(msg, &id)) != 0) 734 fatal_fr(r, "parse"); 735 736 debug3("Received reply T:%u I:%u", type, id); 737 738 if (id != expected_id) 739 fatal("ID mismatch (%u != %u)", id, expected_id); 740 741 if (type == SSH2_FXP_STATUS) { 742 u_int rstatus; 743 744 if ((r = sshbuf_get_u32(msg, &rstatus)) != 0) 745 fatal_fr(r, "parse status"); 746 debug3("Received SSH2_FXP_STATUS %d", rstatus); 747 if (rstatus == SSH2_FX_EOF) 748 break; 749 error("Couldn't read directory: %s", fx2txt(rstatus)); 750 goto out; 751 } else if (type != SSH2_FXP_NAME) 752 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 753 SSH2_FXP_NAME, type); 754 755 if ((r = sshbuf_get_u32(msg, &count)) != 0) 756 fatal_fr(r, "parse count"); 757 if (count > SSHBUF_SIZE_MAX) 758 fatal_f("nonsensical number of entries"); 759 if (count == 0) 760 break; 761 debug3("Received %d SSH2_FXP_NAME responses", count); 762 for (i = 0; i < count; i++) { 763 char *filename, *longname; 764 Attrib a; 765 766 if ((r = sshbuf_get_cstring(msg, &filename, 767 NULL)) != 0 || 768 (r = sshbuf_get_cstring(msg, &longname, 769 NULL)) != 0) 770 fatal_fr(r, "parse filenames"); 771 if ((r = decode_attrib(msg, &a)) != 0) { 772 error_fr(r, "couldn't decode attrib"); 773 free(filename); 774 free(longname); 775 goto out; 776 } 777 778 if (print_flag) 779 mprintf("%s\n", longname); 780 781 /* 782 * Directory entries should never contain '/' 783 * These can be used to attack recursive ops 784 * (e.g. send '../../../../etc/passwd') 785 */ 786 if (strpbrk(filename, SFTP_DIRECTORY_CHARS) != NULL) { 787 error("Server sent suspect path \"%s\" " 788 "during readdir of \"%s\"", filename, path); 789 } else if (dir) { 790 *dir = xreallocarray(*dir, ents + 2, sizeof(**dir)); 791 (*dir)[ents] = xcalloc(1, sizeof(***dir)); 792 (*dir)[ents]->filename = xstrdup(filename); 793 (*dir)[ents]->longname = xstrdup(longname); 794 memcpy(&(*dir)[ents]->a, &a, sizeof(a)); 795 (*dir)[++ents] = NULL; 796 } 797 free(filename); 798 free(longname); 799 } 800 } 801 status = 0; 802 803 out: 804 sshbuf_free(msg); 805 do_close(conn, handle, handle_len); 806 free(handle); 807 808 if (status != 0 && dir != NULL) { 809 /* Don't return results on error */ 810 free_sftp_dirents(*dir); 811 *dir = NULL; 812 } else if (interrupted && dir != NULL && *dir != NULL) { 813 /* Don't return partial matches on interrupt */ 814 free_sftp_dirents(*dir); 815 *dir = xcalloc(1, sizeof(**dir)); 816 **dir = NULL; 817 } 818 819 return status == SSH2_FX_OK ? 0 : -1; 820 } 821 822 int 823 do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) 824 { 825 return(do_lsreaddir(conn, path, 0, dir)); 826 } 827 828 void free_sftp_dirents(SFTP_DIRENT **s) 829 { 830 int i; 831 832 if (s == NULL) 833 return; 834 for (i = 0; s[i]; i++) { 835 free(s[i]->filename); 836 free(s[i]->longname); 837 free(s[i]); 838 } 839 free(s); 840 } 841 842 int 843 do_rm(struct sftp_conn *conn, const char *path) 844 { 845 u_int status, id; 846 847 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); 848 849 id = conn->msg_id++; 850 send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path)); 851 status = get_status(conn, id); 852 if (status != SSH2_FX_OK) 853 error("Couldn't delete file: %s", fx2txt(status)); 854 return status == SSH2_FX_OK ? 0 : -1; 855 } 856 857 int 858 do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag) 859 { 860 u_int status, id; 861 862 id = conn->msg_id++; 863 send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path, 864 strlen(path), a); 865 866 status = get_status(conn, id); 867 if (status != SSH2_FX_OK && print_flag) 868 error("Couldn't create directory: %s", fx2txt(status)); 869 870 return status == SSH2_FX_OK ? 0 : -1; 871 } 872 873 int 874 do_rmdir(struct sftp_conn *conn, const char *path) 875 { 876 u_int status, id; 877 878 id = conn->msg_id++; 879 send_string_request(conn, id, SSH2_FXP_RMDIR, path, 880 strlen(path)); 881 882 status = get_status(conn, id); 883 if (status != SSH2_FX_OK) 884 error("Couldn't remove directory: %s", fx2txt(status)); 885 886 return status == SSH2_FX_OK ? 0 : -1; 887 } 888 889 Attrib * 890 do_stat(struct sftp_conn *conn, const char *path, int quiet) 891 { 892 u_int id; 893 894 id = conn->msg_id++; 895 896 send_string_request(conn, id, 897 conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, 898 path, strlen(path)); 899 900 return(get_decode_stat(conn, id, quiet)); 901 } 902 903 Attrib * 904 do_lstat(struct sftp_conn *conn, const char *path, int quiet) 905 { 906 u_int id; 907 908 if (conn->version == 0) { 909 if (quiet) 910 debug("Server version does not support lstat operation"); 911 else 912 logit("Server version does not support lstat operation"); 913 return(do_stat(conn, path, quiet)); 914 } 915 916 id = conn->msg_id++; 917 send_string_request(conn, id, SSH2_FXP_LSTAT, path, 918 strlen(path)); 919 920 return(get_decode_stat(conn, id, quiet)); 921 } 922 923 #ifdef notyet 924 Attrib * 925 do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 926 int quiet) 927 { 928 u_int id; 929 930 id = conn->msg_id++; 931 send_string_request(conn, id, SSH2_FXP_FSTAT, handle, 932 handle_len); 933 934 return(get_decode_stat(conn, id, quiet)); 935 } 936 #endif 937 938 int 939 do_setstat(struct sftp_conn *conn, const char *path, Attrib *a) 940 { 941 u_int status, id; 942 943 id = conn->msg_id++; 944 send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path, 945 strlen(path), a); 946 947 status = get_status(conn, id); 948 if (status != SSH2_FX_OK) 949 error("Couldn't setstat on \"%s\": %s", path, 950 fx2txt(status)); 951 952 return status == SSH2_FX_OK ? 0 : -1; 953 } 954 955 int 956 do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 957 Attrib *a) 958 { 959 u_int status, id; 960 961 id = conn->msg_id++; 962 send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle, 963 handle_len, a); 964 965 status = get_status(conn, id); 966 if (status != SSH2_FX_OK) 967 error("Couldn't fsetstat: %s", fx2txt(status)); 968 969 return status == SSH2_FX_OK ? 0 : -1; 970 } 971 972 /* Implements both the realpath and expand-path operations */ 973 static char * 974 do_realpath_expand(struct sftp_conn *conn, const char *path, int expand) 975 { 976 struct sshbuf *msg; 977 u_int expected_id, count, id; 978 char *filename, *longname; 979 Attrib a; 980 u_char type; 981 int r; 982 const char *what = "SSH2_FXP_REALPATH"; 983 984 if (expand) 985 what = "expand-path@openssh.com"; 986 if ((msg = sshbuf_new()) == NULL) 987 fatal_f("sshbuf_new failed"); 988 989 expected_id = id = conn->msg_id++; 990 if (expand) { 991 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 992 (r = sshbuf_put_u32(msg, id)) != 0 || 993 (r = sshbuf_put_cstring(msg, 994 "expand-path@openssh.com")) != 0 || 995 (r = sshbuf_put_cstring(msg, path)) != 0) 996 fatal_fr(r, "compose %s", what); 997 send_msg(conn, msg); 998 } else { 999 send_string_request(conn, id, SSH2_FXP_REALPATH, 1000 path, strlen(path)); 1001 } 1002 get_msg(conn, msg); 1003 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1004 (r = sshbuf_get_u32(msg, &id)) != 0) 1005 fatal_fr(r, "parse"); 1006 1007 if (id != expected_id) 1008 fatal("ID mismatch (%u != %u)", id, expected_id); 1009 1010 if (type == SSH2_FXP_STATUS) { 1011 u_int status; 1012 1013 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1014 fatal_fr(r, "parse status"); 1015 error("Couldn't canonicalize: %s", fx2txt(status)); 1016 sshbuf_free(msg); 1017 return NULL; 1018 } else if (type != SSH2_FXP_NAME) 1019 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 1020 SSH2_FXP_NAME, type); 1021 1022 if ((r = sshbuf_get_u32(msg, &count)) != 0) 1023 fatal_fr(r, "parse count"); 1024 if (count != 1) 1025 fatal("Got multiple names (%d) from %s", count, what); 1026 1027 if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || 1028 (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || 1029 (r = decode_attrib(msg, &a)) != 0) 1030 fatal_fr(r, "parse filename/attrib"); 1031 1032 debug3("%s %s -> %s", what, path, filename); 1033 1034 free(longname); 1035 1036 sshbuf_free(msg); 1037 1038 return(filename); 1039 } 1040 1041 char * 1042 do_realpath(struct sftp_conn *conn, const char *path) 1043 { 1044 return do_realpath_expand(conn, path, 0); 1045 } 1046 1047 int 1048 can_expand_path(struct sftp_conn *conn) 1049 { 1050 return (conn->exts & SFTP_EXT_PATH_EXPAND) != 0; 1051 } 1052 1053 char * 1054 do_expand_path(struct sftp_conn *conn, const char *path) 1055 { 1056 if (!can_expand_path(conn)) { 1057 debug3_f("no server support, fallback to realpath"); 1058 return do_realpath_expand(conn, path, 0); 1059 } 1060 return do_realpath_expand(conn, path, 1); 1061 } 1062 1063 int 1064 do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, 1065 int force_legacy) 1066 { 1067 struct sshbuf *msg; 1068 u_int status, id; 1069 int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; 1070 1071 if ((msg = sshbuf_new()) == NULL) 1072 fatal_f("sshbuf_new failed"); 1073 1074 /* Send rename request */ 1075 id = conn->msg_id++; 1076 if (use_ext) { 1077 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1078 (r = sshbuf_put_u32(msg, id)) != 0 || 1079 (r = sshbuf_put_cstring(msg, 1080 "posix-rename@openssh.com")) != 0) 1081 fatal_fr(r, "compose posix-rename"); 1082 } else { 1083 if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 || 1084 (r = sshbuf_put_u32(msg, id)) != 0) 1085 fatal_fr(r, "compose rename"); 1086 } 1087 if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 || 1088 (r = sshbuf_put_cstring(msg, newpath)) != 0) 1089 fatal_fr(r, "compose paths"); 1090 send_msg(conn, msg); 1091 debug3("Sent message %s \"%s\" -> \"%s\"", 1092 use_ext ? "posix-rename@openssh.com" : 1093 "SSH2_FXP_RENAME", oldpath, newpath); 1094 sshbuf_free(msg); 1095 1096 status = get_status(conn, id); 1097 if (status != SSH2_FX_OK) 1098 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, 1099 newpath, fx2txt(status)); 1100 1101 return status == SSH2_FX_OK ? 0 : -1; 1102 } 1103 1104 int 1105 do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) 1106 { 1107 struct sshbuf *msg; 1108 u_int status, id; 1109 int r; 1110 1111 if ((conn->exts & SFTP_EXT_HARDLINK) == 0) { 1112 error("Server does not support hardlink@openssh.com extension"); 1113 return -1; 1114 } 1115 1116 if ((msg = sshbuf_new()) == NULL) 1117 fatal_f("sshbuf_new failed"); 1118 1119 /* Send link request */ 1120 id = conn->msg_id++; 1121 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1122 (r = sshbuf_put_u32(msg, id)) != 0 || 1123 (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 || 1124 (r = sshbuf_put_cstring(msg, oldpath)) != 0 || 1125 (r = sshbuf_put_cstring(msg, newpath)) != 0) 1126 fatal_fr(r, "compose"); 1127 send_msg(conn, msg); 1128 debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"", 1129 oldpath, newpath); 1130 sshbuf_free(msg); 1131 1132 status = get_status(conn, id); 1133 if (status != SSH2_FX_OK) 1134 error("Couldn't link file \"%s\" to \"%s\": %s", oldpath, 1135 newpath, fx2txt(status)); 1136 1137 return status == SSH2_FX_OK ? 0 : -1; 1138 } 1139 1140 int 1141 do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) 1142 { 1143 struct sshbuf *msg; 1144 u_int status, id; 1145 int r; 1146 1147 if (conn->version < 3) { 1148 error("This server does not support the symlink operation"); 1149 return(SSH2_FX_OP_UNSUPPORTED); 1150 } 1151 1152 if ((msg = sshbuf_new()) == NULL) 1153 fatal_f("sshbuf_new failed"); 1154 1155 /* Send symlink request */ 1156 id = conn->msg_id++; 1157 if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 || 1158 (r = sshbuf_put_u32(msg, id)) != 0 || 1159 (r = sshbuf_put_cstring(msg, oldpath)) != 0 || 1160 (r = sshbuf_put_cstring(msg, newpath)) != 0) 1161 fatal_fr(r, "compose"); 1162 send_msg(conn, msg); 1163 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, 1164 newpath); 1165 sshbuf_free(msg); 1166 1167 status = get_status(conn, id); 1168 if (status != SSH2_FX_OK) 1169 error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, 1170 newpath, fx2txt(status)); 1171 1172 return status == SSH2_FX_OK ? 0 : -1; 1173 } 1174 1175 int 1176 do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len) 1177 { 1178 struct sshbuf *msg; 1179 u_int status, id; 1180 int r; 1181 1182 /* Silently return if the extension is not supported */ 1183 if ((conn->exts & SFTP_EXT_FSYNC) == 0) 1184 return -1; 1185 1186 /* Send fsync request */ 1187 if ((msg = sshbuf_new()) == NULL) 1188 fatal_f("sshbuf_new failed"); 1189 id = conn->msg_id++; 1190 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1191 (r = sshbuf_put_u32(msg, id)) != 0 || 1192 (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || 1193 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 1194 fatal_fr(r, "compose"); 1195 send_msg(conn, msg); 1196 debug3("Sent message fsync@openssh.com I:%u", id); 1197 sshbuf_free(msg); 1198 1199 status = get_status(conn, id); 1200 if (status != SSH2_FX_OK) 1201 error("Couldn't sync file: %s", fx2txt(status)); 1202 1203 return status == SSH2_FX_OK ? 0 : -1; 1204 } 1205 1206 #ifdef notyet 1207 char * 1208 do_readlink(struct sftp_conn *conn, const char *path) 1209 { 1210 struct sshbuf *msg; 1211 u_int expected_id, count, id; 1212 char *filename, *longname; 1213 Attrib a; 1214 u_char type; 1215 int r; 1216 1217 expected_id = id = conn->msg_id++; 1218 send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); 1219 1220 if ((msg = sshbuf_new()) == NULL) 1221 fatal_f("sshbuf_new failed"); 1222 1223 get_msg(conn, msg); 1224 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1225 (r = sshbuf_get_u32(msg, &id)) != 0) 1226 fatal_fr(r, "parse"); 1227 1228 if (id != expected_id) 1229 fatal("ID mismatch (%u != %u)", id, expected_id); 1230 1231 if (type == SSH2_FXP_STATUS) { 1232 u_int status; 1233 1234 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1235 fatal_fr(r, "parse status"); 1236 error("Couldn't readlink: %s", fx2txt(status)); 1237 sshbuf_free(msg); 1238 return(NULL); 1239 } else if (type != SSH2_FXP_NAME) 1240 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", 1241 SSH2_FXP_NAME, type); 1242 1243 if ((r = sshbuf_get_u32(msg, &count)) != 0) 1244 fatal_fr(r, "parse count"); 1245 if (count != 1) 1246 fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); 1247 1248 if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || 1249 (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || 1250 (r = decode_attrib(msg, &a)) != 0) 1251 fatal_fr(r, "parse filenames/attrib"); 1252 1253 debug3("SSH_FXP_READLINK %s -> %s", path, filename); 1254 1255 free(longname); 1256 1257 sshbuf_free(msg); 1258 1259 return filename; 1260 } 1261 #endif 1262 1263 int 1264 do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, 1265 int quiet) 1266 { 1267 struct sshbuf *msg; 1268 u_int id; 1269 int r; 1270 1271 if ((conn->exts & SFTP_EXT_STATVFS) == 0) { 1272 error("Server does not support statvfs@openssh.com extension"); 1273 return -1; 1274 } 1275 1276 id = conn->msg_id++; 1277 1278 if ((msg = sshbuf_new()) == NULL) 1279 fatal_f("sshbuf_new failed"); 1280 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1281 (r = sshbuf_put_u32(msg, id)) != 0 || 1282 (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 || 1283 (r = sshbuf_put_cstring(msg, path)) != 0) 1284 fatal_fr(r, "compose"); 1285 send_msg(conn, msg); 1286 sshbuf_free(msg); 1287 1288 return get_decode_statvfs(conn, st, id, quiet); 1289 } 1290 1291 #ifdef notyet 1292 int 1293 do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len, 1294 struct sftp_statvfs *st, int quiet) 1295 { 1296 struct sshbuf *msg; 1297 u_int id; 1298 1299 if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) { 1300 error("Server does not support fstatvfs@openssh.com extension"); 1301 return -1; 1302 } 1303 1304 id = conn->msg_id++; 1305 1306 if ((msg = sshbuf_new()) == NULL) 1307 fatal_f("sshbuf_new failed"); 1308 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1309 (r = sshbuf_put_u32(msg, id)) != 0 || 1310 (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 || 1311 (r = sshbuf_put_string(msg, handle, handle_len)) != 0) 1312 fatal_fr(r, "compose"); 1313 send_msg(conn, msg); 1314 sshbuf_free(msg); 1315 1316 return get_decode_statvfs(conn, st, id, quiet); 1317 } 1318 #endif 1319 1320 int 1321 do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a) 1322 { 1323 struct sshbuf *msg; 1324 u_int status, id; 1325 int r; 1326 1327 if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) { 1328 error("Server does not support lsetstat@openssh.com extension"); 1329 return -1; 1330 } 1331 1332 id = conn->msg_id++; 1333 if ((msg = sshbuf_new()) == NULL) 1334 fatal_f("sshbuf_new failed"); 1335 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1336 (r = sshbuf_put_u32(msg, id)) != 0 || 1337 (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 || 1338 (r = sshbuf_put_cstring(msg, path)) != 0 || 1339 (r = encode_attrib(msg, a)) != 0) 1340 fatal_fr(r, "compose"); 1341 send_msg(conn, msg); 1342 sshbuf_free(msg); 1343 1344 status = get_status(conn, id); 1345 if (status != SSH2_FX_OK) 1346 error("Couldn't setstat on \"%s\": %s", path, 1347 fx2txt(status)); 1348 1349 return status == SSH2_FX_OK ? 0 : -1; 1350 } 1351 1352 static void 1353 send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, 1354 u_int len, const u_char *handle, u_int handle_len) 1355 { 1356 struct sshbuf *msg; 1357 int r; 1358 1359 if ((msg = sshbuf_new()) == NULL) 1360 fatal_f("sshbuf_new failed"); 1361 if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 || 1362 (r = sshbuf_put_u32(msg, id)) != 0 || 1363 (r = sshbuf_put_string(msg, handle, handle_len)) != 0 || 1364 (r = sshbuf_put_u64(msg, offset)) != 0 || 1365 (r = sshbuf_put_u32(msg, len)) != 0) 1366 fatal_fr(r, "compose"); 1367 send_msg(conn, msg); 1368 sshbuf_free(msg); 1369 } 1370 1371 static int 1372 send_open(struct sftp_conn *conn, const char *path, const char *tag, 1373 u_int openmode, Attrib *a, u_char **handlep, size_t *handle_lenp) 1374 { 1375 Attrib junk; 1376 u_char *handle; 1377 size_t handle_len; 1378 struct sshbuf *msg; 1379 int r; 1380 u_int id; 1381 1382 *handlep = NULL; 1383 *handle_lenp = 0; 1384 1385 if (a == NULL) { 1386 attrib_clear(&junk); /* Send empty attributes */ 1387 a = &junk; 1388 } 1389 /* Send open request */ 1390 if ((msg = sshbuf_new()) == NULL) 1391 fatal_f("sshbuf_new failed"); 1392 id = conn->msg_id++; 1393 if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || 1394 (r = sshbuf_put_u32(msg, id)) != 0 || 1395 (r = sshbuf_put_cstring(msg, path)) != 0 || 1396 (r = sshbuf_put_u32(msg, openmode)) != 0 || 1397 (r = encode_attrib(msg, a)) != 0) 1398 fatal_fr(r, "compose %s open", tag); 1399 send_msg(conn, msg); 1400 sshbuf_free(msg); 1401 debug3("Sent %s message SSH2_FXP_OPEN I:%u P:%s M:0x%04x", 1402 tag, id, path, openmode); 1403 if ((handle = get_handle(conn, id, &handle_len, 1404 "%s open(\"%s\")", tag, path)) == NULL) 1405 return -1; 1406 /* success */ 1407 *handlep = handle; 1408 *handle_lenp = handle_len; 1409 return 0; 1410 } 1411 1412 static const char * 1413 progress_meter_path(const char *path) 1414 { 1415 const char *progresspath; 1416 1417 if ((progresspath = strrchr(path, '/')) == NULL) 1418 return path; 1419 progresspath++; 1420 if (*progresspath == '\0') 1421 return path; 1422 return progresspath; 1423 } 1424 1425 int 1426 do_download(struct sftp_conn *conn, const char *remote_path, 1427 const char *local_path, Attrib *a, int preserve_flag, int resume_flag, 1428 int fsync_flag) 1429 { 1430 struct sshbuf *msg; 1431 u_char *handle; 1432 int local_fd = -1, write_error; 1433 int read_error, write_errno, lmodified = 0, reordered = 0, r; 1434 u_int64_t offset = 0, size, highwater; 1435 u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK; 1436 off_t progress_counter; 1437 size_t handle_len; 1438 struct stat st; 1439 struct requests requests; 1440 struct request *req; 1441 u_char type; 1442 1443 TAILQ_INIT(&requests); 1444 1445 if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL) 1446 return -1; 1447 1448 /* Do not preserve set[ug]id here, as we do not preserve ownership */ 1449 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) 1450 mode = a->perm & 0777; 1451 else 1452 mode = 0666; 1453 1454 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && 1455 (!S_ISREG(a->perm))) { 1456 error("Cannot download non-regular file: %s", remote_path); 1457 return(-1); 1458 } 1459 1460 if (a->flags & SSH2_FILEXFER_ATTR_SIZE) 1461 size = a->size; 1462 else 1463 size = 0; 1464 1465 buflen = conn->download_buflen; 1466 1467 /* Send open request */ 1468 if (send_open(conn, remote_path, "remote", SSH2_FXF_READ, NULL, 1469 &handle, &handle_len) != 0) 1470 return -1; 1471 1472 local_fd = open(local_path, 1473 O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR); 1474 if (local_fd == -1) { 1475 error("Couldn't open local file \"%s\" for writing: %s", 1476 local_path, strerror(errno)); 1477 goto fail; 1478 } 1479 offset = highwater = 0; 1480 if (resume_flag) { 1481 if (fstat(local_fd, &st) == -1) { 1482 error("Unable to stat local file \"%s\": %s", 1483 local_path, strerror(errno)); 1484 goto fail; 1485 } 1486 if (st.st_size < 0) { 1487 error("\"%s\" has negative size", local_path); 1488 goto fail; 1489 } 1490 if ((u_int64_t)st.st_size > size) { 1491 error("Unable to resume download of \"%s\": " 1492 "local file is larger than remote", local_path); 1493 fail: 1494 do_close(conn, handle, handle_len); 1495 free(handle); 1496 if (local_fd != -1) 1497 close(local_fd); 1498 return -1; 1499 } 1500 offset = highwater = st.st_size; 1501 } 1502 1503 /* Read from remote and write to local */ 1504 write_error = read_error = write_errno = num_req = 0; 1505 max_req = 1; 1506 progress_counter = offset; 1507 1508 if (showprogress && size != 0) { 1509 start_progress_meter(progress_meter_path(remote_path), 1510 size, &progress_counter); 1511 } 1512 1513 if ((msg = sshbuf_new()) == NULL) 1514 fatal_f("sshbuf_new failed"); 1515 1516 while (num_req > 0 || max_req > 0) { 1517 u_char *data; 1518 size_t len; 1519 1520 /* 1521 * Simulate EOF on interrupt: stop sending new requests and 1522 * allow outstanding requests to drain gracefully 1523 */ 1524 if (interrupted) { 1525 if (num_req == 0) /* If we haven't started yet... */ 1526 break; 1527 max_req = 0; 1528 } 1529 1530 /* Send some more requests */ 1531 while (num_req < max_req) { 1532 debug3("Request range %llu -> %llu (%d/%d)", 1533 (unsigned long long)offset, 1534 (unsigned long long)offset + buflen - 1, 1535 num_req, max_req); 1536 req = request_enqueue(&requests, conn->msg_id++, 1537 buflen, offset); 1538 offset += buflen; 1539 num_req++; 1540 send_read_request(conn, req->id, req->offset, 1541 req->len, handle, handle_len); 1542 } 1543 1544 sshbuf_reset(msg); 1545 get_msg(conn, msg); 1546 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1547 (r = sshbuf_get_u32(msg, &id)) != 0) 1548 fatal_fr(r, "parse"); 1549 debug3("Received reply T:%u I:%u R:%d", type, id, max_req); 1550 1551 /* Find the request in our queue */ 1552 if ((req = request_find(&requests, id)) == NULL) 1553 fatal("Unexpected reply %u", id); 1554 1555 switch (type) { 1556 case SSH2_FXP_STATUS: 1557 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1558 fatal_fr(r, "parse status"); 1559 if (status != SSH2_FX_EOF) 1560 read_error = 1; 1561 max_req = 0; 1562 TAILQ_REMOVE(&requests, req, tq); 1563 free(req); 1564 num_req--; 1565 break; 1566 case SSH2_FXP_DATA: 1567 if ((r = sshbuf_get_string(msg, &data, &len)) != 0) 1568 fatal_fr(r, "parse data"); 1569 debug3("Received data %llu -> %llu", 1570 (unsigned long long)req->offset, 1571 (unsigned long long)req->offset + len - 1); 1572 if (len > req->len) 1573 fatal("Received more data than asked for " 1574 "%zu > %zu", len, req->len); 1575 lmodified = 1; 1576 if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || 1577 atomicio(vwrite, local_fd, data, len) != len) && 1578 !write_error) { 1579 write_errno = errno; 1580 write_error = 1; 1581 max_req = 0; 1582 } 1583 else if (!reordered && req->offset <= highwater) 1584 highwater = req->offset + len; 1585 else if (!reordered && req->offset > highwater) 1586 reordered = 1; 1587 progress_counter += len; 1588 free(data); 1589 1590 if (len == req->len) { 1591 TAILQ_REMOVE(&requests, req, tq); 1592 free(req); 1593 num_req--; 1594 } else { 1595 /* Resend the request for the missing data */ 1596 debug3("Short data block, re-requesting " 1597 "%llu -> %llu (%2d)", 1598 (unsigned long long)req->offset + len, 1599 (unsigned long long)req->offset + 1600 req->len - 1, num_req); 1601 req->id = conn->msg_id++; 1602 req->len -= len; 1603 req->offset += len; 1604 send_read_request(conn, req->id, 1605 req->offset, req->len, handle, handle_len); 1606 /* Reduce the request size */ 1607 if (len < buflen) 1608 buflen = MAXIMUM(MIN_READ_SIZE, len); 1609 } 1610 if (max_req > 0) { /* max_req = 0 iff EOF received */ 1611 if (size > 0 && offset > size) { 1612 /* Only one request at a time 1613 * after the expected EOF */ 1614 debug3("Finish at %llu (%2d)", 1615 (unsigned long long)offset, 1616 num_req); 1617 max_req = 1; 1618 } else if (max_req < conn->num_requests) { 1619 ++max_req; 1620 } 1621 } 1622 break; 1623 default: 1624 fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", 1625 SSH2_FXP_DATA, type); 1626 } 1627 } 1628 1629 if (showprogress && size) 1630 stop_progress_meter(); 1631 1632 /* Sanity check */ 1633 if (TAILQ_FIRST(&requests) != NULL) 1634 fatal("Transfer complete, but requests still in queue"); 1635 /* Truncate at highest contiguous point to avoid holes on interrupt */ 1636 if (read_error || write_error || interrupted) { 1637 if (reordered && resume_flag) { 1638 error("Unable to resume download of \"%s\": " 1639 "server reordered requests", local_path); 1640 } 1641 debug("truncating at %llu", (unsigned long long)highwater); 1642 if (ftruncate(local_fd, highwater) == -1) 1643 error("ftruncate \"%s\": %s", local_path, 1644 strerror(errno)); 1645 } 1646 if (read_error) { 1647 error("Couldn't read from remote file \"%s\" : %s", 1648 remote_path, fx2txt(status)); 1649 status = -1; 1650 do_close(conn, handle, handle_len); 1651 } else if (write_error) { 1652 error("Couldn't write to \"%s\": %s", local_path, 1653 strerror(write_errno)); 1654 status = SSH2_FX_FAILURE; 1655 do_close(conn, handle, handle_len); 1656 } else { 1657 if (do_close(conn, handle, handle_len) != 0 || interrupted) 1658 status = SSH2_FX_FAILURE; 1659 else 1660 status = SSH2_FX_OK; 1661 /* Override umask and utimes if asked */ 1662 #ifdef HAVE_FCHMOD 1663 if (preserve_flag && fchmod(local_fd, mode) == -1) 1664 #else 1665 if (preserve_flag && chmod(local_path, mode) == -1) 1666 #endif /* HAVE_FCHMOD */ 1667 error("Couldn't set mode on \"%s\": %s", local_path, 1668 strerror(errno)); 1669 if (preserve_flag && 1670 (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) { 1671 struct timeval tv[2]; 1672 tv[0].tv_sec = a->atime; 1673 tv[1].tv_sec = a->mtime; 1674 tv[0].tv_usec = tv[1].tv_usec = 0; 1675 if (utimes(local_path, tv) == -1) 1676 error("Can't set times on \"%s\": %s", 1677 local_path, strerror(errno)); 1678 } 1679 if (resume_flag && !lmodified) 1680 logit("File \"%s\" was not modified", local_path); 1681 else if (fsync_flag) { 1682 debug("syncing \"%s\"", local_path); 1683 if (fsync(local_fd) == -1) 1684 error("Couldn't sync file \"%s\": %s", 1685 local_path, strerror(errno)); 1686 } 1687 } 1688 close(local_fd); 1689 sshbuf_free(msg); 1690 free(handle); 1691 1692 return status == SSH2_FX_OK ? 0 : -1; 1693 } 1694 1695 static int 1696 download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, 1697 int depth, Attrib *dirattrib, int preserve_flag, int print_flag, 1698 int resume_flag, int fsync_flag, int follow_link_flag) 1699 { 1700 int i, ret = 0; 1701 SFTP_DIRENT **dir_entries; 1702 char *filename, *new_src = NULL, *new_dst = NULL; 1703 mode_t mode = 0777, tmpmode = mode; 1704 1705 if (depth >= MAX_DIR_DEPTH) { 1706 error("Maximum directory depth exceeded: %d levels", depth); 1707 return -1; 1708 } 1709 1710 if (dirattrib == NULL && 1711 (dirattrib = do_stat(conn, src, 1)) == NULL) { 1712 error("Unable to stat remote directory \"%s\"", src); 1713 return -1; 1714 } 1715 if (!S_ISDIR(dirattrib->perm)) { 1716 error("\"%s\" is not a directory", src); 1717 return -1; 1718 } 1719 if (print_flag && print_flag != SFTP_PROGRESS_ONLY) 1720 mprintf("Retrieving %s\n", src); 1721 1722 if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) { 1723 mode = dirattrib->perm & 01777; 1724 tmpmode = mode | (S_IWUSR|S_IXUSR); 1725 } else { 1726 debug("Server did not send permissions for " 1727 "directory \"%s\"", dst); 1728 } 1729 1730 if (mkdir(dst, tmpmode) == -1 && errno != EEXIST) { 1731 error("mkdir %s: %s", dst, strerror(errno)); 1732 return -1; 1733 } 1734 1735 if (do_readdir(conn, src, &dir_entries) == -1) { 1736 error("%s: Failed to get directory contents", src); 1737 return -1; 1738 } 1739 1740 for (i = 0; dir_entries[i] != NULL && !interrupted; i++) { 1741 free(new_dst); 1742 free(new_src); 1743 1744 filename = dir_entries[i]->filename; 1745 new_dst = path_append(dst, filename); 1746 new_src = path_append(src, filename); 1747 1748 if (S_ISDIR(dir_entries[i]->a.perm)) { 1749 if (strcmp(filename, ".") == 0 || 1750 strcmp(filename, "..") == 0) 1751 continue; 1752 if (download_dir_internal(conn, new_src, new_dst, 1753 depth + 1, &(dir_entries[i]->a), preserve_flag, 1754 print_flag, resume_flag, 1755 fsync_flag, follow_link_flag) == -1) 1756 ret = -1; 1757 } else if (S_ISREG(dir_entries[i]->a.perm) || 1758 (follow_link_flag && S_ISLNK(dir_entries[i]->a.perm))) { 1759 /* 1760 * If this is a symlink then don't send the link's 1761 * Attrib. do_download() will do a FXP_STAT operation 1762 * and get the link target's attributes. 1763 */ 1764 if (do_download(conn, new_src, new_dst, 1765 S_ISLNK(dir_entries[i]->a.perm) ? NULL : 1766 &(dir_entries[i]->a), 1767 preserve_flag, resume_flag, fsync_flag) == -1) { 1768 error("Download of file %s to %s failed", 1769 new_src, new_dst); 1770 ret = -1; 1771 } 1772 } else 1773 logit("%s: not a regular file\n", new_src); 1774 1775 } 1776 free(new_dst); 1777 free(new_src); 1778 1779 if (preserve_flag) { 1780 if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) { 1781 struct timeval tv[2]; 1782 tv[0].tv_sec = dirattrib->atime; 1783 tv[1].tv_sec = dirattrib->mtime; 1784 tv[0].tv_usec = tv[1].tv_usec = 0; 1785 if (utimes(dst, tv) == -1) 1786 error("Can't set times on \"%s\": %s", 1787 dst, strerror(errno)); 1788 } else 1789 debug("Server did not send times for directory " 1790 "\"%s\"", dst); 1791 } 1792 1793 if (mode != tmpmode && chmod(dst, mode) == -1) 1794 error("Can't set final mode on \"%s\": %s", dst, 1795 strerror(errno)); 1796 1797 free_sftp_dirents(dir_entries); 1798 1799 return ret; 1800 } 1801 1802 int 1803 download_dir(struct sftp_conn *conn, const char *src, const char *dst, 1804 Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, 1805 int fsync_flag, int follow_link_flag) 1806 { 1807 char *src_canon; 1808 int ret; 1809 1810 if ((src_canon = do_realpath(conn, src)) == NULL) { 1811 error("Unable to canonicalize path \"%s\"", src); 1812 return -1; 1813 } 1814 1815 ret = download_dir_internal(conn, src_canon, dst, 0, 1816 dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag, 1817 follow_link_flag); 1818 free(src_canon); 1819 return ret; 1820 } 1821 1822 int 1823 do_upload(struct sftp_conn *conn, const char *local_path, 1824 const char *remote_path, int preserve_flag, int resume, int fsync_flag) 1825 { 1826 int r, local_fd; 1827 u_int status = SSH2_FX_OK; 1828 u_int id; 1829 u_char type; 1830 off_t offset, progress_counter; 1831 u_char *handle, *data; 1832 struct sshbuf *msg; 1833 struct stat sb; 1834 Attrib a, *c = NULL; 1835 u_int32_t startid; 1836 u_int32_t ackid; 1837 struct request *ack = NULL; 1838 struct requests acks; 1839 size_t handle_len; 1840 1841 TAILQ_INIT(&acks); 1842 1843 if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) { 1844 error("Couldn't open local file \"%s\" for reading: %s", 1845 local_path, strerror(errno)); 1846 return(-1); 1847 } 1848 if (fstat(local_fd, &sb) == -1) { 1849 error("Couldn't fstat local file \"%s\": %s", 1850 local_path, strerror(errno)); 1851 close(local_fd); 1852 return(-1); 1853 } 1854 if (!S_ISREG(sb.st_mode)) { 1855 error("%s is not a regular file", local_path); 1856 close(local_fd); 1857 return(-1); 1858 } 1859 stat_to_attrib(&sb, &a); 1860 1861 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 1862 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 1863 a.perm &= 0777; 1864 if (!preserve_flag) 1865 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 1866 1867 if (resume) { 1868 /* Get remote file size if it exists */ 1869 if ((c = do_stat(conn, remote_path, 0)) == NULL) { 1870 close(local_fd); 1871 return -1; 1872 } 1873 1874 if ((off_t)c->size >= sb.st_size) { 1875 error("destination file bigger or same size as " 1876 "source file"); 1877 close(local_fd); 1878 return -1; 1879 } 1880 1881 if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) { 1882 close(local_fd); 1883 return -1; 1884 } 1885 } 1886 1887 /* Send open request */ 1888 if (send_open(conn, remote_path, "dest", SSH2_FXF_WRITE|SSH2_FXF_CREAT| 1889 (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC), 1890 &a, &handle, &handle_len) != 0) { 1891 close(local_fd); 1892 return -1; 1893 } 1894 1895 id = conn->msg_id; 1896 startid = ackid = id + 1; 1897 data = xmalloc(conn->upload_buflen); 1898 1899 /* Read from local and write to remote */ 1900 offset = progress_counter = (resume ? c->size : 0); 1901 if (showprogress) { 1902 start_progress_meter(progress_meter_path(local_path), 1903 sb.st_size, &progress_counter); 1904 } 1905 1906 if ((msg = sshbuf_new()) == NULL) 1907 fatal_f("sshbuf_new failed"); 1908 for (;;) { 1909 int len; 1910 1911 /* 1912 * Can't use atomicio here because it returns 0 on EOF, 1913 * thus losing the last block of the file. 1914 * Simulate an EOF on interrupt, allowing ACKs from the 1915 * server to drain. 1916 */ 1917 if (interrupted || status != SSH2_FX_OK) 1918 len = 0; 1919 else do 1920 len = read(local_fd, data, conn->upload_buflen); 1921 while ((len == -1) && 1922 (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)); 1923 1924 if (len == -1) 1925 fatal("Couldn't read from \"%s\": %s", local_path, 1926 strerror(errno)); 1927 1928 if (len != 0) { 1929 ack = request_enqueue(&acks, ++id, len, offset); 1930 sshbuf_reset(msg); 1931 if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || 1932 (r = sshbuf_put_u32(msg, ack->id)) != 0 || 1933 (r = sshbuf_put_string(msg, handle, 1934 handle_len)) != 0 || 1935 (r = sshbuf_put_u64(msg, offset)) != 0 || 1936 (r = sshbuf_put_string(msg, data, len)) != 0) 1937 fatal_fr(r, "compose"); 1938 send_msg(conn, msg); 1939 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", 1940 id, (unsigned long long)offset, len); 1941 } else if (TAILQ_FIRST(&acks) == NULL) 1942 break; 1943 1944 if (ack == NULL) 1945 fatal("Unexpected ACK %u", id); 1946 1947 if (id == startid || len == 0 || 1948 id - ackid >= conn->num_requests) { 1949 u_int rid; 1950 1951 sshbuf_reset(msg); 1952 get_msg(conn, msg); 1953 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 1954 (r = sshbuf_get_u32(msg, &rid)) != 0) 1955 fatal_fr(r, "parse"); 1956 1957 if (type != SSH2_FXP_STATUS) 1958 fatal("Expected SSH2_FXP_STATUS(%d) packet, " 1959 "got %d", SSH2_FXP_STATUS, type); 1960 1961 if ((r = sshbuf_get_u32(msg, &status)) != 0) 1962 fatal_fr(r, "parse status"); 1963 debug3("SSH2_FXP_STATUS %u", status); 1964 1965 /* Find the request in our queue */ 1966 if ((ack = request_find(&acks, rid)) == NULL) 1967 fatal("Can't find request for ID %u", rid); 1968 TAILQ_REMOVE(&acks, ack, tq); 1969 debug3("In write loop, ack for %u %zu bytes at %lld", 1970 ack->id, ack->len, (unsigned long long)ack->offset); 1971 ++ackid; 1972 progress_counter += ack->len; 1973 free(ack); 1974 } 1975 offset += len; 1976 if (offset < 0) 1977 fatal_f("offset < 0"); 1978 } 1979 sshbuf_free(msg); 1980 1981 if (showprogress) 1982 stop_progress_meter(); 1983 free(data); 1984 1985 if (status != SSH2_FX_OK) { 1986 error("Couldn't write to remote file \"%s\": %s", 1987 remote_path, fx2txt(status)); 1988 status = SSH2_FX_FAILURE; 1989 } 1990 1991 if (close(local_fd) == -1) { 1992 error("Couldn't close local file \"%s\": %s", local_path, 1993 strerror(errno)); 1994 status = SSH2_FX_FAILURE; 1995 } 1996 1997 /* Override umask and utimes if asked */ 1998 if (preserve_flag) 1999 do_fsetstat(conn, handle, handle_len, &a); 2000 2001 if (fsync_flag) 2002 (void)do_fsync(conn, handle, handle_len); 2003 2004 if (do_close(conn, handle, handle_len) != 0) 2005 status = SSH2_FX_FAILURE; 2006 2007 free(handle); 2008 2009 return status == SSH2_FX_OK ? 0 : -1; 2010 } 2011 2012 static int 2013 upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, 2014 int depth, int preserve_flag, int print_flag, int resume, int fsync_flag, 2015 int follow_link_flag) 2016 { 2017 int ret = 0; 2018 DIR *dirp; 2019 struct dirent *dp; 2020 char *filename, *new_src = NULL, *new_dst = NULL; 2021 struct stat sb; 2022 Attrib a, *dirattrib; 2023 u_int32_t saved_perm; 2024 2025 if (depth >= MAX_DIR_DEPTH) { 2026 error("Maximum directory depth exceeded: %d levels", depth); 2027 return -1; 2028 } 2029 2030 if (stat(src, &sb) == -1) { 2031 error("Couldn't stat directory \"%s\": %s", 2032 src, strerror(errno)); 2033 return -1; 2034 } 2035 if (!S_ISDIR(sb.st_mode)) { 2036 error("\"%s\" is not a directory", src); 2037 return -1; 2038 } 2039 if (print_flag && print_flag != SFTP_PROGRESS_ONLY) 2040 mprintf("Entering %s\n", src); 2041 2042 attrib_clear(&a); 2043 stat_to_attrib(&sb, &a); 2044 a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 2045 a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 2046 a.perm &= 01777; 2047 if (!preserve_flag) 2048 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 2049 2050 /* 2051 * sftp lacks a portable status value to match errno EEXIST, 2052 * so if we get a failure back then we must check whether 2053 * the path already existed and is a directory. Ensure we can 2054 * write to the directory we create for the duration of the transfer. 2055 */ 2056 saved_perm = a.perm; 2057 a.perm |= (S_IWUSR|S_IXUSR); 2058 if (do_mkdir(conn, dst, &a, 0) != 0) { 2059 if ((dirattrib = do_stat(conn, dst, 0)) == NULL) 2060 return -1; 2061 if (!S_ISDIR(dirattrib->perm)) { 2062 error("\"%s\" exists but is not a directory", dst); 2063 return -1; 2064 } 2065 } 2066 a.perm = saved_perm; 2067 2068 if ((dirp = opendir(src)) == NULL) { 2069 error("Failed to open dir \"%s\": %s", src, strerror(errno)); 2070 return -1; 2071 } 2072 2073 while (((dp = readdir(dirp)) != NULL) && !interrupted) { 2074 if (dp->d_ino == 0) 2075 continue; 2076 free(new_dst); 2077 free(new_src); 2078 filename = dp->d_name; 2079 new_dst = path_append(dst, filename); 2080 new_src = path_append(src, filename); 2081 2082 if (lstat(new_src, &sb) == -1) { 2083 logit("%s: lstat failed: %s", filename, 2084 strerror(errno)); 2085 ret = -1; 2086 } else if (S_ISDIR(sb.st_mode)) { 2087 if (strcmp(filename, ".") == 0 || 2088 strcmp(filename, "..") == 0) 2089 continue; 2090 2091 if (upload_dir_internal(conn, new_src, new_dst, 2092 depth + 1, preserve_flag, print_flag, resume, 2093 fsync_flag, follow_link_flag) == -1) 2094 ret = -1; 2095 } else if (S_ISREG(sb.st_mode) || 2096 (follow_link_flag && S_ISLNK(sb.st_mode))) { 2097 if (do_upload(conn, new_src, new_dst, 2098 preserve_flag, resume, fsync_flag) == -1) { 2099 error("Uploading of file %s to %s failed!", 2100 new_src, new_dst); 2101 ret = -1; 2102 } 2103 } else 2104 logit("%s: not a regular file\n", filename); 2105 } 2106 free(new_dst); 2107 free(new_src); 2108 2109 do_setstat(conn, dst, &a); 2110 2111 (void) closedir(dirp); 2112 return ret; 2113 } 2114 2115 int 2116 upload_dir(struct sftp_conn *conn, const char *src, const char *dst, 2117 int preserve_flag, int print_flag, int resume, int fsync_flag, 2118 int follow_link_flag) 2119 { 2120 char *dst_canon; 2121 int ret; 2122 2123 if ((dst_canon = do_realpath(conn, dst)) == NULL) { 2124 error("Unable to canonicalize path \"%s\"", dst); 2125 return -1; 2126 } 2127 2128 ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, 2129 print_flag, resume, fsync_flag, follow_link_flag); 2130 2131 free(dst_canon); 2132 return ret; 2133 } 2134 2135 static void 2136 handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous, 2137 u_int *nreqsp, u_int *write_errorp) 2138 { 2139 struct sshbuf *msg; 2140 u_char type; 2141 u_int id, status; 2142 int r; 2143 struct pollfd pfd; 2144 2145 if ((msg = sshbuf_new()) == NULL) 2146 fatal_f("sshbuf_new failed"); 2147 2148 /* Try to eat replies from the upload side */ 2149 while (*nreqsp > 0) { 2150 debug3_f("%u outstanding replies", *nreqsp); 2151 if (!synchronous) { 2152 /* Bail out if no data is ready to be read */ 2153 pfd.fd = to->fd_in; 2154 pfd.events = POLLIN; 2155 if ((r = poll(&pfd, 1, 0)) == -1) { 2156 if (errno == EINTR) 2157 break; 2158 fatal_f("poll: %s", strerror(errno)); 2159 } else if (r == 0) 2160 break; /* fd not ready */ 2161 } 2162 sshbuf_reset(msg); 2163 get_msg(to, msg); 2164 2165 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 2166 (r = sshbuf_get_u32(msg, &id)) != 0) 2167 fatal_fr(r, "dest parse"); 2168 debug3("Received dest reply T:%u I:%u R:%u", type, id, *nreqsp); 2169 if (type != SSH2_FXP_STATUS) { 2170 fatal_f("Expected SSH2_FXP_STATUS(%d) packet, got %d", 2171 SSH2_FXP_STATUS, type); 2172 } 2173 if ((r = sshbuf_get_u32(msg, &status)) != 0) 2174 fatal_fr(r, "parse dest status"); 2175 debug3("dest SSH2_FXP_STATUS %u", status); 2176 if (status != SSH2_FX_OK) { 2177 /* record first error */ 2178 if (*write_errorp == 0) 2179 *write_errorp = status; 2180 } 2181 /* 2182 * XXX this doesn't do full reply matching like do_upload and 2183 * so cannot gracefully truncate terminated uploads at a 2184 * high-water mark. ATM the only caller of this function (scp) 2185 * doesn't support transfer resumption, so this doesn't matter 2186 * a whole lot. 2187 * 2188 * To be safe, do_crossload truncates the destination file to 2189 * zero length on upload failure, since we can't trust the 2190 * server not to have reordered replies that could have 2191 * inserted holes where none existed in the source file. 2192 * 2193 * XXX we could get a more accutate progress bar if we updated 2194 * the counter based on the reply from the destination... 2195 */ 2196 (*nreqsp)--; 2197 } 2198 debug3_f("done: %u outstanding replies", *nreqsp); 2199 } 2200 2201 int 2202 do_crossload(struct sftp_conn *from, struct sftp_conn *to, 2203 const char *from_path, const char *to_path, 2204 Attrib *a, int preserve_flag) 2205 { 2206 struct sshbuf *msg; 2207 int write_error, read_error, r; 2208 u_int64_t offset = 0, size; 2209 u_int id, buflen, num_req, max_req, status = SSH2_FX_OK; 2210 u_int num_upload_req; 2211 off_t progress_counter; 2212 u_char *from_handle, *to_handle; 2213 size_t from_handle_len, to_handle_len; 2214 struct requests requests; 2215 struct request *req; 2216 u_char type; 2217 2218 TAILQ_INIT(&requests); 2219 2220 if (a == NULL && (a = do_stat(from, from_path, 0)) == NULL) 2221 return -1; 2222 2223 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) && 2224 (!S_ISREG(a->perm))) { 2225 error("Cannot download non-regular file: %s", from_path); 2226 return(-1); 2227 } 2228 if (a->flags & SSH2_FILEXFER_ATTR_SIZE) 2229 size = a->size; 2230 else 2231 size = 0; 2232 2233 buflen = from->download_buflen; 2234 if (buflen > to->upload_buflen) 2235 buflen = to->upload_buflen; 2236 2237 /* Send open request to read side */ 2238 if (send_open(from, from_path, "origin", SSH2_FXF_READ, NULL, 2239 &from_handle, &from_handle_len) != 0) 2240 return -1; 2241 2242 /* Send open request to write side */ 2243 a->flags &= ~SSH2_FILEXFER_ATTR_SIZE; 2244 a->flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 2245 a->perm &= 0777; 2246 if (!preserve_flag) 2247 a->flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 2248 if (send_open(to, to_path, "dest", 2249 SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a, 2250 &to_handle, &to_handle_len) != 0) { 2251 do_close(from, from_handle, from_handle_len); 2252 return -1; 2253 } 2254 2255 /* Read from remote "from" and write to remote "to" */ 2256 offset = 0; 2257 write_error = read_error = num_req = num_upload_req = 0; 2258 max_req = 1; 2259 progress_counter = 0; 2260 2261 if (showprogress && size != 0) { 2262 start_progress_meter(progress_meter_path(from_path), 2263 size, &progress_counter); 2264 } 2265 if ((msg = sshbuf_new()) == NULL) 2266 fatal_f("sshbuf_new failed"); 2267 while (num_req > 0 || max_req > 0) { 2268 u_char *data; 2269 size_t len; 2270 2271 /* 2272 * Simulate EOF on interrupt: stop sending new requests and 2273 * allow outstanding requests to drain gracefully 2274 */ 2275 if (interrupted) { 2276 if (num_req == 0) /* If we haven't started yet... */ 2277 break; 2278 max_req = 0; 2279 } 2280 2281 /* Send some more requests */ 2282 while (num_req < max_req) { 2283 debug3("Request range %llu -> %llu (%d/%d)", 2284 (unsigned long long)offset, 2285 (unsigned long long)offset + buflen - 1, 2286 num_req, max_req); 2287 req = request_enqueue(&requests, from->msg_id++, 2288 buflen, offset); 2289 offset += buflen; 2290 num_req++; 2291 send_read_request(from, req->id, req->offset, 2292 req->len, from_handle, from_handle_len); 2293 } 2294 2295 /* Try to eat replies from the upload side (nonblocking) */ 2296 handle_dest_replies(to, to_path, 0, 2297 &num_upload_req, &write_error); 2298 2299 sshbuf_reset(msg); 2300 get_msg(from, msg); 2301 if ((r = sshbuf_get_u8(msg, &type)) != 0 || 2302 (r = sshbuf_get_u32(msg, &id)) != 0) 2303 fatal_fr(r, "parse"); 2304 debug3("Received origin reply T:%u I:%u R:%d", 2305 type, id, max_req); 2306 2307 /* Find the request in our queue */ 2308 if ((req = request_find(&requests, id)) == NULL) 2309 fatal("Unexpected reply %u", id); 2310 2311 switch (type) { 2312 case SSH2_FXP_STATUS: 2313 if ((r = sshbuf_get_u32(msg, &status)) != 0) 2314 fatal_fr(r, "parse status"); 2315 if (status != SSH2_FX_EOF) 2316 read_error = 1; 2317 max_req = 0; 2318 TAILQ_REMOVE(&requests, req, tq); 2319 free(req); 2320 num_req--; 2321 break; 2322 case SSH2_FXP_DATA: 2323 if ((r = sshbuf_get_string(msg, &data, &len)) != 0) 2324 fatal_fr(r, "parse data"); 2325 debug3("Received data %llu -> %llu", 2326 (unsigned long long)req->offset, 2327 (unsigned long long)req->offset + len - 1); 2328 if (len > req->len) 2329 fatal("Received more data than asked for " 2330 "%zu > %zu", len, req->len); 2331 2332 /* Write this chunk out to the destination */ 2333 sshbuf_reset(msg); 2334 if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || 2335 (r = sshbuf_put_u32(msg, to->msg_id++)) != 0 || 2336 (r = sshbuf_put_string(msg, to_handle, 2337 to_handle_len)) != 0 || 2338 (r = sshbuf_put_u64(msg, req->offset)) != 0 || 2339 (r = sshbuf_put_string(msg, data, len)) != 0) 2340 fatal_fr(r, "compose write"); 2341 send_msg(to, msg); 2342 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%zu", 2343 id, (unsigned long long)offset, len); 2344 num_upload_req++; 2345 progress_counter += len; 2346 free(data); 2347 2348 if (len == req->len) { 2349 TAILQ_REMOVE(&requests, req, tq); 2350 free(req); 2351 num_req--; 2352 } else { 2353 /* Resend the request for the missing data */ 2354 debug3("Short data block, re-requesting " 2355 "%llu -> %llu (%2d)", 2356 (unsigned long long)req->offset + len, 2357 (unsigned long long)req->offset + 2358 req->len - 1, num_req); 2359 req->id = from->msg_id++; 2360 req->len -= len; 2361 req->offset += len; 2362 send_read_request(from, req->id, 2363 req->offset, req->len, 2364 from_handle, from_handle_len); 2365 /* Reduce the request size */ 2366 if (len < buflen) 2367 buflen = MAXIMUM(MIN_READ_SIZE, len); 2368 } 2369 if (max_req > 0) { /* max_req = 0 iff EOF received */ 2370 if (size > 0 && offset > size) { 2371 /* Only one request at a time 2372 * after the expected EOF */ 2373 debug3("Finish at %llu (%2d)", 2374 (unsigned long long)offset, 2375 num_req); 2376 max_req = 1; 2377 } else if (max_req < from->num_requests) { 2378 ++max_req; 2379 } 2380 } 2381 break; 2382 default: 2383 fatal("Expected SSH2_FXP_DATA(%u) packet, got %u", 2384 SSH2_FXP_DATA, type); 2385 } 2386 } 2387 2388 if (showprogress && size) 2389 stop_progress_meter(); 2390 2391 /* Drain replies from the server (blocking) */ 2392 debug3_f("waiting for %u replies from destination", num_upload_req); 2393 handle_dest_replies(to, to_path, 1, &num_upload_req, &write_error); 2394 2395 /* Sanity check */ 2396 if (TAILQ_FIRST(&requests) != NULL) 2397 fatal("Transfer complete, but requests still in queue"); 2398 /* Truncate at 0 length on interrupt or error to avoid holes at dest */ 2399 if (read_error || write_error || interrupted) { 2400 debug("truncating \"%s\" at 0", to_path); 2401 do_close(to, to_handle, to_handle_len); 2402 free(to_handle); 2403 if (send_open(to, to_path, "dest", 2404 SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a, 2405 &to_handle, &to_handle_len) != 0) { 2406 error("truncation failed for \"%s\"", to_path); 2407 to_handle = NULL; 2408 } 2409 } 2410 if (read_error) { 2411 error("Couldn't read from origin file \"%s\" : %s", 2412 from_path, fx2txt(status)); 2413 status = -1; 2414 do_close(from, from_handle, from_handle_len); 2415 if (to_handle != NULL) 2416 do_close(to, to_handle, to_handle_len); 2417 } else if (write_error) { 2418 error("Couldn't write to \"%s\": %s", 2419 to_path, fx2txt(write_error)); 2420 status = SSH2_FX_FAILURE; 2421 do_close(from, from_handle, from_handle_len); 2422 if (to_handle != NULL) 2423 do_close(to, to_handle, to_handle_len); 2424 } else { 2425 if (do_close(from, from_handle, from_handle_len) != 0 || 2426 interrupted) 2427 status = -1; 2428 else 2429 status = SSH2_FX_OK; 2430 if (to_handle != NULL) { 2431 /* Need to resend utimes after write */ 2432 if (preserve_flag) 2433 do_fsetstat(to, to_handle, to_handle_len, a); 2434 do_close(to, to_handle, to_handle_len); 2435 } 2436 } 2437 sshbuf_free(msg); 2438 free(from_handle); 2439 free(to_handle); 2440 2441 return status == SSH2_FX_OK ? 0 : -1; 2442 } 2443 2444 static int 2445 crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to, 2446 const char *from_path, const char *to_path, 2447 int depth, Attrib *dirattrib, int preserve_flag, int print_flag, 2448 int follow_link_flag) 2449 { 2450 int i, ret = 0; 2451 SFTP_DIRENT **dir_entries; 2452 char *filename, *new_from_path = NULL, *new_to_path = NULL; 2453 mode_t mode = 0777; 2454 Attrib curdir; 2455 2456 if (depth >= MAX_DIR_DEPTH) { 2457 error("Maximum directory depth exceeded: %d levels", depth); 2458 return -1; 2459 } 2460 2461 if (dirattrib == NULL && 2462 (dirattrib = do_stat(from, from_path, 1)) == NULL) { 2463 error("Unable to stat remote directory \"%s\"", from_path); 2464 return -1; 2465 } 2466 if (!S_ISDIR(dirattrib->perm)) { 2467 error("\"%s\" is not a directory", from_path); 2468 return -1; 2469 } 2470 if (print_flag && print_flag != SFTP_PROGRESS_ONLY) 2471 mprintf("Retrieving %s\n", from_path); 2472 2473 curdir = *dirattrib; /* dirattrib will be clobbered */ 2474 curdir.flags &= ~SSH2_FILEXFER_ATTR_SIZE; 2475 curdir.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; 2476 if ((curdir.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) == 0) { 2477 debug("Origin did not send permissions for " 2478 "directory \"%s\"", to_path); 2479 curdir.perm = S_IWUSR|S_IXUSR; 2480 curdir.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS; 2481 } 2482 /* We need to be able to write to the directory while we transfer it */ 2483 mode = curdir.perm & 01777; 2484 curdir.perm = mode | (S_IWUSR|S_IXUSR); 2485 2486 /* 2487 * sftp lacks a portable status value to match errno EEXIST, 2488 * so if we get a failure back then we must check whether 2489 * the path already existed and is a directory. Ensure we can 2490 * write to the directory we create for the duration of the transfer. 2491 */ 2492 if (do_mkdir(to, to_path, &curdir, 0) != 0) { 2493 if ((dirattrib = do_stat(to, to_path, 0)) == NULL) 2494 return -1; 2495 if (!S_ISDIR(dirattrib->perm)) { 2496 error("\"%s\" exists but is not a directory", to_path); 2497 return -1; 2498 } 2499 } 2500 curdir.perm = mode; 2501 2502 if (do_readdir(from, from_path, &dir_entries) == -1) { 2503 error("%s: Failed to get directory contents", from_path); 2504 return -1; 2505 } 2506 2507 for (i = 0; dir_entries[i] != NULL && !interrupted; i++) { 2508 free(new_from_path); 2509 free(new_to_path); 2510 2511 filename = dir_entries[i]->filename; 2512 new_from_path = path_append(from_path, filename); 2513 new_to_path = path_append(to_path, filename); 2514 2515 if (S_ISDIR(dir_entries[i]->a.perm)) { 2516 if (strcmp(filename, ".") == 0 || 2517 strcmp(filename, "..") == 0) 2518 continue; 2519 if (crossload_dir_internal(from, to, 2520 new_from_path, new_to_path, 2521 depth + 1, &(dir_entries[i]->a), preserve_flag, 2522 print_flag, follow_link_flag) == -1) 2523 ret = -1; 2524 } else if (S_ISREG(dir_entries[i]->a.perm) || 2525 (follow_link_flag && S_ISLNK(dir_entries[i]->a.perm))) { 2526 /* 2527 * If this is a symlink then don't send the link's 2528 * Attrib. do_download() will do a FXP_STAT operation 2529 * and get the link target's attributes. 2530 */ 2531 if (do_crossload(from, to, new_from_path, new_to_path, 2532 S_ISLNK(dir_entries[i]->a.perm) ? NULL : 2533 &(dir_entries[i]->a), preserve_flag) == -1) { 2534 error("Transfer of file %s to %s failed", 2535 new_from_path, new_to_path); 2536 ret = -1; 2537 } 2538 } else 2539 logit("%s: not a regular file\n", new_from_path); 2540 2541 } 2542 free(new_to_path); 2543 free(new_from_path); 2544 2545 do_setstat(to, to_path, &curdir); 2546 2547 free_sftp_dirents(dir_entries); 2548 2549 return ret; 2550 } 2551 2552 int 2553 crossload_dir(struct sftp_conn *from, struct sftp_conn *to, 2554 const char *from_path, const char *to_path, 2555 Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag) 2556 { 2557 char *from_path_canon; 2558 int ret; 2559 2560 if ((from_path_canon = do_realpath(from, from_path)) == NULL) { 2561 error("Unable to canonicalize path \"%s\"", from_path); 2562 return -1; 2563 } 2564 2565 ret = crossload_dir_internal(from, to, from_path_canon, to_path, 0, 2566 dirattrib, preserve_flag, print_flag, follow_link_flag); 2567 free(from_path_canon); 2568 return ret; 2569 } 2570 2571 char * 2572 path_append(const char *p1, const char *p2) 2573 { 2574 char *ret; 2575 size_t len = strlen(p1) + strlen(p2) + 2; 2576 2577 ret = xmalloc(len); 2578 strlcpy(ret, p1, len); 2579 if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/') 2580 strlcat(ret, "/", len); 2581 strlcat(ret, p2, len); 2582 2583 return(ret); 2584 } 2585 2586 char * 2587 make_absolute(char *p, const char *pwd) 2588 { 2589 char *abs_str; 2590 2591 /* Derelativise */ 2592 if (p && !path_absolute(p)) { 2593 abs_str = path_append(pwd, p); 2594 free(p); 2595 return(abs_str); 2596 } else 2597 return(p); 2598 } 2599 2600 int 2601 remote_is_dir(struct sftp_conn *conn, const char *path) 2602 { 2603 Attrib *a; 2604 2605 /* XXX: report errors? */ 2606 if ((a = do_stat(conn, path, 1)) == NULL) 2607 return(0); 2608 if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)) 2609 return(0); 2610 return(S_ISDIR(a->perm)); 2611 } 2612 2613 2614 int 2615 local_is_dir(const char *path) 2616 { 2617 struct stat sb; 2618 2619 /* XXX: report errors? */ 2620 if (stat(path, &sb) == -1) 2621 return(0); 2622 2623 return(S_ISDIR(sb.st_mode)); 2624 } 2625 2626 /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */ 2627 int 2628 globpath_is_dir(const char *pathname) 2629 { 2630 size_t l = strlen(pathname); 2631 2632 return l > 0 && pathname[l - 1] == '/'; 2633 } 2634 2635