11e8db6e2SBrian Feldman /* 2efcad6b7SDag-Erling Smørgrav * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 31e8db6e2SBrian Feldman * 4efcad6b7SDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 5efcad6b7SDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 6efcad6b7SDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 71e8db6e2SBrian Feldman * 8efcad6b7SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9efcad6b7SDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10efcad6b7SDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11efcad6b7SDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12efcad6b7SDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13efcad6b7SDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14efcad6b7SDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 151e8db6e2SBrian Feldman */ 161e8db6e2SBrian Feldman 171e8db6e2SBrian Feldman #include "includes.h" 18efcad6b7SDag-Erling Smørgrav RCSID("$OpenBSD: sftp-glob.c,v 1.15 2004/02/17 07:17:29 djm Exp $"); 191e8db6e2SBrian Feldman 201e8db6e2SBrian Feldman #include "buffer.h" 211e8db6e2SBrian Feldman #include "bufaux.h" 221e8db6e2SBrian Feldman #include "xmalloc.h" 231e8db6e2SBrian Feldman #include "log.h" 241e8db6e2SBrian Feldman 251e8db6e2SBrian Feldman #include "sftp.h" 261e8db6e2SBrian Feldman #include "sftp-common.h" 271e8db6e2SBrian Feldman #include "sftp-client.h" 28efcad6b7SDag-Erling Smørgrav 29efcad6b7SDag-Erling Smørgrav int remote_glob(struct sftp_conn *, const char *, int, 30efcad6b7SDag-Erling Smørgrav int (*)(const char *, int), glob_t *); 311e8db6e2SBrian Feldman 321e8db6e2SBrian Feldman struct SFTP_OPENDIR { 331e8db6e2SBrian Feldman SFTP_DIRENT **dir; 341e8db6e2SBrian Feldman int offset; 351e8db6e2SBrian Feldman }; 361e8db6e2SBrian Feldman 371e8db6e2SBrian Feldman static struct { 38ae1f160dSDag-Erling Smørgrav struct sftp_conn *conn; 391e8db6e2SBrian Feldman } cur; 401e8db6e2SBrian Feldman 41ae1f160dSDag-Erling Smørgrav static void * 42ae1f160dSDag-Erling Smørgrav fudge_opendir(const char *path) 431e8db6e2SBrian Feldman { 441e8db6e2SBrian Feldman struct SFTP_OPENDIR *r; 451e8db6e2SBrian Feldman 461e8db6e2SBrian Feldman r = xmalloc(sizeof(*r)); 471e8db6e2SBrian Feldman 484b17dab0SDag-Erling Smørgrav if (do_readdir(cur.conn, (char *)path, &r->dir)) { 494b17dab0SDag-Erling Smørgrav xfree(r); 501e8db6e2SBrian Feldman return(NULL); 514b17dab0SDag-Erling Smørgrav } 521e8db6e2SBrian Feldman 531e8db6e2SBrian Feldman r->offset = 0; 541e8db6e2SBrian Feldman 551e8db6e2SBrian Feldman return((void *)r); 561e8db6e2SBrian Feldman } 571e8db6e2SBrian Feldman 58ae1f160dSDag-Erling Smørgrav static struct dirent * 59ae1f160dSDag-Erling Smørgrav fudge_readdir(struct SFTP_OPENDIR *od) 601e8db6e2SBrian Feldman { 6183d2307dSDag-Erling Smørgrav /* Solaris needs sizeof(dirent) + path length (see below) */ 6283d2307dSDag-Erling Smørgrav static char buf[sizeof(struct dirent) + MAXPATHLEN]; 6383d2307dSDag-Erling Smørgrav struct dirent *ret = (struct dirent *)buf; 6483d2307dSDag-Erling Smørgrav #ifdef __GNU_LIBRARY__ 6583d2307dSDag-Erling Smørgrav static int inum = 1; 6683d2307dSDag-Erling Smørgrav #endif /* __GNU_LIBRARY__ */ 671e8db6e2SBrian Feldman 681e8db6e2SBrian Feldman if (od->dir[od->offset] == NULL) 691e8db6e2SBrian Feldman return(NULL); 701e8db6e2SBrian Feldman 7183d2307dSDag-Erling Smørgrav memset(buf, 0, sizeof(buf)); 721e8db6e2SBrian Feldman 7383d2307dSDag-Erling Smørgrav /* 7483d2307dSDag-Erling Smørgrav * Solaris defines dirent->d_name as a one byte array and expects 7583d2307dSDag-Erling Smørgrav * you to hack around it. 7683d2307dSDag-Erling Smørgrav */ 7783d2307dSDag-Erling Smørgrav #ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME 7883d2307dSDag-Erling Smørgrav strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN); 7983d2307dSDag-Erling Smørgrav #else 8083d2307dSDag-Erling Smørgrav strlcpy(ret->d_name, od->dir[od->offset++]->filename, 8183d2307dSDag-Erling Smørgrav sizeof(ret->d_name)); 8283d2307dSDag-Erling Smørgrav #endif 8383d2307dSDag-Erling Smørgrav #ifdef __GNU_LIBRARY__ 8483d2307dSDag-Erling Smørgrav /* 8583d2307dSDag-Erling Smørgrav * Idiot glibc uses extensions to struct dirent for readdir with 8683d2307dSDag-Erling Smørgrav * ALTDIRFUNCs. Not that this is documented anywhere but the 8783d2307dSDag-Erling Smørgrav * source... Fake an inode number to appease it. 8883d2307dSDag-Erling Smørgrav */ 8983d2307dSDag-Erling Smørgrav ret->d_ino = inum++; 9083d2307dSDag-Erling Smørgrav if (!inum) 9183d2307dSDag-Erling Smørgrav inum = 1; 9283d2307dSDag-Erling Smørgrav #endif /* __GNU_LIBRARY__ */ 9383d2307dSDag-Erling Smørgrav 9483d2307dSDag-Erling Smørgrav return(ret); 951e8db6e2SBrian Feldman } 961e8db6e2SBrian Feldman 97ae1f160dSDag-Erling Smørgrav static void 98ae1f160dSDag-Erling Smørgrav fudge_closedir(struct SFTP_OPENDIR *od) 991e8db6e2SBrian Feldman { 1001e8db6e2SBrian Feldman free_sftp_dirents(od->dir); 1011e8db6e2SBrian Feldman xfree(od); 1021e8db6e2SBrian Feldman } 1031e8db6e2SBrian Feldman 104ae1f160dSDag-Erling Smørgrav static int 105ae1f160dSDag-Erling Smørgrav fudge_lstat(const char *path, struct stat *st) 1061e8db6e2SBrian Feldman { 1071e8db6e2SBrian Feldman Attrib *a; 1081e8db6e2SBrian Feldman 109ae1f160dSDag-Erling Smørgrav if (!(a = do_lstat(cur.conn, (char *)path, 0))) 1101e8db6e2SBrian Feldman return(-1); 1111e8db6e2SBrian Feldman 1121e8db6e2SBrian Feldman attrib_to_stat(a, st); 1131e8db6e2SBrian Feldman 1141e8db6e2SBrian Feldman return(0); 1151e8db6e2SBrian Feldman } 1161e8db6e2SBrian Feldman 117ae1f160dSDag-Erling Smørgrav static int 118ae1f160dSDag-Erling Smørgrav fudge_stat(const char *path, struct stat *st) 1191e8db6e2SBrian Feldman { 1201e8db6e2SBrian Feldman Attrib *a; 1211e8db6e2SBrian Feldman 122ae1f160dSDag-Erling Smørgrav if (!(a = do_stat(cur.conn, (char *)path, 0))) 1231e8db6e2SBrian Feldman return(-1); 1241e8db6e2SBrian Feldman 1251e8db6e2SBrian Feldman attrib_to_stat(a, st); 1261e8db6e2SBrian Feldman 1271e8db6e2SBrian Feldman return(0); 1281e8db6e2SBrian Feldman } 1291e8db6e2SBrian Feldman 1301e8db6e2SBrian Feldman int 131ae1f160dSDag-Erling Smørgrav remote_glob(struct sftp_conn *conn, const char *pattern, int flags, 1321e8db6e2SBrian Feldman int (*errfunc)(const char *, int), glob_t *pglob) 1331e8db6e2SBrian Feldman { 134ae1f160dSDag-Erling Smørgrav pglob->gl_opendir = fudge_opendir; 135ae1f160dSDag-Erling Smørgrav pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir; 136ae1f160dSDag-Erling Smørgrav pglob->gl_closedir = (void (*)(void *))fudge_closedir; 1371e8db6e2SBrian Feldman pglob->gl_lstat = fudge_lstat; 1381e8db6e2SBrian Feldman pglob->gl_stat = fudge_stat; 1391e8db6e2SBrian Feldman 1401e8db6e2SBrian Feldman memset(&cur, 0, sizeof(cur)); 141ae1f160dSDag-Erling Smørgrav cur.conn = conn; 1421e8db6e2SBrian Feldman 143ae1f160dSDag-Erling Smørgrav return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob)); 1441e8db6e2SBrian Feldman } 145