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