Back to index

php5  5.3.10
zip_source_filep.c
Go to the documentation of this file.
00001 /*
00002   zip_source_filep.c -- create data source from FILE *
00003   Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
00004 
00005   This file is part of libzip, a library to manipulate ZIP archives.
00006   The authors can be contacted at <libzip@nih.at>
00007 
00008   Redistribution and use in source and binary forms, with or without
00009   modification, are permitted provided that the following conditions
00010   are met:
00011   1. Redistributions of source code must retain the above copyright
00012      notice, this list of conditions and the following disclaimer.
00013   2. Redistributions in binary form must reproduce the above copyright
00014      notice, this list of conditions and the following disclaimer in
00015      the documentation and/or other materials provided with the
00016      distribution.
00017   3. The names of the authors may not be used to endorse or promote
00018      products derived from this software without specific prior
00019      written permission.
00020  
00021   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
00022   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00023   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
00025   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00027   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00028   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00029   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00030   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00031   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 */
00033 
00034 
00035 
00036 #include <sys/stat.h>
00037 #include <errno.h>
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 
00042 #include "zipint.h"
00043 
00044 struct read_file {
00045     char *fname;     /* name of file to copy from */
00046     FILE *f;         /* file to copy from */
00047     off_t off;              /* start offset of */
00048     off_t len;              /* lengt of data to copy */
00049     off_t remain;    /* bytes remaining to be copied */
00050     int e[2];        /* error codes */
00051 };
00052 
00053 static ssize_t read_file(void *state, void *data, size_t len,
00054                    enum zip_source_cmd cmd);
00055 
00056 
00057 
00058 ZIP_EXTERN(struct zip_source *)
00059 zip_source_filep(struct zip *za, FILE *file, off_t start, off_t len)
00060 {
00061     if (za == NULL)
00062        return NULL;
00063 
00064     if (file == NULL || start < 0 || len < -1) {
00065        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
00066        return NULL;
00067     }
00068 
00069     return _zip_source_file_or_p(za, NULL, file, start, len);
00070 }
00071 
00072 
00073 
00074 struct zip_source *
00075 _zip_source_file_or_p(struct zip *za, const char *fname, FILE *file,
00076                     off_t start, off_t len)
00077 {
00078     struct read_file *f;
00079     struct zip_source *zs;
00080 
00081     if (file == NULL && fname == NULL) {
00082        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
00083        return NULL;
00084     }
00085 
00086     if ((f=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) {
00087        _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
00088        return NULL;
00089     }
00090 
00091     f->fname = NULL;
00092     if (fname) {
00093        if ((f->fname=strdup(fname)) == NULL) {
00094            _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
00095            free(f);
00096            return NULL;
00097        }
00098     }
00099     f->f = file;
00100     f->off = start;
00101     f->len = (len ? len : -1);
00102     
00103     if ((zs=zip_source_function(za, read_file, f)) == NULL) {
00104        free(f);
00105        return NULL;
00106     }
00107 
00108     return zs;
00109 }
00110 
00111 
00112 
00113 static ssize_t
00114 read_file(void *state, void *data, size_t len, enum zip_source_cmd cmd)
00115 {
00116     struct read_file *z;
00117     char *buf;
00118     int i, n;
00119 
00120     z = (struct read_file *)state;
00121     buf = (char *)data;
00122 
00123     switch (cmd) {
00124     case ZIP_SOURCE_OPEN:
00125        if (z->fname) {
00126            if ((z->f=fopen(z->fname, "rb")) == NULL) {
00127               z->e[0] = ZIP_ER_OPEN;
00128               z->e[1] = errno;
00129               return -1;
00130            }
00131        }
00132 
00133        if (fseeko(z->f, z->off, SEEK_SET) < 0) {
00134            z->e[0] = ZIP_ER_SEEK;
00135            z->e[1] = errno;
00136            return -1;
00137        }
00138        z->remain = z->len;
00139        return 0;
00140        
00141     case ZIP_SOURCE_READ:
00142        if (z->remain != -1)
00143            n = len > z->remain ? z->remain : len;
00144        else
00145            n = len;
00146        
00147        if ((i=fread(buf, 1, n, z->f)) < 0) {
00148            z->e[0] = ZIP_ER_READ;
00149            z->e[1] = errno;
00150            return -1;
00151        }
00152 
00153        if (z->remain != -1)
00154            z->remain -= i;
00155 
00156        return i;
00157        
00158     case ZIP_SOURCE_CLOSE:
00159        if (z->fname) {
00160            fclose(z->f);
00161            z->f = NULL;
00162        }
00163        return 0;
00164 
00165     case ZIP_SOURCE_STAT:
00166         {
00167            struct zip_stat *st;
00168            struct stat fst;
00169            int err;
00170            
00171            if (len < sizeof(*st))
00172               return -1;
00173 
00174            if (z->f)
00175               err = fstat(fileno(z->f), &fst);
00176            else
00177               err = stat(z->fname, &fst);
00178 
00179            if (err != 0) {
00180               z->e[0] = ZIP_ER_READ; /* best match */
00181               z->e[1] = errno;
00182               return -1;
00183            }
00184 
00185            st = (struct zip_stat *)data;
00186 
00187            zip_stat_init(st);
00188            st->mtime = fst.st_mtime;
00189            if (z->len != -1)
00190               st->size = z->len;
00191            else if ((fst.st_mode&S_IFMT) == S_IFREG)
00192               st->size = fst.st_size;
00193 
00194            return sizeof(*st);
00195        }
00196 
00197     case ZIP_SOURCE_ERROR:
00198        if (len < sizeof(int)*2)
00199            return -1;
00200 
00201        memcpy(data, z->e, sizeof(int)*2);
00202        return sizeof(int)*2;
00203 
00204     case ZIP_SOURCE_FREE:
00205        free(z->fname);
00206        if (z->f)
00207        fclose(z->f);
00208        free(z);
00209        return 0;
00210 
00211     default:
00212        ;
00213     }
00214 
00215     return -1;
00216 }