1*f7167e0eSDag-Erling Smørgrav /* $OpenBSD: sftp-glob.c,v 1.26 2013/11/08 11:15:19 dtucker Exp $ */ 21e8db6e2SBrian Feldman /* 3efcad6b7SDag-Erling Smørgrav * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 41e8db6e2SBrian Feldman * 5efcad6b7SDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 6efcad6b7SDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 7efcad6b7SDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 81e8db6e2SBrian Feldman * 9efcad6b7SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10efcad6b7SDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11efcad6b7SDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12efcad6b7SDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13efcad6b7SDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14efcad6b7SDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15efcad6b7SDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 161e8db6e2SBrian Feldman */ 171e8db6e2SBrian Feldman 181e8db6e2SBrian Feldman #include "includes.h" 191e8db6e2SBrian Feldman 20761efaa7SDag-Erling Smørgrav #include <sys/types.h> 21761efaa7SDag-Erling Smørgrav #ifdef HAVE_SYS_STAT_H 22761efaa7SDag-Erling Smørgrav # include <sys/stat.h> 23761efaa7SDag-Erling Smørgrav #endif 24761efaa7SDag-Erling Smørgrav 25761efaa7SDag-Erling Smørgrav #include <dirent.h> 26*f7167e0eSDag-Erling Smørgrav #include <stdlib.h> 27761efaa7SDag-Erling Smørgrav #include <string.h> 28761efaa7SDag-Erling Smørgrav 291e8db6e2SBrian Feldman #include "xmalloc.h" 301e8db6e2SBrian Feldman #include "sftp.h" 31761efaa7SDag-Erling Smørgrav #include "buffer.h" 321e8db6e2SBrian Feldman #include "sftp-common.h" 331e8db6e2SBrian Feldman #include "sftp-client.h" 34efcad6b7SDag-Erling Smørgrav 35efcad6b7SDag-Erling Smørgrav int remote_glob(struct sftp_conn *, const char *, int, 36efcad6b7SDag-Erling Smørgrav int (*)(const char *, int), glob_t *); 371e8db6e2SBrian Feldman 381e8db6e2SBrian Feldman struct SFTP_OPENDIR { 391e8db6e2SBrian Feldman SFTP_DIRENT **dir; 401e8db6e2SBrian Feldman int offset; 411e8db6e2SBrian Feldman }; 421e8db6e2SBrian Feldman 431e8db6e2SBrian Feldman static struct { 44ae1f160dSDag-Erling Smørgrav struct sftp_conn *conn; 451e8db6e2SBrian Feldman } cur; 461e8db6e2SBrian Feldman 47ae1f160dSDag-Erling Smørgrav static void * 48ae1f160dSDag-Erling Smørgrav fudge_opendir(const char *path) 491e8db6e2SBrian Feldman { 501e8db6e2SBrian Feldman struct SFTP_OPENDIR *r; 511e8db6e2SBrian Feldman 520a37d4a3SXin LI r = xcalloc(1, sizeof(*r)); 531e8db6e2SBrian Feldman 544b17dab0SDag-Erling Smørgrav if (do_readdir(cur.conn, (char *)path, &r->dir)) { 55e4a9863fSDag-Erling Smørgrav free(r); 561e8db6e2SBrian Feldman return(NULL); 574b17dab0SDag-Erling Smørgrav } 581e8db6e2SBrian Feldman 591e8db6e2SBrian Feldman r->offset = 0; 601e8db6e2SBrian Feldman 611e8db6e2SBrian Feldman return((void *)r); 621e8db6e2SBrian Feldman } 631e8db6e2SBrian Feldman 64ae1f160dSDag-Erling Smørgrav static struct dirent * 65ae1f160dSDag-Erling Smørgrav fudge_readdir(struct SFTP_OPENDIR *od) 661e8db6e2SBrian Feldman { 6783d2307dSDag-Erling Smørgrav /* Solaris needs sizeof(dirent) + path length (see below) */ 6883d2307dSDag-Erling Smørgrav static char buf[sizeof(struct dirent) + MAXPATHLEN]; 6983d2307dSDag-Erling Smørgrav struct dirent *ret = (struct dirent *)buf; 7083d2307dSDag-Erling Smørgrav #ifdef __GNU_LIBRARY__ 7183d2307dSDag-Erling Smørgrav static int inum = 1; 7283d2307dSDag-Erling Smørgrav #endif /* __GNU_LIBRARY__ */ 731e8db6e2SBrian Feldman 741e8db6e2SBrian Feldman if (od->dir[od->offset] == NULL) 751e8db6e2SBrian Feldman return(NULL); 761e8db6e2SBrian Feldman 7783d2307dSDag-Erling Smørgrav memset(buf, 0, sizeof(buf)); 781e8db6e2SBrian Feldman 7983d2307dSDag-Erling Smørgrav /* 8083d2307dSDag-Erling Smørgrav * Solaris defines dirent->d_name as a one byte array and expects 8183d2307dSDag-Erling Smørgrav * you to hack around it. 8283d2307dSDag-Erling Smørgrav */ 8383d2307dSDag-Erling Smørgrav #ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME 8483d2307dSDag-Erling Smørgrav strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN); 8583d2307dSDag-Erling Smørgrav #else 8683d2307dSDag-Erling Smørgrav strlcpy(ret->d_name, od->dir[od->offset++]->filename, 8783d2307dSDag-Erling Smørgrav sizeof(ret->d_name)); 8883d2307dSDag-Erling Smørgrav #endif 8983d2307dSDag-Erling Smørgrav #ifdef __GNU_LIBRARY__ 9083d2307dSDag-Erling Smørgrav /* 9183d2307dSDag-Erling Smørgrav * Idiot glibc uses extensions to struct dirent for readdir with 9283d2307dSDag-Erling Smørgrav * ALTDIRFUNCs. Not that this is documented anywhere but the 9383d2307dSDag-Erling Smørgrav * source... Fake an inode number to appease it. 9483d2307dSDag-Erling Smørgrav */ 9583d2307dSDag-Erling Smørgrav ret->d_ino = inum++; 9683d2307dSDag-Erling Smørgrav if (!inum) 9783d2307dSDag-Erling Smørgrav inum = 1; 9883d2307dSDag-Erling Smørgrav #endif /* __GNU_LIBRARY__ */ 9983d2307dSDag-Erling Smørgrav 10083d2307dSDag-Erling Smørgrav return(ret); 1011e8db6e2SBrian Feldman } 1021e8db6e2SBrian Feldman 103ae1f160dSDag-Erling Smørgrav static void 104ae1f160dSDag-Erling Smørgrav fudge_closedir(struct SFTP_OPENDIR *od) 1051e8db6e2SBrian Feldman { 1061e8db6e2SBrian Feldman free_sftp_dirents(od->dir); 107e4a9863fSDag-Erling Smørgrav free(od); 1081e8db6e2SBrian Feldman } 1091e8db6e2SBrian Feldman 110ae1f160dSDag-Erling Smørgrav static int 111ae1f160dSDag-Erling Smørgrav fudge_lstat(const char *path, struct stat *st) 1121e8db6e2SBrian Feldman { 1131e8db6e2SBrian Feldman Attrib *a; 1141e8db6e2SBrian Feldman 115462c32cbSDag-Erling Smørgrav if (!(a = do_lstat(cur.conn, (char *)path, 1))) 1161e8db6e2SBrian Feldman return(-1); 1171e8db6e2SBrian Feldman 1181e8db6e2SBrian Feldman attrib_to_stat(a, st); 1191e8db6e2SBrian Feldman 1201e8db6e2SBrian Feldman return(0); 1211e8db6e2SBrian Feldman } 1221e8db6e2SBrian Feldman 123ae1f160dSDag-Erling Smørgrav static int 124ae1f160dSDag-Erling Smørgrav fudge_stat(const char *path, struct stat *st) 1251e8db6e2SBrian Feldman { 1261e8db6e2SBrian Feldman Attrib *a; 1271e8db6e2SBrian Feldman 128462c32cbSDag-Erling Smørgrav if (!(a = do_stat(cur.conn, (char *)path, 1))) 1291e8db6e2SBrian Feldman return(-1); 1301e8db6e2SBrian Feldman 1311e8db6e2SBrian Feldman attrib_to_stat(a, st); 1321e8db6e2SBrian Feldman 1331e8db6e2SBrian Feldman return(0); 1341e8db6e2SBrian Feldman } 1351e8db6e2SBrian Feldman 1361e8db6e2SBrian Feldman int 137ae1f160dSDag-Erling Smørgrav remote_glob(struct sftp_conn *conn, const char *pattern, int flags, 1381e8db6e2SBrian Feldman int (*errfunc)(const char *, int), glob_t *pglob) 1391e8db6e2SBrian Feldman { 140ae1f160dSDag-Erling Smørgrav pglob->gl_opendir = fudge_opendir; 141ae1f160dSDag-Erling Smørgrav pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir; 142ae1f160dSDag-Erling Smørgrav pglob->gl_closedir = (void (*)(void *))fudge_closedir; 1431e8db6e2SBrian Feldman pglob->gl_lstat = fudge_lstat; 1441e8db6e2SBrian Feldman pglob->gl_stat = fudge_stat; 1451e8db6e2SBrian Feldman 1461e8db6e2SBrian Feldman memset(&cur, 0, sizeof(cur)); 147ae1f160dSDag-Erling Smørgrav cur.conn = conn; 1481e8db6e2SBrian Feldman 149ae1f160dSDag-Erling Smørgrav return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob)); 1501e8db6e2SBrian Feldman } 151