Annotation of embedaddon/php/ext/zip/lib/zip_source_filep.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:   zip_source_filep.c -- create data source from FILE *
                      3:   Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
                      4: 
                      5:   This file is part of libzip, a library to manipulate ZIP archives.
                      6:   The authors can be contacted at <libzip@nih.at>
                      7: 
                      8:   Redistribution and use in source and binary forms, with or without
                      9:   modification, are permitted provided that the following conditions
                     10:   are met:
                     11:   1. Redistributions of source code must retain the above copyright
                     12:      notice, this list of conditions and the following disclaimer.
                     13:   2. Redistributions in binary form must reproduce the above copyright
                     14:      notice, this list of conditions and the following disclaimer in
                     15:      the documentation and/or other materials provided with the
                     16:      distribution.
                     17:   3. The names of the authors may not be used to endorse or promote
                     18:      products derived from this software without specific prior
                     19:      written permission.
                     20:  
                     21:   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
                     22:   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     23:   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
                     25:   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
                     27:   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     28:   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
                     29:   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     30:   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
                     31:   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     32: */
                     33: 
                     34: 
                     35: 
                     36: #include <sys/stat.h>
                     37: #include <errno.h>
                     38: #include <stdio.h>
                     39: #include <stdlib.h>
                     40: #include <string.h>
                     41: 
                     42: #include "zipint.h"
                     43: 
                     44: struct read_file {
                     45:     char *fname;       /* name of file to copy from */
                     46:     FILE *f;           /* file to copy from */
1.1.1.2 ! misho      47:     int closep;                /* close f */
        !            48:     struct zip_stat st;        /* stat information passed in */
        !            49: 
        !            50:     zip_uint64_t off;  /* start offset of */
        !            51:     zip_int64_t len;   /* length of data to copy */
        !            52:     zip_int64_t remain;        /* bytes remaining to be copied */
1.1       misho      53:     int e[2];          /* error codes */
                     54: };
                     55: 
1.1.1.2 ! misho      56: static zip_int64_t read_file(void *state, void *data, zip_uint64_t len,
1.1       misho      57:                     enum zip_source_cmd cmd);
                     58: 
                     59: 
                     60: 
                     61: ZIP_EXTERN(struct zip_source *)
1.1.1.2 ! misho      62: zip_source_filep(struct zip *za, FILE *file, zip_uint64_t start,
        !            63:                 zip_int64_t len)
1.1       misho      64: {
                     65:     if (za == NULL)
                     66:        return NULL;
                     67: 
                     68:     if (file == NULL || start < 0 || len < -1) {
                     69:        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
                     70:        return NULL;
                     71:     }
                     72: 
1.1.1.2 ! misho      73:     return _zip_source_file_or_p(za, NULL, file, start, len, 1, NULL);
1.1       misho      74: }
                     75: 
                     76: 
                     77: 
                     78: struct zip_source *
                     79: _zip_source_file_or_p(struct zip *za, const char *fname, FILE *file,
1.1.1.2 ! misho      80:                      zip_uint64_t start, zip_int64_t len, int closep,
        !            81:                      const struct zip_stat *st)
1.1       misho      82: {
                     83:     struct read_file *f;
                     84:     struct zip_source *zs;
                     85: 
                     86:     if (file == NULL && fname == NULL) {
                     87:        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
                     88:        return NULL;
                     89:     }
                     90: 
                     91:     if ((f=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) {
                     92:        _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
                     93:        return NULL;
                     94:     }
                     95: 
                     96:     f->fname = NULL;
                     97:     if (fname) {
                     98:        if ((f->fname=strdup(fname)) == NULL) {
                     99:            _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
                    100:            free(f);
                    101:            return NULL;
                    102:        }
                    103:     }
                    104:     f->f = file;
                    105:     f->off = start;
                    106:     f->len = (len ? len : -1);
1.1.1.2 ! misho     107:     f->closep = f->fname ? 1 : closep;
        !           108:     if (st)
        !           109:        memcpy(&f->st, st, sizeof(f->st));
        !           110:     else
        !           111:        zip_stat_init(&f->st);
        !           112: 
1.1       misho     113:     if ((zs=zip_source_function(za, read_file, f)) == NULL) {
                    114:        free(f);
                    115:        return NULL;
                    116:     }
                    117: 
                    118:     return zs;
                    119: }
                    120: 
                    121: 
                    122: 
1.1.1.2 ! misho     123: static zip_int64_t
        !           124: read_file(void *state, void *data, zip_uint64_t len, enum zip_source_cmd cmd)
1.1       misho     125: {
                    126:     struct read_file *z;
                    127:     char *buf;
                    128:     int i, n;
                    129: 
                    130:     z = (struct read_file *)state;
                    131:     buf = (char *)data;
                    132: 
                    133:     switch (cmd) {
                    134:     case ZIP_SOURCE_OPEN:
                    135:        if (z->fname) {
                    136:            if ((z->f=fopen(z->fname, "rb")) == NULL) {
                    137:                z->e[0] = ZIP_ER_OPEN;
                    138:                z->e[1] = errno;
                    139:                return -1;
                    140:            }
                    141:        }
                    142: 
1.1.1.2 ! misho     143:        if (z->closep) {
        !           144:            if (fseeko(z->f, (off_t)z->off, SEEK_SET) < 0) {
        !           145:                z->e[0] = ZIP_ER_SEEK;
        !           146:                z->e[1] = errno;
        !           147:                return -1;
        !           148:            }
1.1       misho     149:        }
                    150:        z->remain = z->len;
                    151:        return 0;
                    152:        
                    153:     case ZIP_SOURCE_READ:
1.1.1.2 ! misho     154:        /* XXX: return INVAL if len > size_t max */
1.1       misho     155:        if (z->remain != -1)
                    156:            n = len > z->remain ? z->remain : len;
                    157:        else
                    158:            n = len;
1.1.1.2 ! misho     159: 
        !           160:        if (!z->closep) {
        !           161:            /* we might share this file with others, so let's be safe */
        !           162:            if (fseeko(z->f, (off_t)(z->off + z->len-z->remain),
        !           163:                       SEEK_SET) < 0) {
        !           164:                z->e[0] = ZIP_ER_SEEK;
        !           165:                z->e[1] = errno;
        !           166:                return -1;
        !           167:            }
        !           168:        }
        !           169: 
1.1       misho     170:        if ((i=fread(buf, 1, n, z->f)) < 0) {
                    171:            z->e[0] = ZIP_ER_READ;
                    172:            z->e[1] = errno;
                    173:            return -1;
                    174:        }
                    175: 
                    176:        if (z->remain != -1)
                    177:            z->remain -= i;
                    178: 
                    179:        return i;
                    180:        
                    181:     case ZIP_SOURCE_CLOSE:
                    182:        if (z->fname) {
                    183:            fclose(z->f);
                    184:            z->f = NULL;
                    185:        }
                    186:        return 0;
                    187: 
                    188:     case ZIP_SOURCE_STAT:
                    189:         {
1.1.1.2 ! misho     190:            if (len < sizeof(z->st))
1.1       misho     191:                return -1;
                    192: 
1.1.1.2 ! misho     193:            if (z->st.valid != 0)
        !           194:                memcpy(data, &z->st, sizeof(z->st));
        !           195:            else {
        !           196:                struct zip_stat *st;
        !           197:                struct stat fst;
        !           198:                int err;
        !           199:            
        !           200:                if (z->f)
        !           201:                    err = fstat(fileno(z->f), &fst);
        !           202:                else
        !           203:                    err = stat(z->fname, &fst);
        !           204: 
        !           205:                if (err != 0) {
        !           206:                    z->e[0] = ZIP_ER_READ; /* best match */
        !           207:                    z->e[1] = errno;
        !           208:                    return -1;
        !           209:                }
        !           210: 
        !           211:                st = (struct zip_stat *)data;
        !           212:                
        !           213:                zip_stat_init(st);
        !           214:                st->mtime = fst.st_mtime;
        !           215:                st->valid |= ZIP_STAT_MTIME;
        !           216:                if (z->len != -1) {
        !           217:                    st->size = z->len;
        !           218:                    st->valid |= ZIP_STAT_SIZE;
        !           219:                }
        !           220:                else if ((fst.st_mode&S_IFMT) == S_IFREG) {
        !           221:                    st->size = fst.st_size;
        !           222:                    st->valid |= ZIP_STAT_SIZE;
        !           223:                }
1.1       misho     224:            }
1.1.1.2 ! misho     225:            return sizeof(z->st);
1.1       misho     226:        }
                    227: 
                    228:     case ZIP_SOURCE_ERROR:
                    229:        if (len < sizeof(int)*2)
                    230:            return -1;
                    231: 
                    232:        memcpy(data, z->e, sizeof(int)*2);
                    233:        return sizeof(int)*2;
                    234: 
                    235:     case ZIP_SOURCE_FREE:
                    236:        free(z->fname);
1.1.1.2 ! misho     237:        if (z->closep && z->f)
        !           238:            fclose(z->f);
1.1       misho     239:        free(z);
                    240:        return 0;
                    241: 
                    242:     default:
                    243:        ;
                    244:     }
                    245: 
                    246:     return -1;
                    247: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>