示例#1
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;
    }
}
示例#2
0
/** => zzip_dir_creat
 *
 * If the third argument "ext" has another special meaning here, as it
 * is used to ensure that a given zip-file is created with the first entry 
 * of the ext-list appended as an extension unless the file-path already 
 * ends with a file-extension registered in the list. Therefore {"",0} 
 * matches all files and creates them as zip-archives under the given 
 * nonmodified name. (Some magic here? If the path ends in the path
 * separator then make a real directory even in the presence of ext-list?)
 *
 * This function is not yet implemented, check for #def ZZIP_NO_CREAT
 * Write-support will extend => zzip_closedir with semantics to finalize the
 * zip-archive by writing the zip-trailer and closing the archive file.
 */
ZZIP_DIR *
zzip_dir_creat_ext_io(zzip_char_t * name, int o_mode,
                      zzip_strings_t * ext, zzip_plugin_io_t io)
{
    if (! io)
        io = zzip_get_default_io();

    if (io != zzip_get_default_io())
    {
        /* the current io-structure does not contain a "write" entry,
         * and therefore this parameter is useless. Anyone to expect
         * some behavior should be warned, so here we let the function
         * fail bluntly - and leaving the recovery to the application
         */
        errno = EINVAL;
        return 0;
    }


    if (! _ZZIP_TRY)
    {
        /* not implemented - however, we respect that a null argument to 
         * zzip_mkdir and zzip_creat works, so we silently still do the mkdir 
         */
        if (! _mkdir(name, o_mode) || errno == EEXIST)
            errno = EROFS;
        return 0;
    } else
    {
#       define MAX_EXT_LEN 10
        ZZIP_DIR *dir = zzip_dir_alloc(ext);
        int name_len = strlen(name);
        dir->realname = malloc(name_len + MAX_EXT_LEN);
        if (! dir->realname)
            goto error;

        memcpy(dir->realname, name, name_len + 1);
        ___ int fd =
            __zzip_try_open(dir->realname, O_EXCL | O_TRUNC | O_WRONLY, ext,
                            io);
        if (fd != -1)
            { dir->fd = fd; return dir; }

        ___ zzip_strings_t *exx = ext;
        int exx_len;
        for (; *exx; exx++)
        {
            if ((exx_len = strlen(*exx) + 1) <= name_len &&
                ! memcmp(dir->realname + (name_len - exx_len), *exx, exx_len))
                break;          /* keep unmodified */
            exx++;
            if (*exx)
                continue;

            if (! (exx_len = strlen(*exx)) || exx_len >= MAX_EXT_LEN)
                break;
            memcpy(dir->realname + name_len, exx, exx_len);     /* append! */
        }
        ____;
        fd = (io->fd.open)(dir->realname, O_CREAT | O_TRUNC | O_WRONLY, o_mode);
        dir->realname[name_len] = '\0'; /* keep ummodified */
        if (fd != -1)
            { dir->fd = fd; return dir; }
      error:
        zzip_dir_free(dir);
        return 0;
        ____;
    }
}