diff options
Diffstat (limited to 'Build/source/libs/zziplib/zziplib-0.13.58/zzip/dir.c')
-rw-r--r-- | Build/source/libs/zziplib/zziplib-0.13.58/zzip/dir.c | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/Build/source/libs/zziplib/zziplib-0.13.58/zzip/dir.c b/Build/source/libs/zziplib/zziplib-0.13.58/zzip/dir.c new file mode 100644 index 00000000000..a84a130486a --- /dev/null +++ b/Build/source/libs/zziplib/zziplib-0.13.58/zzip/dir.c @@ -0,0 +1,296 @@ +/* + * Author: + * Guido Draheim <guidod@gmx.de> + * + * Copyright (c) 1999,2000,2001,2002,2003 Guido Draheim + * All rights reserved, + * use under the restrictions of the + * Lesser GNU General Public License + * or alternatively the restrictions + * of the Mozilla Public License 1.1 + */ + +#include <zzip/lib.h> /* exported... */ +#include <zzip/file.h> +#include <stddef.h> /*offsetof*/ +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#ifdef ZZIP_HAVE_SYS_STAT_H +#include <sys/stat.h> +#else +#include <stdio.h> +#endif + +#include <zzip/__dirent.h> + +#ifndef offsetof +#pragma warning had to DEFINE offsetof as it was not in stddef.h +#define offsetof(T,M) ((unsigned)(& ((T*)0)->M)) +#endif + +#ifdef ZZIP_HAVE_SYS_STAT_H +/* MSVC does have IFbitmask but not the corresponding IStests */ +# if !defined S_ISDIR && defined S_IFDIR +# define S_ISDIR(_X_) ((_X_) & S_IFDIR) +# endif +# if !defined S_ISREG && defined S_IFREG +# define S_ISREG(_X_) ((_X_) & S_IFREG) +# endif +#endif + +/** + * This function is the equivalent of a => rewinddir(2) for a realdir or + * the zipfile in place of a directory. The ZZIP_DIR handle returned from + * => zzip_opendir has a flag saying realdir or zipfile. As for a zipfile, + * the filenames will include the filesubpath, so take care. + */ +void +zzip_rewinddir(ZZIP_DIR * dir) +{ + if (! dir) return; + + if (USE_DIRENT && dir->realdir) + { + _zzip_rewinddir(dir->realdir); + return; + } + + if (dir->hdr0) + dir->hdr = dir->hdr0; + else + dir->hdr = 0; +} + +#if ! USE_DIRENT +#define real_readdir(_X_) 1 +#else +static int +real_readdir(ZZIP_DIR* dir) +{ + struct stat st = { 0 }; + char filename[PATH_MAX]; + struct dirent* dirent = _zzip_readdir(dir->realdir); + if (! dirent) return 0; + + dir->dirent.d_name = dirent->d_name; + strcpy(filename, dir->realname); + strcat(filename, "/"); + strcat(filename, dirent->d_name); + + if (stat(filename, &st) == -1) + return -1; + + dir->dirent.d_csize = dir->dirent.st_size = st.st_size; + + if (st.st_mode) + { + if (! S_ISREG(st.st_mode)) + { + dir->dirent.d_compr = st.st_mode; + dir->dirent.d_compr |= 0x80000000; + /* makes it effectively negative, + * but can still be fed to S_ISXXX(x) */ + }else + { + dir->dirent.d_compr = 0; /* stored */ + } + }else + { + dir->dirent.d_compr = 0; /* stored */ + } + + return 1; +} +#endif + +/** + * This function is the equivalent of a => readdir(2) for a realdir + * or a zipfile referenced by the ZZIP_DIR returned from => zzip_opendir. + * + * The ZZIP_DIR handle (as returned by => zzip_opendir) contains a few more + * entries than being copied into the ZZIP_DIRENT. The only valid fields in + * a ZZIP_DIRENT are d_name (the file name), d_compr (compression), d_csize + * (compressed size), st_size (uncompressed size). + */ +ZZIP_DIRENT* +zzip_readdir(ZZIP_DIR * dir) +{ + if (! dir) { errno=EBADF; return 0; } + + if (USE_DIRENT && dir->realdir) + { + if (! real_readdir(dir)) + return 0; + }else + { + if (! dir->hdr) return 0; + + dir->dirent.d_name = dir->hdr->d_name; + dir->dirent.d_compr = dir->hdr->d_compr; + + dir->dirent.d_csize = dir->hdr->d_csize; + dir->dirent.st_size = dir->hdr->d_usize; + + if (! dir->hdr->d_reclen) dir->hdr = 0; + else dir->hdr = (struct zzip_dir_hdr *) + ((char *)dir->hdr + dir->hdr->d_reclen); + } + return &dir->dirent; +} + +/** => zzip_rewinddir + * This function is the equivalent of => telldir(2) for a realdir or zipfile. + */ +zzip_off_t +zzip_telldir(ZZIP_DIR* dir) +{ + if (! dir) { errno=EBADF; return -1; } + + if (USE_DIRENT && dir->realdir) + { + return _zzip_telldir(dir->realdir); + }else + { + return ((zzip_off_t) ((char*) dir->hdr - (char*) dir->hdr0)); + } +} + +/** => zzip_rewinddir + * This function is the equivalent of => seekdir(2) for a realdir or zipfile. + */ +void +zzip_seekdir(ZZIP_DIR* dir, zzip_off_t offset) +{ + if (! dir) return; + + if (USE_DIRENT && dir->realdir) + { + _zzip_seekdir(dir->realdir, offset); + }else + { + dir->hdr = (struct zzip_dir_hdr*) + (dir->hdr0 ? (char*) dir->hdr0 + (size_t) offset : 0); + } +} + +#if defined ZZIP_LARGEFILE_RENAME && defined EOVERFLOW && defined PIC +#undef zzip_seekdir /* zzip_seekdir64 */ +#undef zzip_telldir /* zzip_telldir64 */ + +long zzip_telldir(ZZIP_DIR* dir); +void zzip_seekdir(ZZIP_DIR* dir, long offset); + +/* DLL compatibility layer - so that 32bit code can link with this lib too */ + +long zzip_telldir(ZZIP_DIR* dir) +{ + off_t off = zzip_telldir64 (dir); + long offs = off; + if (offs != off) { errno = EOVERFLOW; return -1; } + return offs; +} + +void zzip_seekdir(ZZIP_DIR* dir, long offset) +{ + zzip_seekdir64 (dir, offset); +} +#endif + +/** + * This function is the equivalent of => opendir(3) for a realdir or zipfile. + * + * This function has some magic - if the given argument-path + * is a directory, it will wrap a real => opendir(3) into the ZZIP_DIR + * structure. Otherwise it will divert to => zzip_dir_open which + * can also attach a ".zip" extension if needed to find the archive. + * + * the error-code is mapped to => errno(3). + */ +ZZIP_DIR* +zzip_opendir(zzip_char_t* filename) +{ + return zzip_opendir_ext_io (filename, 0, 0, 0); +} + +/** => zzip_opendir + * This function uses explicit ext and io instead of the internal + * defaults, setting them to zero is equivalent to => zzip_opendir + */ +ZZIP_DIR* +zzip_opendir_ext_io(zzip_char_t* filename, int o_modes, + zzip_strings_t* ext, zzip_plugin_io_t io) +{ + zzip_error_t e; + ZZIP_DIR* dir; + +# ifdef ZZIP_HAVE_SYS_STAT_H + struct stat st; +# endif + + if (o_modes & (ZZIP_PREFERZIP|ZZIP_ONLYZIP)) goto try_zzip; + try_real: + +# ifdef ZZIP_HAVE_SYS_STAT_H + if (stat(filename, &st) >= 0 && S_ISDIR(st.st_mode) + ){ + if (USE_DIRENT) + { + _zzip_DIR* realdir = _zzip_opendir(filename); + if (realdir) + { + if (! (dir = (ZZIP_DIR *)calloc(1, sizeof (*dir)))) + { + _zzip_closedir(realdir); + return 0; + }else + { + dir->realdir = realdir; + dir->realname = strdup(filename); + return dir; + } + } + } + return 0; + } +# endif /* HAVE_SYS_STAT_H */ + + try_zzip: + dir = zzip_dir_open_ext_io (filename, &e, ext, io); + if (! dir && (o_modes & ZZIP_PREFERZIP)) goto try_real; + if (e) errno = zzip_errno(e); + return dir; +} + +/** + * This function is the equivalent of => closedir(3) for a realdir or zipfile. + * + * This function is magic - if the given arg-ZZIP_DIR + * is a real directory, it will call the real => closedir(3) and then + * free the wrapping ZZIP_DIR structure. Otherwise it will divert + * to => zzip_dir_close which will free the ZZIP_DIR structure. + */ +int +zzip_closedir(ZZIP_DIR* dir) +{ + if (! dir) { errno = EBADF; return -1; } + + if (USE_DIRENT && dir->realdir) + { + _zzip_closedir(dir->realdir); + free(dir->realname); + free(dir); + return 0; + }else + { + zzip_dir_close(dir); + return 0; + } +} + +/* + * Local variables: + * c-file-style: "stroustrup" + * End: + */ |