xref: /freebsd/crypto/openssh/sftp-glob.c (revision 761efaa70c2ed8d35722b7bc234a46bf2457f876)
1761efaa7SDag-Erling Smørgrav /* $OpenBSD: sftp-glob.c,v 1.22 2006/08/03 03:34:42 deraadt Exp $ */
21e8db6e2SBrian Feldman /*
3efcad6b7SDag-Erling Smørgrav  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
41e8db6e2SBrian Feldman  *
5efcad6b7SDag-Erling Smørgrav  * Permission to use, copy, modify, and distribute this software for any
6efcad6b7SDag-Erling Smørgrav  * purpose with or without fee is hereby granted, provided that the above
7efcad6b7SDag-Erling Smørgrav  * copyright notice and this permission notice appear in all copies.
81e8db6e2SBrian Feldman  *
9efcad6b7SDag-Erling Smørgrav  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10efcad6b7SDag-Erling Smørgrav  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11efcad6b7SDag-Erling Smørgrav  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12efcad6b7SDag-Erling Smørgrav  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13efcad6b7SDag-Erling Smørgrav  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14efcad6b7SDag-Erling Smørgrav  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15efcad6b7SDag-Erling Smørgrav  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
161e8db6e2SBrian Feldman  */
171e8db6e2SBrian Feldman 
181e8db6e2SBrian Feldman #include "includes.h"
191e8db6e2SBrian Feldman 
20761efaa7SDag-Erling Smørgrav #include <sys/types.h>
21761efaa7SDag-Erling Smørgrav #ifdef HAVE_SYS_STAT_H
22761efaa7SDag-Erling Smørgrav # include <sys/stat.h>
23761efaa7SDag-Erling Smørgrav #endif
24761efaa7SDag-Erling Smørgrav 
25761efaa7SDag-Erling Smørgrav #include <dirent.h>
26761efaa7SDag-Erling Smørgrav #include <string.h>
27761efaa7SDag-Erling Smørgrav 
281e8db6e2SBrian Feldman #include "xmalloc.h"
291e8db6e2SBrian Feldman #include "sftp.h"
30761efaa7SDag-Erling Smørgrav #include "buffer.h"
311e8db6e2SBrian Feldman #include "sftp-common.h"
321e8db6e2SBrian Feldman #include "sftp-client.h"
33efcad6b7SDag-Erling Smørgrav 
34efcad6b7SDag-Erling Smørgrav int remote_glob(struct sftp_conn *, const char *, int,
35efcad6b7SDag-Erling Smørgrav     int (*)(const char *, int), glob_t *);
361e8db6e2SBrian Feldman 
371e8db6e2SBrian Feldman struct SFTP_OPENDIR {
381e8db6e2SBrian Feldman 	SFTP_DIRENT **dir;
391e8db6e2SBrian Feldman 	int offset;
401e8db6e2SBrian Feldman };
411e8db6e2SBrian Feldman 
421e8db6e2SBrian Feldman static struct {
43ae1f160dSDag-Erling Smørgrav 	struct sftp_conn *conn;
441e8db6e2SBrian Feldman } cur;
451e8db6e2SBrian Feldman 
46ae1f160dSDag-Erling Smørgrav static void *
47ae1f160dSDag-Erling Smørgrav fudge_opendir(const char *path)
481e8db6e2SBrian Feldman {
491e8db6e2SBrian Feldman 	struct SFTP_OPENDIR *r;
501e8db6e2SBrian Feldman 
511e8db6e2SBrian Feldman 	r = xmalloc(sizeof(*r));
521e8db6e2SBrian Feldman 
534b17dab0SDag-Erling Smørgrav 	if (do_readdir(cur.conn, (char *)path, &r->dir)) {
544b17dab0SDag-Erling Smørgrav 		xfree(r);
551e8db6e2SBrian Feldman 		return(NULL);
564b17dab0SDag-Erling Smørgrav 	}
571e8db6e2SBrian Feldman 
581e8db6e2SBrian Feldman 	r->offset = 0;
591e8db6e2SBrian Feldman 
601e8db6e2SBrian Feldman 	return((void *)r);
611e8db6e2SBrian Feldman }
621e8db6e2SBrian Feldman 
63ae1f160dSDag-Erling Smørgrav static struct dirent *
64ae1f160dSDag-Erling Smørgrav fudge_readdir(struct SFTP_OPENDIR *od)
651e8db6e2SBrian Feldman {
6683d2307dSDag-Erling Smørgrav 	/* Solaris needs sizeof(dirent) + path length (see below) */
6783d2307dSDag-Erling Smørgrav 	static char buf[sizeof(struct dirent) + MAXPATHLEN];
6883d2307dSDag-Erling Smørgrav 	struct dirent *ret = (struct dirent *)buf;
6983d2307dSDag-Erling Smørgrav #ifdef __GNU_LIBRARY__
7083d2307dSDag-Erling Smørgrav 	static int inum = 1;
7183d2307dSDag-Erling Smørgrav #endif /* __GNU_LIBRARY__ */
721e8db6e2SBrian Feldman 
731e8db6e2SBrian Feldman 	if (od->dir[od->offset] == NULL)
741e8db6e2SBrian Feldman 		return(NULL);
751e8db6e2SBrian Feldman 
7683d2307dSDag-Erling Smørgrav 	memset(buf, 0, sizeof(buf));
771e8db6e2SBrian Feldman 
7883d2307dSDag-Erling Smørgrav 	/*
7983d2307dSDag-Erling Smørgrav 	 * Solaris defines dirent->d_name as a one byte array and expects
8083d2307dSDag-Erling Smørgrav 	 * you to hack around it.
8183d2307dSDag-Erling Smørgrav 	 */
8283d2307dSDag-Erling Smørgrav #ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME
8383d2307dSDag-Erling Smørgrav 	strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN);
8483d2307dSDag-Erling Smørgrav #else
8583d2307dSDag-Erling Smørgrav 	strlcpy(ret->d_name, od->dir[od->offset++]->filename,
8683d2307dSDag-Erling Smørgrav 	    sizeof(ret->d_name));
8783d2307dSDag-Erling Smørgrav #endif
8883d2307dSDag-Erling Smørgrav #ifdef __GNU_LIBRARY__
8983d2307dSDag-Erling Smørgrav 	/*
9083d2307dSDag-Erling Smørgrav 	 * Idiot glibc uses extensions to struct dirent for readdir with
9183d2307dSDag-Erling Smørgrav 	 * ALTDIRFUNCs. Not that this is documented anywhere but the
9283d2307dSDag-Erling Smørgrav 	 * source... Fake an inode number to appease it.
9383d2307dSDag-Erling Smørgrav 	 */
9483d2307dSDag-Erling Smørgrav 	ret->d_ino = inum++;
9583d2307dSDag-Erling Smørgrav 	if (!inum)
9683d2307dSDag-Erling Smørgrav 		inum = 1;
9783d2307dSDag-Erling Smørgrav #endif /* __GNU_LIBRARY__ */
9883d2307dSDag-Erling Smørgrav 
9983d2307dSDag-Erling Smørgrav 	return(ret);
1001e8db6e2SBrian Feldman }
1011e8db6e2SBrian Feldman 
102ae1f160dSDag-Erling Smørgrav static void
103ae1f160dSDag-Erling Smørgrav fudge_closedir(struct SFTP_OPENDIR *od)
1041e8db6e2SBrian Feldman {
1051e8db6e2SBrian Feldman 	free_sftp_dirents(od->dir);
1061e8db6e2SBrian Feldman 	xfree(od);
1071e8db6e2SBrian Feldman }
1081e8db6e2SBrian Feldman 
109ae1f160dSDag-Erling Smørgrav static int
110ae1f160dSDag-Erling Smørgrav fudge_lstat(const char *path, struct stat *st)
1111e8db6e2SBrian Feldman {
1121e8db6e2SBrian Feldman 	Attrib *a;
1131e8db6e2SBrian Feldman 
114ae1f160dSDag-Erling Smørgrav 	if (!(a = do_lstat(cur.conn, (char *)path, 0)))
1151e8db6e2SBrian Feldman 		return(-1);
1161e8db6e2SBrian Feldman 
1171e8db6e2SBrian Feldman 	attrib_to_stat(a, st);
1181e8db6e2SBrian Feldman 
1191e8db6e2SBrian Feldman 	return(0);
1201e8db6e2SBrian Feldman }
1211e8db6e2SBrian Feldman 
122ae1f160dSDag-Erling Smørgrav static int
123ae1f160dSDag-Erling Smørgrav fudge_stat(const char *path, struct stat *st)
1241e8db6e2SBrian Feldman {
1251e8db6e2SBrian Feldman 	Attrib *a;
1261e8db6e2SBrian Feldman 
127ae1f160dSDag-Erling Smørgrav 	if (!(a = do_stat(cur.conn, (char *)path, 0)))
1281e8db6e2SBrian Feldman 		return(-1);
1291e8db6e2SBrian Feldman 
1301e8db6e2SBrian Feldman 	attrib_to_stat(a, st);
1311e8db6e2SBrian Feldman 
1321e8db6e2SBrian Feldman 	return(0);
1331e8db6e2SBrian Feldman }
1341e8db6e2SBrian Feldman 
1351e8db6e2SBrian Feldman int
136ae1f160dSDag-Erling Smørgrav remote_glob(struct sftp_conn *conn, const char *pattern, int flags,
1371e8db6e2SBrian Feldman     int (*errfunc)(const char *, int), glob_t *pglob)
1381e8db6e2SBrian Feldman {
139ae1f160dSDag-Erling Smørgrav 	pglob->gl_opendir = fudge_opendir;
140ae1f160dSDag-Erling Smørgrav 	pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir;
141ae1f160dSDag-Erling Smørgrav 	pglob->gl_closedir = (void (*)(void *))fudge_closedir;
1421e8db6e2SBrian Feldman 	pglob->gl_lstat = fudge_lstat;
1431e8db6e2SBrian Feldman 	pglob->gl_stat = fudge_stat;
1441e8db6e2SBrian Feldman 
1451e8db6e2SBrian Feldman 	memset(&cur, 0, sizeof(cur));
146ae1f160dSDag-Erling Smørgrav 	cur.conn = conn;
1471e8db6e2SBrian Feldman 
148ae1f160dSDag-Erling Smørgrav 	return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob));
1491e8db6e2SBrian Feldman }
150