1 
2 /*
3  * Author:
4  *	Guido Draheim <guidod@gmx.de>
5  *	Tomi Ollila <Tomi.Ollila@iki.fi>
6  *
7  * Copyright (c) Guido Draheim, use under copyleft (LGPL,MPL)
8  *
9  * Description:
10  *      although this file is defining a function called zzip_stat it
11  *      will not need a real stat(2) exported by the Operating System.
12  *      It will just try to fill the fields of the ZZIP_STAT structure
13  *      of
14  */
15 
16 #include <zzip/lib.h>           /* exported... */
17 #include <zzip/file.h>
18 #include <string.h>
19 #if defined(_AIX)
20 #include <strings.h> /* for strcasecmp */
21 #endif
22 #include <sys/stat.h>
23 
24 #define ZZIP_USE_INTERNAL
25 #include <zzip/info.h>
26 
27 /**    get meta infornation on a zipped element.
28  * This function obtains information about a filename in an opened zip-archive
29  * without opening that file first. Mostly used to obtain the uncompressed
30  * size of a file inside a zip-archive. see => zzip_dir_open.
31  */
32 int
zzip_dir_stat(ZZIP_DIR * dir,zzip_char_t * name,ZZIP_STAT * zs,int flags)33 zzip_dir_stat(ZZIP_DIR * dir, zzip_char_t * name, ZZIP_STAT * zs, int flags)
34 {
35     struct zzip_dir_hdr *hdr = dir->hdr0;
36     int (*cmp) (zzip_char_t *, zzip_char_t *);
37 
38     if (flags & ZZIP_CASEINSENSITIVE) flags |= ZZIP_CASELESS;
39     cmp = (flags & ZZIP_CASELESS) ? strcasecmp : strcmp;
40 
41     if (! hdr)
42     {
43         dir->errcode = ZZIP_ENOENT;
44         return -1;
45     }
46 
47     if (flags & ZZIP_IGNOREPATH)
48     {
49         char *n = strrchr(name, '/');
50         if (n)
51             name = n + 1;
52     }
53 
54     while (1)
55     {
56         register char *hdr_name = hdr->d_name;
57         if (flags & ZZIP_IGNOREPATH)
58         {
59             register char *n = strrchr(hdr_name, '/');
60             if (n)
61                 hdr_name = n + 1;
62         }
63 
64         if (! cmp(hdr_name, name))
65             break;
66 
67         if (! hdr->d_reclen)
68         {
69             dir->errcode = ZZIP_ENOENT;
70             return -1;
71         }
72 
73         hdr = (struct zzip_dir_hdr *) ((char *) hdr + hdr->d_reclen);
74     }
75 
76     zs->d_compr = hdr->d_compr;
77     zs->d_csize = hdr->d_csize;
78     zs->st_size = hdr->d_usize;
79     zs->d_name = hdr->d_name;
80 
81     return 0;
82 }
83 
84 /** => zzip_dir_stat
85  * This function will obtain information about a opened file _within_ a
86  * zip-archive. The file is supposed to be open (otherwise -1 is returned).
87  * The st_size stat-member contains the uncompressed size. The optional
88  * d_name is never set here.
89  */
90 int
zzip_file_stat(ZZIP_FILE * file,ZZIP_STAT * zs)91 zzip_file_stat(ZZIP_FILE * file, ZZIP_STAT * zs)
92 {
93     if (! file)
94         return -1;
95     zs->d_compr = file->method;
96     zs->d_csize = file->csize;
97     zs->st_size = file->usize;
98     zs->d_name = 0;
99     return 0;
100 }
101 
102 /** => zzip_dir_stat
103  * This function will obtain information about a opened file which may be
104  * either real/zipped. The file is supposed to be open (otherwise -1 is
105  * returned). The st_size stat-member contains the uncompressed size.
106  * The optional d_name is never set here. For a real file, we do set the
107  * d_csize := st_size and d_compr := 0 for meaningful defaults.
108  */
109 int
zzip_fstat(ZZIP_FILE * file,ZZIP_STAT * zs)110 zzip_fstat(ZZIP_FILE * file, ZZIP_STAT * zs)
111 {
112     if (ZZIP_file_real(file))
113     {
114         struct stat st;
115         if (fstat(file->fd, &st) < 0)
116             return -1;
117         zs->st_size = st.st_size;
118         zs->d_csize = st.st_size;
119         zs->d_compr = 0;
120         return 0;
121     } else
122     {
123         return zzip_file_stat(file, zs);
124     }
125 }
126 
127 /*
128  * Local variables:
129  * c-file-style: "stroustrup"
130  * End:
131  */
132