4 * Guido Draheim <guidod@gmx.de>
6 * Copyright (c) 1999,2000,2001,2002,2003 Guido Draheim
8 * use under the restrictions of the
9 * Lesser GNU General Public License
10 * or alternatively the restrictions
11 * of the Mozilla Public License 1.1
14 #include <zzip/lib.h> /* exported... */
15 #include <zzip/file.h>
16 #include <stddef.h> /*offsetof */
21 #ifdef ZZIP_HAVE_SYS_STAT_H
27 #include <zzip/__dirent.h>
30 #pragma warning had to DEFINE offsetof as it was not in stddef.h
31 #define offsetof(T,M) ((unsigned)(& ((T*)0)->M))
34 #ifdef ZZIP_HAVE_SYS_STAT_H
36 /* MSVC does have IFbitmask but not the corresponding IStests */
37 # if ! defined S_ISDIR && defined S_IFDIR
38 # define S_ISDIR(_X_) ((_X_) & S_IFDIR)
40 # if ! defined S_ISREG && defined S_IFREG
41 # define S_ISREG(_X_) ((_X_) & S_IFREG)
46 * This function is the equivalent of a => rewinddir(2) for a realdir or
47 * the zipfile in place of a directory. The ZZIP_DIR handle returned from
48 * => zzip_opendir has a flag saying realdir or zipfile. As for a zipfile,
49 * the filenames will include the filesubpath, so take care.
52 zzip_rewinddir(ZZIP_DIR
* dir
)
57 if (USE_DIRENT
&& dir
->realdir
)
59 _zzip_rewinddir(dir
->realdir
);
70 #define real_readdir(_X_) 1
73 real_readdir(ZZIP_DIR
* dir
)
75 struct stat st
= { 0 };
76 char filename
[PATH_MAX
];
77 struct dirent
*dirent
= _zzip_readdir(dir
->realdir
);
82 dir
->dirent
.d_name
= dirent
->d_name
;
83 strcpy(filename
, dir
->realname
);
84 strcat(filename
, "/");
85 strcat(filename
, dirent
->d_name
);
87 if (stat(filename
, &st
) == -1)
90 dir
->dirent
.d_csize
= dir
->dirent
.st_size
= st
.st_size
;
94 if (! S_ISREG(st
.st_mode
))
96 dir
->dirent
.d_compr
= st
.st_mode
;
97 dir
->dirent
.d_compr
|= 0x80000000;
98 /* makes it effectively negative,
99 * but can still be fed to S_ISXXX(x) */
102 dir
->dirent
.d_compr
= 0; /* stored */
106 dir
->dirent
.d_compr
= 0; /* stored */
114 * This function is the equivalent of a => readdir(2) for a realdir
115 * or a zipfile referenced by the ZZIP_DIR returned from => zzip_opendir.
117 * The ZZIP_DIR handle (as returned by => zzip_opendir) contains a few more
118 * entries than being copied into the ZZIP_DIRENT. The only valid fields in
119 * a ZZIP_DIRENT are d_name (the file name), d_compr (compression), d_csize
120 * (compressed size), st_size (uncompressed size).
123 zzip_readdir(ZZIP_DIR
* dir
)
126 { errno
=EBADF
; return 0; }
128 if (USE_DIRENT
&& dir
->realdir
)
130 if (! real_readdir(dir
))
137 dir
->dirent
.d_name
= dir
->hdr
->d_name
;
138 dir
->dirent
.d_compr
= dir
->hdr
->d_compr
;
140 dir
->dirent
.d_csize
= dir
->hdr
->d_csize
;
141 dir
->dirent
.st_size
= dir
->hdr
->d_usize
;
143 if (! dir
->hdr
->d_reclen
)
146 dir
->hdr
= (struct zzip_dir_hdr
*)
147 ((char *) dir
->hdr
+ dir
->hdr
->d_reclen
);
152 /** => zzip_rewinddir
153 * This function is the equivalent of => telldir(2) for a realdir or zipfile.
156 zzip_telldir(ZZIP_DIR
* dir
)
159 { errno
=EBADF
; return -1; }
161 if (USE_DIRENT
&& dir
->realdir
)
163 return _zzip_telldir(dir
->realdir
);
166 return ((zzip_off_t
) ((char *) dir
->hdr
- (char *) dir
->hdr0
));
170 /** => zzip_rewinddir
171 * This function is the equivalent of => seekdir(2) for a realdir or zipfile.
174 zzip_seekdir(ZZIP_DIR
* dir
, zzip_off_t offset
)
179 if (USE_DIRENT
&& dir
->realdir
)
181 _zzip_seekdir(dir
->realdir
, offset
);
184 dir
->hdr
= (struct zzip_dir_hdr
*)
185 (dir
->hdr0
? (char *) dir
->hdr0
+ (size_t) offset
: 0);
190 #define EOVERFLOW EFBIG
193 /** => zzip_rewinddir
194 * This function is provided for users who can not use any largefile-mode.
197 zzip_telldir32(ZZIP_DIR
* dir
)
199 if (sizeof(zzip_off_t
) == sizeof(long))
201 return zzip_telldir(dir
);
204 off_t off
= zzip_telldir(dir
);
206 register long off32
= off
;
207 if (off32
== off
) return off32
;
214 /** => zzip_rewinddir
215 * This function is provided for users who can not use any largefile-mode.
218 zzip_seekdir32(ZZIP_DIR
* dir
, long offset
)
220 zzip_seekdir(dir
, offset
);
223 #if defined ZZIP_LARGEFILE_RENAME && defined EOVERFLOW && defined PIC
224 #undef zzip_seekdir /* zzip_seekdir64 */
225 #undef zzip_telldir /* zzip_telldir64 */
227 /* DLL compatibility layer - so that 32bit code can link with a 64on32 too */
228 long zzip_telldir(ZZIP_DIR
* dir
) { return zzip_telldir32(dir
); }
229 void zzip_seekdir(ZZIP_DIR
* dir
, long offset
) { zzip_seekdir32(dir
, offset
); }
233 * This function is the equivalent of => opendir(3) for a realdir or zipfile.
235 * This function has some magic - if the given argument-path
236 * is a directory, it will wrap a real => opendir(3) into the ZZIP_DIR
237 * structure. Otherwise it will divert to => zzip_dir_open which
238 * can also attach a ".zip" extension if needed to find the archive.
240 * the error-code is mapped to => errno(3).
243 zzip_opendir(zzip_char_t
* filename
)
245 return zzip_opendir_ext_io(filename
, 0, 0, 0);
249 * This function uses explicit ext and io instead of the internal
250 * defaults, setting them to zero is equivalent to => zzip_opendir
253 zzip_opendir_ext_io(zzip_char_t
* filename
, int o_modes
,
254 zzip_strings_t
* ext
, zzip_plugin_io_t io
)
259 # ifdef ZZIP_HAVE_SYS_STAT_H
263 if (o_modes
& (ZZIP_PREFERZIP
| ZZIP_ONLYZIP
))
267 # ifdef ZZIP_HAVE_SYS_STAT_H
268 if (stat(filename
, &st
) >= 0 && S_ISDIR(st
.st_mode
))
272 _zzip_DIR
*realdir
= _zzip_opendir(filename
);
276 if (! (dir
= (ZZIP_DIR
*) calloc(1, sizeof(*dir
))))
278 _zzip_closedir(realdir
);
282 dir
->realdir
= realdir
;
283 dir
->realname
= strdup(filename
);
290 # endif /* HAVE_SYS_STAT_H */
293 dir
= zzip_dir_open_ext_io(filename
, &e
, ext
, io
);
294 if (! dir
&& (o_modes
& ZZIP_PREFERZIP
))
297 errno
= zzip_errno(e
);
302 * This function is the equivalent of => closedir(3) for a realdir or zipfile.
304 * This function is magic - if the given arg-ZZIP_DIR
305 * is a real directory, it will call the real => closedir(3) and then
306 * free the wrapping ZZIP_DIR structure. Otherwise it will divert
307 * to => zzip_dir_close which will free the ZZIP_DIR structure.
310 zzip_closedir(ZZIP_DIR
* dir
)
313 { errno
= EBADF
; return -1; }
315 if (USE_DIRENT
&& dir
->realdir
)
317 _zzip_closedir(dir
->realdir
);
330 * c-file-style: "stroustrup"