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