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

(-)a/scp.c (-2 / +32 lines)
Lines 1474-1480 sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn) Link Here
1474
	}
1474
	}
1475
1475
1476
	debug3_f("copying remote %s to local %s", abs_src, dst);
1476
	debug3_f("copying remote %s to local %s", abs_src, dst);
1477
	if ((r = remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) {
1477
	if ((r = remote_glob(conn, abs_src, GLOB_NOCHECK|GLOB_MARK,
1478
	    NULL, &g)) != 0) {
1478
		if (r == GLOB_NOSPACE)
1479
		if (r == GLOB_NOSPACE)
1479
			error("%s: too many glob matches", src);
1480
			error("%s: too many glob matches", src);
1480
		else
1481
		else
Lines 1483-1488 sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn) Link Here
1483
		goto out;
1484
		goto out;
1484
	}
1485
	}
1485
1486
1487
	/* Did we actually get any matches back from the glob? */
1488
	if (g.gl_matchc == 0 && g.gl_pathc == 1 && g.gl_pathv[0] != 0) {
1489
		/*
1490
		 * If nothing matched but a path returned, then it's probably
1491
		 * a GLOB_NOCHECK result. Check whether the unglobbed path
1492
		 * exists so we can give a nice error message early.
1493
		 */
1494
		if (do_stat(conn, g.gl_pathv[0], 1) == NULL) {
1495
			error("%s: %s", src, strerror(ENOENT));
1496
			err = -1;
1497
			goto out;
1498
		}
1499
	}
1500
1486
	if ((r = stat(dst, &st)) != 0)
1501
	if ((r = stat(dst, &st)) != 0)
1487
		debug2_f("stat local \"%s\": %s", dst, strerror(errno));
1502
		debug2_f("stat local \"%s\": %s", dst, strerror(errno));
1488
	dst_is_dir = r == 0 && S_ISDIR(st.st_mode);
1503
	dst_is_dir = r == 0 && S_ISDIR(st.st_mode);
Lines 1883-1889 throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to, Link Here
1883
	}
1898
	}
1884
1899
1885
	debug3_f("copying remote %s to remote %s", abs_src, target);
1900
	debug3_f("copying remote %s to remote %s", abs_src, target);
1886
	if ((r = remote_glob(from, abs_src, GLOB_MARK, NULL, &g)) != 0) {
1901
	if ((r = remote_glob(from, abs_src, GLOB_NOCHECK|GLOB_MARK,
1902
	    NULL, &g)) != 0) {
1887
		if (r == GLOB_NOSPACE)
1903
		if (r == GLOB_NOSPACE)
1888
			error("%s: too many glob matches", src);
1904
			error("%s: too many glob matches", src);
1889
		else
1905
		else
Lines 1892-1897 throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to, Link Here
1892
		goto out;
1908
		goto out;
1893
	}
1909
	}
1894
1910
1911
	/* Did we actually get any matches back from the glob? */
1912
	if (g.gl_matchc == 0 && g.gl_pathc == 1 && g.gl_pathv[0] != 0) {
1913
		/*
1914
		 * If nothing matched but a path returned, then it's probably
1915
		 * a GLOB_NOCHECK result. Check whether the unglobbed path
1916
		 * exists so we can give a nice error message early.
1917
		 */
1918
		if (do_stat(from, g.gl_pathv[0], 1) == NULL) {
1919
			error("%s: %s", src, strerror(ENOENT));
1920
			err = -1;
1921
			goto out;
1922
		}
1923
	}
1924
1895
	for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1925
	for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
1896
		tmp = xstrdup(g.gl_pathv[i]);
1926
		tmp = xstrdup(g.gl_pathv[i]);
1897
		if ((filename = basename(tmp)) == NULL) {
1927
		if ((filename = basename(tmp)) == NULL) {
(-)a/sftp-glob.c (-1 / +31 lines)
Lines 110-115 int Link Here
110
remote_glob(struct sftp_conn *conn, const char *pattern, int flags,
110
remote_glob(struct sftp_conn *conn, const char *pattern, int flags,
111
    int (*errfunc)(const char *, int), glob_t *pglob)
111
    int (*errfunc)(const char *, int), glob_t *pglob)
112
{
112
{
113
	int r;
114
	size_t l;
115
	char *s;
116
	struct stat sb;
117
113
	pglob->gl_opendir = fudge_opendir;
118
	pglob->gl_opendir = fudge_opendir;
114
	pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir;
119
	pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir;
115
	pglob->gl_closedir = (void (*)(void *))fudge_closedir;
120
	pglob->gl_closedir = (void (*)(void *))fudge_closedir;
Lines 119-123 remote_glob(struct sftp_conn *conn, const char *pattern, int flags, Link Here
119
	memset(&cur, 0, sizeof(cur));
124
	memset(&cur, 0, sizeof(cur));
120
	cur.conn = conn;
125
	cur.conn = conn;
121
126
122
	return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob));
127
	if ((r = glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob)) != 0)
128
		return r;
129
	/*
130
	 * When both GLOB_NOCHECK and GLOB_MARK are active, a single gl_pathv
131
	 * entry has been returned and that entry has not already been marked,
132
	 * then check whether it needs a '/' appended as a directory mark.
133
	 *
134
	 * This ensures that a NOCHECK result is annotated as a directory.
135
	 * The glob(3) spec doesn't promise to mark NOCHECK entries, but doing
136
	 * it simplifies our callers (sftp/scp) considerably.
137
	 *
138
	 * XXX doesn't try to handle gl_offs.
139
	 */
140
	if ((flags & (GLOB_NOCHECK|GLOB_MARK)) == (GLOB_NOCHECK|GLOB_MARK) &&
141
	    pglob->gl_matchc == 0 && pglob->gl_offs == 0 &&
142
	    pglob->gl_pathc == 1 && (s = pglob->gl_pathv[0]) != NULL &&
143
	    (l = strlen(s)) > 0 && s[l-1] != '/') {
144
		if (fudge_stat(s, &sb) == 0 && S_ISDIR(sb.st_mode)) {
145
			/* NOCHECK on a directory; annotate */
146
			if ((s = realloc(s, l + 2)) != NULL) {
147
				memcpy(s + l, "/", 2);
148
				pglob->gl_pathv[0] = s;
149
			}
150
		}
151
	}
152
	return 0;
123
}
153
}

Return to bug 3488