xref: /dragonfly/crypto/openssh/sftp-glob.c (revision ee116499)
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