xref: /openssh-portable/sftp-glob.c (revision 72687c8e)
1*72687c8eSderaadt@openbsd.org /* $OpenBSD: sftp-glob.c,v 1.29 2019/11/13 04:47:52 deraadt Exp $ */
24870afd7SDamien Miller /*
34e60ed74SDamien Miller  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
44870afd7SDamien Miller  *
54e60ed74SDamien Miller  * Permission to use, copy, modify, and distribute this software for any
64e60ed74SDamien Miller  * purpose with or without fee is hereby granted, provided that the above
74e60ed74SDamien Miller  * copyright notice and this permission notice appear in all copies.
84870afd7SDamien Miller  *
94e60ed74SDamien Miller  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
104e60ed74SDamien Miller  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
114e60ed74SDamien Miller  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
124e60ed74SDamien Miller  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
134e60ed74SDamien Miller  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
144e60ed74SDamien Miller  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
154e60ed74SDamien Miller  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
164870afd7SDamien Miller  */
174870afd7SDamien Miller 
184870afd7SDamien Miller #include "includes.h"
19f17883e6SDamien Miller 
20f17883e6SDamien Miller #include <sys/types.h>
21f17883e6SDamien Miller #ifdef HAVE_SYS_STAT_H
22f17883e6SDamien Miller # include <sys/stat.h>
23f17883e6SDamien Miller #endif
2488f254b9SDamien Miller 
2588f254b9SDamien Miller #include <dirent.h>
260600c702SDamien Miller #include <stdlib.h>
27e3476ed0SDamien Miller #include <string.h>
28*72687c8eSderaadt@openbsd.org #include <stdarg.h>
294870afd7SDamien Miller 
304870afd7SDamien Miller #include "xmalloc.h"
314870afd7SDamien Miller #include "sftp.h"
324870afd7SDamien Miller #include "sftp-common.h"
334870afd7SDamien Miller #include "sftp-client.h"
34d7d46bb6SDamien Miller 
35d7d46bb6SDamien Miller int remote_glob(struct sftp_conn *, const char *, int,
36d7d46bb6SDamien Miller     int (*)(const char *, int), glob_t *);
374870afd7SDamien Miller 
384870afd7SDamien Miller struct SFTP_OPENDIR {
394870afd7SDamien Miller 	SFTP_DIRENT **dir;
404870afd7SDamien Miller 	int offset;
414870afd7SDamien Miller };
424870afd7SDamien Miller 
434870afd7SDamien Miller static struct {
443db5f530SDamien Miller 	struct sftp_conn *conn;
454870afd7SDamien Miller } cur;
464870afd7SDamien Miller 
47bba81213SBen Lindstrom static void *
fudge_opendir(const char * path)48bba81213SBen Lindstrom fudge_opendir(const char *path)
494870afd7SDamien Miller {
504870afd7SDamien Miller 	struct SFTP_OPENDIR *r;
514870afd7SDamien Miller 
526c81fee6SDamien Miller 	r = xcalloc(1, sizeof(*r));
534870afd7SDamien Miller 
54c51b924aSBen Lindstrom 	if (do_readdir(cur.conn, (char *)path, &r->dir)) {
55a627d42eSDarren Tucker 		free(r);
564870afd7SDamien Miller 		return(NULL);
57c51b924aSBen Lindstrom 	}
584870afd7SDamien Miller 
594870afd7SDamien Miller 	r->offset = 0;
604870afd7SDamien Miller 
614870afd7SDamien Miller 	return((void *)r);
624870afd7SDamien Miller }
634870afd7SDamien Miller 
64bba81213SBen Lindstrom static struct dirent *
fudge_readdir(struct SFTP_OPENDIR * od)65bba81213SBen Lindstrom fudge_readdir(struct SFTP_OPENDIR *od)
664870afd7SDamien Miller {
6718bb473eSDamien Miller 	/* Solaris needs sizeof(dirent) + path length (see below) */
6818bb473eSDamien Miller 	static char buf[sizeof(struct dirent) + MAXPATHLEN];
6918bb473eSDamien Miller 	struct dirent *ret = (struct dirent *)buf;
704870afd7SDamien Miller #ifdef __GNU_LIBRARY__
714870afd7SDamien Miller 	static int inum = 1;
724870afd7SDamien Miller #endif /* __GNU_LIBRARY__ */
734870afd7SDamien Miller 
744870afd7SDamien Miller 	if (od->dir[od->offset] == NULL)
754870afd7SDamien Miller 		return(NULL);
764870afd7SDamien Miller 
7718bb473eSDamien Miller 	memset(buf, 0, sizeof(buf));
784870afd7SDamien Miller 
7918bb473eSDamien Miller 	/*
8018bb473eSDamien Miller 	 * Solaris defines dirent->d_name as a one byte array and expects
8118bb473eSDamien Miller 	 * you to hack around it.
8218bb473eSDamien Miller 	 */
8318bb473eSDamien Miller #ifdef BROKEN_ONE_BYTE_DIRENT_D_NAME
8418bb473eSDamien Miller 	strlcpy(ret->d_name, od->dir[od->offset++]->filename, MAXPATHLEN);
8518bb473eSDamien Miller #else
8618bb473eSDamien Miller 	strlcpy(ret->d_name, od->dir[od->offset++]->filename,
8718bb473eSDamien Miller 	    sizeof(ret->d_name));
8818bb473eSDamien Miller #endif
894870afd7SDamien Miller #ifdef __GNU_LIBRARY__
904870afd7SDamien Miller 	/*
914870afd7SDamien Miller 	 * Idiot glibc uses extensions to struct dirent for readdir with
924870afd7SDamien Miller 	 * ALTDIRFUNCs. Not that this is documented anywhere but the
934870afd7SDamien Miller 	 * source... Fake an inode number to appease it.
944870afd7SDamien Miller 	 */
9518bb473eSDamien Miller 	ret->d_ino = inum++;
964870afd7SDamien Miller 	if (!inum)
974870afd7SDamien Miller 		inum = 1;
984870afd7SDamien Miller #endif /* __GNU_LIBRARY__ */
994870afd7SDamien Miller 
10018bb473eSDamien Miller 	return(ret);
1014870afd7SDamien Miller }
1024870afd7SDamien Miller 
103bba81213SBen Lindstrom static void
fudge_closedir(struct SFTP_OPENDIR * od)104bba81213SBen Lindstrom fudge_closedir(struct SFTP_OPENDIR *od)
1054870afd7SDamien Miller {
1064870afd7SDamien Miller 	free_sftp_dirents(od->dir);
107a627d42eSDarren Tucker 	free(od);
1084870afd7SDamien Miller }
1094870afd7SDamien Miller 
110bba81213SBen Lindstrom static int
fudge_lstat(const char * path,struct stat * st)111bba81213SBen Lindstrom fudge_lstat(const char *path, struct stat *st)
1124870afd7SDamien Miller {
1134870afd7SDamien Miller 	Attrib *a;
1144870afd7SDamien Miller 
115d3e6990cSDamien Miller 	if (!(a = do_lstat(cur.conn, (char *)path, 1)))
1164870afd7SDamien Miller 		return(-1);
1174870afd7SDamien Miller 
1184870afd7SDamien Miller 	attrib_to_stat(a, st);
1194870afd7SDamien Miller 
1204870afd7SDamien Miller 	return(0);
1214870afd7SDamien Miller }
1224870afd7SDamien Miller 
123bba81213SBen Lindstrom static int
fudge_stat(const char * path,struct stat * st)124bba81213SBen Lindstrom fudge_stat(const char *path, struct stat *st)
1254870afd7SDamien Miller {
1264870afd7SDamien Miller 	Attrib *a;
1274870afd7SDamien Miller 
128d3e6990cSDamien Miller 	if (!(a = do_stat(cur.conn, (char *)path, 1)))
1294870afd7SDamien Miller 		return(-1);
1304870afd7SDamien Miller 
1314870afd7SDamien Miller 	attrib_to_stat(a, st);
1324870afd7SDamien Miller 
1334870afd7SDamien Miller 	return(0);
1344870afd7SDamien Miller }
1354870afd7SDamien Miller 
1364870afd7SDamien Miller int
remote_glob(struct sftp_conn * conn,const char * pattern,int flags,int (* errfunc)(const char *,int),glob_t * pglob)1373db5f530SDamien Miller remote_glob(struct sftp_conn *conn, const char *pattern, int flags,
138206941fdSBen Lindstrom     int (*errfunc)(const char *, int), glob_t *pglob)
1394870afd7SDamien Miller {
140ea12acf3SDamien Miller 	pglob->gl_opendir = fudge_opendir;
141ea12acf3SDamien Miller 	pglob->gl_readdir = (struct dirent *(*)(void *))fudge_readdir;
142ea12acf3SDamien Miller 	pglob->gl_closedir = (void (*)(void *))fudge_closedir;
1434870afd7SDamien Miller 	pglob->gl_lstat = fudge_lstat;
1444870afd7SDamien Miller 	pglob->gl_stat = fudge_stat;
1454870afd7SDamien Miller 
1464870afd7SDamien Miller 	memset(&cur, 0, sizeof(cur));
1473db5f530SDamien Miller 	cur.conn = conn;
1484870afd7SDamien Miller 
1493db5f530SDamien Miller 	return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob));
1504870afd7SDamien Miller }
151