Olivier Abad's patches to add:
[obnox/wireshark/wip.git] / wiretap / file.c
1 /* file.c
2  *
3  * $Id: file.c,v 1.26 1999/10/18 01:51:34 guy Exp $
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.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 #include <stdio.h>
27 #include <fcntl.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <sys/stat.h>
31 #include <errno.h>
32 #include "wtap.h"
33 #include "file.h"
34 #include "buffer.h"
35 #include "lanalyzer.h"
36 #include "ngsniffer.h"
37 #include "radcom.h"
38 #include "ascend.h"
39 #include "nettl.h"
40 #include "libpcap.h"
41 #include "snoop.h"
42 #include "iptrace.h"
43 #include "netmon.h"
44 #include "netxray.h"
45
46 /* The open_file_* routines should return:
47  *
48  *      -1 on an I/O error;
49  *
50  *      1 if the file they're reading is one of the types it handles;
51  *
52  *      0 if the file they're reading isn't the type they're checking for.
53  *
54  * If the routine handles this type of file, it should set the "file_type"
55  * field in the "struct wtap" to the type of the file.
56  *
57  * XXX - I need to drag my damn ANSI C spec in to figure out how to
58  * declare a "const" array of pointers to functions; putting "const"
59  * right after "static" isn't the right answer, at least according
60  * to GCC, which whines if I do that.
61  */
62
63 static int (*open_routines[])(wtap *, int *) = {
64         libpcap_open,
65         lanalyzer_open,
66         ngsniffer_open,
67         snoop_open,
68         iptrace_open,
69         netmon_open,
70         netxray_open,
71         radcom_open,
72         ascend_open,
73         nettl_open
74 };
75
76 int wtap_def_seek_read (FILE *fh, int seek_off, guint8 *pd, int len)
77 {
78         file_seek(fh, seek_off, SEEK_SET);
79         return file_read(pd, sizeof(guint8), len, fh);
80 }
81
82 #define N_FILE_TYPES    (sizeof open_routines / sizeof open_routines[0])
83
84 /* Opens a file and prepares a wtap struct */
85 wtap* wtap_open_offline(const char *filename, int *err)
86 {
87         struct stat statb;
88         wtap    *wth;
89         int     i;
90
91         /* First, make sure the file is valid */
92         if (stat(filename, &statb) < 0) {
93                 *err = errno;
94                 return NULL;
95         }
96 #ifndef WIN32
97         if (! S_ISREG(statb.st_mode) && ! S_ISFIFO(statb.st_mode)) {
98                 *err = WTAP_ERR_NOT_REGULAR_FILE;
99                 return NULL;
100         }
101 #endif
102
103         errno = ENOMEM;
104         wth = (wtap*)malloc(sizeof(wtap));
105         if (wth == NULL) {
106                 *err = errno;
107                 return NULL;
108         }
109
110         /* Open the file */
111         errno = WTAP_ERR_CANT_OPEN;
112         if (!(wth->fd = open(filename, O_RDONLY))) {
113                 *err = errno;
114                 free(wth);
115                 return NULL;
116         }
117         if (!(wth->fh = filed_open(wth->fd, "rb"))) {
118                 *err = errno;
119                 free(wth);
120                 return NULL;
121         }
122
123         /* initialization */
124         wth->file_encap = WTAP_ENCAP_UNKNOWN;
125         wth->data_offset = 0;
126
127         /* Try all file types */
128         for (i = 0; i < N_FILE_TYPES; i++) {
129                 switch ((*open_routines[i])(wth, err)) {
130
131                 case -1:
132                         /* I/O error - give up */
133                         *err = errno;
134                         file_close(wth->fh);
135                         free(wth);
136                         return NULL;
137
138                 case 0:
139                         /* No I/O error, but not that type of file */
140                         break;
141
142                 case 1:
143                         /* We found the file type */
144                         goto success;
145                 }
146         }
147
148         /* Well, it's not one of the types of file we know about. */
149         file_close(wth->fh);
150         free(wth);
151         *err = WTAP_ERR_FILE_UNKNOWN_FORMAT;
152         return NULL;
153
154 success:
155         wth->frame_buffer = g_malloc(sizeof(struct Buffer));
156         buffer_init(wth->frame_buffer, 1500);
157         return wth;
158 }
159
160
161 static wtap_dumper* wtap_dump_open_common(FILE *fh, int filetype,
162     int encap, int snaplen, int *err);
163
164 wtap_dumper* wtap_dump_open(const char *filename, int filetype, int encap,
165                                 int snaplen, int *err)
166 {
167         FILE *fh;
168
169         /* In case "fopen()" fails but doesn't set "errno", set "errno"
170            to a generic "the open failed" error. */
171         errno = WTAP_ERR_CANT_OPEN;
172         fh = fopen(filename, "w");
173         if (fh == NULL) {
174                 *err = errno;
175                 return NULL;    /* can't create file */
176         }
177         return wtap_dump_open_common(fh, filetype, encap, snaplen, err);
178 }
179
180 wtap_dumper* wtap_dump_fdopen(int fd, int filetype, int encap, int snaplen,
181                                 int *err)
182 {
183         FILE *fh;
184
185         /* In case "fopen()" fails but doesn't set "errno", set "errno"
186            to a generic "the open failed" error. */
187         errno = WTAP_ERR_CANT_OPEN;
188         fh = fdopen(fd, "w");
189         if (fh == NULL) {
190                 *err = errno;
191                 return NULL;    /* can't create standard I/O stream */
192         }
193         return wtap_dump_open_common(fh, filetype, encap, snaplen, err);
194 }
195
196 static wtap_dumper* wtap_dump_open_common(FILE *fh, int filetype, int encap,
197                                         int snaplen, int *err)
198 {
199         wtap_dumper *wdh;
200
201         wdh = malloc(sizeof (wtap_dumper));
202         if (wdh == NULL) {
203                 *err = errno;
204                 /* NOTE: this means the FD handed to "wtap_dump_fdopen()"
205                    will be closed if the malloc fails. */
206                 fclose(fh);
207                 return NULL;
208         }
209         wdh->fh = fh;
210         wdh->file_type = filetype;
211         wdh->snaplen = snaplen;
212         wdh->encap = encap;
213
214         switch (filetype) {
215
216         case WTAP_FILE_PCAP:
217                 if (!libpcap_dump_open(wdh, err))
218                         goto fail;
219                 break;
220
221         default:
222                 /* We currently only support dumping "libpcap" files */
223                 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
224                 goto fail;
225         }
226         return wdh;
227
228 fail:
229         free(wdh);
230         fclose(fh);
231         return NULL;    /* XXX - provide a reason why we failed */
232 }
233
234 FILE* wtap_dump_file(wtap_dumper *wdh)
235 {
236         return wdh->fh;
237 }
238
239 int wtap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
240     const u_char *pd, int *err)
241 {
242         return (wdh->subtype_write)(wdh, phdr, pd, err);
243 }
244
245 int wtap_dump_close(wtap_dumper *wdh, int *err)
246 {
247         int ret = 1;
248
249         if (!(wdh->subtype_close)(wdh, err))
250                 ret = 0;
251         errno = WTAP_ERR_CANT_CLOSE;
252         if (fclose(wdh->fh) == EOF) {
253                 if (ret) {
254                         /* The per-format close function succeeded,
255                            but the fclose didn't.  Save the reason
256                            why, if our caller asked for it. */
257                         if (err != NULL)
258                                 *err = errno;
259                 }
260                 ret = 0;
261         }
262         free(wdh);
263         return ret;
264 }
265
266 /*
267  * Routine to return a Wiretap error code (0 for no error, an errno
268  * for a file error, or a WTAP_ERR_ code for other errors) for an
269  * I/O stream.
270  */
271 #ifdef HAVE_LIBZ
272 int
273 file_error(void *fh)
274 {
275         int errnum;
276
277         gzerror(fh, &errnum);
278         switch (errnum) {
279
280         case Z_OK:              /* no error */
281                 return 0;
282
283         case Z_STREAM_END:      /* EOF - not an error */
284                 return 0;
285
286         case Z_ERRNO:           /* file I/O error */
287                 return errno;
288
289         default:
290                 return WTAP_ERR_ZLIB + errnum;
291         }
292 }
293 #else /* HAVE_LIBZ */
294 int
295 file_error(FILE *fh)
296 {
297         if (ferror(fh))
298                 return errno;
299         else
300                 return 0;
301 }
302 #endif /* HAVE_LIBZ */