1*ee116499SAntonio Huete Jimenez /* $OpenBSD: sftp-glob.c,v 1.30 2022/02/25 09:46:24 dtucker Exp $ */
218de8d7fSPeter Avalos /*
318de8d7fSPeter Avalos * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
418de8d7fSPeter Avalos *
518de8d7fSPeter Avalos * Permission to use, copy, modify, and distribute this software for any
618de8d7fSPeter Avalos * purpose with or without fee is hereby granted, provided that the above
718de8d7fSPeter Avalos * copyright notice and this permission notice appear in all copies.
818de8d7fSPeter Avalos *
918de8d7fSPeter Avalos * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1018de8d7fSPeter Avalos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1118de8d7fSPeter Avalos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1218de8d7fSPeter Avalos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1318de8d7fSPeter Avalos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1418de8d7fSPeter Avalos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1518de8d7fSPeter Avalos * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1618de8d7fSPeter Avalos */
1718de8d7fSPeter Avalos
1818de8d7fSPeter Avalos #include "includes.h"
1918de8d7fSPeter Avalos
2018de8d7fSPeter Avalos #include <sys/types.h>
2118de8d7fSPeter Avalos #ifdef HAVE_SYS_STAT_H
2218de8d7fSPeter Avalos # include <sys/stat.h>
2318de8d7fSPeter Avalos #endif
2418de8d7fSPeter Avalos
2518de8d7fSPeter Avalos #include <dirent.h>
2636e94dc5SPeter Avalos #include <stdlib.h>
2718de8d7fSPeter Avalos #include <string.h>
280cbfa66cSDaniel Fojt #include <stdarg.h>
2918de8d7fSPeter Avalos
3018de8d7fSPeter Avalos #include "xmalloc.h"
3118de8d7fSPeter Avalos #include "sftp.h"
3218de8d7fSPeter Avalos #include "sftp-common.h"
3318de8d7fSPeter Avalos #include "sftp-client.h"
3418de8d7fSPeter Avalos
3518de8d7fSPeter Avalos int remote_glob(struct sftp_conn *, const char *, int,
3618de8d7fSPeter Avalos int (*)(const char *, int), glob_t *);
3718de8d7fSPeter Avalos
3818de8d7fSPeter Avalos struct SFTP_OPENDIR {
3918de8d7fSPeter Avalos SFTP_DIRENT **dir;
4018de8d7fSPeter Avalos int offset;
4118de8d7fSPeter Avalos };
4218de8d7fSPeter Avalos
4318de8d7fSPeter Avalos static struct {
4418de8d7fSPeter Avalos struct sftp_conn *conn;
4518de8d7fSPeter Avalos } cur;
4618de8d7fSPeter Avalos
4718de8d7fSPeter Avalos static void *
fudge_opendir(const char * path)4818de8d7fSPeter Avalos fudge_opendir(const char *path)
4918de8d7fSPeter Avalos {
5018de8d7fSPeter Avalos struct SFTP_OPENDIR *r;
5118de8d7fSPeter Avalos
5236e94dc5SPeter Avalos r = xcalloc(1, sizeof(*r));
5318de8d7fSPeter Avalos
54*ee116499SAntonio Huete Jimenez if (do_readdir(cur.conn, path, &r->dir)) {
5536e94dc5SPeter Avalos free(r);
5618de8d7fSPeter Avalos return(NULL);
5718de8d7fSPeter Avalos }
5818de8d7fSPeter Avalos
5918de8d7fSPeter Avalos r->offset = 0;
6018de8d7fSPeter Avalos
6118de8d7fSPeter Avalos return((void *)r);
6218de8d7fSPeter Avalos }
6318de8d7fSPeter Avalos
6418de8d7fSPeter Avalos static struct dirent *
fudge_readdir(struct SFTP_OPENDIR * od)6518de8d7fSPeter Avalos fudge_readdir(struct SFTP_OPENDIR *od)
6618de8d7fSPeter Avalos {
6718de8d7fSPeter Avalos /* Solaris needs sizeof(dirent) + path length (see below) */
6818de8d7fSPeter Avalos static char buf[sizeof(struct dirent) + MAXPATHLEN];
6918de8d7fSPeter Avalos struct dirent *ret = (struct dirent *)buf;
7018de8d7fSPeter Avalos #ifdef __GNU_LIBRARY__
7118de8d7fSPeter Avalos static int inum = 1;
7218de8d7fSPeter Avalos #endif /* __GNU_LIBRARY__ */
7318de8d7fSPeter Avalos
7418de8d7fSPeter Avalos if (od->dir[od->offset] == NULL)
7518de8d7fSPeter Avalos return(NULL);
7618de8d7fSPeter Avalos
7718de8d7fSPeter Avalos memset(buf, 0, sizeof(buf));
7818de8d7fSPeter Avalos
7918de8d7fSPeter Avalos /*
8018de8d7fSPeter Avalos * Solaris defines dirent->d_name as a one byte array and expects
8118de8d7fSPeter Avalos * you to hack around it.
8218de8d7fSPeter Avalos */
8318de8d7fSPeter Avalos #ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME
8418de8d7fSPeter Avalos strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN);
8518de8d7fSPeter Avalos #else
8618de8d7fSPeter Avalos strlcpy(ret->d_name, od->dir[od->offset++]->filename,
8718de8d7fSPeter Avalos sizeof(ret->d_name));
8818de8d7fSPeter Avalos #endif
8918de8d7fSPeter Avalos #ifdef __GNU_LIBRARY__
9018de8d7fSPeter Avalos /*
9118de8d7fSPeter Avalos * Idiot glibc uses extensions to struct dirent for readdir with
9218de8d7fSPeter Avalos * ALTDIRFUNCs. Not that this is documented anywhere but the
9318de8d7fSPeter Avalos * source... Fake an inode number to appease it.
9418de8d7fSPeter Avalos */
9518de8d7fSPeter Avalos ret->d_ino = inum++;
9618de8d7fSPeter Avalos if (!inum)
9718de8d7fSPeter Avalos inum = 1;
9818de8d7fSPeter Avalos #endif /* __GNU_LIBRARY__ */
9918de8d7fSPeter Avalos
10018de8d7fSPeter Avalos return(ret);
10118de8d7fSPeter Avalos }
10218de8d7fSPeter Avalos
10318de8d7fSPeter Avalos static void
fudge_closedir(struct SFTP_OPENDIR * od)10418de8d7fSPeter Avalos fudge_closedir(struct SFTP_OPENDIR *od)
10518de8d7fSPeter Avalos {
10618de8d7fSPeter Avalos free_sftp_dirents(od->dir);
10736e94dc5SPeter Avalos free(od);
10818de8d7fSPeter Avalos }
10918de8d7fSPeter Avalos
11018de8d7fSPeter Avalos static int
fudge_lstat(const char * path,struct stat * st)11118de8d7fSPeter Avalos fudge_lstat(const char *path, struct stat *st)
11218de8d7fSPeter Avalos {
11318de8d7fSPeter Avalos Attrib *a;
11418de8d7fSPeter Avalos
115*ee116499SAntonio Huete Jimenez if (!(a = do_lstat(cur.conn, path, 1)))
11618de8d7fSPeter Avalos return(-1);
11718de8d7fSPeter Avalos
11818de8d7fSPeter Avalos attrib_to_stat(a, st);
11918de8d7fSPeter Avalos
12018de8d7fSPeter Avalos return(0);
12118de8d7fSPeter Avalos }
12218de8d7fSPeter Avalos
12318de8d7fSPeter Avalos static int
fudge_stat(const char * path,struct stat * st)12418de8d7fSPeter Avalos fudge_stat(const char *path, struct stat *st)
12518de8d7fSPeter Avalos {
12618de8d7fSPeter Avalos Attrib *a;
12718de8d7fSPeter Avalos
128*ee116499SAntonio Huete Jimenez if (!(a = do_stat(cur.conn, path, 1)))
12918de8d7fSPeter Avalos return(-1);
13018de8d7fSPeter Avalos
13118de8d7fSPeter Avalos attrib_to_stat(a, st);
13218de8d7fSPeter Avalos
13318de8d7fSPeter Avalos return(0);
13418de8d7fSPeter Avalos }
13518de8d7fSPeter Avalos
13618de8d7fSPeter Avalos int
remote_glob(struct sftp_conn * conn,const char * pattern,int flags,int (* errfunc)(const char *,int),glob_t * pglob)13718de8d7fSPeter Avalos remote_glob(struct sftp_conn *conn, const char *pattern, int flags,
13818de8d7fSPeter Avalos int (*errfunc)(const char *, int), glob_t *pglob)
13918de8d7fSPeter Avalos {
14018de8d7fSPeter Avalos pglob->gl_opendir = fudge_opendir;
14118de8d7fSPeter Avalos pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir;
14218de8d7fSPeter Avalos pglob->gl_closedir = (void (*)(void *))fudge_closedir;
14318de8d7fSPeter Avalos pglob->gl_lstat = fudge_lstat;
14418de8d7fSPeter Avalos pglob->gl_stat = fudge_stat;
14518de8d7fSPeter Avalos
14618de8d7fSPeter Avalos memset(&cur, 0, sizeof(cur));
14718de8d7fSPeter Avalos cur.conn = conn;
14818de8d7fSPeter Avalos
14918de8d7fSPeter Avalos return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob));
15018de8d7fSPeter Avalos }
151