View | Details | Raw Unified | Return to bug 2152
Collapse All | Expand All

(-)sftp-client.c (-25 / +25 lines)
Lines 991-997 Link Here
991
991
992
int
992
int
993
do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
993
do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
994
    Attrib *a, int pflag, int resume)
994
    Attrib *a, SftpFlags *flags)
995
{
995
{
996
	Attrib junk;
996
	Attrib junk;
997
	Buffer msg;
997
	Buffer msg;
Lines 1054-1068 Link Here
1054
		return(-1);
1054
		return(-1);
1055
	}
1055
	}
1056
1056
1057
	local_fd = open(local_path, O_WRONLY | O_CREAT | (resume ? 0 : O_TRUNC),
1057
	local_fd = open(local_path, O_WRONLY | O_CREAT |
1058
	    mode | S_IWUSR);
1058
	    (flags->append ? 0 : O_TRUNC), mode | S_IWUSR);
1059
	if (local_fd == -1) {
1059
	if (local_fd == -1) {
1060
		error("Couldn't open local file \"%s\" for writing: %s",
1060
		error("Couldn't open local file \"%s\" for writing: %s",
1061
		    local_path, strerror(errno));
1061
		    local_path, strerror(errno));
1062
		goto fail;
1062
		goto fail;
1063
	}
1063
	}
1064
	offset = highwater = 0;
1064
	offset = highwater = 0;
1065
	if (resume) {
1065
	if (flags->append) {
1066
		if (fstat(local_fd, &st) == -1) {
1066
		if (fstat(local_fd, &st) == -1) {
1067
			error("Unable to stat local file \"%s\": %s",
1067
			error("Unable to stat local file \"%s\": %s",
1068
			    local_path, strerror(errno));
1068
			    local_path, strerror(errno));
Lines 1212-1218 Link Here
1212
		fatal("Transfer complete, but requests still in queue");
1212
		fatal("Transfer complete, but requests still in queue");
1213
	/* Truncate at highest contiguous point to avoid holes on interrupt */
1213
	/* Truncate at highest contiguous point to avoid holes on interrupt */
1214
	if (read_error || write_error || interrupted) {
1214
	if (read_error || write_error || interrupted) {
1215
		if (reordered && resume) {
1215
		if (reordered && flags->append) {
1216
			error("Unable to resume download of \"%s\": "
1216
			error("Unable to resume download of \"%s\": "
1217
			    "server reordered requests", local_path);
1217
			    "server reordered requests", local_path);
1218
		}
1218
		}
Lines 1235-1247 Link Here
1235
			status = -1;
1235
			status = -1;
1236
		/* Override umask and utimes if asked */
1236
		/* Override umask and utimes if asked */
1237
#ifdef HAVE_FCHMOD
1237
#ifdef HAVE_FCHMOD
1238
		if (pflag && fchmod(local_fd, mode) == -1)
1238
		if (flags->preserve && fchmod(local_fd, mode) == -1)
1239
#else
1239
#else
1240
		if (pflag && chmod(local_path, mode) == -1)
1240
		if (flags->preserve && chmod(local_path, mode) == -1)
1241
#endif /* HAVE_FCHMOD */
1241
#endif /* HAVE_FCHMOD */
1242
			error("Couldn't set mode on \"%s\": %s", local_path,
1242
			error("Couldn't set mode on \"%s\": %s", local_path,
1243
			    strerror(errno));
1243
			    strerror(errno));
1244
		if (pflag && (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) {
1244
		if (flags->preserve && (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) {
1245
			struct timeval tv[2];
1245
			struct timeval tv[2];
1246
			tv[0].tv_sec = a->atime;
1246
			tv[0].tv_sec = a->atime;
1247
			tv[1].tv_sec = a->mtime;
1247
			tv[1].tv_sec = a->mtime;
Lines 1260-1266 Link Here
1260
1260
1261
static int
1261
static int
1262
download_dir_internal(struct sftp_conn *conn, char *src, char *dst,
1262
download_dir_internal(struct sftp_conn *conn, char *src, char *dst,
1263
    Attrib *dirattrib, int pflag, int printflag, int depth, int resume)
1263
    Attrib *dirattrib, SftpFlags *flags, int printflag, int depth)
1264
{
1264
{
1265
	int i, ret = 0;
1265
	int i, ret = 0;
1266
	SFTP_DIRENT **dir_entries;
1266
	SFTP_DIRENT **dir_entries;
Lines 1312-1323 Link Here
1312
			    strcmp(filename, "..") == 0)
1312
			    strcmp(filename, "..") == 0)
1313
				continue;
1313
				continue;
1314
			if (download_dir_internal(conn, new_src, new_dst,
1314
			if (download_dir_internal(conn, new_src, new_dst,
1315
			    &(dir_entries[i]->a), pflag, printflag,
1315
			    &(dir_entries[i]->a), flags, printflag,
1316
			    depth + 1, resume) == -1)
1316
			    depth + 1) == -1)
1317
				ret = -1;
1317
				ret = -1;
1318
		} else if (S_ISREG(dir_entries[i]->a.perm) ) {
1318
		} else if (S_ISREG(dir_entries[i]->a.perm) ) {
1319
			if (do_download(conn, new_src, new_dst,
1319
			if (do_download(conn, new_src, new_dst,
1320
			    &(dir_entries[i]->a), pflag, resume) == -1) {
1320
			    &(dir_entries[i]->a), flags) == -1) {
1321
				error("Download of file %s to %s failed",
1321
				error("Download of file %s to %s failed",
1322
				    new_src, new_dst);
1322
				    new_src, new_dst);
1323
				ret = -1;
1323
				ret = -1;
Lines 1329-1335 Link Here
1329
		free(new_src);
1329
		free(new_src);
1330
	}
1330
	}
1331
1331
1332
	if (pflag) {
1332
	if (flags->preserve) {
1333
		if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
1333
		if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
1334
			struct timeval tv[2];
1334
			struct timeval tv[2];
1335
			tv[0].tv_sec = dirattrib->atime;
1335
			tv[0].tv_sec = dirattrib->atime;
Lines 1350-1356 Link Here
1350
1350
1351
int
1351
int
1352
download_dir(struct sftp_conn *conn, char *src, char *dst,
1352
download_dir(struct sftp_conn *conn, char *src, char *dst,
1353
    Attrib *dirattrib, int pflag, int printflag, int resume)
1353
    Attrib *dirattrib, SftpFlags *flags, int printflag)
1354
{
1354
{
1355
	char *src_canon;
1355
	char *src_canon;
1356
	int ret;
1356
	int ret;
Lines 1361-1374 Link Here
1361
	}
1361
	}
1362
1362
1363
	ret = download_dir_internal(conn, src_canon, dst,
1363
	ret = download_dir_internal(conn, src_canon, dst,
1364
	    dirattrib, pflag, printflag, 0, resume);
1364
	    dirattrib, flags, printflag, 0);
1365
	free(src_canon);
1365
	free(src_canon);
1366
	return ret;
1366
	return ret;
1367
}
1367
}
1368
1368
1369
int
1369
int
1370
do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1370
do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1371
    int pflag)
1371
    SftpFlags *flags)
1372
{
1372
{
1373
	int local_fd;
1373
	int local_fd;
1374
	int status = SSH2_FX_OK;
1374
	int status = SSH2_FX_OK;
Lines 1412-1418 Link Here
1412
	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
1412
	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
1413
	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
1413
	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
1414
	a.perm &= 0777;
1414
	a.perm &= 0777;
1415
	if (!pflag)
1415
	if (!flags->preserve)
1416
		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
1416
		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
1417
1417
1418
	buffer_init(&msg);
1418
	buffer_init(&msg);
Lines 1541-1547 Link Here
1541
	}
1541
	}
1542
1542
1543
	/* Override umask and utimes if asked */
1543
	/* Override umask and utimes if asked */
1544
	if (pflag)
1544
	if (flags->preserve)
1545
		do_fsetstat(conn, handle, handle_len, &a);
1545
		do_fsetstat(conn, handle, handle_len, &a);
1546
1546
1547
	if (do_close(conn, handle, handle_len) != SSH2_FX_OK)
1547
	if (do_close(conn, handle, handle_len) != SSH2_FX_OK)
Lines 1553-1559 Link Here
1553
1553
1554
static int
1554
static int
1555
upload_dir_internal(struct sftp_conn *conn, char *src, char *dst,
1555
upload_dir_internal(struct sftp_conn *conn, char *src, char *dst,
1556
    int pflag, int printflag, int depth)
1556
    SftpFlags *flags, int printflag, int depth)
1557
{
1557
{
1558
	int ret = 0, status;
1558
	int ret = 0, status;
1559
	DIR *dirp;
1559
	DIR *dirp;
Lines 1584-1590 Link Here
1584
	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
1584
	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
1585
	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
1585
	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
1586
	a.perm &= 01777;
1586
	a.perm &= 01777;
1587
	if (!pflag)
1587
	if (!flags->preserve)
1588
		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
1588
		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
1589
1589
1590
	status = do_mkdir(conn, dst, &a, 0);
1590
	status = do_mkdir(conn, dst, &a, 0);
Lines 1622-1631 Link Here
1622
				continue;
1622
				continue;
1623
1623
1624
			if (upload_dir_internal(conn, new_src, new_dst,
1624
			if (upload_dir_internal(conn, new_src, new_dst,
1625
			    pflag, printflag, depth + 1) == -1)
1625
			    flags, printflag, depth + 1) == -1)
1626
				ret = -1;
1626
				ret = -1;
1627
		} else if (S_ISREG(sb.st_mode)) {
1627
		} else if (S_ISREG(sb.st_mode)) {
1628
			if (do_upload(conn, new_src, new_dst, pflag) == -1) {
1628
			if (do_upload(conn, new_src, new_dst, flags) == -1) {
1629
				error("Uploading of file %s to %s failed!",
1629
				error("Uploading of file %s to %s failed!",
1630
				    new_src, new_dst);
1630
				    new_src, new_dst);
1631
				ret = -1;
1631
				ret = -1;
Lines 1643-1650 Link Here
1643
}
1643
}
1644
1644
1645
int
1645
int
1646
upload_dir(struct sftp_conn *conn, char *src, char *dst, int printflag,
1646
upload_dir(struct sftp_conn *conn, char *src, char *dst, 
1647
    int pflag)
1647
    SftpFlags *flags, int printflag)
1648
{
1648
{
1649
	char *dst_canon;
1649
	char *dst_canon;
1650
	int ret;
1650
	int ret;
Lines 1654-1660 Link Here
1654
		return -1;
1654
		return -1;
1655
	}
1655
	}
1656
1656
1657
	ret = upload_dir_internal(conn, src, dst_canon, pflag, printflag, 0);
1657
	ret = upload_dir_internal(conn, src, dst_canon, flags, printflag, 0);
1658
	free(dst_canon);
1658
	free(dst_canon);
1659
	return ret;
1659
	return ret;
1660
}
1660
}
(-)sftp-client.h (-4 / +16 lines)
Lines 29-34 Link Here
29
	Attrib a;
29
	Attrib a;
30
};
30
};
31
31
32
typedef struct {
33
	int	append;
34
	int	human_readable;
35
	int	ignore_errors;
36
	int	inodes;
37
	int	legacy_rename;
38
	int	ls_opts;
39
	int	preserve;
40
	int	recurse;
41
	int	symlink;
42
}	SftpFlags;
43
32
/*
44
/*
33
 * Used for statvfs responses on the wire from the server, because the
45
 * Used for statvfs responses on the wire from the server, because the
34
 * server's native format may be larger than the client's.
46
 * server's native format may be larger than the client's.
Lines 106-130 Link Here
106
 * Download 'remote_path' to 'local_path'. Preserve permissions and times
118
 * Download 'remote_path' to 'local_path'. Preserve permissions and times
107
 * if 'pflag' is set
119
 * if 'pflag' is set
108
 */
120
 */
109
int do_download(struct sftp_conn *, char *, char *, Attrib *, int, int);
121
int do_download(struct sftp_conn *, char *, char *, Attrib *, SftpFlags *);
110
122
111
/*
123
/*
112
 * Recursively download 'remote_directory' to 'local_directory'. Preserve 
124
 * Recursively download 'remote_directory' to 'local_directory'. Preserve 
113
 * times if 'pflag' is set
125
 * times if 'pflag' is set
114
 */
126
 */
115
int download_dir(struct sftp_conn *, char *, char *, Attrib *, int, int, int);
127
int download_dir(struct sftp_conn *, char *, char *, Attrib *, SftpFlags *, int);
116
128
117
/*
129
/*
118
 * Upload 'local_path' to 'remote_path'. Preserve permissions and times
130
 * Upload 'local_path' to 'remote_path'. Preserve permissions and times
119
 * if 'pflag' is set
131
 * if 'pflag' is set
120
 */
132
 */
121
int do_upload(struct sftp_conn *, char *, char *, int);
133
int do_upload(struct sftp_conn *, char *, char *, SftpFlags *);
122
134
123
/*
135
/*
124
 * Recursively upload 'local_directory' to 'remote_directory'. Preserve 
136
 * Recursively upload 'local_directory' to 'remote_directory'. Preserve 
125
 * times if 'pflag' is set
137
 * times if 'pflag' is set
126
 */
138
 */
127
int upload_dir(struct sftp_conn *, char *, char *, int, int);
139
int upload_dir(struct sftp_conn *, char *, char *, SftpFlags *, int);
128
140
129
/* Concatenate paths, taking care of slashes. Caller must free result. */
141
/* Concatenate paths, taking care of slashes. Caller must free result. */
130
char *path_append(char *, char *);
142
char *path_append(char *, char *);
(-)sftp.c (-74 / +67 lines)
Lines 358-365 Link Here
358
}
358
}
359
359
360
static int
360
static int
361
parse_getput_flags(const char *cmd, char **argv, int argc,
361
parse_getput_flags(const char *cmd, char **argv, int argc, SftpFlags *flags)
362
    int *aflag, int *pflag, int *rflag)
363
{
362
{
364
	extern int opterr, optind, optopt, optreset;
363
	extern int opterr, optind, optopt, optreset;
365
	int ch;
364
	int ch;
Lines 367-385 Link Here
367
	optind = optreset = 1;
366
	optind = optreset = 1;
368
	opterr = 0;
367
	opterr = 0;
369
368
370
	*aflag = *rflag = *pflag = 0;
371
	while ((ch = getopt(argc, argv, "aPpRr")) != -1) {
369
	while ((ch = getopt(argc, argv, "aPpRr")) != -1) {
372
		switch (ch) {
370
		switch (ch) {
373
		case 'a':
371
		case 'a':
374
			*aflag = 1;
372
			flags->append = 1;
375
			break;
373
			break;
376
		case 'p':
374
		case 'p':
377
		case 'P':
375
		case 'P':
378
			*pflag = 1;
376
			flags->preserve = 1;
379
			break;
377
			break;
380
		case 'r':
378
		case 'r':
381
		case 'R':
379
		case 'R':
382
			*rflag = 1;
380
			flags->recurse = 1;
383
			break;
381
			break;
384
		default:
382
		default:
385
			error("%s: Invalid flag -%c", cmd, optopt);
383
			error("%s: Invalid flag -%c", cmd, optopt);
Lines 391-397 Link Here
391
}
389
}
392
390
393
static int
391
static int
394
parse_link_flags(const char *cmd, char **argv, int argc, int *sflag)
392
parse_link_flags(const char *cmd, char **argv, int argc, SftpFlags *flags)
395
{
393
{
396
	extern int opterr, optind, optopt, optreset;
394
	extern int opterr, optind, optopt, optreset;
397
	int ch;
395
	int ch;
Lines 399-409 Link Here
399
	optind = optreset = 1;
397
	optind = optreset = 1;
400
	opterr = 0;
398
	opterr = 0;
401
399
402
	*sflag = 0;
403
	while ((ch = getopt(argc, argv, "s")) != -1) {
400
	while ((ch = getopt(argc, argv, "s")) != -1) {
404
		switch (ch) {
401
		switch (ch) {
405
		case 's':
402
		case 's':
406
			*sflag = 1;
403
			flags->symlink = 1;
407
			break;
404
			break;
408
		default:
405
		default:
409
			error("%s: Invalid flag -%c", cmd, optopt);
406
			error("%s: Invalid flag -%c", cmd, optopt);
Lines 415-421 Link Here
415
}
412
}
416
413
417
static int
414
static int
418
parse_rename_flags(const char *cmd, char **argv, int argc, int *lflag)
415
parse_rename_flags(const char *cmd, char **argv, int argc, SftpFlags *flags)
419
{
416
{
420
	extern int opterr, optind, optopt, optreset;
417
	extern int opterr, optind, optopt, optreset;
421
	int ch;
418
	int ch;
Lines 423-433 Link Here
423
	optind = optreset = 1;
420
	optind = optreset = 1;
424
	opterr = 0;
421
	opterr = 0;
425
422
426
	*lflag = 0;
427
	while ((ch = getopt(argc, argv, "l")) != -1) {
423
	while ((ch = getopt(argc, argv, "l")) != -1) {
428
		switch (ch) {
424
		switch (ch) {
429
		case 'l':
425
		case 'l':
430
			*lflag = 1;
426
			flags->legacy_rename = 1;
431
			break;
427
			break;
432
		default:
428
		default:
433
			error("%s: Invalid flag -%c", cmd, optopt);
429
			error("%s: Invalid flag -%c", cmd, optopt);
Lines 439-445 Link Here
439
}
435
}
440
436
441
static int
437
static int
442
parse_ls_flags(char **argv, int argc, int *lflag)
438
parse_ls_flags(char **argv, int argc, SftpFlags *flags)
443
{
439
{
444
	extern int opterr, optind, optopt, optreset;
440
	extern int opterr, optind, optopt, optreset;
445
	int ch;
441
	int ch;
Lines 447-486 Link Here
447
	optind = optreset = 1;
443
	optind = optreset = 1;
448
	opterr = 0;
444
	opterr = 0;
449
445
450
	*lflag = LS_NAME_SORT;
446
	flags->ls_opts = LS_NAME_SORT;
451
	while ((ch = getopt(argc, argv, "1Safhlnrt")) != -1) {
447
	while ((ch = getopt(argc, argv, "1Safhlnrt")) != -1) {
452
		switch (ch) {
448
		switch (ch) {
453
		case '1':
449
		case '1':
454
			*lflag &= ~VIEW_FLAGS;
450
			flags->ls_opts &= ~VIEW_FLAGS;
455
			*lflag |= LS_SHORT_VIEW;
451
			flags->ls_opts |= LS_SHORT_VIEW;
456
			break;
452
			break;
457
		case 'S':
453
		case 'S':
458
			*lflag &= ~SORT_FLAGS;
454
			flags->ls_opts &= ~SORT_FLAGS;
459
			*lflag |= LS_SIZE_SORT;
455
			flags->ls_opts |= LS_SIZE_SORT;
460
			break;
456
			break;
461
		case 'a':
457
		case 'a':
462
			*lflag |= LS_SHOW_ALL;
458
			flags->ls_opts |= LS_SHOW_ALL;
463
			break;
459
			break;
464
		case 'f':
460
		case 'f':
465
			*lflag &= ~SORT_FLAGS;
461
			flags->ls_opts &= ~SORT_FLAGS;
466
			break;
462
			break;
467
		case 'h':
463
		case 'h':
468
			*lflag |= LS_SI_UNITS;
464
			flags->ls_opts |= LS_SI_UNITS;
469
			break;
465
			break;
470
		case 'l':
466
		case 'l':
471
			*lflag &= ~LS_SHORT_VIEW;
467
			flags->ls_opts &= ~LS_SHORT_VIEW;
472
			*lflag |= LS_LONG_VIEW;
468
			flags->ls_opts |= LS_LONG_VIEW;
473
			break;
469
			break;
474
		case 'n':
470
		case 'n':
475
			*lflag &= ~LS_SHORT_VIEW;
471
			flags->ls_opts &= ~LS_SHORT_VIEW;
476
			*lflag |= LS_NUMERIC_VIEW|LS_LONG_VIEW;
472
			flags->ls_opts |= LS_NUMERIC_VIEW|LS_LONG_VIEW;
477
			break;
473
			break;
478
		case 'r':
474
		case 'r':
479
			*lflag |= LS_REVERSE_SORT;
475
			flags->ls_opts |= LS_REVERSE_SORT;
480
			break;
476
			break;
481
		case 't':
477
		case 't':
482
			*lflag &= ~SORT_FLAGS;
478
			flags->ls_opts &= ~SORT_FLAGS;
483
			*lflag |= LS_TIME_SORT;
479
			flags->ls_opts |= LS_TIME_SORT;
484
			break;
480
			break;
485
		default:
481
		default:
486
			error("ls: Invalid flag -%c", optopt);
482
			error("ls: Invalid flag -%c", optopt);
Lines 492-498 Link Here
492
}
488
}
493
489
494
static int
490
static int
495
parse_df_flags(const char *cmd, char **argv, int argc, int *hflag, int *iflag)
491
parse_df_flags(const char *cmd, char **argv, int argc, SftpFlags *flags)
496
{
492
{
497
	extern int opterr, optind, optopt, optreset;
493
	extern int opterr, optind, optopt, optreset;
498
	int ch;
494
	int ch;
Lines 500-513 Link Here
500
	optind = optreset = 1;
496
	optind = optreset = 1;
501
	opterr = 0;
497
	opterr = 0;
502
498
503
	*hflag = *iflag = 0;
504
	while ((ch = getopt(argc, argv, "hi")) != -1) {
499
	while ((ch = getopt(argc, argv, "hi")) != -1) {
505
		switch (ch) {
500
		switch (ch) {
506
		case 'h':
501
		case 'h':
507
			*hflag = 1;
502
			flags->human_readable = 1;
508
			break;
503
			break;
509
		case 'i':
504
		case 'i':
510
			*iflag = 1;
505
			flags->inodes = 1;
511
			break;
506
			break;
512
		default:
507
		default:
513
			error("%s: Invalid flag -%c", cmd, optopt);
508
			error("%s: Invalid flag -%c", cmd, optopt);
Lines 574-580 Link Here
574
569
575
static int
570
static int
576
process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
571
process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
577
    int pflag, int rflag, int resume)
572
    SftpFlags *flags)
578
{
573
{
579
	char *abs_src = NULL;
574
	char *abs_src = NULL;
580
	char *abs_dst = NULL;
575
	char *abs_dst = NULL;
Lines 626-643 Link Here
626
		}
621
		}
627
		free(tmp);
622
		free(tmp);
628
623
629
		resume |= global_aflag;
624
		if (!quiet && flags->append)
630
		if (!quiet && resume)
631
			printf("Resuming %s to %s\n", g.gl_pathv[i], abs_dst);
625
			printf("Resuming %s to %s\n", g.gl_pathv[i], abs_dst);
632
		else if (!quiet && !resume)
626
		else if (!quiet && !flags->append)
633
			printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
627
			printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
634
		if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
628
		if (pathname_is_dir(g.gl_pathv[i]) && flags->recurse) {
635
			if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
629
			if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
636
			    pflag || global_pflag, 1, resume) == -1)
630
			    flags, 1) == -1)
637
				err = -1;
631
				err = -1;
638
		} else {
632
		} else {
639
			if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
633
			if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
640
			    pflag || global_pflag, resume) == -1)
634
			    flags) == -1)
641
				err = -1;
635
				err = -1;
642
		}
636
		}
643
		free(abs_dst);
637
		free(abs_dst);
Lines 652-658 Link Here
652
646
653
static int
647
static int
654
process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
648
process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
655
    int pflag, int rflag)
649
    SftpFlags *flags)
656
{
650
{
657
	char *tmp_dst = NULL;
651
	char *tmp_dst = NULL;
658
	char *abs_dst = NULL;
652
	char *abs_dst = NULL;
Lines 717-729 Link Here
717
711
718
		if (!quiet)
712
		if (!quiet)
719
			printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
713
			printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
720
		if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
714
		if (pathname_is_dir(g.gl_pathv[i]) && flags->recurse) {
721
			if (upload_dir(conn, g.gl_pathv[i], abs_dst,
715
			if (upload_dir(conn, g.gl_pathv[i], abs_dst,
722
			    pflag || global_pflag, 1) == -1)
716
			    flags, 1) == -1)
723
				err = -1;
717
				err = -1;
724
		} else {
718
		} else {
725
			if (do_upload(conn, g.gl_pathv[i], abs_dst,
719
			if (do_upload(conn, g.gl_pathv[i], abs_dst,
726
			    pflag || global_pflag) == -1)
720
			    flags) == -1)
727
				err = -1;
721
				err = -1;
728
		}
722
		}
729
	}
723
	}
Lines 921-927 Link Here
921
}
915
}
922
916
923
static int
917
static int
924
do_df(struct sftp_conn *conn, char *path, int hflag, int iflag)
918
do_df(struct sftp_conn *conn, char *path, SftpFlags *flags)
925
{
919
{
926
	struct sftp_statvfs st;
920
	struct sftp_statvfs st;
927
	char s_used[FMT_SCALED_STRSIZE];
921
	char s_used[FMT_SCALED_STRSIZE];
Lines 932-938 Link Here
932
926
933
	if (do_statvfs(conn, path, &st, 1) == -1)
927
	if (do_statvfs(conn, path, &st, 1) == -1)
934
		return -1;
928
		return -1;
935
	if (iflag) {
929
	if (flags->inodes) {
936
		ffree = st.f_files ? (100 * (st.f_files - st.f_ffree) / st.f_files) : 0;
930
		ffree = st.f_files ? (100 * (st.f_files - st.f_ffree) / st.f_files) : 0;
937
		printf("     Inodes        Used       Avail      "
931
		printf("     Inodes        Used       Avail      "
938
		    "(root)    %%Capacity\n");
932
		    "(root)    %%Capacity\n");
Lines 941-947 Link Here
941
		    (unsigned long long)(st.f_files - st.f_ffree),
935
		    (unsigned long long)(st.f_files - st.f_ffree),
942
		    (unsigned long long)st.f_favail,
936
		    (unsigned long long)st.f_favail,
943
		    (unsigned long long)st.f_ffree, ffree);
937
		    (unsigned long long)st.f_ffree, ffree);
944
	} else if (hflag) {
938
	} else if (flags->human_readable) {
945
		strlcpy(s_used, "error", sizeof(s_used));
939
		strlcpy(s_used, "error", sizeof(s_used));
946
		strlcpy(s_avail, "error", sizeof(s_avail));
940
		strlcpy(s_avail, "error", sizeof(s_avail));
947
		strlcpy(s_root, "error", sizeof(s_root));
941
		strlcpy(s_root, "error", sizeof(s_root));
Lines 1176-1183 Link Here
1176
}
1170
}
1177
1171
1178
static int
1172
static int
1179
parse_args(const char **cpp, int *aflag, int *hflag, int *iflag, int *lflag,
1173
parse_args(const char **cpp, SftpFlags *flags, unsigned long *n_arg,
1180
    int *pflag, int *rflag, int *sflag, unsigned long *n_arg,
1181
    char **path1, char **path2)
1174
    char **path1, char **path2)
1182
{
1175
{
1183
	const char *cmd, *cp = *cpp;
1176
	const char *cmd, *cp = *cpp;
Lines 1190-1198 Link Here
1190
	cp = cp + strspn(cp, WHITESPACE);
1183
	cp = cp + strspn(cp, WHITESPACE);
1191
1184
1192
	/* Check for leading '-' (disable error processing) */
1185
	/* Check for leading '-' (disable error processing) */
1193
	*iflag = 0;
1194
	if (*cp == '-') {
1186
	if (*cp == '-') {
1195
		*iflag = 1;
1187
		flags->ignore_errors = 1;
1196
		cp++;
1188
		cp++;
1197
		cp = cp + strspn(cp, WHITESPACE);
1189
		cp = cp + strspn(cp, WHITESPACE);
1198
	}
1190
	}
Lines 1222-1228 Link Here
1222
	}
1214
	}
1223
1215
1224
	/* Get arguments and parse flags */
1216
	/* Get arguments and parse flags */
1225
	*aflag = *lflag = *pflag = *rflag = *hflag = *n_arg = 0;
1217
	*n_arg = 0;
1226
	*path1 = *path2 = NULL;
1218
	*path1 = *path2 = NULL;
1227
	optidx = 1;
1219
	optidx = 1;
1228
	switch (cmdnum) {
1220
	switch (cmdnum) {
Lines 1230-1236 Link Here
1230
	case I_REGET:
1222
	case I_REGET:
1231
	case I_PUT:
1223
	case I_PUT:
1232
		if ((optidx = parse_getput_flags(cmd, argv, argc,
1224
		if ((optidx = parse_getput_flags(cmd, argv, argc,
1233
		    aflag, pflag, rflag)) == -1)
1225
		    flags)) == -1)
1234
			return -1;
1226
			return -1;
1235
		/* Get first pathname (mandatory) */
1227
		/* Get first pathname (mandatory) */
1236
		if (argc - optidx < 1) {
1228
		if (argc - optidx < 1) {
Lines 1245-1262 Link Here
1245
			/* Destination is not globbed */
1237
			/* Destination is not globbed */
1246
			undo_glob_escape(*path2);
1238
			undo_glob_escape(*path2);
1247
		}
1239
		}
1248
		if (*aflag && cmdnum == I_PUT) {
1240
		if (flags->append && cmdnum == I_PUT) {
1249
			/* XXX implement resume for uploads */
1241
			/* XXX implement resume for uploads */
1250
			error("Resume is not supported for uploads");
1242
			error("Resume is not supported for uploads");
1251
			return -1;
1243
			return -1;
1252
		}
1244
		}
1253
		break;
1245
		break;
1254
	case I_LINK:
1246
	case I_LINK:
1255
		if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
1247
		if ((optidx = parse_link_flags(cmd, argv, argc, flags)) == -1)
1256
			return -1;
1248
			return -1;
1257
		goto parse_two_paths;
1249
		goto parse_two_paths;
1258
	case I_RENAME:
1250
	case I_RENAME:
1259
		if ((optidx = parse_rename_flags(cmd, argv, argc, lflag)) == -1)
1251
		if ((optidx = parse_rename_flags(cmd, argv, argc, flags)) == -1)
1260
			return -1;
1252
			return -1;
1261
		goto parse_two_paths;
1253
		goto parse_two_paths;
1262
	case I_SYMLINK:
1254
	case I_SYMLINK:
Lines 1294-1301 Link Here
1294
			undo_glob_escape(*path1);
1286
			undo_glob_escape(*path1);
1295
		break;
1287
		break;
1296
	case I_DF:
1288
	case I_DF:
1297
		if ((optidx = parse_df_flags(cmd, argv, argc, hflag,
1289
		if ((optidx = parse_df_flags(cmd, argv, argc, flags)) == -1)
1298
		    iflag)) == -1)
1299
			return -1;
1290
			return -1;
1300
		/* Default to current directory if no path specified */
1291
		/* Default to current directory if no path specified */
1301
		if (argc - optidx < 1)
1292
		if (argc - optidx < 1)
Lines 1306-1312 Link Here
1306
		}
1297
		}
1307
		break;
1298
		break;
1308
	case I_LS:
1299
	case I_LS:
1309
		if ((optidx = parse_ls_flags(argv, argc, lflag)) == -1)
1300
		if ((optidx = parse_ls_flags(argv, argc, flags)) == -1)
1310
			return(-1);
1301
			return(-1);
1311
		/* Path is optional */
1302
		/* Path is optional */
1312
		if (argc - optidx > 0)
1303
		if (argc - optidx > 0)
Lines 1371-1378 Link Here
1371
    int err_abort)
1362
    int err_abort)
1372
{
1363
{
1373
	char *path1, *path2, *tmp;
1364
	char *path1, *path2, *tmp;
1374
	int aflag = 0, hflag = 0, iflag = 0, lflag = 0, pflag = 0;
1365
	SftpFlags flags;
1375
	int rflag = 0, sflag = 0;
1376
	int cmdnum, i;
1366
	int cmdnum, i;
1377
	unsigned long n_arg = 0;
1367
	unsigned long n_arg = 0;
1378
	Attrib a, *aa;
1368
	Attrib a, *aa;
Lines 1380-1389 Link Here
1380
	int err = 0;
1370
	int err = 0;
1381
	glob_t g;
1371
	glob_t g;
1382
1372
1373
	bzero(&flags, sizeof(flags));
1374
	if (global_aflag) flags.append = 1;
1375
	if (global_pflag) flags.preserve = 1;
1376
	if (global_rflag) flags.recurse = 1;
1377
	
1383
	path1 = path2 = NULL;
1378
	path1 = path2 = NULL;
1384
	cmdnum = parse_args(&cmd, &aflag, &hflag, &iflag, &lflag, &pflag,
1379
	cmdnum = parse_args(&cmd, &flags, &n_arg, &path1, &path2);
1385
	    &rflag, &sflag, &n_arg, &path1, &path2);
1380
	if (flags.ignore_errors != 0)
1386
	if (iflag != 0)
1387
		err_abort = 0;
1381
		err_abort = 0;
1388
1382
1389
	memset(&g, 0, sizeof(g));
1383
	memset(&g, 0, sizeof(g));
Lines 1398-1424 Link Here
1398
		err = -1;
1392
		err = -1;
1399
		break;
1393
		break;
1400
	case I_REGET:
1394
	case I_REGET:
1401
		aflag = 1;
1395
		flags.append = 1;
1402
		/* FALLTHROUGH */
1396
		/* FALLTHROUGH */
1403
	case I_GET:
1397
	case I_GET:
1404
		err = process_get(conn, path1, path2, *pwd, pflag,
1398
		err = process_get(conn, path1, path2, *pwd, &flags);
1405
		    rflag, aflag);
1406
		break;
1399
		break;
1407
	case I_PUT:
1400
	case I_PUT:
1408
		err = process_put(conn, path1, path2, *pwd, pflag, rflag);
1401
		err = process_put(conn, path1, path2, *pwd, &flags);
1409
		break;
1402
		break;
1410
	case I_RENAME:
1403
	case I_RENAME:
1411
		path1 = make_absolute(path1, *pwd);
1404
		path1 = make_absolute(path1, *pwd);
1412
		path2 = make_absolute(path2, *pwd);
1405
		path2 = make_absolute(path2, *pwd);
1413
		err = do_rename(conn, path1, path2, lflag);
1406
		err = do_rename(conn, path1, path2, flags.legacy_rename);
1414
		break;
1407
		break;
1415
	case I_SYMLINK:
1408
	case I_SYMLINK:
1416
		sflag = 1;
1409
		flags.symlink = 1;
1417
	case I_LINK:
1410
	case I_LINK:
1418
		if (!sflag)
1411
		if (!flags.symlink)
1419
			path1 = make_absolute(path1, *pwd);
1412
			path1 = make_absolute(path1, *pwd);
1420
		path2 = make_absolute(path2, *pwd);
1413
		path2 = make_absolute(path2, *pwd);
1421
		err = (sflag ? do_symlink : do_hardlink)(conn, path1, path2);
1414
		err = (flags.symlink ? do_symlink : do_hardlink)(conn, path1, path2);
1422
		break;
1415
		break;
1423
	case I_RM:
1416
	case I_RM:
1424
		path1 = make_absolute(path1, *pwd);
1417
		path1 = make_absolute(path1, *pwd);
Lines 1471-1477 Link Here
1471
		break;
1464
		break;
1472
	case I_LS:
1465
	case I_LS:
1473
		if (!path1) {
1466
		if (!path1) {
1474
			do_ls_dir(conn, *pwd, *pwd, lflag);
1467
			do_ls_dir(conn, *pwd, *pwd, flags.ls_opts);
1475
			break;
1468
			break;
1476
		}
1469
		}
1477
1470
Lines 1481-1494 Link Here
1481
			tmp = *pwd;
1474
			tmp = *pwd;
1482
1475
1483
		path1 = make_absolute(path1, *pwd);
1476
		path1 = make_absolute(path1, *pwd);
1484
		err = do_globbed_ls(conn, path1, tmp, lflag);
1477
		err = do_globbed_ls(conn, path1, tmp, flags.ls_opts);
1485
		break;
1478
		break;
1486
	case I_DF:
1479
	case I_DF:
1487
		/* Default to current directory if no path specified */
1480
		/* Default to current directory if no path specified */
1488
		if (path1 == NULL)
1481
		if (path1 == NULL)
1489
			path1 = xstrdup(*pwd);
1482
			path1 = xstrdup(*pwd);
1490
		path1 = make_absolute(path1, *pwd);
1483
		path1 = make_absolute(path1, *pwd);
1491
		err = do_df(conn, path1, hflag, iflag);
1484
		err = do_df(conn, path1, &flags);
1492
		break;
1485
		break;
1493
	case I_LCHDIR:
1486
	case I_LCHDIR:
1494
		if (chdir(path1) == -1) {
1487
		if (chdir(path1) == -1) {

Return to bug 2152