xref: /onnv-gate/usr/src/cmd/ssh/sftp/sftp-glob.c (revision 5087:929c96aa57f2)
10Sstevel@tonic-gate /*
2*5087Sjp161948  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
3*5087Sjp161948  *
4*5087Sjp161948  * Permission to use, copy, modify, and distribute this software for any
5*5087Sjp161948  * purpose with or without fee is hereby granted, provided that the above
6*5087Sjp161948  * copyright notice and this permission notice appear in all copies.
70Sstevel@tonic-gate  *
8*5087Sjp161948  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9*5087Sjp161948  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10*5087Sjp161948  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11*5087Sjp161948  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12*5087Sjp161948  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13*5087Sjp161948  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14*5087Sjp161948  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
150Sstevel@tonic-gate  */
160Sstevel@tonic-gate 
17*5087Sjp161948 /* $OpenBSD: sftp-glob.c,v 1.22 2006/08/03 03:34:42 deraadt Exp $ */
180Sstevel@tonic-gate 
190Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
200Sstevel@tonic-gate 
21*5087Sjp161948 #include "includes.h"
22*5087Sjp161948 
23*5087Sjp161948 #include <sys/types.h>
24*5087Sjp161948 #ifdef HAVE_SYS_STAT_H
25*5087Sjp161948 # include <sys/stat.h>
26*5087Sjp161948 #endif
27*5087Sjp161948 
28*5087Sjp161948 #include <dirent.h>
29*5087Sjp161948 #include <string.h>
30*5087Sjp161948 
310Sstevel@tonic-gate #include "xmalloc.h"
320Sstevel@tonic-gate #include "sftp.h"
33*5087Sjp161948 #include "buffer.h"
340Sstevel@tonic-gate #include "sftp-common.h"
350Sstevel@tonic-gate #include "sftp-client.h"
36*5087Sjp161948 
37*5087Sjp161948 int remote_glob(struct sftp_conn *, const char *, int,
38*5087Sjp161948     int (*)(const char *, int), glob_t *);
390Sstevel@tonic-gate 
400Sstevel@tonic-gate struct SFTP_OPENDIR {
410Sstevel@tonic-gate 	SFTP_DIRENT **dir;
420Sstevel@tonic-gate 	int offset;
430Sstevel@tonic-gate };
440Sstevel@tonic-gate 
450Sstevel@tonic-gate static struct {
460Sstevel@tonic-gate 	struct sftp_conn *conn;
470Sstevel@tonic-gate } cur;
480Sstevel@tonic-gate 
490Sstevel@tonic-gate static void *
fudge_opendir(const char * path)500Sstevel@tonic-gate fudge_opendir(const char *path)
510Sstevel@tonic-gate {
520Sstevel@tonic-gate 	struct SFTP_OPENDIR *r;
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	r = xmalloc(sizeof(*r));
550Sstevel@tonic-gate 
560Sstevel@tonic-gate 	if (do_readdir(cur.conn, (char *)path, &r->dir)) {
570Sstevel@tonic-gate 		xfree(r);
580Sstevel@tonic-gate 		return(NULL);
590Sstevel@tonic-gate 	}
600Sstevel@tonic-gate 
610Sstevel@tonic-gate 	r->offset = 0;
620Sstevel@tonic-gate 
630Sstevel@tonic-gate 	return((void *)r);
640Sstevel@tonic-gate }
650Sstevel@tonic-gate 
660Sstevel@tonic-gate static struct dirent *
fudge_readdir(struct SFTP_OPENDIR * od)670Sstevel@tonic-gate fudge_readdir(struct SFTP_OPENDIR *od)
680Sstevel@tonic-gate {
690Sstevel@tonic-gate 	/* Solaris needs sizeof(dirent) + path length (see below) */
700Sstevel@tonic-gate 	static union {
710Sstevel@tonic-gate 		char buf_chars[sizeof (struct dirent) + MAXPATHLEN];
720Sstevel@tonic-gate 		struct dirent buf_dirent;
730Sstevel@tonic-gate 	} buf;
740Sstevel@tonic-gate 	struct dirent *ret = &buf.buf_dirent;
750Sstevel@tonic-gate #ifdef __GNU_LIBRARY__
760Sstevel@tonic-gate 	static int inum = 1;
770Sstevel@tonic-gate #endif /* __GNU_LIBRARY__ */
78*5087Sjp161948 
790Sstevel@tonic-gate 	if (od->dir[od->offset] == NULL)
800Sstevel@tonic-gate 		return(NULL);
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 	memset(buf.buf_chars, 0, sizeof (buf.buf_chars));
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 	/*
850Sstevel@tonic-gate 	 * Solaris defines dirent->d_name as a one byte array and expects
860Sstevel@tonic-gate 	 * you to hack around it.
870Sstevel@tonic-gate 	 */
880Sstevel@tonic-gate #ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME
890Sstevel@tonic-gate 	strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN);
900Sstevel@tonic-gate #else
910Sstevel@tonic-gate 	strlcpy(ret->d_name, od->dir[od->offset++]->filename,
920Sstevel@tonic-gate 	    sizeof(ret->d_name));
930Sstevel@tonic-gate #endif
940Sstevel@tonic-gate #ifdef __GNU_LIBRARY__
950Sstevel@tonic-gate 	/*
960Sstevel@tonic-gate 	 * Idiot glibc uses extensions to struct dirent for readdir with
97*5087Sjp161948 	 * ALTDIRFUNCs. Not that this is documented anywhere but the
980Sstevel@tonic-gate 	 * source... Fake an inode number to appease it.
990Sstevel@tonic-gate 	 */
1000Sstevel@tonic-gate 	ret->d_ino = inum++;
1010Sstevel@tonic-gate 	if (!inum)
1020Sstevel@tonic-gate 		inum = 1;
1030Sstevel@tonic-gate #endif /* __GNU_LIBRARY__ */
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate 	return(ret);
1060Sstevel@tonic-gate }
1070Sstevel@tonic-gate 
1080Sstevel@tonic-gate static void
fudge_closedir(struct SFTP_OPENDIR * od)1090Sstevel@tonic-gate fudge_closedir(struct SFTP_OPENDIR *od)
1100Sstevel@tonic-gate {
1110Sstevel@tonic-gate 	free_sftp_dirents(od->dir);
1120Sstevel@tonic-gate 	xfree(od);
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate static int
fudge_lstat(const char * path,struct stat * st)1160Sstevel@tonic-gate fudge_lstat(const char *path, struct stat *st)
1170Sstevel@tonic-gate {
1180Sstevel@tonic-gate 	Attrib *a;
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	if (!(a = do_lstat(cur.conn, (char *)path, 0)))
1210Sstevel@tonic-gate 		return(-1);
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	attrib_to_stat(a, st);
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 	return(0);
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate static int
fudge_stat(const char * path,struct stat * st)1290Sstevel@tonic-gate fudge_stat(const char *path, struct stat *st)
1300Sstevel@tonic-gate {
1310Sstevel@tonic-gate 	Attrib *a;
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 	if (!(a = do_stat(cur.conn, (char *)path, 0)))
1340Sstevel@tonic-gate 		return(-1);
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	attrib_to_stat(a, st);
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 	return(0);
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate int
remote_glob(struct sftp_conn * conn,const char * pattern,int flags,int (* errfunc)(const char *,int),glob_t * pglob)1420Sstevel@tonic-gate remote_glob(struct sftp_conn *conn, const char *pattern, int flags,
1430Sstevel@tonic-gate     int (*errfunc)(const char *, int), glob_t *pglob)
1440Sstevel@tonic-gate {
1450Sstevel@tonic-gate 	pglob->gl_opendir = fudge_opendir;
1460Sstevel@tonic-gate 	pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir;
1470Sstevel@tonic-gate 	pglob->gl_closedir = (void (*)(void *))fudge_closedir;
1480Sstevel@tonic-gate 	pglob->gl_lstat = fudge_lstat;
1490Sstevel@tonic-gate 	pglob->gl_stat = fudge_stat;
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 	memset(&cur, 0, sizeof(cur));
1520Sstevel@tonic-gate 	cur.conn = conn;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob));
1550Sstevel@tonic-gate }
156