xref: /onnv-gate/usr/src/cmd/ssh/sftp/sftp-glob.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*0Sstevel@tonic-gate  * Use is subject to license terms.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate /*
6*0Sstevel@tonic-gate  * Copyright (c) 2001,2002 Damien Miller.  All rights reserved.
7*0Sstevel@tonic-gate  *
8*0Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
9*0Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
10*0Sstevel@tonic-gate  * are met:
11*0Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
12*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
13*0Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
14*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
15*0Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
16*0Sstevel@tonic-gate  *
17*0Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18*0Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19*0Sstevel@tonic-gate  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*0Sstevel@tonic-gate  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21*0Sstevel@tonic-gate  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22*0Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23*0Sstevel@tonic-gate  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24*0Sstevel@tonic-gate  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25*0Sstevel@tonic-gate  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26*0Sstevel@tonic-gate  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*0Sstevel@tonic-gate  */
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include "includes.h"
30*0Sstevel@tonic-gate RCSID("$OpenBSD: sftp-glob.c,v 1.13 2002/09/11 22:41:50 djm Exp $");
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #include "buffer.h"
35*0Sstevel@tonic-gate #include "bufaux.h"
36*0Sstevel@tonic-gate #include "xmalloc.h"
37*0Sstevel@tonic-gate #include "log.h"
38*0Sstevel@tonic-gate 
39*0Sstevel@tonic-gate #include "sftp.h"
40*0Sstevel@tonic-gate #include "sftp-common.h"
41*0Sstevel@tonic-gate #include "sftp-client.h"
42*0Sstevel@tonic-gate #include "sftp-glob.h"
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate struct SFTP_OPENDIR {
45*0Sstevel@tonic-gate 	SFTP_DIRENT **dir;
46*0Sstevel@tonic-gate 	int offset;
47*0Sstevel@tonic-gate };
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate static struct {
50*0Sstevel@tonic-gate 	struct sftp_conn *conn;
51*0Sstevel@tonic-gate } cur;
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate static void *
54*0Sstevel@tonic-gate fudge_opendir(const char *path)
55*0Sstevel@tonic-gate {
56*0Sstevel@tonic-gate 	struct SFTP_OPENDIR *r;
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate 	r = xmalloc(sizeof(*r));
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate 	if (do_readdir(cur.conn, (char *)path, &r->dir)) {
61*0Sstevel@tonic-gate 		xfree(r);
62*0Sstevel@tonic-gate 		return(NULL);
63*0Sstevel@tonic-gate 	}
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate 	r->offset = 0;
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate 	return((void *)r);
68*0Sstevel@tonic-gate }
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate static struct dirent *
71*0Sstevel@tonic-gate fudge_readdir(struct SFTP_OPENDIR *od)
72*0Sstevel@tonic-gate {
73*0Sstevel@tonic-gate 	/* Solaris needs sizeof(dirent) + path length (see below) */
74*0Sstevel@tonic-gate 	static union {
75*0Sstevel@tonic-gate 		char buf_chars[sizeof (struct dirent) + MAXPATHLEN];
76*0Sstevel@tonic-gate 		struct dirent buf_dirent;
77*0Sstevel@tonic-gate 	} buf;
78*0Sstevel@tonic-gate 	struct dirent *ret = &buf.buf_dirent;
79*0Sstevel@tonic-gate #ifdef __GNU_LIBRARY__
80*0Sstevel@tonic-gate 	static int inum = 1;
81*0Sstevel@tonic-gate #endif /* __GNU_LIBRARY__ */
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate 	if (od->dir[od->offset] == NULL)
84*0Sstevel@tonic-gate 		return(NULL);
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate 	memset(buf.buf_chars, 0, sizeof (buf.buf_chars));
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate 	/*
89*0Sstevel@tonic-gate 	 * Solaris defines dirent->d_name as a one byte array and expects
90*0Sstevel@tonic-gate 	 * you to hack around it.
91*0Sstevel@tonic-gate 	 */
92*0Sstevel@tonic-gate #ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME
93*0Sstevel@tonic-gate 	strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN);
94*0Sstevel@tonic-gate #else
95*0Sstevel@tonic-gate 	strlcpy(ret->d_name, od->dir[od->offset++]->filename,
96*0Sstevel@tonic-gate 	    sizeof(ret->d_name));
97*0Sstevel@tonic-gate #endif
98*0Sstevel@tonic-gate #ifdef __GNU_LIBRARY__
99*0Sstevel@tonic-gate 	/*
100*0Sstevel@tonic-gate 	 * Idiot glibc uses extensions to struct dirent for readdir with
101*0Sstevel@tonic-gate 	 * ALTDIRFUNCs. Not that this is documented anywhere but the
102*0Sstevel@tonic-gate 	 * source... Fake an inode number to appease it.
103*0Sstevel@tonic-gate 	 */
104*0Sstevel@tonic-gate 	ret->d_ino = inum++;
105*0Sstevel@tonic-gate 	if (!inum)
106*0Sstevel@tonic-gate 		inum = 1;
107*0Sstevel@tonic-gate #endif /* __GNU_LIBRARY__ */
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate 	return(ret);
110*0Sstevel@tonic-gate }
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate static void
113*0Sstevel@tonic-gate fudge_closedir(struct SFTP_OPENDIR *od)
114*0Sstevel@tonic-gate {
115*0Sstevel@tonic-gate 	free_sftp_dirents(od->dir);
116*0Sstevel@tonic-gate 	xfree(od);
117*0Sstevel@tonic-gate }
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate static int
120*0Sstevel@tonic-gate fudge_lstat(const char *path, struct stat *st)
121*0Sstevel@tonic-gate {
122*0Sstevel@tonic-gate 	Attrib *a;
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 	if (!(a = do_lstat(cur.conn, (char *)path, 0)))
125*0Sstevel@tonic-gate 		return(-1);
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate 	attrib_to_stat(a, st);
128*0Sstevel@tonic-gate 
129*0Sstevel@tonic-gate 	return(0);
130*0Sstevel@tonic-gate }
131*0Sstevel@tonic-gate 
132*0Sstevel@tonic-gate static int
133*0Sstevel@tonic-gate fudge_stat(const char *path, struct stat *st)
134*0Sstevel@tonic-gate {
135*0Sstevel@tonic-gate 	Attrib *a;
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 	if (!(a = do_stat(cur.conn, (char *)path, 0)))
138*0Sstevel@tonic-gate 		return(-1);
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 	attrib_to_stat(a, st);
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate 	return(0);
143*0Sstevel@tonic-gate }
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate int
146*0Sstevel@tonic-gate remote_glob(struct sftp_conn *conn, const char *pattern, int flags,
147*0Sstevel@tonic-gate     int (*errfunc)(const char *, int), glob_t *pglob)
148*0Sstevel@tonic-gate {
149*0Sstevel@tonic-gate 	pglob->gl_opendir = fudge_opendir;
150*0Sstevel@tonic-gate 	pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir;
151*0Sstevel@tonic-gate 	pglob->gl_closedir = (void (*)(void *))fudge_closedir;
152*0Sstevel@tonic-gate 	pglob->gl_lstat = fudge_lstat;
153*0Sstevel@tonic-gate 	pglob->gl_stat = fudge_stat;
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate 	memset(&cur, 0, sizeof(cur));
156*0Sstevel@tonic-gate 	cur.conn = conn;
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate 	return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob));
159*0Sstevel@tonic-gate }
160