17c478bd9Sstevel@tonic-gate /* 2*90685d2cSjp161948 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 37c478bd9Sstevel@tonic-gate * 4*90685d2cSjp161948 * Permission to use, copy, modify, and distribute this software for any 5*90685d2cSjp161948 * purpose with or without fee is hereby granted, provided that the above 6*90685d2cSjp161948 * copyright notice and this permission notice appear in all copies. 77c478bd9Sstevel@tonic-gate * 8*90685d2cSjp161948 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9*90685d2cSjp161948 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10*90685d2cSjp161948 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11*90685d2cSjp161948 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12*90685d2cSjp161948 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13*90685d2cSjp161948 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14*90685d2cSjp161948 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 157c478bd9Sstevel@tonic-gate */ 167c478bd9Sstevel@tonic-gate 17*90685d2cSjp161948 /* $OpenBSD: sftp-glob.c,v 1.22 2006/08/03 03:34:42 deraadt Exp $ */ 187c478bd9Sstevel@tonic-gate 197c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 207c478bd9Sstevel@tonic-gate 21*90685d2cSjp161948 #include "includes.h" 227c478bd9Sstevel@tonic-gate 23*90685d2cSjp161948 #include <sys/types.h> 24*90685d2cSjp161948 #ifdef HAVE_SYS_STAT_H 25*90685d2cSjp161948 # include <sys/stat.h> 26*90685d2cSjp161948 #endif 27*90685d2cSjp161948 28*90685d2cSjp161948 #include <dirent.h> 29*90685d2cSjp161948 #include <string.h> 30*90685d2cSjp161948 31*90685d2cSjp161948 #include "xmalloc.h" 327c478bd9Sstevel@tonic-gate #include "sftp.h" 33*90685d2cSjp161948 #include "buffer.h" 347c478bd9Sstevel@tonic-gate #include "sftp-common.h" 357c478bd9Sstevel@tonic-gate #include "sftp-client.h" 36*90685d2cSjp161948 37*90685d2cSjp161948 int remote_glob(struct sftp_conn *, const char *, int, 38*90685d2cSjp161948 int (*)(const char *, int), glob_t *); 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate struct SFTP_OPENDIR { 417c478bd9Sstevel@tonic-gate SFTP_DIRENT **dir; 427c478bd9Sstevel@tonic-gate int offset; 437c478bd9Sstevel@tonic-gate }; 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate static struct { 467c478bd9Sstevel@tonic-gate struct sftp_conn *conn; 477c478bd9Sstevel@tonic-gate } cur; 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate static void * 507c478bd9Sstevel@tonic-gate fudge_opendir(const char *path) 517c478bd9Sstevel@tonic-gate { 527c478bd9Sstevel@tonic-gate struct SFTP_OPENDIR *r; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate r = xmalloc(sizeof(*r)); 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate if (do_readdir(cur.conn, (char *)path, &r->dir)) { 577c478bd9Sstevel@tonic-gate xfree(r); 587c478bd9Sstevel@tonic-gate return(NULL); 597c478bd9Sstevel@tonic-gate } 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate r->offset = 0; 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate return((void *)r); 647c478bd9Sstevel@tonic-gate } 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate static struct dirent * 677c478bd9Sstevel@tonic-gate fudge_readdir(struct SFTP_OPENDIR *od) 687c478bd9Sstevel@tonic-gate { 697c478bd9Sstevel@tonic-gate /* Solaris needs sizeof(dirent) + path length (see below) */ 707c478bd9Sstevel@tonic-gate static union { 717c478bd9Sstevel@tonic-gate char buf_chars[sizeof (struct dirent) + MAXPATHLEN]; 727c478bd9Sstevel@tonic-gate struct dirent buf_dirent; 737c478bd9Sstevel@tonic-gate } buf; 747c478bd9Sstevel@tonic-gate struct dirent *ret = &buf.buf_dirent; 757c478bd9Sstevel@tonic-gate #ifdef __GNU_LIBRARY__ 767c478bd9Sstevel@tonic-gate static int inum = 1; 777c478bd9Sstevel@tonic-gate #endif /* __GNU_LIBRARY__ */ 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate if (od->dir[od->offset] == NULL) 807c478bd9Sstevel@tonic-gate return(NULL); 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate memset(buf.buf_chars, 0, sizeof (buf.buf_chars)); 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* 857c478bd9Sstevel@tonic-gate * Solaris defines dirent->d_name as a one byte array and expects 867c478bd9Sstevel@tonic-gate * you to hack around it. 877c478bd9Sstevel@tonic-gate */ 887c478bd9Sstevel@tonic-gate #ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME 897c478bd9Sstevel@tonic-gate strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN); 907c478bd9Sstevel@tonic-gate #else 917c478bd9Sstevel@tonic-gate strlcpy(ret->d_name, od->dir[od->offset++]->filename, 927c478bd9Sstevel@tonic-gate sizeof(ret->d_name)); 937c478bd9Sstevel@tonic-gate #endif 947c478bd9Sstevel@tonic-gate #ifdef __GNU_LIBRARY__ 957c478bd9Sstevel@tonic-gate /* 967c478bd9Sstevel@tonic-gate * Idiot glibc uses extensions to struct dirent for readdir with 977c478bd9Sstevel@tonic-gate * ALTDIRFUNCs. Not that this is documented anywhere but the 987c478bd9Sstevel@tonic-gate * source... Fake an inode number to appease it. 997c478bd9Sstevel@tonic-gate */ 1007c478bd9Sstevel@tonic-gate ret->d_ino = inum++; 1017c478bd9Sstevel@tonic-gate if (!inum) 1027c478bd9Sstevel@tonic-gate inum = 1; 1037c478bd9Sstevel@tonic-gate #endif /* __GNU_LIBRARY__ */ 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate return(ret); 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate static void 1097c478bd9Sstevel@tonic-gate fudge_closedir(struct SFTP_OPENDIR *od) 1107c478bd9Sstevel@tonic-gate { 1117c478bd9Sstevel@tonic-gate free_sftp_dirents(od->dir); 1127c478bd9Sstevel@tonic-gate xfree(od); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate static int 1167c478bd9Sstevel@tonic-gate fudge_lstat(const char *path, struct stat *st) 1177c478bd9Sstevel@tonic-gate { 1187c478bd9Sstevel@tonic-gate Attrib *a; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate if (!(a = do_lstat(cur.conn, (char *)path, 0))) 1217c478bd9Sstevel@tonic-gate return(-1); 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate attrib_to_stat(a, st); 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate return(0); 1267c478bd9Sstevel@tonic-gate } 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate static int 1297c478bd9Sstevel@tonic-gate fudge_stat(const char *path, struct stat *st) 1307c478bd9Sstevel@tonic-gate { 1317c478bd9Sstevel@tonic-gate Attrib *a; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate if (!(a = do_stat(cur.conn, (char *)path, 0))) 1347c478bd9Sstevel@tonic-gate return(-1); 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate attrib_to_stat(a, st); 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate return(0); 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate int 1427c478bd9Sstevel@tonic-gate remote_glob(struct sftp_conn *conn, const char *pattern, int flags, 1437c478bd9Sstevel@tonic-gate int (*errfunc)(const char *, int), glob_t *pglob) 1447c478bd9Sstevel@tonic-gate { 1457c478bd9Sstevel@tonic-gate pglob->gl_opendir = fudge_opendir; 1467c478bd9Sstevel@tonic-gate pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir; 1477c478bd9Sstevel@tonic-gate pglob->gl_closedir = (void (*)(void *))fudge_closedir; 1487c478bd9Sstevel@tonic-gate pglob->gl_lstat = fudge_lstat; 1497c478bd9Sstevel@tonic-gate pglob->gl_stat = fudge_stat; 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate memset(&cur, 0, sizeof(cur)); 1527c478bd9Sstevel@tonic-gate cur.conn = conn; 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob)); 1557c478bd9Sstevel@tonic-gate } 156