From Olivier Jacques: Add #defines to disable XML validation.
[obnox/wireshark/wip.git] / wiretap / file_wrappers.c
1 /* file_wrappers.c
2  *
3  * $Id$
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7  *
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.
12  *
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.
17  *
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.
21  *
22  */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 /*
28  * OK, now this is tricky.
29  *
30  * At least on FreeBSD 3.2, "/usr/include/zlib.h" includes
31  * "/usr/include/zconf.h", which, if HAVE_UNISTD_H is defined,
32  * #defines "z_off_t" to be "off_t", and if HAVE_UNISTD_H is
33  * not defines, #defines "z_off_t" to be "long" if it's not
34  * already #defined.
35  *
36  * In 4.4-Lite-derived systems such as FreeBSD, "off_t" is
37  * "long long int", not "long int", so the definition of "z_off_t" -
38  * and therefore the types of the arguments to routines such as
39  * "gzseek()", as declared, with prototypes, in "zlib.h" - depends
40  * on whether HAVE_UNISTD_H is defined prior to including "zlib.h"!
41  *
42  * It's not defined in the FreeBSD 3.2 "zlib", so if we include "zlib.h"
43  * after defining HAVE_UNISTD_H, we get a misdeclaration of "gzseek()",
44  * and, if we're building with "zlib" support, anything that seeks
45  * on a file may not work.
46  *
47  * Other BSDs may have the same problem, if they haven't done something
48  * such as defining HAVE_UNISTD_H in "zconf.h".
49  *
50  * "config.h" defines HAVE_UNISTD_H, on all systems that have it, and all
51  * 4.4-Lite-derived BSDs have it.  Therefore, given that "zlib.h" is included
52  * by "file_wrappers.h", that means that unless we include "zlib.h" before
53  * we include "config.h", we get a misdeclaration of "gzseek()".
54  *
55  * Unfortunately, it's "config.h" that tells us whether we have "zlib"
56  * in the first place, so we don't know whether to include "zlib.h"
57  * until we include "config.h"....
58  *
59  * A similar problem appears to occur with "gztell()", at least on
60  * NetBSD.
61  *
62  * To add further complication, on recent versions, at least, of OpenBSD,
63  * the Makefile for zlib defines HAVE_UNISTD_H.
64  *
65  * So what we do is, on all OSes other than OpenBSD, *undefine* HAVE_UNISTD_H
66  * before including "wtap.h" (we need "wtap.h" to get the WTAP_ERR_ZLIB
67  * values, and it also includes "zlib.h" if HAVE_ZLIB" is defined), and,
68  * if we have zlib, make "file_seek()" and "file_tell()" subroutines, so
69  * that the only calls to "gzseek()" and "gztell()" are in this file, which,
70  * by dint of the hackery described above, manages to correctly declare
71  * "gzseek()" and "gztell()".
72  *
73  * On OpenBSD, we forcibly *define* HAVE_UNISTD_H if it's not defined.
74  *
75  * Hopefully, the BSDs will, over time, remove the test for HAVE_UNISTD_H
76  * from "zconf.h", so that "gzseek()" and "gztell()" will be declared
77  * with the correct signature regardless of whether HAVE_UNISTD_H is
78  * defined, so that if they change the signature we don't have to worry
79  * about making sure it's defined or not defined.
80  *
81  * DO NOT, UNDER ANY CIRCUMSTANCES, REMOVE THE FOLLOWING LINES, OR MOVE
82  * THEM AFTER THE INCLUDE OF "wtap.h"!  Doing so will cause any program
83  * using Wiretap to read capture files to fail miserably on a FreeBSD
84  * 3.2 or 3.3 system - and possibly some other BSD systems - if zlib is
85  * installed.  If you *must* include <unistd.h> here, do so *before*
86  * including "wtap.h", and before undefining HAVE_UNISTD_H.  If you
87  * *must* have HAVE_UNISTD_H defined before including "wtap.h", put
88  * "file_error()" into a file by itself, which can cheerfully include
89  * "wtap.h" and get "gzseek()" misdeclared, and include just "zlib.h"
90  * in this file - *after* undefining HAVE_UNISTD_H.
91  */
92 #ifdef __OpenBSD__
93 #ifndef HAVE_UNISTD_H
94 #define HAVE_UNISTD_H
95 #endif /* HAVE_UNISTD_H */
96 #else /* __OpenBSD__ */
97 #undef HAVE_UNISTD_H
98 #endif /* __OpenBSD__ */
99
100 #include <errno.h>
101 #include <stdio.h>
102 #include "wtap-int.h"
103 #include "file_wrappers.h"
104
105 #ifdef HAVE_LIBZ
106 long
107 file_seek(void *stream, long offset, int whence, int *err)
108 {
109         long ret;
110
111         ret = gzseek(stream, (z_off_t)offset, whence);
112         if (ret == -1) {
113                 /*
114                  * XXX - "gzseek()", as of zlib 1.1.4, doesn't set
115                  * "z_err" for the stream, so "gzerror()" could return
116                  * a bogus Z_OK.
117                  *
118                  * As this call failed, we know "gzerror()" shouldn't
119                  * return Z_OK; if it does, we assume that "errno" is
120                  * the real error.
121                  */
122                 *err = file_error(stream);
123                 if (*err == 0)
124                         *err = errno;
125         }
126         return ret;
127 }
128
129 long
130 file_tell(void *stream)
131 {
132         return (long)gztell(stream);
133 }
134 #else /* HAVE_LIBZ */
135 long
136 file_seek(void *stream, long offset, int whence, int *err)
137 {
138         long ret;
139
140         ret = fseek(stream, offset, whence);
141         if (ret == -1)
142                 *err = file_error(stream);
143         return ret;
144 }
145 #endif /* HAVE_LIBZ */
146
147 /*
148  * Routine to return a Wiretap error code (0 for no error, an errno
149  * for a file error, or a WTAP_ERR_ code for other errors) for an
150  * I/O stream.
151  */
152 #ifdef HAVE_LIBZ
153 int
154 file_error(void *fh)
155 {
156         int errnum;
157
158         gzerror(fh, &errnum);
159         switch (errnum) {
160
161         case Z_OK:              /* no error */
162                 return 0;
163
164         case Z_STREAM_END:      /* EOF - not an error */
165                 return 0;
166
167         case Z_ERRNO:           /* file I/O error */
168                 return errno;
169
170         default:
171                 return WTAP_ERR_ZLIB + errnum;
172         }
173 }
174 #else /* HAVE_LIBZ */
175 int
176 file_error(FILE *fh)
177 {
178         if (ferror(fh))
179                 return errno;
180         else
181                 return 0;
182 }
183 #endif /* HAVE_LIBZ */