Esempio n. 1
0
File: luazip.c Progetto: msva/luazip
static int pushresult (lua_State *L, int i, const char *filename) {
  if (i) {
    lua_pushboolean(L, 1);
    return 1;
  }
  else {
    lua_pushnil(L);
    if (filename)
      lua_pushfstring(L, "%s: %s", filename, zzip_strerror(zzip_errno(errno)));
    else
      lua_pushfstring(L, "%s", zzip_strerror(zzip_errno(errno)));
    lua_pushnumber(L, zzip_errno(errno));
    return 3;
  }
}
Esempio n. 2
0
/**                                                               
 * This function will read(2) data from a real/zipped file.
 *
 * the replacement for => read(2) will fill the given buffer with bytes from
 * the opened file. It will return the number of bytes read, so if the EOF
 * is encountered you will be prompted with the number of bytes actually read.
 * 
 * If the file-handle is wrapping a stat'able file then it will actually just
 * perform a normal => read(2)-call, otherwise => zzip_file_read is called
 * to decompress the data stream and any error is mapped to => errno(3).
 */
zzip_ssize_t
zzip_read(ZZIP_FILE * fp, char * buf, zzip_size_t len)
{
    if (! fp) return 0;
    if (! fp->dir) 
      { return fp->io->read(fp->fd, buf, len); } /* stat fd */
    else
    {   register zzip_ssize_t v;
        v = zzip_file_read(fp, buf, len);
        if (v == -1) { errno = zzip_errno(fp->dir->errcode); }
        return v;
    }
}
Esempio n. 3
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 = kdStrdup(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)
        kdSetError ( zzip_errno(e) );
    return dir;
}
Esempio n. 4
0
/**
 * This function will read(2) data from a real/zipped file.
 *
 * the replacement for => read(2) will fill the given buffer with bytes from
 * the opened file. It will return the number of bytes read, so if the EOF
 * is encountered you will be prompted with the number of bytes actually read.
 *
 * If the file-handle is wrapping a stat'able file then it will actually just
 * perform a normal => read(2)-call, otherwise => zzip_file_read is called
 * to decompress the data stream and any error is mapped to => errno(3).
 */
zzip_ssize_t
zzip_read(ZZIP_FILE * fp, void *buf, zzip_size_t len)
{
    if (! fp)
        return 0;
    if (! fp->dir)
        { return fp->io->fd.read(fp->fd, buf, len); }    /* stat fd */
    else
    {
        register zzip_ssize_t v;

        v = zzip_file_read(fp, buf, len);
#ifdef ZZIP_DISABLED
        if (v == -1)
            { errno = zzip_errno(fp->dir->errcode); }
#endif /* ZZIP_DISABLED */
        return v;
    }
}
Esempio n. 5
0
/**
**	Generate a list of files within a specified directory
**
**	@param dirname	Directory to read.
**	@param filter	Optional xdata-filter function.
**	@param flp	Filelist pointer.
**
**	@return		Pointer to FileList struct describing Files found.
*/
global int ReadDataDirectory(const char* dirname,int (*filter)(char*,FileList *),FileList **flp)
{
#ifdef USE_ZZIPLIB
    ZZIP_DIR *dirp = NULL;
    ZZIP_DIRENT *dp;
    // ATTENTION: valid until end of file!
    #define readdir zzip_readdir
    #define closedir zzip_closedir
    int i;
    int entvalid;
    char zzbasepath[PATH_MAX];
    struct stat st;
    char *cp;
#else
#ifndef _MSC_VER
    DIR *dirp;
    struct dirent *dp;
#endif
    struct stat st;
#endif
#ifdef _MSC_VER
    struct _finddata_t fileinfo;
    long hFile;
#endif
    FileList *nfl;
    FileList *fl = NULL;
    int n;
    int isdir = 0; // silence gcc..
    char *np;
    char buffer[PATH_MAX];
    char *filename;

    strcpy(buffer, dirname);
    n = strlen(buffer);
    if (!n || buffer[n - 1] != '/') {
	buffer[n++] = '/';
	buffer[n] = 0;
    }
    np = buffer + n;
    n = 0;

#ifdef USE_ZZIPLIB
    strcpy (zzbasepath, dirname);
    /* per each slash in filename, check if it there is a zzip around */
    while ((cp = strrchr(zzbasepath, '/')))
    {
	int fd;
	zzip_error_t e;

	*cp = '\0'; /* cut at path separator == possible zipfile basename */
	fd = __my_zzip_open_zip(zzbasepath, O_RDONLY|O_BINARY);
	if (fd != -1) {
	    /* found zip-file, now open it */
	    dirp = zzip_dir_fdopen(fd, &e);
	    if (e) {
		errno = zzip_errno(e);
		close(fd);
		dirp = NULL;
	    }
	    break;
	}
    }
    if (!dirp) {
	int fd;
	zzip_error_t e;

	// this is tricky - we used to simply zzip_opendir(dirname) here, but
	// zziplib (correctly) prefers real directories over same named zipfiles
	// and we want it vice versa in this special case. Otherwise it would not
	// match the path separator backtrace above, which relies on recursive
	// __zip_open_dir(). __zip_open_dir() only detects zipfiles, not real dirs!
	fd = __my_zzip_open_zip(dirname, O_RDONLY|O_BINARY);
	if (fd == -1) {
	    dirp = zzip_opendir(dirname);
	    zzbasepath[0] = 0;
	} else {
	    dirp = zzip_dir_fdopen(fd, &e);
	    if (e) {
		errno = zzip_errno(e);
		close(fd);
		dirp = NULL;
	    } else {
		strcpy (zzbasepath, dirname);
	    }
	    DebugLevel3Fn("zzbasepath `%s', dirname `%s'\n"
		_C_ zzbasepath _C_ dirname);
	}
    }
#ifndef _MSC_VER
    IfDebug(if (!dirp) { DebugLevel0Fn("Dir `%s' not found\n" _C_ dirname); });
Esempio n. 6
0
ZZIP_FILE*
zzip_open_shared_io (ZZIP_FILE* stream,
                     zzip_char_t* filename, int o_flags, int o_modes,
                     zzip_strings_t* ext, zzip_plugin_io_t io)
{
    if (stream && stream->dir)
    {
        if (! ext) ext = stream->dir->fileext;
        if (! io) io = stream->dir->io;
    }
    if (! io) io = zzip_get_default_io ();

    if (o_modes & (ZZIP_PREFERZIP|ZZIP_ONLYZIP)) goto try_zzip;
try_real:
    /* prefer an existing real file */
    {
        zzip_plugin_io_t os = (o_modes & ZZIP_ALLOWREAL)
                              ?  zzip_get_default_io () : io;
        int fd = os->fd.open(filename, o_flags); /* io->fd.open */
        if (fd != -1)
        {
#if !defined(WINDOWSPC) || defined(__MINGW32__)
            struct stat st; // JMW
#endif
            ZZIP_FILE* fp = calloc (1, sizeof(ZZIP_FILE));
            if (! fp) {
                os->fd.close(fd);
                return 0;
            } /* io->fd.close */

            fp->dir = NULL;
            fp->fd = fd;
            fp->io = os;

#if !defined(WINDOWSPC) || defined(__MINGW32__)
            if (stat(filename,&st) >=0)
                fp->usize = st.st_size;
#else
            fp->usize = os->fd.filesize(fd);
#endif
            return fp;
        }
        if (o_modes & ZZIP_PREFERZIP) {
            return 0;
        }
    }
try_zzip:

    /* if the user had it in place of a normal xopen, then
     * we better defend this lib against illegal usage */
    if (o_flags & (O_CREAT|O_WRONLY))     {
        errno = EINVAL;
        return 0;
    }
    if (o_flags & (O_RDWR)) {
        o_flags ^= O_RDWR;
        o_flags |= O_RDONLY;
    }

    /* this is just for backward compatibility -and strictly needed to
     * prepare ourselves for more options and more options later on... */
    /*# if (o_modes & ZZIP_CASELESS) { o_flags |= ZZIP_CASEINSENSITIVE; } */
    /*# if (o_modes & ZZIP_NOPATHS)  { o_flags |= ZZIP_IGNOREPATH; } */

    /* see if we can open a file that is a zip file */
    {   char basename[PATH_MAX];
        char* p;
        int filename_len = strlen (filename);

        if (filename_len >= PATH_MAX) {
#ifdef ENAMETOOLONG
            errno = ENAMETOOLONG;
#endif
            return 0;
        }
        memcpy (basename, filename, filename_len+1);

        /* see if we can share the same zip directory */
        if (stream && stream->dir && stream->dir->realname)
        {
            zzip_size_t len = strlen (stream->dir->realname);
            if (! memcmp (filename, stream->dir->realname, len) &&
                    ((filename[len] == '/') || (filename[len] == '\\'))
                    && filename[len+1])
            {
                ZZIP_FILE* fp =
                    zzip_file_open (stream->dir, filename+len+1, o_modes);
                if (! fp) {
                    errno = zzip_errno (stream->dir->errcode);
                }
                return fp;
            }
        }

        /* per each slash in filename, check if it there is a zzip around */

        while ((p = strrchr (basename, '/')) || (p = strrchr (basename, '\\')))
        {
            zzip_error_t e = 0;
            ZZIP_DIR* dir;
            ZZIP_FILE* fp;
            int fd;

            *p = '\0'; /* cut at path separator == possible zipfile basename */
            fd = __zzip_try_open (basename, o_flags|O_RDONLY|O_BINARY, ext, io);

            if (fd == -1) {
                continue;
            }

            /*    found: */
            /* found zip-file, now try to parse it */
            dir = zzip_dir_fdopen_ext_io(fd, &e, ext, io);
            if (e) {
                errno = zzip_errno(e);
                io->fd.close(fd);
                return 0;
            }

            /* (p - basename) is the lenghtof zzip_dir part of the filename */
            fp = zzip_file_open(dir, filename + (p - basename) +1, o_modes);
            if (! fp) {
                errno = zzip_errno(dir->errcode);
            }
            else {
                if (! dir->realname) dir->realname = strdup (basename);
            }

            zzip_dir_close(dir);
            /* note: since (fp) is attached that (dir) will survive */
            /* but (dir) is implicitly closed on next zzip_close(fp) */

            return fp;
        } /*again*/

        if (o_modes & ZZIP_PREFERZIP) goto try_real;
        errno = ENOENT;
        return 0;
    }
}
Esempio n. 7
0
/**
 * open an => ZZIP_FILE from an already open => ZZIP_DIR handle. Since
 * we have a chance to reuse a cached => buf32k and => ZZIP_FILE memchunk
 * this is the best choice to unpack multiple files.
 * 
 * Note: the zlib supports 2..15 bit windowsize, hence we provide a 32k
 *       memchunk here... just to be safe.
 */
ZZIP_FILE * 
zzip_file_open(ZZIP_DIR * dir, zzip_char_t* name, int o_mode)
{
    zzip_error_t err = 0;
    struct zzip_file * fp = 0;
    struct zzip_dir_hdr * hdr = dir->hdr0;
    int (*cmp)(zzip_char_t*, zzip_char_t*);
 
    cmp = (o_mode & ZZIP_CASELESS)? dirsep_casecmp: strcmp;

    if (! dir || !dir->fd || dir->fd == -1 ) return 0;

    if (o_mode & ZZIP_NOPATHS)
    {
        register zzip_char_t* n = dirsep_strrchr(name, '/');
        if (n)  name = n + 1;
    }

    if (hdr)
    while (1)
    {
        register zzip_char_t* hdr_name = hdr->d_name;
        if (o_mode & ZZIP_NOPATHS)
        {
            register zzip_char_t* n = dirsep_strrchr(hdr_name, '/');
            if (n)  hdr_name = n + 1;
        }

        HINT4("name='%s', compr=%d, size=%d\n", 
	      hdr->d_name, hdr->d_compr, hdr->d_usize);

        if (!cmp(hdr_name, name))
        {
            switch (hdr->d_compr)
            {
            case 0: /* store */
            case 8: /* inflate */
                break;
            default:
                { err = ZZIP_UNSUPP_COMPR; goto error; }
            }

            if (dir->cache.fp) 
            {
                fp = dir->cache.fp; dir->cache.fp = NULL;
                /* memset(zfp, 0, sizeof *fp); cleared in zzip_file_close() */
            }else
            {
                if (! (fp = (ZZIP_FILE *)calloc(1, sizeof(*fp))))
                    { err =  ZZIP_OUTOFMEM; goto error; }
            }

            fp->dir = dir;
            fp->io = dir->io;
            dir->refcount++;
        
            if (dir->cache.buf32k) 
              { fp->buf32k = dir->cache.buf32k; dir->cache.buf32k = NULL; }
            else
            {
                if (! (fp->buf32k = (char *)malloc(ZZIP_32K)))
                    { err = ZZIP_OUTOFMEM; goto error; }
            }

            /*
             * In order to support simultaneous open files in one zip archive
             * we'll fix the fd offset when opening new file/changing which
             * file to read...
             */ 

            if (zzip_file_saveoffset(dir->currentfp) < 0)
                { err = ZZIP_DIR_SEEK; goto error; }

            fp->offset = hdr->d_off;
            dir->currentfp = fp;

            if (dir->io->seeks(dir->fd, hdr->d_off, SEEK_SET) < 0)
                { err = ZZIP_DIR_SEEK; goto error; }

            {   /* skip local header - should test tons of other info, 
		 * but trust that those are correct */
                zzip_ssize_t dataoff;
                struct zzip_file_header * p = (void*) fp->buf32k;

		dataoff = dir->io->read(dir->fd, (void*)p, sizeof(*p));
		if (dataoff < (zzip_ssize_t)sizeof(*p))
		{ err = ZZIP_DIR_READ;  goto error; }
                if (! ZZIP_FILE_HEADER_CHECKMAGIC(p)) /* PK\3\4 */
		{ err = ZZIP_CORRUPTED; goto error; }

                dataoff = ZZIP_GET16(p->z_namlen) + ZZIP_GET16(p->z_extras);
              
                if (dir->io->seeks(dir->fd, dataoff, SEEK_CUR) < 0)
                { err = ZZIP_DIR_SEEK; goto error; }

                fp->dataoffset = dir->io->tells(dir->fd);
                fp->usize = hdr->d_usize;
                fp->csize = hdr->d_csize;
            }

            err = zzip_inflate_init (fp, hdr);
            if (err) { goto error; }
                                        
            return fp;
        }else
        {
            if (hdr->d_reclen == 0)
                break;
            hdr = (struct zzip_dir_hdr *)((char *)hdr + hdr->d_reclen);
        }/*cmp name*/
    }/*forever*/
    dir->errcode = ZZIP_ENOENT;         zzip_errno(ZZIP_ENOENT);
    return NULL;
error:
    if (fp) zzip_file_close(fp);
    dir->errcode = err;                 zzip_errno(err);
    return NULL;
}