11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: sftp-glob.c,v 1.22 2006/08/03 03:34:42 deraadt Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Permission to use, copy, modify, and distribute this software for any
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * purpose with or without fee is hereby granted, provided that the above
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * copyright notice and this permission notice appear in all copies.
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_SYS_STAT_H
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <sys/stat.h>
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <dirent.h>
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h"
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sftp.h"
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h"
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sftp-common.h"
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sftp-client.h"
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint remote_glob(struct sftp_conn *, const char *, int,
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    int (*)(const char *, int), glob_t *);
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct SFTP_OPENDIR {
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	SFTP_DIRENT **dir;
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int offset;
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood};
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic struct {
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct sftp_conn *conn;
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} cur;
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void *
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfudge_opendir(const char *path)
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct SFTP_OPENDIR *r;
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	r = xmalloc(sizeof(*r));
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (do_readdir(cur.conn, (char *)path, &r->dir)) {
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xfree(r);
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return(NULL);
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	r->offset = 0;
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return((void *)r);
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic struct dirent *
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfudge_readdir(struct SFTP_OPENDIR *od)
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Solaris needs sizeof(dirent) + path length (see below) */
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static char buf[sizeof(struct dirent) + MAXPATHLEN];
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct dirent *ret = (struct dirent *)buf;
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef __GNU_LIBRARY__
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static int inum = 1;
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* __GNU_LIBRARY__ */
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (od->dir[od->offset] == NULL)
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return(NULL);
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(buf, 0, sizeof(buf));
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Solaris defines dirent->d_name as a one byte array and expects
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * you to hack around it.
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN);
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	strlcpy(ret->d_name, od->dir[od->offset++]->filename,
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    sizeof(ret->d_name));
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef __GNU_LIBRARY__
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Idiot glibc uses extensions to struct dirent for readdir with
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * ALTDIRFUNCs. Not that this is documented anywhere but the
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * source... Fake an inode number to appease it.
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ret->d_ino = inum++;
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!inum)
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		inum = 1;
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* __GNU_LIBRARY__ */
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return(ret);
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfudge_closedir(struct SFTP_OPENDIR *od)
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	free_sftp_dirents(od->dir);
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(od);
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfudge_lstat(const char *path, struct stat *st)
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Attrib *a;
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!(a = do_lstat(cur.conn, (char *)path, 0)))
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return(-1);
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	attrib_to_stat(a, st);
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return(0);
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfudge_stat(const char *path, struct stat *st)
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Attrib *a;
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!(a = do_stat(cur.conn, (char *)path, 0)))
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return(-1);
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	attrib_to_stat(a, st);
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return(0);
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodremote_glob(struct sftp_conn *conn, const char *pattern, int flags,
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    int (*errfunc)(const char *, int), glob_t *pglob)
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pglob->gl_opendir = fudge_opendir;
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir;
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pglob->gl_closedir = (void (*)(void *))fudge_closedir;
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pglob->gl_lstat = fudge_lstat;
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pglob->gl_stat = fudge_stat;
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(&cur, 0, sizeof(cur));
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	cur.conn = conn;
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob));
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
150