#if HAVE_CONFIG_H
#include "clamav-config.h"
#endif
#include <zzip.h>
#include <zzip-file.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifdef ZZIP_HAVE_SYS_STAT_H
#include <sys/stat.h>
#else
#include <stdio.h>
#endif
#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
# 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
void
zzip_rewinddir(ZZIP_DIR * dir)
{
if (! dir) 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;
dir->dirent.d_flags = 0;
if (st.st_mode)
{
if (! S_ISREG(st.st_mode))
{
dir->dirent.d_compr = st.st_mode;
dir->dirent.d_compr |= 0x80000000;
}else
{
dir->dirent.d_compr = 0;
}
}else
{
dir->dirent.d_compr = 0;
}
return 1;
}
#endif
ZZIP_DIRENT*
zzip_readdir(ZZIP_DIR * dir)
{
if (! dir) { errno=EBADF; return 0; }
{
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;
dir->dirent.d_flags = dir->hdr->d_flags;
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_off_t
zzip_telldir(ZZIP_DIR* dir)
{
if (! dir) { errno=EBADF; return -1; }
{
return ((zzip_off_t) ((char*) dir->hdr - (char*) dir->hdr0));
}
}
void
zzip_seekdir(ZZIP_DIR* dir, zzip_off_t offset)
{
if (! dir) return;
{
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
#undef zzip_telldir
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
ZZIP_DIR*
zzip_opendir(zzip_char_t* filename)
{
return zzip_opendir_ext_io (filename, 0, 0, 0);
}
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)
){
return 0;
}
# endif
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;
}
int
zzip_closedir(ZZIP_DIR* dir)
{
if (! dir) { errno = EBADF; return -1; }
{
zzip_dir_close(dir);
return 0;
}
}