Refactor Wiretap
[metze/wireshark/wip.git] / filetap / file_access.c
1 /* file_access.c
2  *
3  * Wiretap Library
4  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26
27 #ifdef HAVE_FCNTL_H
28 #include <fcntl.h>
29 #endif
30
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34
35 #include <errno.h>
36
37 #include <wsutil/file_util.h>
38
39 #include "ftap-int.h"
40 #include "ft_file_wrappers.h"
41 #include "buffer.h"
42
43 /*
44  * Add an extension, and all compressed versions thereof, to a GSList
45  * of extensions.
46  */
47 static GSList *add_extensions(GSList *extensions, const gchar *extension,
48     GSList *compressed_file_extensions)
49 {
50         GSList *compressed_file_extension;
51
52         /*
53          * Add the specified extension.
54          */
55         extensions = g_slist_append(extensions, g_strdup(extension));
56
57         /*
58          * Now add the extensions for compressed-file versions of
59          * that extension.
60          */
61         for (compressed_file_extension = compressed_file_extensions;
62             compressed_file_extension != NULL;
63             compressed_file_extension = g_slist_next(compressed_file_extension)) {
64                 extensions = g_slist_append(extensions,
65                     g_strdup_printf("%s.%s", extension,
66                       (gchar *)compressed_file_extension->data));
67         }
68
69         return extensions;
70 }
71
72 /*
73  * File types that can be identified by file extensions.
74  */
75 static const struct filetap_extension_info file_type_extensions_base[] = {
76         { "Wireshark/tcpdump/... - pcap", "pcap;cap;dmp" },
77 };
78
79 #define N_FILE_TYPE_EXTENSIONS  (sizeof file_type_extensions_base / sizeof file_type_extensions_base[0])
80
81 static const struct filetap_extension_info* file_type_extensions = NULL;
82
83 static GArray* file_type_extensions_arr = NULL;
84
85 /* initialize the extensions array if it has not been initialized yet */
86 static void init_file_type_extensions(void) {
87
88         if (file_type_extensions_arr) return;
89
90         file_type_extensions_arr = g_array_new(FALSE,TRUE,sizeof(struct filetap_extension_info));
91
92         g_array_append_vals(file_type_extensions_arr,file_type_extensions_base,N_FILE_TYPE_EXTENSIONS);
93
94         file_type_extensions = (struct filetap_extension_info*)(void *)file_type_extensions_arr->data;
95 }
96
97 void ftap_register_file_type_extension(const struct filetap_extension_info *ei) {
98         init_file_type_extensions();
99
100         g_array_append_val(file_type_extensions_arr,*ei);
101
102         file_type_extensions = (const struct filetap_extension_info*)(void *)file_type_extensions_arr->data;
103 }
104
105 int ftap_get_num_file_type_extensions(void)
106 {
107         return file_type_extensions_arr->len;
108 }
109
110 const char *ftap_get_file_extension_type_name(int extension_type)
111 {
112         return file_type_extensions[extension_type].name;
113 }
114
115 static GSList *add_extensions_for_file_extensions_type(int extension_type,
116     GSList *extensions, GSList *compressed_file_extensions)
117 {
118         gchar **extensions_set, **extensionp, *extension;
119
120         /*
121          * Split the extension-list string into a set of extensions.
122          */
123         extensions_set = g_strsplit(file_type_extensions[extension_type].extensions,
124             ";", 0);
125
126         /*
127          * Add each of those extensions to the list.
128          */
129         for (extensionp = extensions_set; *extensionp != NULL; extensionp++) {
130                 extension = *extensionp;
131
132                 /*
133                  * Add the extension, and all compressed variants
134                  * of it.
135                  */
136                 extensions = add_extensions(extensions, extension,
137                     compressed_file_extensions);
138         }
139
140         g_strfreev(extensions_set);
141         return extensions;
142 }
143
144 /* Return a list of file extensions that are used by the specified file
145    extension type.
146
147    All strings in the list are allocated with g_malloc() and must be freed
148    with g_free(). */
149 GSList *ftap_get_file_extension_type_extensions(guint extension_type)
150 {
151         GSList *compressed_file_extensions;
152         GSList *extensions;
153
154         if (extension_type >= file_type_extensions_arr->len)
155                 return NULL;    /* not a valid extension type */
156
157         extensions = NULL;      /* empty list, to start with */
158
159         /*
160          * Get the list of compressed-file extensions.
161          */
162         compressed_file_extensions = ftap_get_compressed_file_extensions();
163
164         /*
165          * Add all this file extension type's extensions, with compressed
166          * variants.
167          */
168         extensions = add_extensions_for_file_extensions_type(extension_type,
169             extensions, compressed_file_extensions);
170
171         g_slist_free(compressed_file_extensions);
172         return extensions;
173 }
174
175 /* Return a list of all extensions that are used by all file types,
176    including compressed extensions, e.g. not just "pcap" but also
177    "pcap.gz" if we can read gzipped files.
178
179    All strings in the list are allocated with g_malloc() and must be freed
180    with g_free(). */
181 GSList *ftap_get_all_file_extensions_list(void)
182 {
183         GSList *compressed_file_extensions;
184         GSList *extensions;
185         unsigned int i;
186
187         init_file_type_extensions();
188
189         extensions = NULL;      /* empty list, to start with */
190
191         /*
192          * Get the list of compressed-file extensions.
193          */
194         compressed_file_extensions = ftap_get_compressed_file_extensions();
195
196         for (i = 0; i < file_type_extensions_arr->len; i++) {
197                 /*
198                  * Add all this file extension type's extensions, with
199                  * compressed variants.
200                  */
201                 extensions = add_extensions_for_file_extensions_type(i,
202                     extensions, compressed_file_extensions);
203         }
204
205         g_slist_free(compressed_file_extensions);
206         return extensions;
207 }
208
209 static int empty_open(ftap *wth _U_, int *err _U_, gchar **err_info _U_)
210 {
211         return 0;
212 }
213
214 /* The open_file_* routines should return:
215  *
216  *      -1 on an I/O error;
217  *
218  *      1 if the file they're reading is one of the types it handles;
219  *
220  *      0 if the file they're reading isn't the type they're checking for.
221  *
222  * If the routine handles this type of file, it should set the "file_type"
223  * field in the "struct ftap" to the type of the file.
224  *
225  * Note that the routine does not have to free the private data pointer on
226  * error. The caller takes care of that by calling ftap_close on error.
227  * (See https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=8518)
228  *
229  * However, the caller does have to free the private data pointer when
230  * returning 0, since the next file type will be called and will likely
231  * just overwrite the pointer.
232  */
233
234 /* Files that have magic bytes in fixed locations. These
235  * are easy to identify.  Only an open routine is needed.
236  */
237 static const ftap_open_routine_t magic_number_open_routines_base[] = {
238         empty_open/* libpcap_open, */
239 };
240 #define N_MAGIC_FILE_TYPES      (sizeof magic_number_open_routines_base / sizeof magic_number_open_routines_base[0])
241
242 static ftap_open_routine_t* magic_number_open_routines = NULL;
243
244 static GArray* magic_number_open_routines_arr = NULL;
245
246 /*
247  * Initialize the magic-number open routines array if it has not been
248  * initialized yet.
249  */
250 static void init_magic_number_open_routines(void) {
251
252         if (magic_number_open_routines_arr) return;
253
254         magic_number_open_routines_arr = g_array_new(FALSE,TRUE,sizeof(ftap_open_routine_t));
255
256         g_array_append_vals(magic_number_open_routines_arr,magic_number_open_routines_base,N_MAGIC_FILE_TYPES);
257
258         magic_number_open_routines = (ftap_open_routine_t*)(void *)magic_number_open_routines_arr->data;
259 }
260
261 void ftap_register_magic_number_open_routine(ftap_open_routine_t open_routine) {
262         init_magic_number_open_routines();
263
264         g_array_append_val(magic_number_open_routines_arr,open_routine);
265
266         magic_number_open_routines = (ftap_open_routine_t*)(void *)magic_number_open_routines_arr->data;
267 }
268
269 /* Files that don't have magic bytes at a fixed location,
270  * but that instead require a heuristic of some sort to
271  * identify them.  This includes ASCII trace files.
272  *
273  * Entries for the ASCII trace files that would be, for example,
274  * saved copies of a Telnet session to some box are put after
275  * most of the other entries, as we don't want to treat a capture
276  * of such a session as a trace file from such a session
277  * merely because it has the right text in it.  They still
278  * appear before the *really* weak entries, such as the VWR entry.
279  */
280 static const struct ftap_heuristic_open_info heuristic_open_info_base[] = {
281         { NULL, "(empty)", NULL},
282 };
283 #define N_HEURISTIC_FILE_TYPES  (sizeof heuristic_open_info_base / sizeof heuristic_open_info_base[0])
284
285 static struct ftap_heuristic_open_info* heuristic_open_info = NULL;
286
287 static GArray* heuristic_open_info_arr = NULL;
288
289 /*
290  * Initialize the heuristics array if it has not been initialized yet.
291  */
292 static void init_heuristic_open_info(void) {
293         unsigned int i;
294         struct ftap_heuristic_open_info *i_open;
295
296         if (heuristic_open_info_arr)
297                 return;
298
299         heuristic_open_info_arr = g_array_new(FALSE,TRUE,sizeof(struct ftap_heuristic_open_info));
300
301         g_array_append_vals(heuristic_open_info_arr,heuristic_open_info_base,N_HEURISTIC_FILE_TYPES);
302
303         heuristic_open_info = (struct ftap_heuristic_open_info*)(void *)heuristic_open_info_arr->data;
304
305         /* Populate the extensions_set list now */
306         for (i = 0, i_open = heuristic_open_info; i < heuristic_open_info_arr->len; i++, i_open++) {
307                 if (i_open->extensions != NULL)
308                         i_open->extensions_set = g_strsplit(i_open->extensions, ";", 0);
309         }
310 }
311
312 void ftap_register_heuristic_open_info(struct ftap_heuristic_open_info *hi) {
313         init_heuristic_open_info();
314
315         g_array_append_val(heuristic_open_info_arr,*hi);
316
317         if (hi->extensions != NULL)
318                 hi->extensions_set = g_strsplit(hi->extensions, ";", 0);
319
320         heuristic_open_info = (struct ftap_heuristic_open_info*)(void *)heuristic_open_info_arr->data;
321 }
322
323 /*
324  * Visual C++ on Win32 systems doesn't define these.  (Old UNIX systems don't
325  * define them either.)
326  *
327  * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
328  */
329 #ifndef S_ISREG
330 #define S_ISREG(mode)   (((mode) & S_IFMT) == S_IFREG)
331 #endif
332 #ifndef S_IFIFO
333 #define S_IFIFO _S_IFIFO
334 #endif
335 #ifndef S_ISFIFO
336 #define S_ISFIFO(mode)  (((mode) & S_IFMT) == S_IFIFO)
337 #endif
338 #ifndef S_ISDIR
339 #define S_ISDIR(mode)   (((mode) & S_IFMT) == S_IFDIR)
340 #endif
341
342 static char *get_file_extension(const char *pathname)
343 {
344         gchar *filename;
345         gchar **components;
346         size_t ncomponents;
347         GSList *compressed_file_extensions, *compressed_file_extension;
348         gchar *extensionp;
349
350         /*
351          * Is the pathname empty?
352          */
353         if (strcmp(pathname, "") == 0)
354                 return NULL;    /* no extension */
355
356         /*
357          * Find the last component of the pathname.
358          */
359         filename = g_path_get_basename(pathname);
360
361         /*
362          * Does it have an extension?
363          */
364         if (strchr(filename, '.') == NULL) {
365                 g_free(filename);
366                 return NULL;    /* no extension whatsoever */
367         }
368
369         /*
370          * Yes.  Split it into components separated by ".".
371          */
372         components = g_strsplit(filename, ".", 0);
373         g_free(filename);
374
375         /*
376          * Count the components.
377          */
378         for (ncomponents = 0; components[ncomponents] != NULL; ncomponents++)
379                 ;
380
381         if (ncomponents == 0) {
382                 g_strfreev(components);
383                 return NULL;    /* no components */
384         }
385         if (ncomponents == 1) {
386                 g_strfreev(components);
387                 return NULL;    /* only one component, with no "." */
388         }
389
390         /*
391          * Is the last component one of the extensions used for compressed
392          * files?
393          */
394         compressed_file_extensions = ftap_get_compressed_file_extensions();
395         if (compressed_file_extensions == NULL) {
396                 /*
397                  * We don't support reading compressed files, so just
398                  * return a copy of whatever extension we did find.
399                  */
400                 extensionp = g_strdup(components[ncomponents - 1]);
401                 g_strfreev(components);
402                 return extensionp;
403         }
404         extensionp = components[ncomponents - 1];
405         for (compressed_file_extension = compressed_file_extensions;
406             compressed_file_extension != NULL;
407             compressed_file_extension = g_slist_next(compressed_file_extension)) {
408                 if (strcmp(extensionp, (char *)compressed_file_extension->data) == 0) {
409                         /*
410                          * Yes, it's one of the compressed-file extensions.
411                          * Is there an extension before that?
412                          */
413                         if (ncomponents == 2) {
414                                 g_strfreev(components);
415                                 return NULL;    /* no, only two components */
416                         }
417
418                         /*
419                          * Yes, return that extension.
420                          */
421                         extensionp = g_strdup(components[ncomponents - 2]);
422                         g_strfreev(components);
423                         return extensionp;
424                 }
425         }
426
427         /*
428          * The extension isn't one of the compressed-file extensions;
429          * return it.
430          */
431         extensionp = g_strdup(extensionp);
432         g_strfreev(components);
433         return extensionp;
434 }
435
436 static gboolean heuristic_uses_extension(unsigned int i, const char *extension)
437 {
438         gchar **extensionp;
439
440         /*
441          * Does this file type *have* any extensions?
442          */
443         if (heuristic_open_info[i].extensions == NULL)
444                 return FALSE;   /* no */
445
446         /*
447          * Check each of them against the specified extension.
448          */
449         for (extensionp = heuristic_open_info[i].extensions_set; *extensionp != NULL;
450             extensionp++) {
451                 if (strcmp(extension, *extensionp) == 0) {
452                         return TRUE;    /* it's one of them */
453                 }
454         }
455         return FALSE;   /* it's not one of them */
456 }
457
458 /* Opens a file and prepares a ftap struct.
459    If "do_random" is TRUE, it opens the file twice; the second open
460    allows the application to do random-access I/O without moving
461    the seek offset for sequential I/O, which is used by Wireshark
462    so that it can do sequential I/O to a capture file that's being
463    written to as new packets arrive independently of random I/O done
464    to display protocol trees for packets when they're selected. */
465 ftap* ftap_open_offline(const char *filename, int *err, char **err_info,
466                         gboolean do_random)
467 {
468         int     fd;
469         ws_statb64 statb;
470         ftap    *fth;
471         unsigned int    i;
472         gboolean use_stdin = FALSE;
473         gchar *extension;
474
475         /* open standard input if filename is '-' */
476         if (strcmp(filename, "-") == 0)
477                 use_stdin = TRUE;
478
479         /* First, make sure the file is valid */
480         if (use_stdin) {
481                 if (ws_fstat64(0, &statb) < 0) {
482                         *err = errno;
483                         return NULL;
484                 }
485         } else {
486                 if (ws_stat64(filename, &statb) < 0) {
487                         *err = errno;
488                         return NULL;
489                 }
490         }
491         if (S_ISFIFO(statb.st_mode)) {
492                 /*
493                  * Opens of FIFOs are allowed only when not opening
494                  * for random access.
495                  *
496                  * XXX - currently, we do seeking when trying to find
497                  * out the file type, so we don't actually support
498                  * opening FIFOs.  However, we may eventually
499                  * do buffering that allows us to do at least some
500                  * file type determination even on pipes, so we
501                  * allow FIFO opens and let things fail later when
502                  * we try to seek.
503                  */
504                 if (do_random) {
505                         *err = FTAP_ERR_RANDOM_OPEN_PIPE;
506                         return NULL;
507                 }
508         } else if (S_ISDIR(statb.st_mode)) {
509                 /*
510                  * Return different errors for "this is a directory"
511                  * and "this is some random special file type", so
512                  * the user can get a potentially more helpful error.
513                  */
514                 *err = EISDIR;
515                 return NULL;
516         } else if (! S_ISREG(statb.st_mode)) {
517                 *err = FTAP_ERR_NOT_REGULAR_FILE;
518                 return NULL;
519         }
520
521         /*
522          * We need two independent descriptors for random access, so
523          * they have different file positions.  If we're opening the
524          * standard input, we can only dup it to get additional
525          * descriptors, so we can't have two independent descriptors,
526          * and thus can't do random access.
527          */
528         if (use_stdin && do_random) {
529                 *err = FTAP_ERR_RANDOM_OPEN_STDIN;
530                 return NULL;
531         }
532
533         errno = ENOMEM;
534         fth = (ftap *)g_malloc0(sizeof(ftap));
535
536         /* Open the file */
537         errno = FTAP_ERR_CANT_OPEN;
538         if (use_stdin) {
539                 /*
540                  * We dup FD 0, so that we don't have to worry about
541                  * a file_close of wfth->fh closing the standard
542                  * input of the process.
543                  */
544                 fd = ws_dup(0);
545                 if (fd < 0) {
546                         *err = errno;
547                         g_free(fth);
548                         return NULL;
549                 }
550 #ifdef _WIN32
551                 if (_setmode(fd, O_BINARY) == -1) {
552                         /* "Shouldn't happen" */
553                         *err = errno;
554                         g_free(fth);
555                         return NULL;
556                 }
557 #endif
558                 if (!(fth->fh = file_fdopen(fd))) {
559                         *err = errno;
560                         ws_close(fd);
561                         g_free(fth);
562                         return NULL;
563                 }
564         } else {
565                 if (!(fth->fh = file_open(filename))) {
566                         *err = errno;
567                         g_free(fth);
568                         return NULL;
569                 }
570         }
571
572         if (do_random) {
573                 if (!(fth->random_fh = file_open(filename))) {
574                         *err = errno;
575                         file_close(fth->fh);
576                         g_free(fth);
577                         return NULL;
578                 }
579         } else
580                 fth->random_fh = NULL;
581
582         /* initialization */
583         fth->file_encap = FTAP_ENCAP_UNKNOWN;
584         fth->subtype_sequential_close = NULL;
585         fth->subtype_close = NULL;
586     fth->priv = NULL;
587
588     init_magic_number_open_routines();
589         init_heuristic_open_info();
590         if (fth->random_fh) {
591                 fth->fast_seek = g_ptr_array_new();
592
593                 file_set_random_access(fth->fh, FALSE, fth->fast_seek);
594                 file_set_random_access(fth->random_fh, TRUE, fth->fast_seek);
595         }
596
597         /* Try all file types that support magic numbers */
598         for (i = 0; i < magic_number_open_routines_arr->len; i++) {
599                 /* Seek back to the beginning of the file; the open routine
600                    for the previous file type may have left the file
601                    position somewhere other than the beginning, and the
602                    open routine for this file type will probably want
603                    to start reading at the beginning.
604
605                    Initialize the data offset while we're at it. */
606                 if (file_seek(fth->fh, 0, SEEK_SET, err) == -1) {
607                         /* I/O error - give up */
608                         ftap_close(fth);
609                         return NULL;
610                 }
611
612                 switch ((*magic_number_open_routines[i])(fth, err, err_info)) {
613
614                 case -1:
615                         /* I/O error - give up */
616                         ftap_close(fth);
617                         return NULL;
618
619                 case 0:
620                         /* No I/O error, but not that type of file */
621                         break;
622
623                 case 1:
624                         /* We found the file type */
625                         goto success;
626                 }
627         }
628
629         /* Does this file's name have an extension? */
630         extension = get_file_extension(filename);
631         if (extension != NULL) {
632                 /* Yes - try the heuristic types that use that extension first. */
633                 for (i = 0; i < heuristic_open_info_arr->len; i++) {
634                         /* Does this type use that extension? */
635                         if (heuristic_uses_extension(i, extension)) {
636                                 /* Yes. */
637                                 if (file_seek(fth->fh, 0, SEEK_SET, err) == -1) {
638                                         /* I/O error - give up */
639                                         g_free(extension);
640                                         ftap_close(fth);
641                                         return NULL;
642                                 }
643
644                                 switch ((*heuristic_open_info[i].open_routine)(fth,
645                                     err, err_info)) {
646
647                                 case -1:
648                                         /* I/O error - give up */
649                                         g_free(extension);
650                                         ftap_close(fth);
651                                         return NULL;
652
653                                 case 0:
654                                         /* No I/O error, but not that type of file */
655                                         break;
656
657                                 case 1:
658                                         /* We found the file type */
659                                         g_free(extension);
660                                         goto success;
661                                 }
662                         }
663                 }
664
665                 /* Now try the ones that don't use it. */
666                 for (i = 0; i < heuristic_open_info_arr->len; i++) {
667                         /* Does this type use that extension? */
668                         if (!heuristic_uses_extension(i, extension)) {
669                                 /* No. */
670                                 if (file_seek(fth->fh, 0, SEEK_SET, err) == -1) {
671                                         /* I/O error - give up */
672                                         g_free(extension);
673                                         ftap_close(fth);
674                                         return NULL;
675                                 }
676
677                                 switch ((*heuristic_open_info[i].open_routine)(fth,
678                                     err, err_info)) {
679
680                                 case -1:
681                                         /* I/O error - give up */
682                                         g_free(extension);
683                                         ftap_close(fth);
684                                         return NULL;
685
686                                 case 0:
687                                         /* No I/O error, but not that type of file */
688                                         break;
689
690                                 case 1:
691                                         /* We found the file type */
692                                         g_free(extension);
693                                         goto success;
694                                 }
695                         }
696                 }
697                 g_free(extension);
698         } else {
699                 /* No - try all the heuristics types in order. */
700                 for (i = 0; i < heuristic_open_info_arr->len; i++) {
701                         if (file_seek(fth->fh, 0, SEEK_SET, err) == -1) {
702                                 /* I/O error - give up */
703                                 ftap_close(fth);
704                                 return NULL;
705                         }
706
707                         switch ((*heuristic_open_info[i].open_routine)(fth,
708                             err, err_info)) {
709
710                         case -1:
711                                 /* I/O error - give up */
712                                 ftap_close(fth);
713                                 return NULL;
714
715                         case 0:
716                                 /* No I/O error, but not that type of file */
717                                 break;
718
719                         case 1:
720                                 /* We found the file type */
721                                 goto success;
722                         }
723                 }
724         }
725
726     /* Well, it's not one of the types of file we know about. */
727         ftap_close(fth);
728         *err = FTAP_ERR_FILE_UNKNOWN_FORMAT;
729         return NULL;
730
731 success:
732         fth->frame_buffer = (struct Buffer *)g_malloc(sizeof(struct Buffer));
733         buffer_init(fth->frame_buffer, 1500);
734
735         return fth;
736 }
737
738 /*
739  * Given the pathname of the file we just closed with ftap_fdclose(), attempt
740  * to reopen that file and assign the new file descriptor(s) to the sequential
741  * stream and, if do_random is TRUE, to the random stream.  Used on Windows
742  * after the rename of a file we had open was done or if the rename of a
743  * file on top of a file we had open failed.
744  *
745  * This is only required by Wireshark, not TShark, and, at the point that
746  * Wireshark is doing this, the sequential stream is closed, and the
747  * random stream is open, so this refuses to open pipes, and only
748  * reopens the random stream.
749  */
750 gboolean
751 ftap_fdreopen(ftap *fth, const char *filename, int *err)
752 {
753         ws_statb64 statb;
754
755         /*
756          * We need two independent descriptors for random access, so
757          * they have different file positions.  If we're opening the
758          * standard input, we can only dup it to get additional
759          * descriptors, so we can't have two independent descriptors,
760          * and thus can't do random access.
761          */
762         if (strcmp(filename, "-") == 0) {
763                 *err = FTAP_ERR_RANDOM_OPEN_STDIN;
764                 return FALSE;
765         }
766
767         /* First, make sure the file is valid */
768         if (ws_stat64(filename, &statb) < 0) {
769                 *err = errno;
770                 return FALSE;
771         }
772         if (S_ISFIFO(statb.st_mode)) {
773                 /*
774                  * Opens of FIFOs are not allowed; see above.
775                  */
776                 *err = FTAP_ERR_RANDOM_OPEN_PIPE;
777                 return FALSE;
778         } else if (S_ISDIR(statb.st_mode)) {
779                 /*
780                  * Return different errors for "this is a directory"
781                  * and "this is some random special file type", so
782                  * the user can get a potentially more helpful error.
783                  */
784                 *err = EISDIR;
785                 return FALSE;
786         } else if (! S_ISREG(statb.st_mode)) {
787                 *err = FTAP_ERR_NOT_REGULAR_FILE;
788                 return FALSE;
789         }
790
791         /* Open the file */
792         errno = FTAP_ERR_CANT_OPEN;
793         if (!file_fdreopen(fth->random_fh, filename)) {
794                 *err = errno;
795                 return FALSE;
796         }
797         return TRUE;
798 }
799
800 /* Table of the file types we know about.
801    Entries must be sorted by FTAP_FILE_TYPE_SUBTYPE_xxx values in ascending order */
802 static const struct ftap_file_type_subtype_info dump_open_table_base[] = {
803         /* FTAP_FILE_TYPE_SUBTYPE_UNKNOWN (only used internally for initialization) */
804         { NULL, NULL, NULL, NULL },
805 };
806
807 gint ftap_num_file_types_subtypes = sizeof(dump_open_table_base) / sizeof(struct ftap_file_type_subtype_info);
808
809 static GArray*  dump_open_table_arr = NULL;
810 static const struct ftap_file_type_subtype_info* dump_open_table = dump_open_table_base;
811
812 /* initialize the file types array if it has not being initialized yet */
813 static void init_file_types_subtypes(void) {
814
815         if (dump_open_table_arr) return;
816
817         dump_open_table_arr = g_array_new(FALSE,TRUE,sizeof(struct ftap_file_type_subtype_info));
818
819         g_array_append_vals(dump_open_table_arr,dump_open_table_base,ftap_num_file_types_subtypes);
820
821         dump_open_table = (const struct ftap_file_type_subtype_info*)(void *)dump_open_table_arr->data;
822 }
823
824 int ftap_register_file_type_subtypes(const struct ftap_file_type_subtype_info* fi) {
825         init_file_types_subtypes();
826
827         g_array_append_val(dump_open_table_arr,*fi);
828
829         dump_open_table = (const struct ftap_file_type_subtype_info*)(void *)dump_open_table_arr->data;
830
831         return ftap_num_file_types_subtypes++;
832 }
833
834 int ftap_get_num_file_types_subtypes(void)
835 {
836         return ftap_num_file_types_subtypes;
837 }
838
839 /*
840  * Given a GArray of FTAP_ENCAP_ types, return the per-file encapsulation
841  * type that would be needed to write out a file with those types.  If
842  * there's only one type, it's that type, otherwise it's
843  * FTAP_ENCAP_PER_RECORD.
844  */
845 int
846 ftap_dump_file_encap_type(const GArray *file_encaps)
847 {
848         int encap;
849
850         encap = FTAP_ENCAP_PER_RECORD;
851         if (file_encaps->len == 1) {
852                 /* OK, use the one-and-only encapsulation type. */
853                 encap = g_array_index(file_encaps, gint, 0);
854         }
855         return encap;
856 }
857
858 /* Name that should be somewhat descriptive. */
859 const char *ftap_file_type_subtype_string(int file_type_subtype)
860 {
861         if (file_type_subtype < 0 || file_type_subtype >= ftap_num_file_types_subtypes) {
862                 g_error("Unknown capture file type %d", file_type_subtype);
863                 /** g_error() does an abort() and thus never returns **/
864                 return "";
865         } else
866                 return dump_open_table[file_type_subtype].name;
867 }
868
869 /* Name to use in, say, a command-line flag specifying the type/subtype. */
870 const char *ftap_file_type_subtype_short_string(int file_type_subtype)
871 {
872         if (file_type_subtype < 0 || file_type_subtype >= ftap_num_file_types_subtypes)
873                 return NULL;
874         else
875                 return dump_open_table[file_type_subtype].short_name;
876 }
877
878 /* Translate a short name to a capture file type/subtype. */
879 int ftap_short_string_to_file_type_subtype(const char *short_name)
880 {
881         int file_type_subtype;
882
883         for (file_type_subtype = 0; file_type_subtype < ftap_num_file_types_subtypes; file_type_subtype++) {
884                 if (dump_open_table[file_type_subtype].short_name != NULL &&
885                     strcmp(short_name, dump_open_table[file_type_subtype].short_name) == 0)
886                         return file_type_subtype;
887         }
888
889         return -1;      /* no such file type, or we can't write it */
890 }
891
892 static GSList *
893 add_extensions_for_file_type_subtype(int file_type_subtype, GSList *extensions,
894     GSList *compressed_file_extensions)
895 {
896         gchar **extensions_set, **extensionp;
897         gchar *extension;
898
899         /*
900          * Add the default extension, and all compressed variants of
901          * it.
902          */
903         extensions = add_extensions(extensions,
904             dump_open_table[file_type_subtype].default_file_extension,
905             compressed_file_extensions);
906
907         if (dump_open_table[file_type_subtype].additional_file_extensions != NULL) {
908                 /*
909                  * We have additional extensions; add them.
910                  *
911                  * First, split the extension-list string into a set of
912                  * extensions.
913                  */
914                 extensions_set = g_strsplit(dump_open_table[file_type_subtype].additional_file_extensions,
915                     ";", 0);
916
917                 /*
918                  * Add each of those extensions to the list.
919                  */
920                 for (extensionp = extensions_set; *extensionp != NULL;
921                     extensionp++) {
922                         extension = *extensionp;
923
924                         /*
925                          * Add the extension, and all compressed variants
926                          * of it.
927                          */
928                         extensions = add_extensions(extensions, extension,
929                             compressed_file_extensions);
930                 }
931
932                 g_strfreev(extensions_set);
933         }
934         return extensions;
935 }
936
937 /* Return a list of file extensions that are used by the specified file type.
938
939    If include_compressed is TRUE, the list will include compressed
940    extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
941    gzipped files.
942
943    All strings in the list are allocated with g_malloc() and must be freed
944    with g_free(). */
945 GSList *ftap_get_file_extensions_list(int file_type_subtype, gboolean include_compressed)
946 {
947         GSList *compressed_file_extensions;
948         GSList *extensions;
949
950         if (file_type_subtype < 0 || file_type_subtype >= ftap_num_file_types_subtypes)
951                 return NULL;    /* not a valid file type */
952
953         if (dump_open_table[file_type_subtype].default_file_extension == NULL)
954                 return NULL;    /* valid, but no extensions known */
955
956         extensions = NULL;      /* empty list, to start with */
957
958         /*
959          * If include_compressions is true, get the list of compressed-file
960          * extensions.
961          */
962         if (include_compressed)
963                 compressed_file_extensions = ftap_get_compressed_file_extensions();
964         else
965                 compressed_file_extensions = NULL;
966
967         /*
968          * Add all this file type's extensions, with compressed
969          * variants.
970          */
971         extensions = add_extensions_for_file_type_subtype(file_type_subtype, extensions,
972             compressed_file_extensions);
973
974         g_slist_free(compressed_file_extensions);
975         return extensions;
976 }
977
978 /*
979  * Free a list returned by ftap_get_file_extension_type_extensions(),
980  * ftap_get_all_file_extensions_list, or ftap_get_file_extensions_list().
981  */
982 void ftap_free_extensions_list(GSList *extensions)
983 {
984         GSList *extension;
985
986         for (extension = extensions; extension != NULL;
987             extension = g_slist_next(extension)) {
988                 g_free(extension->data);
989         }
990         g_slist_free(extensions);
991 }
992
993 /* Return the default file extension to use with the specified file type;
994    that's just the extension, without any ".". */
995 const char *ftap_default_file_extension(int file_type_subtype)
996 {
997         if (file_type_subtype < 0 || file_type_subtype >= ftap_num_file_types_subtypes)
998                 return NULL;
999         else
1000                 return dump_open_table[file_type_subtype].default_file_extension;
1001 }