1295367Sdes/* $OpenBSD: sftp-glob.c,v 1.27 2015/01/14 13:54:13 djm Exp $ */ 276259Sgreen/* 3126274Sdes * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 476259Sgreen * 5126274Sdes * Permission to use, copy, modify, and distribute this software for any 6126274Sdes * purpose with or without fee is hereby granted, provided that the above 7126274Sdes * copyright notice and this permission notice appear in all copies. 876259Sgreen * 9126274Sdes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10126274Sdes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11126274Sdes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12126274Sdes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13126274Sdes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14126274Sdes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15126274Sdes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1676259Sgreen */ 1776259Sgreen 1876259Sgreen#include "includes.h" 1976259Sgreen 20162852Sdes#include <sys/types.h> 21162852Sdes#ifdef HAVE_SYS_STAT_H 22162852Sdes# include <sys/stat.h> 23162852Sdes#endif 24162852Sdes 25162852Sdes#include <dirent.h> 26262566Sdes#include <stdlib.h> 27162852Sdes#include <string.h> 28295367Sdes#include <stdlib.h> 29162852Sdes 3076259Sgreen#include "xmalloc.h" 3176259Sgreen#include "sftp.h" 3276259Sgreen#include "sftp-common.h" 3376259Sgreen#include "sftp-client.h" 3476259Sgreen 35126274Sdesint remote_glob(struct sftp_conn *, const char *, int, 36126274Sdes int (*)(const char *, int), glob_t *); 37126274Sdes 3876259Sgreenstruct SFTP_OPENDIR { 3976259Sgreen SFTP_DIRENT **dir; 4076259Sgreen int offset; 4176259Sgreen}; 4276259Sgreen 4376259Sgreenstatic struct { 4492555Sdes struct sftp_conn *conn; 4576259Sgreen} cur; 4676259Sgreen 4792555Sdesstatic void * 4892555Sdesfudge_opendir(const char *path) 4976259Sgreen{ 5076259Sgreen struct SFTP_OPENDIR *r; 5192555Sdes 52258343Sdes r = xcalloc(1, sizeof(*r)); 5392555Sdes 54106121Sdes if (do_readdir(cur.conn, (char *)path, &r->dir)) { 55255767Sdes free(r); 5676259Sgreen return(NULL); 57106121Sdes } 5876259Sgreen 5976259Sgreen r->offset = 0; 6076259Sgreen 61106121Sdes return((void *)r); 6276259Sgreen} 6376259Sgreen 6492555Sdesstatic struct dirent * 6592555Sdesfudge_readdir(struct SFTP_OPENDIR *od) 6676259Sgreen{ 6798937Sdes /* Solaris needs sizeof(dirent) + path length (see below) */ 6898937Sdes static char buf[sizeof(struct dirent) + MAXPATHLEN]; 6998937Sdes struct dirent *ret = (struct dirent *)buf; 7098937Sdes#ifdef __GNU_LIBRARY__ 7198937Sdes static int inum = 1; 7298937Sdes#endif /* __GNU_LIBRARY__ */ 73126274Sdes 7476259Sgreen if (od->dir[od->offset] == NULL) 7576259Sgreen return(NULL); 7676259Sgreen 7798937Sdes memset(buf, 0, sizeof(buf)); 7876259Sgreen 7998937Sdes /* 8098937Sdes * Solaris defines dirent->d_name as a one byte array and expects 8198937Sdes * you to hack around it. 8298937Sdes */ 8398937Sdes#ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME 8498937Sdes strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN); 8598937Sdes#else 8698937Sdes strlcpy(ret->d_name, od->dir[od->offset++]->filename, 8798937Sdes sizeof(ret->d_name)); 8898937Sdes#endif 8998937Sdes#ifdef __GNU_LIBRARY__ 9098937Sdes /* 9198937Sdes * Idiot glibc uses extensions to struct dirent for readdir with 92126274Sdes * ALTDIRFUNCs. Not that this is documented anywhere but the 9398937Sdes * source... Fake an inode number to appease it. 9498937Sdes */ 9598937Sdes ret->d_ino = inum++; 9698937Sdes if (!inum) 9798937Sdes inum = 1; 9898937Sdes#endif /* __GNU_LIBRARY__ */ 9998937Sdes 10098937Sdes return(ret); 10176259Sgreen} 10276259Sgreen 10392555Sdesstatic void 10492555Sdesfudge_closedir(struct SFTP_OPENDIR *od) 10576259Sgreen{ 10676259Sgreen free_sftp_dirents(od->dir); 107255767Sdes free(od); 10876259Sgreen} 10976259Sgreen 11092555Sdesstatic int 11192555Sdesfudge_lstat(const char *path, struct stat *st) 11276259Sgreen{ 11376259Sgreen Attrib *a; 11492555Sdes 115240075Sdes if (!(a = do_lstat(cur.conn, (char *)path, 1))) 11676259Sgreen return(-1); 11792555Sdes 11876259Sgreen attrib_to_stat(a, st); 11992555Sdes 12076259Sgreen return(0); 12176259Sgreen} 12276259Sgreen 12392555Sdesstatic int 12492555Sdesfudge_stat(const char *path, struct stat *st) 12576259Sgreen{ 12676259Sgreen Attrib *a; 12792555Sdes 128240075Sdes if (!(a = do_stat(cur.conn, (char *)path, 1))) 12976259Sgreen return(-1); 13092555Sdes 13176259Sgreen attrib_to_stat(a, st); 13292555Sdes 13376259Sgreen return(0); 13476259Sgreen} 13576259Sgreen 13676259Sgreenint 13792555Sdesremote_glob(struct sftp_conn *conn, const char *pattern, int flags, 13876259Sgreen int (*errfunc)(const char *, int), glob_t *pglob) 13976259Sgreen{ 14092555Sdes pglob->gl_opendir = fudge_opendir; 14192555Sdes pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir; 14292555Sdes pglob->gl_closedir = (void (*)(void *))fudge_closedir; 14376259Sgreen pglob->gl_lstat = fudge_lstat; 14476259Sgreen pglob->gl_stat = fudge_stat; 14592555Sdes 14676259Sgreen memset(&cur, 0, sizeof(cur)); 14792555Sdes cur.conn = conn; 14876259Sgreen 14992555Sdes return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob)); 15076259Sgreen} 151