diff options
Diffstat (limited to 'package/heirloom-cpio/src/getdir.c')
-rw-r--r-- | package/heirloom-cpio/src/getdir.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/package/heirloom-cpio/src/getdir.c b/package/heirloom-cpio/src/getdir.c new file mode 100644 index 000000000..245b7641e --- /dev/null +++ b/package/heirloom-cpio/src/getdir.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2003 Gunnar Ritter + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute + * it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source distribution. + */ +/* Sccsid @(#)getdir.c 1.20 (gritter) 5/14/06 */ + +#ifndef __linux__ +/* + * 32-bit Solaris and Open UNIX do not have 64-bit getdents(); but + * having _FILE_OFFSET_BITS=64 will make it use a dirent64 struct + * on Open UNIX -> SEGV. + */ +#undef _FILE_OFFSET_BITS +#endif /* !__linux__ */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <errno.h> +#include <string.h> + +#if defined (__UCLIBC__) +#include <linux/types.h> +#include <linux/dirent.h> +#define getdents(a, b, c) __getdents64(a, b, c) +#define dirent dirent64 +extern int getdents(int, struct dirent *, size_t); +#elif defined (__GLIBC__) || defined (__FreeBSD__) || defined (_AIX) || \ + defined (__NetBSD__) || defined (__OpenBSD__) || \ + defined (__DragonFly__) || defined (__APPLE__) +#include <dirent.h> +#define getdents(a, b, c) getdirentries((a), (char *)(b), (c), &(db->g_offs)) +#if defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) || \ + defined (__DragonFly__) || defined (__APPLE__) +#undef d_ino +#endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ + || __APPLE__ */ +#elif defined (__dietlibc__) +#include <dirent.h> +#include <unistd.h> +#else /* !__GLIBC__, !__dietlibc__ */ +#ifdef __hpux +#define _KERNEL +#endif /* __hpux */ +#include <sys/dirent.h> +#ifdef __hpux +#ifndef _INO64_T +typedef unsigned long long uint64_t; +typedef uint64_t ino64_t; +#endif /* !_INO64_T */ +#ifdef __LP64__ +#define dirent __dirent64 +#else /* !__LP64__ */ +#define dirent __dirent32 +#endif /* !__LP64__ */ +#define d_reclen __d_reclen +#define d_name __d_name +#define d_ino __d_ino +#endif /* __hpux */ +#endif /* !__GLIBC__, !__dietlibc__ */ + +#include "getdir.h" + +#define DIBSIZE 5120 + +struct getdb { +#if !defined (__FreeBSD__) && !defined (__NetBSD__) && !defined (__OpenBSD__) \ + && !defined (__DragonFly__) && !defined (__APPLE__) + off_t g_offs; +#else /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */ + long g_offs; +#endif /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */ + struct dirent *g_dirp; + const char *g_path; + struct direc g_dic; + union { + char g_dirbuf[DIBSIZE+1]; + struct dirent g_dummy[1]; + } g_u; + int g_num; + int g_fd; +}; + +struct getdb * +getdb_alloc(const char *path, int fd) +{ + struct getdb *db; + + if ((db = malloc(sizeof *db)) == NULL) + return NULL; + db->g_dirp = NULL; + db->g_offs = 0; + db->g_fd = fd; + db->g_path = path; + return db; +} + +void +getdb_free(struct getdb *db) +{ + free(db); +} + +struct direc * +getdir(struct getdb *db, int *err) +{ + int reclen; + + *err = 0; + while (db->g_dirp == NULL) + { + /*LINTED*/ + db->g_num = getdents(db->g_fd, + (struct dirent *)db->g_u.g_dirbuf, + DIBSIZE); + if (db->g_num <= 0) { + if (db->g_num < 0) + *err = errno; + db->g_offs = 0; + return NULL; + } + /*LINTED*/ + db->g_dirp = (struct dirent *)db->g_u.g_dirbuf; + while (db->g_dirp && +#if !defined (__FreeBSD__) && !defined (__NetBSD__) && !defined (__OpenBSD__) \ + && !defined (__DragonFly__) && !defined (__APPLE__) + db->g_dirp->d_ino == 0 +#else /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */ + (db->g_dirp->d_fileno == 0 +#ifdef DT_WHT + || db->g_dirp->d_type == DT_WHT +#endif + ) +#endif /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */ + ) + { + next: +#ifndef __DragonFly__ + reclen = db->g_dirp->d_reclen; +#else + reclen = _DIRENT_DIRSIZ(db->g_dirp); +#endif + if ((db->g_num -= reclen) == 0 || reclen == 0) + db->g_dirp = NULL; + else + db->g_dirp = + /*LINTED*/ + (struct dirent *)((char *)db->g_dirp + + reclen); + } + } +#if !defined (__FreeBSD__) && !defined (__NetBSD__) && !defined (__OpenBSD__) \ + && !defined (__DragonFly__) && !defined (__APPLE__) + if (db->g_dirp->d_ino == 0) + goto next; + db->g_dic.d_ino = db->g_dirp->d_ino; +#else /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */ + if (db->g_dirp->d_fileno == 0 +#ifdef DT_WHT + || db->g_dirp->d_type == DT_WHT +#endif + ) + { + goto next; + } + db->g_dic.d_ino = db->g_dirp->d_fileno; +#endif /* __FreeBSD__, __NetBSD__, __OpenBSD__, __DragonFly__, __APPLE__ */ + db->g_dic.d_name = db->g_dirp->d_name; +#ifndef __DragonFly__ + reclen = db->g_dirp->d_reclen; +#else + reclen = _DIRENT_DIRSIZ(db->g_dirp); +#endif + if ((db->g_num -= reclen) == 0 || reclen == 0) + db->g_dirp = NULL; + else + /*LINTED*/ + db->g_dirp = (struct dirent *)((char *)db->g_dirp + reclen); + return &(db->g_dic); +} |