xref: /freebsd/crypto/openssh/sftp-glob.c (revision efcad6b72fe9d4f7ea99c021f4903d09ca31b666)
11e8db6e2SBrian Feldman /*
2efcad6b7SDag-Erling Smørgrav  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
31e8db6e2SBrian Feldman  *
4efcad6b7SDag-Erling Smørgrav  * Permission to use, copy, modify, and distribute this software for any
5efcad6b7SDag-Erling Smørgrav  * purpose with or without fee is hereby granted, provided that the above
6efcad6b7SDag-Erling Smørgrav  * copyright notice and this permission notice appear in all copies.
71e8db6e2SBrian Feldman  *
8efcad6b7SDag-Erling Smørgrav  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9efcad6b7SDag-Erling Smørgrav  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10efcad6b7SDag-Erling Smørgrav  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11efcad6b7SDag-Erling Smørgrav  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12efcad6b7SDag-Erling Smørgrav  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13efcad6b7SDag-Erling Smørgrav  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14efcad6b7SDag-Erling Smørgrav  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
151e8db6e2SBrian Feldman  */
161e8db6e2SBrian Feldman 
171e8db6e2SBrian Feldman #include "includes.h"
18efcad6b7SDag-Erling Smørgrav RCSID("$OpenBSD: sftp-glob.c,v 1.15 2004/02/17 07:17:29 djm Exp $");
191e8db6e2SBrian Feldman 
201e8db6e2SBrian Feldman #include "buffer.h"
211e8db6e2SBrian Feldman #include "bufaux.h"
221e8db6e2SBrian Feldman #include "xmalloc.h"
231e8db6e2SBrian Feldman #include "log.h"
241e8db6e2SBrian Feldman 
251e8db6e2SBrian Feldman #include "sftp.h"
261e8db6e2SBrian Feldman #include "sftp-common.h"
271e8db6e2SBrian Feldman #include "sftp-client.h"
28efcad6b7SDag-Erling Smørgrav 
29efcad6b7SDag-Erling Smørgrav int remote_glob(struct sftp_conn *, const char *, int,
30efcad6b7SDag-Erling Smørgrav     int (*)(const char *, int), glob_t *);
311e8db6e2SBrian Feldman 
321e8db6e2SBrian Feldman struct SFTP_OPENDIR {
331e8db6e2SBrian Feldman 	SFTP_DIRENT **dir;
341e8db6e2SBrian Feldman 	int offset;
351e8db6e2SBrian Feldman };
361e8db6e2SBrian Feldman 
371e8db6e2SBrian Feldman static struct {
38ae1f160dSDag-Erling Smørgrav 	struct sftp_conn *conn;
391e8db6e2SBrian Feldman } cur;
401e8db6e2SBrian Feldman 
41ae1f160dSDag-Erling Smørgrav static void *
42ae1f160dSDag-Erling Smørgrav fudge_opendir(const char *path)
431e8db6e2SBrian Feldman {
441e8db6e2SBrian Feldman 	struct SFTP_OPENDIR *r;
451e8db6e2SBrian Feldman 
461e8db6e2SBrian Feldman 	r = xmalloc(sizeof(*r));
471e8db6e2SBrian Feldman 
484b17dab0SDag-Erling Smørgrav 	if (do_readdir(cur.conn, (char *)path, &r->dir)) {
494b17dab0SDag-Erling Smørgrav 		xfree(r);
501e8db6e2SBrian Feldman 		return(NULL);
514b17dab0SDag-Erling Smørgrav 	}
521e8db6e2SBrian Feldman 
531e8db6e2SBrian Feldman 	r->offset = 0;
541e8db6e2SBrian Feldman 
551e8db6e2SBrian Feldman 	return((void *)r);
561e8db6e2SBrian Feldman }
571e8db6e2SBrian Feldman 
58ae1f160dSDag-Erling Smørgrav static struct dirent *
59ae1f160dSDag-Erling Smørgrav fudge_readdir(struct SFTP_OPENDIR *od)
601e8db6e2SBrian Feldman {
6183d2307dSDag-Erling Smørgrav 	/* Solaris needs sizeof(dirent) + path length (see below) */
6283d2307dSDag-Erling Smørgrav 	static char buf[sizeof(struct dirent) + MAXPATHLEN];
6383d2307dSDag-Erling Smørgrav 	struct dirent *ret = (struct dirent *)buf;
6483d2307dSDag-Erling Smørgrav #ifdef __GNU_LIBRARY__
6583d2307dSDag-Erling Smørgrav 	static int inum = 1;
6683d2307dSDag-Erling Smørgrav #endif /* __GNU_LIBRARY__ */
671e8db6e2SBrian Feldman 
681e8db6e2SBrian Feldman 	if (od->dir[od->offset] == NULL)
691e8db6e2SBrian Feldman 		return(NULL);
701e8db6e2SBrian Feldman 
7183d2307dSDag-Erling Smørgrav 	memset(buf, 0, sizeof(buf));
721e8db6e2SBrian Feldman 
7383d2307dSDag-Erling Smørgrav 	/*
7483d2307dSDag-Erling Smørgrav 	 * Solaris defines dirent->d_name as a one byte array and expects
7583d2307dSDag-Erling Smørgrav 	 * you to hack around it.
7683d2307dSDag-Erling Smørgrav 	 */
7783d2307dSDag-Erling Smørgrav #ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME
7883d2307dSDag-Erling Smørgrav 	strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN);
7983d2307dSDag-Erling Smørgrav #else
8083d2307dSDag-Erling Smørgrav 	strlcpy(ret->d_name, od->dir[od->offset++]->filename,
8183d2307dSDag-Erling Smørgrav 	    sizeof(ret->d_name));
8283d2307dSDag-Erling Smørgrav #endif
8383d2307dSDag-Erling Smørgrav #ifdef __GNU_LIBRARY__
8483d2307dSDag-Erling Smørgrav 	/*
8583d2307dSDag-Erling Smørgrav 	 * Idiot glibc uses extensions to struct dirent for readdir with
8683d2307dSDag-Erling Smørgrav 	 * ALTDIRFUNCs. Not that this is documented anywhere but the
8783d2307dSDag-Erling Smørgrav 	 * source... Fake an inode number to appease it.
8883d2307dSDag-Erling Smørgrav 	 */
8983d2307dSDag-Erling Smørgrav 	ret->d_ino = inum++;
9083d2307dSDag-Erling Smørgrav 	if (!inum)
9183d2307dSDag-Erling Smørgrav 		inum = 1;
9283d2307dSDag-Erling Smørgrav #endif /* __GNU_LIBRARY__ */
9383d2307dSDag-Erling Smørgrav 
9483d2307dSDag-Erling Smørgrav 	return(ret);
951e8db6e2SBrian Feldman }
961e8db6e2SBrian Feldman 
97ae1f160dSDag-Erling Smørgrav static void
98ae1f160dSDag-Erling Smørgrav fudge_closedir(struct SFTP_OPENDIR *od)
991e8db6e2SBrian Feldman {
1001e8db6e2SBrian Feldman 	free_sftp_dirents(od->dir);
1011e8db6e2SBrian Feldman 	xfree(od);
1021e8db6e2SBrian Feldman }
1031e8db6e2SBrian Feldman 
104ae1f160dSDag-Erling Smørgrav static int
105ae1f160dSDag-Erling Smørgrav fudge_lstat(const char *path, struct stat *st)
1061e8db6e2SBrian Feldman {
1071e8db6e2SBrian Feldman 	Attrib *a;
1081e8db6e2SBrian Feldman 
109ae1f160dSDag-Erling Smørgrav 	if (!(a = do_lstat(cur.conn, (char *)path, 0)))
1101e8db6e2SBrian Feldman 		return(-1);
1111e8db6e2SBrian Feldman 
1121e8db6e2SBrian Feldman 	attrib_to_stat(a, st);
1131e8db6e2SBrian Feldman 
1141e8db6e2SBrian Feldman 	return(0);
1151e8db6e2SBrian Feldman }
1161e8db6e2SBrian Feldman 
117ae1f160dSDag-Erling Smørgrav static int
118ae1f160dSDag-Erling Smørgrav fudge_stat(const char *path, struct stat *st)
1191e8db6e2SBrian Feldman {
1201e8db6e2SBrian Feldman 	Attrib *a;
1211e8db6e2SBrian Feldman 
122ae1f160dSDag-Erling Smørgrav 	if (!(a = do_stat(cur.conn, (char *)path, 0)))
1231e8db6e2SBrian Feldman 		return(-1);
1241e8db6e2SBrian Feldman 
1251e8db6e2SBrian Feldman 	attrib_to_stat(a, st);
1261e8db6e2SBrian Feldman 
1271e8db6e2SBrian Feldman 	return(0);
1281e8db6e2SBrian Feldman }
1291e8db6e2SBrian Feldman 
1301e8db6e2SBrian Feldman int
131ae1f160dSDag-Erling Smørgrav remote_glob(struct sftp_conn *conn, const char *pattern, int flags,
1321e8db6e2SBrian Feldman     int (*errfunc)(const char *, int), glob_t *pglob)
1331e8db6e2SBrian Feldman {
134ae1f160dSDag-Erling Smørgrav 	pglob->gl_opendir = fudge_opendir;
135ae1f160dSDag-Erling Smørgrav 	pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir;
136ae1f160dSDag-Erling Smørgrav 	pglob->gl_closedir = (void (*)(void *))fudge_closedir;
1371e8db6e2SBrian Feldman 	pglob->gl_lstat = fudge_lstat;
1381e8db6e2SBrian Feldman 	pglob->gl_stat = fudge_stat;
1391e8db6e2SBrian Feldman 
1401e8db6e2SBrian Feldman 	memset(&cur, 0, sizeof(cur));
141ae1f160dSDag-Erling Smørgrav 	cur.conn = conn;
1421e8db6e2SBrian Feldman 
143ae1f160dSDag-Erling Smørgrav 	return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob));
1441e8db6e2SBrian Feldman }
145