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