6 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 * Do this now, to get close() defined, before we muck with the definition
29 * of HAVE_UNISTD_H. See below for the full sad story of why we do that.
33 #endif /* HAVE_UNISTD_H */
36 * OK, now this is tricky.
38 * At least on FreeBSD 3.2, "/usr/include/zlib.h" includes
39 * "/usr/include/zconf.h", which, if HAVE_UNISTD_H is defined,
40 * #defines "z_off_t" to be "off_t", and if HAVE_UNISTD_H is
41 * not defined, #defines "z_off_t" to be "long" if it's not
44 * In 4.4-Lite-derived systems such as FreeBSD, "off_t" is
45 * "long long int", not "long int", so the definition of "z_off_t" -
46 * and therefore the types of the arguments to routines such as
47 * "gzseek()", as declared, with prototypes, in "zlib.h" - depends
48 * on whether HAVE_UNISTD_H is defined prior to including "zlib.h"!
50 * It's not defined in the FreeBSD 3.2 "zlib", so if we include "zlib.h"
51 * after defining HAVE_UNISTD_H, we get a misdeclaration of "gzseek()",
52 * and, if we're building with "zlib" support, anything that seeks
53 * on a file may not work.
55 * Other BSDs may have the same problem, if they haven't done something
56 * such as defining HAVE_UNISTD_H in "zconf.h".
58 * "config.h" defines HAVE_UNISTD_H, on all systems that have it, and all
59 * 4.4-Lite-derived BSDs have it. Therefore, given that "zlib.h" is included
60 * by "file_wrappers.h", that means that unless we include "zlib.h" before
61 * we include "config.h", we get a misdeclaration of "gzseek()".
63 * Unfortunately, it's "config.h" that tells us whether we have "zlib"
64 * in the first place, so we don't know whether to include "zlib.h"
65 * until we include "config.h"....
67 * A similar problem appears to occur with "gztell()", at least on
70 * To add further complication, on recent versions, at least, of OpenBSD,
71 * the Makefile for zlib defines HAVE_UNISTD_H.
73 * So what we do is, on all OSes other than OpenBSD, *undefine* HAVE_UNISTD_H
74 * before including "wtap-int.h" (it handles including "zlib.h" if HAVE_ZLIB
75 * is defined, and it includes "wtap.h", which we include to get the
76 * WTAP_ERR_ZLIB values), and, if we have zlib, make "file_seek()" and
77 * "file_tell()" subroutines, so that the only calls to "gzseek()" and
78 * "gztell()" are in this file, which, by dint of the hackery described
79 * above, manages to correctly declare "gzseek()" and "gztell()".
81 * On OpenBSD, we forcibly *define* HAVE_UNISTD_H if it's not defined.
83 * Hopefully, the BSDs will, over time, remove the test for HAVE_UNISTD_H
84 * from "zconf.h", so that "gzseek()" and "gztell()" will be declared
85 * with the correct signature regardless of whether HAVE_UNISTD_H is
86 * defined, so that if they change the signature we don't have to worry
87 * about making sure it's defined or not defined.
89 * DO NOT, UNDER ANY CIRCUMSTANCES, REMOVE THE FOLLOWING LINES, OR MOVE
90 * THEM AFTER THE INCLUDE OF "wtap-int.h"! Doing so will cause any program
91 * using Wiretap to read capture files to fail miserably on a FreeBSD
92 * 3.2 or 3.3 system - and possibly some other BSD systems - if zlib is
93 * installed. If you *must* have HAVE_UNISTD_H defined before including
94 * "wtap-int.h", put "file_error()" into a file by itself, which can
95 * cheerfully include "wtap.h" and get "gzseek()" misdeclared, and include
96 * just "zlib.h" in this file - *after* undefining HAVE_UNISTD_H.
100 #define HAVE_UNISTD_H
101 #endif /* HAVE_UNISTD_H */
102 #else /* __OpenBSD__ */
104 #endif /* __OpenBSD__ */
111 #endif /* HAVE_FCNTL_H */
113 #endif /* HAVE_LIBZ */
114 #include "wtap-int.h"
115 #include "file_wrappers.h"
116 #include "file_util.h"
122 file_open(const char *path, const char *mode)
129 if (strchr(mode + 1, '+') != NULL)
133 } else if (*mode == 'w') {
134 if (strchr(mode + 1, '+') != NULL)
135 oflag = O_RDWR|O_CREAT|O_TRUNC;
137 oflag = O_RDONLY|O_CREAT|O_TRUNC;
138 } else if (*mode == 'a') {
139 if (strchr(mode + 1, '+') != NULL)
140 oflag = O_RDWR|O_APPEND;
142 oflag = O_RDONLY|O_APPEND;
148 if (strchr(mode + 1, 'b') != NULL)
151 /* open file and do correct filename conversions */
152 if ((fd = eth_open(path, oflag, 0666)) == -1)
155 /* open zlib file handle */
156 ft = gzdopen(fd, mode);
166 file_seek(void *stream, gint64 offset, int whence, int *err)
170 /* XXX - z_off_t is usually long, won't work >= 2GB! */
171 ret = (gint64) gzseek(stream, (z_off_t)offset, whence);
174 * XXX - "gzseek()", as of zlib 1.1.4, doesn't set
175 * "z_err" for the stream, so "gzerror()" could return
178 * As this call failed, we know "gzerror()" shouldn't
179 * return Z_OK; if it does, we assume that "errno" is
182 *err = file_error(stream);
190 file_tell(void *stream)
192 /* XXX - z_off_t is usually long, won't work >= 2GB! */
193 return (gint64)gztell(stream);
197 * Routine to return a Wiretap error code (0 for no error, an errno
198 * for a file error, or a WTAP_ERR_ code for other errors) for an
206 gzerror(fh, &errnum);
209 case Z_OK: /* no error */
212 case Z_STREAM_END: /* EOF - not an error */
215 case Z_ERRNO: /* file I/O error */
219 return WTAP_ERR_ZLIB + errnum;
223 #else /* HAVE_LIBZ */
226 file_seek(void *stream, gint64 offset, int whence, int *err)
234 /* Win32 version using fsetpos/fgetpos */
235 /* XXX - using fsetpos/fgetpos this way is UNDOCUMENTED, but I don't see a any better way :-( */
236 /* _lseeki64(_fileno(stream)) doesn't work as this will mangle the internal FILE handling data */
243 /* XXX - CURRENTLY UNTESTED!!! */
244 ret = fgetpos(stream, &pos);
253 g_assert_not_reached();
255 ret = fsetpos(stream, &offset);
259 /* XXX - won't work >= 2GB! */
260 /*ret = (gint64) fseek(stream, (long) offset, whence);
265 /* "basic" version using fseek */
266 /* XXX - won't work >= 2GB! */
267 ret = (gint64) fseek(stream, (long) offset, whence);
269 *err = file_error(stream);
271 /*g_warning("Seek %lld whence %u ret %lld size %u", offset, whence, ret, sizeof(fpos_t));*/
276 file_tell(void *stream)
279 /* Win32 version using _telli64 */
280 /* XXX - CURRENTLY UNTESTED!!! */
281 return _telli64(_fileno((FILE *)stream));
283 /* "basic" version using ftell */
284 /* XXX - ftell returns a long - won't work >= 2GB! */
285 return (gint64) ftell(stream);
292 if (ferror((FILE *) fh))
298 #endif /* HAVE_LIBZ */