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