GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/ssh/sftp/../sftp-client.c Lines: 0 998 0.0 %
Date: 2017-11-07 Branches: 0 700 0.0 %

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