Bug Summary

File:wiretap/file_access.c
Warning:line 2290, column 13
Potential leak of memory pointed to by 'wdh'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name file_access.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/libxml2 -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -D wiretap_EXPORTS -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -I /builds/wireshark/wireshark/build/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-11-01-100306-3623-1 -x c /builds/wireshark/wireshark/wiretap/file_access.c
1/* file_access.c
2 *
3 * Wiretap Library
4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include "config.h"
10#define WS_LOG_DOMAIN"Wiretap" LOG_DOMAIN_WIRETAP"Wiretap"
11#include "wtap-int.h"
12
13#include <assert.h>
14
15#include <string.h>
16#include <stdlib.h>
17
18#include <errno(*__errno_location ()).h>
19
20#include <wsutil/file_util.h>
21#include <wsutil/file_compressed.h>
22#include <wsutil/tempfile.h>
23#ifdef HAVE_PLUGINS1
24#include <wsutil/plugins.h>
25#endif
26#include <wsutil/ws_assert.h>
27
28#include "wtap_module.h"
29#include "wtap_modules.h"
30#include "file_wrappers.h"
31#include "required_file_handlers.h"
32#include <wsutil/application_flavor.h>
33#include <wsutil/array.h>
34#include <wsutil/buffer.h>
35#include <wsutil/str_util.h>
36
37#include "lanalyzer.h"
38#include "ngsniffer.h"
39#include "radcom.h"
40#include "ascendtext.h"
41#include "nettl.h"
42#include "libpcap.h"
43#include "snoop.h"
44#include "iptrace.h"
45#include "iseries.h"
46#include "netmon.h"
47#include "netxray.h"
48#include "toshiba.h"
49#include "eyesdn.h"
50#include "i4btrace.h"
51#include "csids.h"
52#include "pppdump.h"
53#include "peekclassic.h"
54#include "peektagged.h"
55#include "vms.h"
56#include "dbs-etherwatch.h"
57#include "visual.h"
58#include "cosine.h"
59#include "5views.h"
60#include "erf.h"
61#include "hcidump.h"
62#include "logcat.h"
63#include "logcat_text.h"
64#include "json.h"
65#include "json_log.h"
66#include "mmodule.h"
67#include "observer.h"
68#include "k12.h"
69#include "ber.h"
70#include "catapult_dct2000.h"
71#include "mp4.h"
72#include "mp2t.h"
73#include "mpeg.h"
74#include "netscreen.h"
75#include "commview.h"
76#include "pcapng.h"
77#include "aethra.h"
78#include "btsnoop.h"
79#include "tnef.h"
80#include "dct3trace.h"
81#include "packetlogger.h"
82#include "daintree-sna.h"
83#include "netscaler.h"
84#include "mime_file.h"
85#include "ipfix.h"
86#include "vwr.h"
87#include "camins.h"
88#include "stanag4607.h"
89#include "capsa.h"
90#include "nettrace_3gpp_32_423.h"
91#include "mplog.h"
92#include "dpa400.h"
93#include "rfc7468.h"
94#include "ruby_marshal.h"
95#include "systemd_journal.h"
96#include "log3gpp.h"
97#include "candump.h"
98#include "busmaster.h"
99#include "cllog.h"
100#include "blf.h"
101#include "eri_enb_log.h"
102#include "autosar_dlt.h"
103#include "rtpdump.h"
104#include "ems.h"
105#include "ttl.h"
106#include "peak-trc.h"
107#include "netlog.h"
108#include "procmon.h"
109
110/*
111 * Add an extension, and all compressed versions thereof if requested,
112 * to a GSList of extensions.
113 */
114static GSList *
115add_extensions(GSList *extensions, const char *extension,
116 GSList *compression_type_extensions)
117{
118 /*
119 * Add the specified extension.
120 */
121 extensions = g_slist_prepend(extensions, g_strdup(extension)g_strdup_inline (extension));
122
123 /*
124 * Add whatever compressed versions we were supplied.
125 */
126 for (GSList *compression_type_extension = compression_type_extensions;
127 compression_type_extension != NULL((void*)0);
128 compression_type_extension = g_slist_next(compression_type_extension)((compression_type_extension) ? (((GSList *)(compression_type_extension
))->next) : ((void*)0))
) {
129 extensions = g_slist_prepend(extensions,
130 ws_strdup_printf("%s.%s", extension,wmem_strdup_printf(((void*)0), "%s.%s", extension, (const char
*)compression_type_extension->data)
131 (const char *)compression_type_extension->data)wmem_strdup_printf(((void*)0), "%s.%s", extension, (const char
*)compression_type_extension->data)
);
132 }
133
134 return extensions;
135}
136
137/*
138 * File types that can be identified by file extensions.
139 *
140 * These are used in file open dialogs to offer choices of extensions
141 * for which to filter. Note that the first field can list more than
142 * one type of file, because, for example, ".cap" is a popular
143 * extension used by a number of capture file types.
144 *
145 * File types that *don't* have a file extension used for them should
146 * *not* be placed here; if there's nothing to put in the last field
147 * of the structure, don't put an entry here, not even one with an
148 * empty string for the extensions list.
149 *
150 * All added file types, regardless of extension or lack thereof,
151 * must also be added open_info_base[] below.
152 */
153static const struct file_extension_info wireshark_file_type_extensions_base[] = {
154 { "Wireshark/tcpdump/... - pcap", true1, "pcap;cap;dmp" },
155 { "Wireshark/... - pcapng", true1, "pcapng;ntar" },
156 { "Network Monitor, Surveyor, NetScaler", true1, "cap" },
157 { "Sun snoop", true1, "snoop" },
158 { "InfoVista 5View capture", true1, "5vw" },
159 { "Sniffer (DOS)", true1, "cap;enc;trc;fdc;syc" },
160 { "Cinco NetXRay, Sniffer (Windows)", true1, "cap;caz" },
161 { "Endace ERF capture", true1, "erf" },
162 { "EyeSDN USB S0/E1 ISDN trace format", true1, "trc" },
163 { "HP-UX nettl trace", true1, "trc0;trc1" },
164 { "Viavi Observer", true1, "bfr" },
165 { "Colasoft Capsa", true1, "cscpkt" },
166 { "Novell LANalyzer", true1, "tr1" },
167 { "Tektronix K12xx 32-bit .rf5 format", true1, "rf5" },
168 { "Savvius *Peek", true1, "pkt;tpc;apc;wpz" },
169 { "Catapult DCT2000 trace (.out format)", true1, "out" },
170 { "Micropross mplog", true1, "mplog" },
171 { "TamoSoft CommView NCF", true1, "ncf" },
172 { "TamoSoft CommView NCFX", true1, "ncfx" },
173 { "Symbian OS btsnoop", true1, "log" },
174 { "XML files (including Gammu DCT3 traces)", true1, "xml" },
175 { "macOS PacketLogger", true1, "pklg" },
176 { "Daintree SNA", true1, "dcf" },
177 { "IPFIX File Format", true1, "pfx;ipfix" },
178 { "Aethra .aps file", true1, "aps" },
179 { "MPEG2 transport stream", true1, "mp2t;ts;m2ts;mpg" },
180 { "Ixia IxVeriWave .vwr Raw 802.11 Capture", true1, "vwr" },
181 { "CAM Inspector file", true1, "camins" },
182 { "BLF file", true1, "blf" },
183 { "AUTOSAR DLT file", true1, "dlt" },
184 { "TTL file", true1, "ttl" },
185 { "MPEG files", false0, "mpeg;mpg;mp3" },
186 { "Transport-Neutral Encapsulation Format", false0, "tnef" },
187 { "JPEG/JFIF files", false0, "jpg;jpeg;jfif" },
188 { "NetLog file", true1, "json" },
189 { "JavaScript Object Notation file", false0, "json" },
190 { "JSON Log", true1, "json;jsonl;log" },
191 { "MP4 file", false0, "mp4" },
192 { "RTPDump file", false0, "rtp;rtpdump" },
193 { "EMS file", false0, "ems" },
194 { "ASN.1 Basic Encoding Rules", false0, "cer;crl;csr;p10;p12;p772;p7c;p7s;p7m;p8;pfx;tsq;tsr" },
195 { "RFC 7468 files", false0, "crt;pem" },
196 { "PEAK CAN TRC log", true1, "trc" },
197};
198
199#define N_WIRESHARK_FILE_TYPE_EXTENSIONS(sizeof (wireshark_file_type_extensions_base) / sizeof (wireshark_file_type_extensions_base
)[0])
array_length(wireshark_file_type_extensions_base)(sizeof (wireshark_file_type_extensions_base) / sizeof (wireshark_file_type_extensions_base
)[0])
200
201static const struct file_extension_info stratoshark_file_type_extensions_base[] = {
202 { "Stratoshark/... - scap", true1, "scap"},
203 { "JSON Log", true1, "json;jsonl;log" },
204 {"MS Procmon", true1, "pml"},
205};
206
207#define N_STRATOSHARK_FILE_TYPE_EXTENSIONS(sizeof (stratoshark_file_type_extensions_base) / sizeof (stratoshark_file_type_extensions_base
)[0])
array_length(stratoshark_file_type_extensions_base)(sizeof (stratoshark_file_type_extensions_base) / sizeof (stratoshark_file_type_extensions_base
)[0])
208
209static const struct file_extension_info* file_type_extensions;
210
211static GArray* file_type_extensions_arr;
212
213/* initialize the extensions array if it has not been initialized yet */
214static void
215init_file_type_extensions(void)
216{
217
218 if (file_type_extensions_arr) return;
219
220 file_type_extensions_arr = g_array_new(false0,true1,sizeof(struct file_extension_info));
221
222 if (application_flavor_is_wireshark()) {
223 g_array_append_vals(file_type_extensions_arr, wireshark_file_type_extensions_base, N_WIRESHARK_FILE_TYPE_EXTENSIONS(sizeof (wireshark_file_type_extensions_base) / sizeof (wireshark_file_type_extensions_base
)[0])
);
224 } else {
225 g_array_append_vals(file_type_extensions_arr, stratoshark_file_type_extensions_base, N_STRATOSHARK_FILE_TYPE_EXTENSIONS(sizeof (stratoshark_file_type_extensions_base) / sizeof (stratoshark_file_type_extensions_base
)[0])
);
226 }
227
228 file_type_extensions = (struct file_extension_info*)(void *)file_type_extensions_arr->data;
229}
230
231void
232wtap_register_file_type_extension(const struct file_extension_info *ei)
233{
234 init_file_type_extensions();
235
236 g_array_append_val(file_type_extensions_arr,*ei)g_array_append_vals (file_type_extensions_arr, &(*ei), 1);
237
238 file_type_extensions = (const struct file_extension_info*)(void *)file_type_extensions_arr->data;
239}
240
241int
242wtap_get_num_file_type_extensions(void)
243{
244 return file_type_extensions_arr->len;
245}
246
247const char *
248wtap_get_file_extension_type_name(int extension_type)
249{
250 return file_type_extensions[extension_type].name;
251}
252
253static GSList *
254add_extensions_for_file_extensions_type(int extension_type, GSList *extensions,
255 GSList *compression_type_extensions)
256{
257 char **extensions_set, **extensionp, *extension;
258
259 /*
260 * Split the extension-list string into a set of extensions.
261 */
262 extensions_set = g_strsplit(file_type_extensions[extension_type].extensions,
263 ";", 0);
264
265 /*
266 * Add each of those extensions to the list.
267 */
268 for (extensionp = extensions_set; *extensionp != NULL((void*)0); extensionp++) {
269 extension = *extensionp;
270
271 /*
272 * Add the extension, and all compressed variants
273 * of it.
274 */
275 extensions = add_extensions(extensions, extension,
276 compression_type_extensions);
277 }
278
279 g_strfreev(extensions_set);
280 return extensions;
281}
282
283/* Return a list of file extensions that are used by the specified file
284 * extension type.
285 *
286 * All strings in the list are allocated with g_malloc() and must be freed
287 * with g_free().
288 */
289GSList *
290wtap_get_file_extension_type_extensions(unsigned extension_type)
291{
292 GSList *extensions, *compression_type_extensions;
293
294 if (extension_type >= file_type_extensions_arr->len)
295 return NULL((void*)0); /* not a valid extension type */
296
297 extensions = NULL((void*)0); /* empty list, to start with */
298
299 /*
300 * Get compression-type extensions, if any.
301 */
302 compression_type_extensions = ws_get_all_compression_type_extensions_list();
303
304 /*
305 * Add all this file extension type's extensions, with compressed
306 * variants.
307 */
308 extensions = add_extensions_for_file_extensions_type(extension_type,
309 extensions, compression_type_extensions);
310
311 g_slist_free(compression_type_extensions);
312
313 return g_slist_reverse(extensions);
314}
315
316/*
317 * The open_file_* routines must return:
318 *
319 * WTAP_OPEN_ERROR on an I/O error;
320 *
321 * WTAP_OPEN_MINE if the file they're reading is one of the types
322 * it handles;
323 *
324 * WTAP_OPEN_NOT_MINE if the file they're reading isn't the type
325 * they're checking for.
326 *
327 * If the routine handles this type of file, it must set the "file_type"
328 * field in the "struct wtap" to the type of the file.
329 *
330 * Note that the routine does *not* have to free the private data pointer on
331 * error. The caller takes care of that by calling wtap_close on error.
332 * (See https://gitlab.com/wireshark/wireshark/-/issues/8518)
333 *
334 * However, the caller *does* have to free the private data pointer when
335 * returning WTAP_OPEN_NOT_MINE, since the next file type will be called
336 * and will likely just overwrite the pointer.
337 *
338 * The names are used in file open dialogs to select, for files that
339 * don't have magic numbers and that could potentially be files of
340 * more than one type based on the heuristics, a particular file
341 * type to interpret it as, if the file name has no extension, the
342 * extension isn't sufficient to determine the appropriate file type,
343 * or the extension is wrong.
344 *
345 * NOTE: when adding file formats to this list you may also want to add them
346 * to the following files so that the various desktop environments will
347 * know that Wireshark can open the file:
348 * 1) resources/freedesktop/org.wireshark.Wireshark-mime.xml (for freedesktop.org environments)
349 * 2) packaging/macosx/WiresharkInfo.plist.in (for macOS)
350 *
351 * If your file format has a commonly-used extension (e.g., ".pcap") then you
352 * should probably also add it to file_type_extensions_base[] (in this file),
353 * to the list of "<glob pattern=...>" entries for this file format in
354 * resources/freedesktop/org.wireshark.Wireshark-mime.xml, to the
355 * CFBundleTypeExtensions array for this file format in
356 * packaging/macosx/WiresharkInfo.plist, and to the PushFileExtensions macro
357 * in packaging/nsis/wireshark-common.nsh and the File Associations in
358 * packaging/wix/ComponentGroups.wxi (for Windows).
359 */
360static const struct open_info open_info_base[] = {
361 /* Open routines that look for magic numbers */
362 { "Wireshark/tcpdump/... - pcap", OPEN_INFO_MAGIC, libpcap_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
363 { "Wireshark/... - pcapng", OPEN_INFO_MAGIC, pcapng_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
364 { "Sniffer (DOS)", OPEN_INFO_MAGIC, ngsniffer_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
365 { "Snoop, Shomiti/Finisar Surveyor", OPEN_INFO_MAGIC, snoop_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
366 { "AIX iptrace", OPEN_INFO_MAGIC, iptrace_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
367 { "Microsoft Network Monitor", OPEN_INFO_MAGIC, netmon_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
368 { "Cinco NetXray/Sniffer (Windows)", OPEN_INFO_MAGIC, netxray_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
369 { "RADCOM WAN/LAN analyzer", OPEN_INFO_MAGIC, radcom_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
370 { "HP-UX nettl trace", OPEN_INFO_MAGIC, nettl_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
371 { "Visual Networks traffic capture", OPEN_INFO_MAGIC, visual_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
372 { "InfoVista 5View capture", OPEN_INFO_MAGIC, _5views_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
373 { "Viavi Observer", OPEN_INFO_MAGIC, observer_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
374 { "Savvius tagged", OPEN_INFO_MAGIC, peektagged_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
375 { "Colasoft Capsa", OPEN_INFO_MAGIC, capsa_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
376 { "DBS Etherwatch (VMS)", OPEN_INFO_MAGIC, dbs_etherwatch_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
377 { "Tektronix K12xx 32-bit .rf5 format", OPEN_INFO_MAGIC, k12_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
378 { "Catapult DCT2000 trace (.out format)", OPEN_INFO_MAGIC, catapult_dct2000_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
379 { "Aethra .aps file", OPEN_INFO_MAGIC, aethra_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
380 { "Symbian OS btsnoop", OPEN_INFO_MAGIC, btsnoop_open, "log", NULL((void*)0), NULL((void*)0) },
381 { "EyeSDN USB S0/E1 ISDN trace format", OPEN_INFO_MAGIC, eyesdn_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
382 { "Transport-Neutral Encapsulation Format", OPEN_INFO_MAGIC, tnef_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
383 /* 3GPP TS 32.423 Trace must come before MIME Files as it's XML based*/
384 { "3GPP TS 32.423 Trace format", OPEN_INFO_MAGIC, nettrace_3gpp_32_423_file_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
385 /* Gammu DCT3 trace must come before MIME files as it's XML based*/
386 { "Gammu DCT3 trace", OPEN_INFO_MAGIC, dct3trace_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
387 { "BLF Logfile", OPEN_INFO_MAGIC, blf_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
388 { "AUTOSAR DLT Logfile", OPEN_INFO_MAGIC, autosar_dlt_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
389 { "TTL Logfile", OPEN_INFO_MAGIC, ttl_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
390 { "RTPDump files", OPEN_INFO_MAGIC, rtpdump_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
391 { "MIME Files Format", OPEN_INFO_MAGIC, mime_file_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
392 { "Micropross mplog", OPEN_INFO_MAGIC, mplog_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
393 { "Unigraf DPA-400 capture", OPEN_INFO_MAGIC, dpa400_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
394 { "RFC 7468 files", OPEN_INFO_MAGIC, rfc7468_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
395 { "MS Procmon Files", OPEN_INFO_MAGIC, procmon_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
396
397 /* Open routines that have no magic numbers and require heuristics. */
398 { "Novell LANalyzer", OPEN_INFO_HEURISTIC, lanalyzer_open, "tr1", NULL((void*)0), NULL((void*)0) },
399 /*
400 * PacketLogger must come before MPEG, because its files
401 * are sometimes grabbed by mpeg_open.
402 */
403 { "macOS PacketLogger", OPEN_INFO_HEURISTIC, packetlogger_open, "pklg", NULL((void*)0), NULL((void*)0) },
404 /* Some MPEG files have magic numbers, others just have heuristics. */
405 { "MPEG", OPEN_INFO_HEURISTIC, mpeg_open, "mpeg;mpg;mp3", NULL((void*)0), NULL((void*)0) },
406 { "Daintree SNA", OPEN_INFO_HEURISTIC, daintree_sna_open, "dcf", NULL((void*)0), NULL((void*)0) },
407 { "STANAG 4607 Format", OPEN_INFO_HEURISTIC, stanag4607_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
408 { "ASN.1 Basic Encoding Rules", OPEN_INFO_HEURISTIC, ber_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
409 /*
410 * I put NetScreen *before* erf, because there were some
411 * false positives with my test-files (Sake Blok, July 2007)
412 *
413 * I put VWR *after* ERF, because there were some cases where
414 * ERF files were misidentified as vwr files (Stephen
415 * Donnelly, August 2013; see bug 9054)
416 *
417 * I put VWR *after* Peek Classic, CommView, iSeries text,
418 * Toshiba text, K12 text, VMS tcpiptrace text, and NetScaler,
419 * because there were some cases where files of those types were
420 * misidentified as vwr files (Guy Harris, December 2013)
421 */
422 { "NetScreen snoop text file", OPEN_INFO_HEURISTIC, netscreen_open, "txt", NULL((void*)0), NULL((void*)0) },
423 { "Endace ERF capture", OPEN_INFO_HEURISTIC, erf_open, "erf", NULL((void*)0), NULL((void*)0) },
424 { "IPFIX File Format", OPEN_INFO_HEURISTIC, ipfix_open, "pfx;ipfix",NULL((void*)0), NULL((void*)0) },
425 { "K12 text file", OPEN_INFO_HEURISTIC, k12text_open, "txt", NULL((void*)0), NULL((void*)0) },
426 { "Savvius classic", OPEN_INFO_HEURISTIC, peekclassic_open, "pkt;tpc;apc;wpz", NULL((void*)0), NULL((void*)0) },
427 { "pppd log (pppdump format)", OPEN_INFO_HEURISTIC, pppdump_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
428 { "IBM iSeries comm. trace", OPEN_INFO_HEURISTIC, iseries_open, "txt", NULL((void*)0), NULL((void*)0) },
429 { "I4B ISDN trace", OPEN_INFO_HEURISTIC, i4btrace_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
430 { "MPEG2 transport stream", OPEN_INFO_HEURISTIC, mp2t_open, "mp2t;ts;mpg", NULL((void*)0), NULL((void*)0) },
431 { "CSIDS IPLog", OPEN_INFO_HEURISTIC, csids_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
432 { "TCPIPtrace (VMS)", OPEN_INFO_HEURISTIC, vms_open, "txt", NULL((void*)0), NULL((void*)0) },
433 { "CoSine IPSX L2 capture", OPEN_INFO_HEURISTIC, cosine_open, "txt", NULL((void*)0), NULL((void*)0) },
434 { "Bluetooth HCI dump", OPEN_INFO_HEURISTIC, hcidump_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
435 { "TamoSoft CommView NCF", OPEN_INFO_HEURISTIC, commview_ncf_open, "ncf", NULL((void*)0), NULL((void*)0) },
436 { "TamoSoft CommView NCFX", OPEN_INFO_HEURISTIC, commview_ncfx_open, "ncfx", NULL((void*)0), NULL((void*)0) },
437 { "NetScaler", OPEN_INFO_HEURISTIC, nstrace_open, "cap", NULL((void*)0), NULL((void*)0) },
438 { "Android Logcat Binary format", OPEN_INFO_HEURISTIC, logcat_open, "logcat", NULL((void*)0), NULL((void*)0) },
439 { "Android Logcat Text formats", OPEN_INFO_HEURISTIC, logcat_text_open, "txt", NULL((void*)0), NULL((void*)0) },
440 { "Candump log", OPEN_INFO_HEURISTIC, candump_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
441 { "Busmaster log", OPEN_INFO_HEURISTIC, busmaster_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
442 { "CSS Electronics CLX000 CAN log", OPEN_INFO_MAGIC, cllog_open, "txt", NULL((void*)0), NULL((void*)0) },
443 { "Ericsson eNode-B raw log", OPEN_INFO_MAGIC, eri_enb_log_open, NULL((void*)0), NULL((void*)0), NULL((void*)0) },
444 { "Systemd Journal", OPEN_INFO_HEURISTIC, systemd_journal_open, "log;jnl;journal", NULL((void*)0), NULL((void*)0) },
445 { "PEAK CAN TRC log", OPEN_INFO_HEURISTIC, peak_trc_open, "trc", NULL((void*)0), NULL((void*)0) },
446
447 /* ASCII trace files from Telnet sessions. */
448 { "Lucent/Ascend access server trace", OPEN_INFO_HEURISTIC, ascend_open, "txt", NULL((void*)0), NULL((void*)0) },
449 { "Toshiba Compact ISDN Router snoop", OPEN_INFO_HEURISTIC, toshiba_open, "txt", NULL((void*)0), NULL((void*)0) },
450
451 { "EGNOS Message Server (EMS) file", OPEN_INFO_HEURISTIC, ems_open, "ems", NULL((void*)0), NULL((void*)0) },
452
453 /* Extremely weak heuristics - put them at the end. */
454 { "Ixia IxVeriWave .vwr Raw Capture", OPEN_INFO_HEURISTIC, vwr_open, "vwr", NULL((void*)0), NULL((void*)0) },
455 { "CAM Inspector file", OPEN_INFO_HEURISTIC, camins_open, "camins", NULL((void*)0), NULL((void*)0) },
456 /* NetLog needs to be before JSON because it is a specifically formatted JSON file */
457 { "NetLog", OPEN_INFO_HEURISTIC, netlog_open, "json", NULL((void*)0), NULL((void*)0) },
458 /* JSON Log needs to be before JSON because it handles a variety of JSON logs */
459 { "JSON Log", OPEN_INFO_HEURISTIC, json_log_open, "json;jsonl;log", NULL((void*)0), NULL((void*)0) },
460 { "JavaScript Object Notation", OPEN_INFO_HEURISTIC, json_open, "json", NULL((void*)0), NULL((void*)0) },
461 { "Bachmann M-Module File", OPEN_INFO_HEURISTIC, mmodule_open, "m", NULL((void*)0), NULL((void*)0) },
462 { "Ruby Marshal Object", OPEN_INFO_HEURISTIC, ruby_marshal_open, "", NULL((void*)0), NULL((void*)0) },
463 { "3gpp phone log", OPEN_INFO_MAGIC, log3gpp_open, "log", NULL((void*)0), NULL((void*)0) },
464 { "MP4 media file", OPEN_INFO_MAGIC, mp4_open, "mp4", NULL((void*)0), NULL((void*)0) },
465};
466
467/* this is only used to build the dynamic array on load, do NOT use this
468 * for anything else, because the size of the actual array will change if
469 * Lua scripts register a new file reader.
470 */
471#define N_OPEN_INFO_ROUTINES(sizeof (open_info_base) / sizeof (open_info_base)[0]) array_length(open_info_base)(sizeof (open_info_base) / sizeof (open_info_base)[0])
472
473static GArray *open_info_arr;
474
475/* this always points to the top of the created array */
476struct open_info *open_routines;
477
478/* this points to the first OPEN_INFO_HEURISTIC type in the array */
479static unsigned heuristic_open_routine_idx;
480
481static void
482set_heuristic_routine(void)
483{
484 unsigned i;
485 ws_assert(open_info_arr != NULL)do { if ((1) && !(open_info_arr != ((void*)0))) ws_log_fatal_full
("Wiretap", LOG_LEVEL_ERROR, "wiretap/file_access.c", 485, __func__
, "assertion failed: %s", "open_info_arr != ((void*)0)"); } while
(0)
;
486
487 for (i = 0; i < open_info_arr->len; i++) {
488 if (open_routines[i].type == OPEN_INFO_HEURISTIC) {
489 heuristic_open_routine_idx = i;
490 break;
491 }
492 /* sanity check */
493 ws_assert(open_routines[i].type == OPEN_INFO_MAGIC)do { if ((1) && !(open_routines[i].type == OPEN_INFO_MAGIC
)) ws_log_fatal_full("Wiretap", LOG_LEVEL_ERROR, "wiretap/file_access.c"
, 493, __func__, "assertion failed: %s", "open_routines[i].type == OPEN_INFO_MAGIC"
); } while (0)
;
494 }
495
496 ws_assert(heuristic_open_routine_idx > 0)do { if ((1) && !(heuristic_open_routine_idx > 0))
ws_log_fatal_full("Wiretap", LOG_LEVEL_ERROR, "wiretap/file_access.c"
, 496, __func__, "assertion failed: %s", "heuristic_open_routine_idx > 0"
); } while (0)
;
497}
498
499void
500init_open_routines(void)
501{
502 unsigned int i;
503 struct open_info *i_open;
504
505 if (open_info_arr)
506 return;
507
508 open_info_arr = g_array_new(true1,true1,sizeof(struct open_info));
509
510 g_array_append_vals(open_info_arr, open_info_base, N_OPEN_INFO_ROUTINES(sizeof (open_info_base) / sizeof (open_info_base)[0]));
511
512 open_routines = (struct open_info *)(void*) open_info_arr->data;
513
514 /* Populate the extensions_set list now */
515 for (i = 0, i_open = open_routines; i < open_info_arr->len; i++, i_open++) {
516 if (i_open->extensions != NULL((void*)0))
517 i_open->extensions_set = g_strsplit(i_open->extensions, ";", 0);
518 }
519
520 set_heuristic_routine();
521}
522
523/*
524 * Registers a new file reader - currently only called by wslua code for
525 * Lua readers and by compiled file reader plugins.
526 *
527 * If first_routine is true, the reader added before other readers of its
528 * type (magic or heuristic). This should be done only in cases where
529 * this reader's open test must be performed early, to avoid false
530 * positives for other readers' tests treating files for this reader
531 * as being for another reader.
532 *
533 * XXX - given that there is no guarantee that registration routines will
534 * be called in a given order, all this really does is divide readers for
535 * a given type (magic or heuristic) into two categories, with open routines
536 * for readers in the first category (first_routine true) all being called
537 * before readers in the second category; it does not guarantee a particular
538 * total order for open routines.
539 *
540 * Checks for an existing reader of the same name and errors if it finds one;
541 * if you want to handle that condition more gracefully, call
542 * wtap_has_open_info() first.
543 */
544void
545wtap_register_open_info(struct open_info *oi, const bool_Bool first_routine)
546{
547 if (!oi || !oi->name) {
548 ws_error("No open_info name given to register")ws_log_fatal_full("Wiretap", LOG_LEVEL_ERROR, "wiretap/file_access.c"
, 548, __func__, "No open_info name given to register")
;
549 return;
550 }
551
552 /* verify name doesn't already exist */
553 if (wtap_has_open_info(oi->name)) {
554 ws_error("Name given to register_open_info already exists")ws_log_fatal_full("Wiretap", LOG_LEVEL_ERROR, "wiretap/file_access.c"
, 554, __func__, "Name given to register_open_info already exists"
)
;
555 return;
556 }
557
558 if (oi->extensions != NULL((void*)0))
559 oi->extensions_set = g_strsplit(oi->extensions, ";", 0);
560
561 /* if it's magic and first, prepend it; if it's heuristic and not first,
562 append it; if it's anything else, stick it in the middle */
563 if (first_routine && oi->type == OPEN_INFO_MAGIC) {
564 g_array_prepend_val(open_info_arr, *oi)g_array_prepend_vals (open_info_arr, &(*oi), 1);
565 } else if (!first_routine && oi->type == OPEN_INFO_HEURISTIC) {
566 g_array_append_val(open_info_arr, *oi)g_array_append_vals (open_info_arr, &(*oi), 1);
567 } else {
568 g_array_insert_val(open_info_arr, heuristic_open_routine_idx, *oi)g_array_insert_vals (open_info_arr, heuristic_open_routine_idx
, &(*oi), 1)
;
569 }
570
571 open_routines = (struct open_info *)(void*) open_info_arr->data;
572 set_heuristic_routine();
573}
574
575/* De-registers a file reader by removing it from the GArray based on its name.
576 * This function must NOT be called during wtap_open_offline(), since it changes the array.
577 * Note: this function will error if it doesn't find the given name; if you want to handle
578 * that condition more gracefully, call wtap_has_open_info() first.
579 */
580void
581wtap_deregister_open_info(const char *name)
582{
583 unsigned i;
584
585 if (!name) {
586 ws_error("Missing open_info name to de-register")ws_log_fatal_full("Wiretap", LOG_LEVEL_ERROR, "wiretap/file_access.c"
, 586, __func__, "Missing open_info name to de-register")
;
587 return;
588 }
589
590 for (i = 0; i < open_info_arr->len; i++) {
591 if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) {
592 g_strfreev(open_routines[i].extensions_set);
593 open_info_arr = g_array_remove_index(open_info_arr, i);
594 set_heuristic_routine();
595 return;
596 }
597 }
598
599 ws_error("deregister_open_info: name not found")ws_log_fatal_full("Wiretap", LOG_LEVEL_ERROR, "wiretap/file_access.c"
, 599, __func__, "deregister_open_info: name not found")
;
600}
601
602/* Determines if a open routine short name already exists
603 */
604bool_Bool
605wtap_has_open_info(const char *name)
606{
607 unsigned i;
608
609 if (!name) {
610 ws_error("No name given to wtap_has_open_info!")ws_log_fatal_full("Wiretap", LOG_LEVEL_ERROR, "wiretap/file_access.c"
, 610, __func__, "No name given to wtap_has_open_info!")
;
611 return false0;
612 }
613
614
615 for (i = 0; i < open_info_arr->len; i++) {
616 if (open_routines[i].name && strcmp(open_routines[i].name, name) == 0) {
617 return true1;
618 }
619 }
620
621 return false0;
622}
623
624bool_Bool
625wtap_uses_lua_filehandler(const wtap* wth)
626{
627 if (wth && wth->wslua_data != NULL((void*)0)) {
628 /*
629 * Currently, wslua_data is set if and only if using a Lua
630 * file handler.
631 */
632 return true1;
633 }
634
635 return false0;
636}
637
638/*
639 * Visual C++ on Win32 systems doesn't define these. (Old UNIX systems don't
640 * define them either.)
641 *
642 * Visual C++ on Win32 systems doesn't define S_IFIFO, it defines _S_IFIFO.
643 */
644#ifndef S_ISREG
645#define S_ISREG(mode)((((mode)) & 0170000) == (0100000)) (((mode) & S_IFMT0170000) == S_IFREG0100000)
646#endif
647#ifndef S_IFIFO0010000
648#define S_IFIFO0010000 _S_IFIFO
649#endif
650#ifndef S_ISFIFO
651#define S_ISFIFO(mode)((((mode)) & 0170000) == (0010000)) (((mode) & S_IFMT0170000) == S_IFIFO0010000)
652#endif
653#ifndef S_ISDIR
654#define S_ISDIR(mode)((((mode)) & 0170000) == (0040000)) (((mode) & S_IFMT0170000) == S_IFDIR0040000)
655#endif
656
657/* returns the 'type' number to use for wtap_open_offline based on the
658 * passed-in name (the name in the open_info struct). It returns WTAP_TYPE_AUTO
659 * on failure, which is the number 0. The 'type' number is the entry's index+1,
660 * because that's what wtap_open_offline() expects it to be.
661 */
662unsigned int
663open_info_name_to_type(const char *name)
664{
665 unsigned int i;
666
667 if (!name)
668 return WTAP_TYPE_AUTO0;
669
670 for (i = 0; i < open_info_arr->len; i++) {
671 if (open_routines[i].name != NULL((void*)0) &&
672 strcmp(name, open_routines[i].name) == 0)
673 return i+1;
674 }
675
676 return WTAP_TYPE_AUTO0; /* no such file type */
677}
678
679static char *
680get_file_extension(const char *pathname)
681{
682 char *filename;
683 char **components;
684 size_t ncomponents;
685 char *extensionp;
686
687 /*
688 * Is the pathname empty?
689 */
690 if (strcmp(pathname, "") == 0)
691 return NULL((void*)0); /* no extension */
692
693 /*
694 * Find the last component of the pathname.
695 */
696 filename = g_path_get_basename(pathname);
697
698 /*
699 * Does it have an extension?
700 */
701 if (strchr(filename, '.') == NULL((void*)0)) {
702 g_free(filename);
703 return NULL((void*)0); /* no extension whatsoever */
704 }
705
706 /*
707 * Yes. Fold it to lowercase, since open_routines[] has
708 * its extensions in lowercase.
709 */
710 ascii_strdown_inplace(filename);
711
712 /*
713 * Split it into components separated by ".".
714 */
715 components = g_strsplit(filename, ".", 0);
716 g_free(filename);
717
718 /*
719 * Count the components.
720 */
721 for (ncomponents = 0; components[ncomponents] != NULL((void*)0); ncomponents++)
722 ;
723
724 if (ncomponents == 0) {
725 g_strfreev(components);
726 return NULL((void*)0); /* no components */
727 }
728 if (ncomponents == 1) {
729 g_strfreev(components);
730 return NULL((void*)0); /* only one component, with no "." */
731 }
732
733 /*
734 * Get compression-type extensions, if any.
735 */
736 GSList *compression_type_extensions = ws_get_all_compression_type_extensions_list();
737
738 /*
739 * Is the last component one of the extensions used for compressed
740 * files?
741 */
742 extensionp = components[ncomponents - 1];
743 for (GSList *compression_type_extension = compression_type_extensions;
744 compression_type_extension != NULL((void*)0);
745 compression_type_extension = g_slist_next(compression_type_extension)((compression_type_extension) ? (((GSList *)(compression_type_extension
))->next) : ((void*)0))
) {
746 if (strcmp(extensionp, (const char *)compression_type_extension->data) == 0) {
747 /*
748 * Yes, so it's one of the compressed-file extensions.
749 * Is there an extension before that?
750 */
751 if (ncomponents == 2) {
752 g_slist_free(compression_type_extensions);
753 g_strfreev(components);
754 return NULL((void*)0); /* no, only two components */
755 }
756
757 /*
758 * Yes, return that extension.
759 */
760 g_slist_free(compression_type_extensions);
761 extensionp = g_strdup(components[ncomponents - 2])g_strdup_inline (components[ncomponents - 2]);
762 g_strfreev(components);
763 return extensionp;
764 }
765 }
766
767 g_slist_free(compression_type_extensions);
768
769 /*
770 * The extension isn't one of the compressed-file extensions;
771 * return it.
772 */
773 extensionp = g_strdup(extensionp)g_strdup_inline (extensionp);
774 g_strfreev(components);
775 return extensionp;
776}
777
778/*
779 * Check if file extension is used in this heuristic
780 */
781static bool_Bool
782heuristic_uses_extension(unsigned int i, const char *extension)
783{
784 char **extensionp;
785
786 /*
787 * Does this file type *have* any extensions?
788 */
789 if (open_routines[i].extensions == NULL((void*)0))
790 return false0; /* no */
791
792 /*
793 * Check each of them against the specified extension.
794 */
795 for (extensionp = open_routines[i].extensions_set; *extensionp != NULL((void*)0);
796 extensionp++) {
797 if (strcmp(extension, *extensionp) == 0) {
798 return true1; /* it's one of them */
799 }
800 }
801
802 return false0; /* it's not one of them */
803}
804
805/*
806 * Attempt to open the file corresponding to "wth" using the file format
807 * handler in "candidate".
808 *
809 * Returns WTAP_OPEN_MINE upon success, WTAP_OPEN_NOT_MINE if the file is not
810 * in a suitable format for "candidate", or WTAP_OPEN_ERROR if a failure
811 * occurred while reading the input.
812 */
813static int
814try_one_open(wtap *wth, const struct open_info *candidate, int *err, char **err_info)
815{
816 /* Seek back to the beginning of the file; the open routine for the
817 * previous file type may have left the file position somewhere other
818 * than the beginning, and the open routine for this file type will
819 * probably want to start reading at the beginning.
820 *
821 * Initialize the data offset while we're at it.
822 */
823 if (file_seek(wth->fh, 0, SEEK_SET0, err) == -1) {
824 /* Error - give up */
825 return WTAP_OPEN_ERROR;
826 }
827
828 /* Set wth with wslua data if any - this is how we pass the data to the
829 * file reader, kinda like the priv member but not free'd later.
830 * It's ok for this to copy a NULL.
831 */
832 wth->wslua_data = candidate->wslua_data;
833
834 return candidate->open_routine(wth, err, err_info);
835}
836
837/*
838 * Attempt to open the file corresponding to "wth". If "type" is supplied
839 * (i.e. other than WTAP_TYPE_AUTO), that will be the only type attempted.
840 * Otherwise, heuristic detection of the file format will be performed,
841 * possibly guided by the extension part of "filename".
842 *
843 * Returns WTAP_OPEN_MINE upon success, WTAP_OPEN_NOT_MINE if it was not
844 * possible to determine a suitable format for the file, or WTAP_OPEN_ERROR if
845 * a failure occurred while reading the input.
846 */
847static int
848try_open(wtap *wth, unsigned int type, int *err, char **err_info)
849{
850 int result = WTAP_OPEN_NOT_MINE;
851 unsigned i;
852 char *extension;
853
854 /* 'type' is 1-based. */
855 if (type != WTAP_TYPE_AUTO0 && type <= open_info_arr->len) {
856 /* Try only the specified type. */
857 return try_one_open(wth, &open_routines[type - 1], err, err_info);
858 }
859
860 /* First, all file types that support magic numbers. */
861 for (i = 0; i < heuristic_open_routine_idx && result == WTAP_OPEN_NOT_MINE; i++) {
862 result = try_one_open(wth, &open_routines[i], err, err_info);
863 }
864
865 if (result != WTAP_OPEN_NOT_MINE) {
866 return result;
867 }
868
869 /* Does this file's name have an extension? */
870 extension = get_file_extension(wth->pathname);
871 if (extension != NULL((void*)0)) {
872 unsigned pass;
873
874 /*
875 * Yes, the filename has an extension.
876 *
877 * The heuristic types fall into one of three categories, which
878 * we attempt in order by scanning for each category in turn.
879 *
880 * First pass selects the heuristic types that list this file's
881 * extension, as these are most likely to be the correct choice
882 * for this file.
883 *
884 * Second pass selects heuristic types which have no
885 * extensions. We try those before the ones that have
886 * extensions that *don't* match this file's extension, on the
887 * theory that files of those types generally have one of the
888 * type's extensions, and, as this file *doesn't* have one of
889 * those extensions, it's probably *not* one of those files.
890 *
891 * Third pass selects heuristic types which support extensions
892 * but where none of them matches this file's extension.
893 *
894 * We need only continue searching until we find a match or an
895 * error occurs.
896 */
897
898 for (pass = 0; pass < 3 && result == WTAP_OPEN_NOT_MINE; pass++) {
899 for (i = heuristic_open_routine_idx; i < open_info_arr->len && result == WTAP_OPEN_NOT_MINE; i++) {
900 if ( (pass == 0 && heuristic_uses_extension(i, extension))
901 || (pass == 1 && open_routines[i].extensions == NULL((void*)0))
902 || (pass == 2 && open_routines[i].extensions != NULL((void*)0)
903 && !heuristic_uses_extension(i, extension))) {
904 result = try_one_open(wth, &open_routines[i], err, err_info);
905 }
906 }
907 }
908
909 g_free(extension);
910 } else {
911 /* No extension. Try all the heuristic types in order. */
912 for (i = heuristic_open_routine_idx; i < open_info_arr->len && result == WTAP_OPEN_NOT_MINE; i++) {
913 result = try_one_open(wth, &open_routines[i], err, err_info);
914 }
915 }
916
917 return result;
918}
919
920/* Opens a file and prepares a wtap struct.
921 * If "do_random" is true, it opens the file twice; the second open
922 * allows the application to do random-access I/O without moving
923 * the seek offset for sequential I/O, which is used by Wireshark
924 * so that it can do sequential I/O to a capture file that's being
925 * written to as new packets arrive independently of random I/O done
926 * to display protocol trees for packets when they're selected.
927 */
928wtap *
929wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_info,
930 bool_Bool do_random)
931{
932 int fd;
933 ws_statb64struct stat statb;
934 bool_Bool ispipe = false0;
935 wtap *wth;
936 bool_Bool use_stdin = false0;
937 wtap_block_t shb;
938
939 *err = 0;
940 *err_info = NULL((void*)0);
941
942 /* open standard input if filename is '-' */
943 if (strcmp(filename, "-") == 0)
944 use_stdin = true1;
945
946 /* First, make sure the file is valid */
947 if (use_stdin) {
948 if (ws_fstat64fstat(0, &statb) < 0) {
949 *err = errno(*__errno_location ());
950 return NULL((void*)0);
951 }
952 } else {
953 if (ws_stat64stat(filename, &statb) < 0) {
954 *err = errno(*__errno_location ());
955 return NULL((void*)0);
956 }
957 }
958 if (S_ISFIFO(statb.st_mode)((((statb.st_mode)) & 0170000) == (0010000))) {
959 /*
960 * Opens of FIFOs are allowed only when not opening
961 * for random access.
962 *
963 * Currently, we do seeking when trying to find out
964 * the file type, but our I/O routines do some amount
965 * of buffering, and do backward seeks within the buffer
966 * if possible, so at least some file types can be
967 * opened from pipes, so we don't completely disallow opens
968 * of pipes.
969 */
970 if (do_random) {
971 *err = WTAP_ERR_RANDOM_OPEN_PIPE-2;
972 return NULL((void*)0);
973 }
974 ispipe = true1;
975 } else if (S_ISDIR(statb.st_mode)((((statb.st_mode)) & 0170000) == (0040000))) {
976 /*
977 * Return different errors for "this is a directory"
978 * and "this is some random special file type", so
979 * the user can get a potentially more helpful error.
980 */
981 *err = EISDIR21;
982 return NULL((void*)0);
983 } else if (! S_ISREG(statb.st_mode)((((statb.st_mode)) & 0170000) == (0100000))) {
984 *err = WTAP_ERR_NOT_REGULAR_FILE-1;
985 return NULL((void*)0);
986 }
987
988 /*
989 * We need two independent descriptors for random access, so
990 * they have different file positions. If we're opening the
991 * standard input, we can only dup it to get additional
992 * descriptors, so we can't have two independent descriptors,
993 * and thus can't do random access.
994 */
995 if (use_stdin && do_random) {
996 *err = WTAP_ERR_RANDOM_OPEN_STDIN-16;
997 return NULL((void*)0);
998 }
999
1000 errno(*__errno_location ()) = ENOMEM12;
1001 wth = g_new0(wtap, 1)((wtap *) g_malloc0_n ((1), sizeof (wtap)));
1002
1003 /* Open the file */
1004 errno(*__errno_location ()) = WTAP_ERR_CANT_OPEN-6;
1005 if (use_stdin) {
1006 /*
1007 * We dup FD 0, so that we don't have to worry about
1008 * a file_close of wth->fh closing the standard
1009 * input of the process.
1010 */
1011 fd = ws_dupdup(0);
1012 if (fd < 0) {
1013 *err = errno(*__errno_location ());
1014 g_free(wth);
1015 return NULL((void*)0);
1016 }
1017#ifdef _WIN32
1018 if (_setmode(fd, O_BINARY0) == -1) {
1019 /* "Shouldn't happen" */
1020 *err = errno(*__errno_location ());
1021 g_free(wth);
1022 return NULL((void*)0);
1023 }
1024#endif
1025 if (!(wth->fh = file_fdopen(fd))) {
1026 *err = errno(*__errno_location ());
1027 ws_closeclose(fd);
1028 g_free(wth);
1029 return NULL((void*)0);
1030 }
1031 } else {
1032 if (!(wth->fh = file_open(filename))) {
1033 *err = errno(*__errno_location ());
1034 g_free(wth);
1035 return NULL((void*)0);
1036 }
1037 }
1038
1039 if (do_random) {
1040 if (!(wth->random_fh = file_open(filename))) {
1041 *err = errno(*__errno_location ());
1042 file_close(wth->fh);
1043 g_free(wth);
1044 return NULL((void*)0);
1045 }
1046 } else
1047 wth->random_fh = NULL((void*)0);
1048
1049 /* initialization */
1050 wth->ispipe = ispipe;
1051 wth->file_encap = WTAP_ENCAP_UNKNOWN0;
1052 wth->subtype_sequential_close = NULL((void*)0);
1053 wth->subtype_close = NULL((void*)0);
1054 wth->file_tsprec = WTAP_TSPREC_USEC6;
1055 nstime_set_unset(&wth->file_start_ts);
1056 nstime_set_unset(&wth->file_end_ts);
1057 wth->pathname = g_strdup(filename)g_strdup_inline (filename);
1058 wth->priv = NULL((void*)0);
1059 wth->wslua_data = NULL((void*)0);
1060 wth->shb_hdrs = g_array_new(false0, false0, sizeof(wtap_block_t));
1061 shb = wtap_block_create(WTAP_BLOCK_SECTION);
1062 if (shb)
1063 g_array_append_val(wth->shb_hdrs, shb)g_array_append_vals (wth->shb_hdrs, &(shb), 1);
1064
1065 /* Initialize the array containing a list of interfaces. pcapng_open and
1066 * erf_open needs this (and libpcap_open for ERF encapsulation types).
1067 * Always initing it here saves checking for a NULL ptr later. */
1068 wth->interface_data = g_array_new(false0, false0, sizeof(wtap_block_t));
1069 /*
1070 * Next interface data that wtap_get_next_interface_description()
1071 * will return.
1072 */
1073 wth->next_interface_data = 0;
1074
1075 wth->shb_iface_to_global = g_array_new(false0, false0, sizeof(unsigned));
1076 g_array_append_val(wth->shb_iface_to_global, wth->interface_data->len)g_array_append_vals (wth->shb_iface_to_global, &(wth->
interface_data->len), 1)
;
1077
1078 if (wth->random_fh) {
1079 wth->fast_seek = g_ptr_array_new();
1080
1081 file_set_random_access(wth->fh, false0, wth->fast_seek);
1082 file_set_random_access(wth->random_fh, true1, wth->fast_seek);
1083 }
1084
1085 /* Find a file format handler which can read the file. */
1086 switch (try_open(wth, type, err, err_info)) {
1087 case WTAP_OPEN_NOT_MINE:
1088 /* Well, it's not one of the types of file we know about. */
1089 *err = WTAP_ERR_FILE_UNKNOWN_FORMAT-3;
1090 /* FALLTHROUGH */
1091
1092 case WTAP_OPEN_ERROR:
1093 wtap_close(wth);
1094 wth = NULL((void*)0);
1095 }
1096
1097 return wth;
1098}
1099
1100/*
1101 * Given the pathname of the file we just closed with wtap_fdclose(), attempt
1102 * to reopen that file and assign the new file descriptor(s) to the sequential
1103 * stream and, if do_random is true, to the random stream. Used on Windows
1104 * after the rename of a file we had open was done or if the rename of a
1105 * file on top of a file we had open failed.
1106 *
1107 * This is only required by Wireshark, not TShark, and, at the point that
1108 * Wireshark is doing this, the sequential stream is closed, and the
1109 * random stream is open, so this refuses to open pipes, and only
1110 * reopens the random stream.
1111 */
1112bool_Bool
1113wtap_fdreopen(wtap *wth, const char *filename, int *err)
1114{
1115 ws_statb64struct stat statb;
1116
1117 /*
1118 * We need two independent descriptors for random access, so
1119 * they have different file positions. If we're opening the
1120 * standard input, we can only dup it to get additional
1121 * descriptors, so we can't have two independent descriptors,
1122 * and thus can't do random access.
1123 */
1124 if (strcmp(filename, "-") == 0) {
1125 *err = WTAP_ERR_RANDOM_OPEN_STDIN-16;
1126 return false0;
1127 }
1128
1129 /* First, make sure the file is valid */
1130 if (ws_stat64stat(filename, &statb) < 0) {
1131 *err = errno(*__errno_location ());
1132 return false0;
1133 }
1134 if (S_ISFIFO(statb.st_mode)((((statb.st_mode)) & 0170000) == (0010000))) {
1135 /*
1136 * Opens of FIFOs are not allowed; see above.
1137 */
1138 *err = WTAP_ERR_RANDOM_OPEN_PIPE-2;
1139 return false0;
1140 } else if (S_ISDIR(statb.st_mode)((((statb.st_mode)) & 0170000) == (0040000))) {
1141 /*
1142 * Return different errors for "this is a directory"
1143 * and "this is some random special file type", so
1144 * the user can get a potentially more helpful error.
1145 */
1146 *err = EISDIR21;
1147 return false0;
1148 } else if (! S_ISREG(statb.st_mode)((((statb.st_mode)) & 0170000) == (0100000))) {
1149 *err = WTAP_ERR_NOT_REGULAR_FILE-1;
1150 return false0;
1151 }
1152
1153 /* Open the file */
1154 errno(*__errno_location ()) = WTAP_ERR_CANT_OPEN-6;
1155 if (!file_fdreopen(wth->random_fh, filename)) {
1156 *err = errno(*__errno_location ());
1157 return false0;
1158 }
1159 if (strcmp(filename, wth->pathname) != 0) {
1160 g_free(wth->pathname);
1161 wth->pathname = g_strdup(filename)g_strdup_inline (filename);
1162 }
1163 return true1;
1164}
1165
1166/* Table of the file types and subtypes for which we have support. */
1167
1168/*
1169 * Pointer to the GArray holding the registered file types.
1170 */
1171static GArray* file_type_subtype_table_arr;
1172
1173/*
1174 * Pointer to the table of registered file types in that GArray.
1175 */
1176static const struct file_type_subtype_info* file_type_subtype_table;
1177
1178/*
1179 * Number of elements in the table for builtin file types/subtypes.
1180 */
1181static unsigned wtap_num_builtin_file_types_subtypes;
1182
1183/*
1184 * Required builtin types.
1185 */
1186int pcap_file_type_subtype = -1;
1187int pcap_nsec_file_type_subtype = -1;
1188int pcapng_file_type_subtype = -1;
1189
1190/*
1191 * Table for mapping old file type/subtype names to new ones for
1192 * backwards compatibility.
1193 */
1194static GHashTable *type_subtype_name_map;
1195
1196/*
1197 * Initialize the table of file types/subtypes with all the builtin
1198 * types/subtypes.
1199 */
1200void
1201wtap_init_file_type_subtypes(void)
1202{
1203 /* Don't do this twice. */
1204 ws_assert(file_type_subtype_table_arr == NULL)do { if ((1) && !(file_type_subtype_table_arr == ((void
*)0))) ws_log_fatal_full("Wiretap", LOG_LEVEL_ERROR, "wiretap/file_access.c"
, 1204, __func__, "assertion failed: %s", "file_type_subtype_table_arr == ((void*)0)"
); } while (0)
;
1205
1206 /*
1207 * Estimate the number of file types/subtypes as twice the
1208 * number of modules; that's probably an overestimate, as
1209 * the average number of file types/subtypes registered by
1210 * a module is > 1 but probably < 2, but that shouldn't
1211 * waste too much memory.
1212 *
1213 * Add on 7 more for pcapng, pcap, nanosecond pcap, and the
1214 * extra modified flavors of pcap.
1215 */
1216 file_type_subtype_table_arr = g_array_sized_new(false0, true1,
1217 sizeof(struct file_type_subtype_info), wtap_module_count*2 + 7);
1218 file_type_subtype_table = (const struct file_type_subtype_info*)(void *)file_type_subtype_table_arr->data;
1219
1220 /*
1221 * Initialize the hash table for mapping old file type/subtype
1222 * names to the corresponding new names.
1223 */
1224 type_subtype_name_map = g_hash_table_new_full(g_str_hash,
1225 g_str_equal, g_free, g_free);
1226
1227 /* No entries yet, so no builtin entries yet. */
1228 wtap_num_builtin_file_types_subtypes = 0;
1229
1230 /*
1231 * Register the builtin entries that aren't in the table.
1232 * First, do the required ones; register pcapng first, then
1233 * pcap, so, at the beginning of the table, we have pcapng,
1234 * pcap, nanosecond pcap, and the weird modified pcaps, so
1235 * searches for file types that can write a file format
1236 * start with pcapng, pcap, and nanosecond pcap.
1237 */
1238 register_pcapng();
1239 register_pcap();
1240
1241 /* Now register the ones found by the build process */
1242 for (unsigned i = 0; i < wtap_module_count; i++)
1243 wtap_module_reg[i].cb_func();
1244
1245 /* Update the number of builtin entries. */
1246 wtap_num_builtin_file_types_subtypes = file_type_subtype_table_arr->len;
1247}
1248
1249/*
1250 * Attempt to register a new file type/subtype; fails if a type/subtype
1251 * with that name is already registered.
1252 */
1253int
1254wtap_register_file_type_subtype(const struct file_type_subtype_info* fi)
1255{
1256 struct file_type_subtype_info* finfo;
1257 unsigned file_type_subtype;
1258
1259 /*
1260 * Check for required fields (description and name).
1261 */
1262 if (!fi || !fi->description || !fi->name) {
1263 ws_warning("no file type info")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_WARNING, "wiretap/file_access.c"
, 1263, __func__, "no file type info"); } } while (0)
;
1264 return -1;
1265 }
1266
1267 /*
1268 * There must be at least one block type that this file
1269 * type/subtype supports.
1270 */
1271 if (fi->num_supported_blocks == 0 || fi->supported_blocks == NULL((void*)0)) {
1272 ws_warning("no blocks supported by file type \"%s\"", fi->name)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_WARNING, "wiretap/file_access.c"
, 1272, __func__, "no blocks supported by file type \"%s\"", fi
->name); } } while (0)
;
1273 return -1;
1274 }
1275
1276 /*
1277 * Is this type already registered?
1278 */
1279 if (wtap_name_to_file_type_subtype(fi->name) != -1) {
1280 /*
1281 * Yes. You don't get to replace an existing handler.
1282 */
1283 ws_warning("file type \"%s\" is already registered", fi->name)do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_WARNING, "wiretap/file_access.c"
, 1283, __func__, "file type \"%s\" is already registered", fi
->name); } } while (0)
;
1284 return -1;
1285 }
1286
1287 /*
1288 * Is there a freed entry in the array, due to a file type
1289 * being de-registered?
1290 *
1291 * Skip the built-in entries, as they're never deregistered.
1292 */
1293 for (file_type_subtype = wtap_num_builtin_file_types_subtypes;
1294 file_type_subtype < file_type_subtype_table_arr->len;
1295 file_type_subtype++) {
1296 if (file_type_subtype_table[file_type_subtype].name == NULL((void*)0)) {
1297 /*
1298 * We found such an entry.
1299 *
1300 * Get the pointer from the GArray, so that we get a
1301 * non-const pointer.
1302 */
1303 finfo = &g_array_index(file_type_subtype_table_arr, struct file_type_subtype_info, file_type_subtype)(((struct file_type_subtype_info*) (void *) (file_type_subtype_table_arr
)->data) [(file_type_subtype)])
;
1304
1305 /*
1306 * Fill in the entry with the new values.
1307 */
1308 *finfo = *fi;
1309
1310 return (int)file_type_subtype;
1311 }
1312 }
1313
1314 /*
1315 * There aren't any free slots, so add a new entry.
1316 * Get the number of current number of entries, which will
1317 * be the index of the new entry, then append this entry
1318 * to the end of the array, change file_type_subtype_table
1319 * in case the array had to get reallocated, and return
1320 * the index of the new entry.
1321 */
1322 file_type_subtype = file_type_subtype_table_arr->len;
1323 g_array_append_val(file_type_subtype_table_arr, *fi)g_array_append_vals (file_type_subtype_table_arr, &(*fi),
1)
;
1324 file_type_subtype_table = (const struct file_type_subtype_info*)(void *)file_type_subtype_table_arr->data;
1325 return file_type_subtype;
1326}
1327
1328/* De-registers a file writer - they can never be removed from the GArray, but we can "clear" an entry.
1329 */
1330void
1331wtap_deregister_file_type_subtype(const int subtype)
1332{
1333 struct file_type_subtype_info* finfo;
1334
1335 if (subtype < 0 || subtype >= (int)file_type_subtype_table_arr->len) {
1336 ws_error("invalid file type to de-register")ws_log_fatal_full("Wiretap", LOG_LEVEL_ERROR, "wiretap/file_access.c"
, 1336, __func__, "invalid file type to de-register")
;
1337 return;
1338 }
1339 if ((unsigned)subtype < wtap_num_builtin_file_types_subtypes) {
1340 ws_error("built-in file types cannot be de-registered")ws_log_fatal_full("Wiretap", LOG_LEVEL_ERROR, "wiretap/file_access.c"
, 1340, __func__, "built-in file types cannot be de-registered"
)
;
1341 return;
1342 }
1343
1344 /*
1345 * Get the pointer from the GArray, so that we get a non-const
1346 * pointer.
1347 */
1348 finfo = &g_array_index(file_type_subtype_table_arr, struct file_type_subtype_info, subtype)(((struct file_type_subtype_info*) (void *) (file_type_subtype_table_arr
)->data) [(subtype)])
;
1349 /*
1350 * Clear out this entry.
1351 */
1352 finfo->description = NULL((void*)0);
1353 finfo->name = NULL((void*)0);
1354 finfo->default_file_extension = NULL((void*)0);
1355 finfo->additional_file_extensions = NULL((void*)0);
1356 finfo->writing_must_seek = false0;
1357 finfo->num_supported_blocks = 0;
1358 finfo->supported_blocks = NULL((void*)0);
1359 finfo->can_write_encap = NULL((void*)0);
1360 finfo->dump_open = NULL((void*)0);
1361 finfo->wslua_info = NULL((void*)0);
1362}
1363
1364/*
1365 * Given a GArray of WTAP_ENCAP_ types, return the per-file encapsulation
1366 * type that would be needed to write out a file with those types. If
1367 * there's only one type, it's that type, otherwise it's
1368 * WTAP_ENCAP_PER_PACKET.
1369 */
1370int
1371wtap_dump_required_file_encap_type(const GArray *file_encaps)
1372{
1373 int encap;
1374
1375 encap = WTAP_ENCAP_PER_PACKET-1;
1376 if (file_encaps->len == 1) {
1377 /* OK, use the one-and-only encapsulation type. */
1378 encap = g_array_index(file_encaps, int, 0)(((int*) (void *) (file_encaps)->data) [(0)]);
1379 }
1380 return encap;
1381}
1382
1383bool_Bool
1384wtap_dump_can_write_encap(int file_type_subtype, int encap)
1385{
1386 int result = 0;
1387
1388 if (file_type_subtype < 0 ||
1389 file_type_subtype >= (int)file_type_subtype_table_arr->len ||
1390 file_type_subtype_table[file_type_subtype].can_write_encap == NULL((void*)0))
1391 return false0;
1392
1393 result = (*file_type_subtype_table[file_type_subtype].can_write_encap)(encap);
1394
1395 if (result != 0) {
1396 /* if the err said to check wslua's can_write_encap, try that */
1397 if (result == WTAP_ERR_CHECK_WSLUA-23
1398 && file_type_subtype_table[file_type_subtype].wslua_info != NULL((void*)0)
1399 && file_type_subtype_table[file_type_subtype].wslua_info->wslua_can_write_encap != NULL((void*)0)) {
1400
1401 result = (*file_type_subtype_table[file_type_subtype].wslua_info->wslua_can_write_encap)(encap, file_type_subtype_table[file_type_subtype].wslua_info->wslua_data);
1402
1403 }
1404
1405 if (result != 0)
1406 return false0;
1407 }
1408
1409 return true1;
1410}
1411
1412/*
1413 * Return true if a capture with a given GArray of encapsulation types
1414 * and a given bitset of comment types can be written in a specified
1415 * format, and false if it can't.
1416 */
1417static bool_Bool
1418wtap_dump_can_write_format(int ft, const GArray *file_encaps,
1419 uint32_t required_comment_types)
1420{
1421 unsigned i;
1422
1423 /*
1424 * Can we write in this format?
1425 */
1426 if (!wtap_dump_can_open(ft)) {
1427 /* No. */
1428 return false0;
1429 }
1430
1431 /*
1432 * Yes. Can we write out all the required comments in this
1433 * format?
1434 */
1435 if (required_comment_types & WTAP_COMMENT_PER_SECTION0x00000001) {
1436 if (wtap_file_type_subtype_supports_option(ft,
1437 WTAP_BLOCK_SECTION, OPT_COMMENT1) == OPTION_NOT_SUPPORTED) {
1438 /* Not section comments. */
1439 return false0;
1440 }
1441 }
1442 if (required_comment_types & WTAP_COMMENT_PER_INTERFACE0x00000002) {
1443 if (wtap_file_type_subtype_supports_option(ft,
1444 WTAP_BLOCK_IF_ID_AND_INFO, OPT_COMMENT1) == OPTION_NOT_SUPPORTED) {
1445 /* Not interface comments. */
1446 return false0;
1447 }
1448 }
1449 if (required_comment_types & WTAP_COMMENT_PER_PACKET0x00000004) {
1450 if (wtap_file_type_subtype_supports_option(ft,
1451 WTAP_BLOCK_PACKET, OPT_COMMENT1) == OPTION_NOT_SUPPORTED) {
1452 /* Not packet comments. */
1453 return false0;
1454 }
1455 }
1456
1457 /*
1458 * Yes. Is the required per-file encapsulation type supported?
1459 * This might be WTAP_ENCAP_PER_PACKET.
1460 */
1461 if (!wtap_dump_can_write_encap(ft, wtap_dump_required_file_encap_type(file_encaps))) {
1462 /* No. */
1463 return false0;
1464 }
1465
1466 /*
1467 * Yes. Are all the individual encapsulation types supported?
1468 */
1469 for (i = 0; i < file_encaps->len; i++) {
1470 if (!wtap_dump_can_write_encap(ft,
1471 g_array_index(file_encaps, int, i)(((int*) (void *) (file_encaps)->data) [(i)]))) {
1472 /* No - one of them isn't. */
1473 return false0;
1474 }
1475 }
1476
1477 /* Yes - we're OK. */
1478 return true1;
1479}
1480
1481/*
1482 * Return true if we can write a file with the given GArray of
1483 * encapsulation types and the given bitmask of comment types.
1484 */
1485bool_Bool
1486wtap_dump_can_write(const GArray *file_encaps, uint32_t required_comment_types)
1487{
1488 int ft;
1489
1490 for (ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
1491 /* To save a file with Wiretap, Wiretap has to handle that format,
1492 * and its code to handle that format must be able to write a file
1493 * with this file's encapsulation types.
1494 */
1495 if (wtap_dump_can_write_format(ft, file_encaps, required_comment_types)) {
1496 /* OK, we can write it out in this type. */
1497 return true1;
1498 }
1499 }
1500
1501 /* No, we couldn't save it in any format. */
1502 return false0;
1503}
1504
1505/*
1506 * Sort by file type/subtype name.
1507 */
1508static int
1509compare_file_type_subtypes_by_name(const void *a, const void *b)
1510{
1511 int file_type_subtype_a = *(const int *)a;
1512 int file_type_subtype_b = *(const int *)b;
1513
1514 return strcmp(wtap_file_type_subtype_name(file_type_subtype_a),
1515 wtap_file_type_subtype_name(file_type_subtype_b));
1516}
1517
1518/*
1519 * Sort by file type/subtype description.
1520 */
1521static int
1522compare_file_type_subtypes_by_description(const void *a, const void *b)
1523{
1524 int file_type_subtype_a = *(const int *)a;
1525 int file_type_subtype_b = *(const int *)b;
1526
1527 return strcmp(wtap_file_type_subtype_description(file_type_subtype_a),
1528 wtap_file_type_subtype_description(file_type_subtype_b));
1529}
1530
1531/*
1532 * Get a GArray of file type/subtype values for file types/subtypes
1533 * that can be used to save a file of a given type/subtype with a given
1534 * GArray of encapsulation types and the given bitmask of comment types.
1535 */
1536GArray *
1537wtap_get_savable_file_types_subtypes_for_file(int file_type_subtype,
1538 const GArray *file_encaps, uint32_t required_comment_types,
1539 ft_sort_order sort_order)
1540{
1541 GArray *savable_file_types_subtypes;
1542 int ft;
1543 int default_file_type_subtype = -1;
1544 int other_file_type_subtype = -1;
1545
1546 /* Can we save this file in its own file type/subtype? */
1547 if (wtap_dump_can_write_format(file_type_subtype, file_encaps,
1548 required_comment_types)) {
1549 /* Yes - make that the default file type/subtype. */
1550 default_file_type_subtype = file_type_subtype;
1551 } else if (wtap_dump_can_write_format(pcap_file_type_subtype,
1552 file_encaps,
1553 required_comment_types)) {
1554 /*
1555 * No, but we can write it as a pcap file; make that
1556 * the default file type/subtype.
1557 */
1558 default_file_type_subtype = pcap_file_type_subtype;
1559 } else if (wtap_dump_can_write_format(pcapng_file_type_subtype,
1560 file_encaps,
1561 required_comment_types)) {
1562 /*
1563 * No, but we can write it as a pcapng file; make that
1564 * the default file type/subtype.
1565 */
1566 default_file_type_subtype = pcapng_file_type_subtype;
1567 } else {
1568 /* OK, find the first file type/subtype we *can* save it as. */
1569 default_file_type_subtype = -1;
1570 for (ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
1571 if (wtap_dump_can_write_format(ft, file_encaps,
1572 required_comment_types)) {
1573 /* OK, got it. */
1574 default_file_type_subtype = ft;
1575 break;
1576 }
1577 }
1578 }
1579
1580 if (default_file_type_subtype == -1) {
1581 /* We don't support writing this file as any file type/subtype. */
1582 return NULL((void*)0);
1583 }
1584
1585 /*
1586 * If the default is pcap, put pcapng right after it if we can
1587 * also write it in pcapng format; otherwise, if the default is
1588 * pcapng, put pcap right after it if we can also write it in
1589 * pcap format.
1590 */
1591 if (default_file_type_subtype == pcap_file_type_subtype) {
1592 if (wtap_dump_can_write_format(pcapng_file_type_subtype,
1593 file_encaps,
1594 required_comment_types))
1595 other_file_type_subtype = pcapng_file_type_subtype;
1596 } else if (default_file_type_subtype == pcapng_file_type_subtype) {
1597 if (wtap_dump_can_write_format(pcap_file_type_subtype,
1598 file_encaps,
1599 required_comment_types))
1600 other_file_type_subtype = pcap_file_type_subtype;
1601 }
1602
1603 /* Allocate the array. */
1604 savable_file_types_subtypes = g_array_new(false0, false0,
1605 sizeof (int));
1606
1607 /*
1608 * First, add the types we don't want to force to the
1609 * beginning of the list.
1610 */
1611 for (ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
1612 if (ft == default_file_type_subtype ||
1613 ft == other_file_type_subtype)
1614 continue; /* we will done this one later */
1615 if (wtap_dump_can_write_format(ft, file_encaps,
1616 required_comment_types)) {
1617 /* OK, we can write it out in this type. */
1618 g_array_append_val(savable_file_types_subtypes, ft)g_array_append_vals (savable_file_types_subtypes, &(ft), 1
)
;
1619 }
1620 }
1621
1622 /* Now, sort the list. */
1623 g_array_sort(savable_file_types_subtypes,
1624 (sort_order == FT_SORT_BY_NAME) ? compare_file_type_subtypes_by_name :
1625 compare_file_type_subtypes_by_description);
1626
1627 /*
1628 * If we have a type/subtype to put above the default one,
1629 * do so.
1630 *
1631 * We put this type at the beginning before putting the
1632 * default there, so the default is at the top.
1633 */
1634 if (other_file_type_subtype != -1)
1635 g_array_prepend_val(savable_file_types_subtypes,g_array_prepend_vals (savable_file_types_subtypes, &(other_file_type_subtype
), 1)
1636 other_file_type_subtype)g_array_prepend_vals (savable_file_types_subtypes, &(other_file_type_subtype
), 1)
;
1637
1638 /* Put the default file type/subtype first in the list. */
1639 g_array_prepend_val(savable_file_types_subtypes,g_array_prepend_vals (savable_file_types_subtypes, &(default_file_type_subtype
), 1)
1640 default_file_type_subtype)g_array_prepend_vals (savable_file_types_subtypes, &(default_file_type_subtype
), 1)
;
1641
1642 return savable_file_types_subtypes;
1643}
1644
1645/*
1646 * Get a GArray of all writable file type/subtype values.
1647 */
1648GArray *
1649wtap_get_writable_file_types_subtypes(ft_sort_order sort_order)
1650{
1651 GArray *writable_file_types_subtypes;
1652 int ft;
1653
1654 /*
1655 * Allocate the array.
1656 * Pre-allocate room enough for all types.
1657 * XXX - that's overkill; just scan the table to find all the
1658 * writable types and count them.
1659 */
1660 writable_file_types_subtypes = g_array_sized_new(false0, false0,
1661 sizeof (int), file_type_subtype_table_arr->len);
1662
1663 /*
1664 * First, add the types we don't want to force to the
1665 * beginning of the list.
1666 */
1667 for (ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
1668 if (ft == pcap_file_type_subtype ||
1669 ft == pcapng_file_type_subtype)
1670 continue; /* we've already done these two */
1671 if (wtap_dump_can_open(ft)) {
1672 /* OK, we can write this type. */
1673 g_array_append_val(writable_file_types_subtypes, ft)g_array_append_vals (writable_file_types_subtypes, &(ft),
1)
;
1674 }
1675 }
1676
1677 /* Now, sort the list. */
1678 g_array_sort(writable_file_types_subtypes,
1679 (sort_order == FT_SORT_BY_NAME) ? compare_file_type_subtypes_by_name :
1680 compare_file_type_subtypes_by_description);
1681
1682 /*
1683 * Now, put pcap and pcapng at the beginning, as they're
1684 * our "native" formats. Put pcapng there first, and
1685 * pcap before it.
1686 */
1687 if (pcapng_file_type_subtype != -1 &&
1688 wtap_dump_can_open(pcapng_file_type_subtype)) {
1689 /*
1690 * We can write pcapng. (If we can't, that's a huge
1691 * mistake.)
1692 */
1693 g_array_prepend_val(writable_file_types_subtypes,g_array_prepend_vals (writable_file_types_subtypes, &(pcapng_file_type_subtype
), 1)
1694 pcapng_file_type_subtype)g_array_prepend_vals (writable_file_types_subtypes, &(pcapng_file_type_subtype
), 1)
;
1695 }
1696 if (pcap_file_type_subtype != -1 &&
1697 wtap_dump_can_open(pcap_file_type_subtype)) {
1698 /*
1699 * We can write pcap. (If we can't, that's a huge
1700 * mistake.)
1701 */
1702 g_array_prepend_val(writable_file_types_subtypes,g_array_prepend_vals (writable_file_types_subtypes, &(pcap_file_type_subtype
), 1)
1703 pcap_file_type_subtype)g_array_prepend_vals (writable_file_types_subtypes, &(pcap_file_type_subtype
), 1)
;
1704 }
1705
1706 return writable_file_types_subtypes;
1707}
1708
1709/*
1710 * String describing the file type/subtype.
1711 */
1712const char *
1713wtap_file_type_subtype_description(int file_type_subtype)
1714{
1715 if (file_type_subtype < 0 ||
1716 file_type_subtype >= (int)file_type_subtype_table_arr->len)
1717 return NULL((void*)0);
1718 else
1719 return file_type_subtype_table[file_type_subtype].description;
1720}
1721
1722/*
1723 * Name to use in, say, a command-line flag specifying the type/subtype.
1724 */
1725const char *
1726wtap_file_type_subtype_name(int file_type_subtype)
1727{
1728 if (file_type_subtype < 0 ||
1729 file_type_subtype >= (int)file_type_subtype_table_arr->len)
1730 return NULL((void*)0);
1731 else
1732 return file_type_subtype_table[file_type_subtype].name;
1733}
1734
1735/*
1736 * Register a backwards-compatibility name.
1737 */
1738void
1739wtap_register_compatibility_file_subtype_name(const char *old_name,
1740 const char *new_name)
1741{
1742 g_hash_table_insert(type_subtype_name_map, g_strdup(old_name)g_strdup_inline (old_name),
1743 g_strdup(new_name)g_strdup_inline (new_name));
1744}
1745
1746/*
1747 * Translate a name to a capture file type/subtype.
1748 */
1749int
1750wtap_name_to_file_type_subtype(const char *name)
1751{
1752 char *new_name;
1753 int file_type_subtype;
1754
1755 /*
1756 * Is this name a backwards-compatibility name?
1757 */
1758 new_name = (char *)g_hash_table_lookup(type_subtype_name_map,
1759 (void *)name);
1760 if (new_name != NULL((void*)0)) {
1761 /*
1762 * Yes, and new_name is the name to which it should
1763 * be mapped.
1764 */
1765 name = new_name;
1766 }
1767 for (file_type_subtype = 0;
1768 file_type_subtype < (int)file_type_subtype_table_arr->len;
1769 file_type_subtype++) {
1770 if (file_type_subtype_table[file_type_subtype].name != NULL((void*)0) &&
1771 strcmp(name, file_type_subtype_table[file_type_subtype].name) == 0)
1772 return file_type_subtype;
1773 }
1774
1775 return -1; /* no such file type, or we can't write it */
1776}
1777
1778/*
1779 * Provide the file type/subtype for pcap.
1780 */
1781int
1782wtap_pcap_file_type_subtype(void)
1783{
1784 /*
1785 * Make sure pcap was registered as a file type/subtype;
1786 * it's one of our "native" formats.
1787 */
1788 ws_assert(pcap_file_type_subtype != -1)do { if ((1) && !(pcap_file_type_subtype != -1)) ws_log_fatal_full
("Wiretap", LOG_LEVEL_ERROR, "wiretap/file_access.c", 1788, __func__
, "assertion failed: %s", "pcap_file_type_subtype != -1"); } while
(0)
;
1789 return pcap_file_type_subtype;
1790}
1791
1792/*
1793 * Provide the file type/subtype for nanosecond-resolution pcap.
1794 */
1795int
1796wtap_pcap_nsec_file_type_subtype(void)
1797{
1798 /*
1799 * Make sure nanosecond-resolution pcap was registered
1800 * as a file type/subtype; it's one of our "native" formats.
1801 */
1802 ws_assert(pcap_nsec_file_type_subtype != -1)do { if ((1) && !(pcap_nsec_file_type_subtype != -1))
ws_log_fatal_full("Wiretap", LOG_LEVEL_ERROR, "wiretap/file_access.c"
, 1802, __func__, "assertion failed: %s", "pcap_nsec_file_type_subtype != -1"
); } while (0)
;
1803 return pcap_nsec_file_type_subtype;
1804}
1805
1806/*
1807 * Provide the file type/subtype for pcapng.
1808 */
1809int
1810wtap_pcapng_file_type_subtype(void)
1811{
1812 /*
1813 * Make sure pcapng was registered as a file type/subtype;
1814 * it's one of our "native" formats.
1815 */
1816 ws_assert(pcapng_file_type_subtype != -1)do { if ((1) && !(pcapng_file_type_subtype != -1)) ws_log_fatal_full
("Wiretap", LOG_LEVEL_ERROR, "wiretap/file_access.c", 1816, __func__
, "assertion failed: %s", "pcapng_file_type_subtype != -1"); }
while (0)
;
1817 return pcapng_file_type_subtype;
1818}
1819
1820/*
1821 * Determine if a file type/subtype can write a block of the given type.
1822 */
1823block_support_t
1824wtap_file_type_subtype_supports_block(int file_type_subtype,
1825 wtap_block_type_t type)
1826{
1827 size_t num_supported_blocks;
1828 const struct supported_block_type *supported_blocks;
1829
1830 if (file_type_subtype < 0 ||
1831 file_type_subtype >= (int)file_type_subtype_table_arr->len) {
1832 /*
1833 * There's no such file type, so it can't support any
1834 * blocks.
1835 */
1836 return BLOCK_NOT_SUPPORTED;
1837 }
1838
1839 num_supported_blocks = file_type_subtype_table[file_type_subtype].num_supported_blocks;
1840 supported_blocks = file_type_subtype_table[file_type_subtype].supported_blocks;
1841
1842 for (size_t block_idx = 0; block_idx < num_supported_blocks;
1843 block_idx++) {
1844 if (supported_blocks[block_idx].type == type)
1845 return supported_blocks[block_idx].support;
1846 }
1847
1848 /*
1849 * Not found, which means not supported.
1850 */
1851 return BLOCK_NOT_SUPPORTED;
1852}
1853
1854/*
1855 * Determine if a file type/subtype, when writing a block of the given type,
1856 * can support adding the given option to the block.
1857 */
1858option_support_t
1859wtap_file_type_subtype_supports_option(int file_type_subtype,
1860 wtap_block_type_t type, unsigned option)
1861{
1862 size_t num_supported_blocks;
1863 const struct supported_block_type *supported_blocks;
1864
1865 if (file_type_subtype < 0 ||
1866 file_type_subtype >= (int)file_type_subtype_table_arr->len) {
1867 /*
1868 * There's no such file type, so it can't support any
1869 * blocks, and thus can't support any options.
1870 */
1871 return OPTION_NOT_SUPPORTED;
1872 }
1873
1874 num_supported_blocks = file_type_subtype_table[file_type_subtype].num_supported_blocks;
1875 supported_blocks = file_type_subtype_table[file_type_subtype].supported_blocks;
1876
1877 for (size_t block_idx = 0; block_idx < num_supported_blocks;
1878 block_idx++) {
1879 if (supported_blocks[block_idx].type == type) {
1880 /*
1881 * OK, that block is known.
1882 * Is it supported?
1883 */
1884 if (supported_blocks[block_idx].support == BLOCK_NOT_SUPPORTED) {
1885 /*
1886 * No, so clearly the option isn't
1887 * supported in that block.
1888 */
1889 return OPTION_NOT_SUPPORTED;
1890 }
1891
1892 /*
1893 * Yes, so check the options.
1894 */
1895 size_t num_supported_options;
1896 const struct supported_option_type *supported_options;
1897
1898 num_supported_options = supported_blocks[block_idx].num_supported_options;
1899 supported_options = supported_blocks[block_idx].supported_options;
1900 for (size_t opt_idx = 0; opt_idx < num_supported_options;
1901 opt_idx++) {
1902 if (supported_options[opt_idx].opt == option)
1903 return supported_options[opt_idx].support;
1904 }
1905
1906 /*
1907 * Not found, which means not supported.
1908 */
1909 return OPTION_NOT_SUPPORTED;
1910 }
1911 }
1912
1913 /*
1914 * The block type wasn't found, which means it's not supported,
1915 * which means the option isn't supported in that block.
1916 */
1917 return OPTION_NOT_SUPPORTED;
1918}
1919
1920static GSList *
1921add_extensions_for_file_type_subtype(int file_type_subtype, GSList *extensions,
1922 GSList *compression_type_extensions)
1923{
1924 char **extensions_set, **extensionp;
1925 char *extension;
1926
1927 if (file_type_subtype < 0 ||
1928 file_type_subtype >= (int)file_type_subtype_table_arr->len) {
1929 /*
1930 * There's no such file type, so it has no extensions
1931 * to add.
1932 */
1933 return extensions;
1934 }
1935
1936 /*
1937 * Add the default extension, and all of the compressed variants
1938 * from the list of compressed-file extensions, if there is a
1939 * default extension.
1940 */
1941 if (file_type_subtype_table[file_type_subtype].default_file_extension != NULL((void*)0)) {
1942 extensions = add_extensions(extensions,
1943 file_type_subtype_table[file_type_subtype].default_file_extension,
1944 compression_type_extensions);
1945 }
1946
1947 if (file_type_subtype_table[file_type_subtype].additional_file_extensions != NULL((void*)0)) {
1948 /*
1949 * We have additional extensions; add them.
1950 *
1951 * First, split the extension-list string into a set of
1952 * extensions.
1953 */
1954 extensions_set = g_strsplit(file_type_subtype_table[file_type_subtype].additional_file_extensions,
1955 ";", 0);
1956
1957 /*
1958 * Add each of those extensions to the list.
1959 */
1960 for (extensionp = extensions_set; *extensionp != NULL((void*)0);
1961 extensionp++) {
1962 extension = *extensionp;
1963
1964 /*
1965 * Add the extension, and all compressed variants
1966 * of it if requested.
1967 */
1968 extensions = add_extensions(extensions, extension,
1969 compression_type_extensions);
1970 }
1971
1972 g_strfreev(extensions_set);
1973 }
1974 return extensions;
1975}
1976
1977/* Return a list of file extensions that are used by the specified file
1978 * type/subtype.
1979 *
1980 * If include_compressed is true, the list will include compressed
1981 * extensions, e.g. not just "pcap" but also "pcap.gz" if we can read
1982 * gzipped files.
1983 *
1984 * All strings in the list are allocated with g_malloc() and must be freed
1985 * with g_free().
1986 */
1987GSList *
1988wtap_get_file_extensions_list(int file_type_subtype, bool_Bool include_compressed)
1989{
1990 GSList *extensions, *compression_type_extensions;
1991
1992 if (file_type_subtype < 0 ||
1993 file_type_subtype >= (int)file_type_subtype_table_arr->len)
1994 return NULL((void*)0); /* not a valid file type */
1995
1996 if (file_type_subtype_table[file_type_subtype].default_file_extension == NULL((void*)0))
1997 return NULL((void*)0); /* valid, but no extensions known */
1998
1999 extensions = NULL((void*)0); /* empty list, to start with */
2000
2001 /*
2002 * Add all this file type's extensions, with compressed
2003 * variants if include_compressed is true.
2004 */
2005 if (include_compressed) {
2006 /*
2007 * Get compression-type extensions, if any.
2008 */
2009 compression_type_extensions = ws_get_all_compression_type_extensions_list();
2010 } else {
2011 /*
2012 * We don't want the compressed file extensions.
2013 */
2014 compression_type_extensions = NULL((void*)0);
2015 }
2016 extensions = add_extensions_for_file_type_subtype(file_type_subtype, extensions,
2017 compression_type_extensions);
2018
2019 g_slist_free(compression_type_extensions);
2020
2021 return g_slist_reverse(extensions);
2022}
2023
2024/* Return a list of all extensions that are used by all capture file
2025 * types, including compressed extensions, e.g. not just "pcap" but
2026 * also "pcap.gz" if we can read gzipped files.
2027 *
2028 * "Capture files" means "include file types that correspond to
2029 * collections of network packets, but not file types that
2030 * store data that just happens to be transported over protocols
2031 * such as HTTP but that aren't collections of network packets",
2032 * so that it could be used for "All Capture Files" without picking
2033 * up JPEG files or files such as that - those aren't capture files,
2034 * and we *do* have them listed in the long list of individual file
2035 * types, so omitting them from "All Capture Files" is the right
2036 * thing to do.
2037 *
2038 * All strings in the list are allocated with g_malloc() and must be freed
2039 * with g_free().
2040 *
2041 * This is used to generate a list of extensions to look for if the user
2042 * chooses "All Capture Files" in a file open dialog.
2043 */
2044GSList *
2045wtap_get_all_capture_file_extensions_list(void)
2046{
2047 GSList *extensions, *compression_type_extensions;
2048 unsigned int i;
2049
2050 init_file_type_extensions();
2051
2052 extensions = NULL((void*)0); /* empty list, to start with */
2053
2054 /*
2055 * Get compression-type extensions, if any.
2056 */
2057 compression_type_extensions = ws_get_all_compression_type_extensions_list();
2058
2059 for (i = 0; i < file_type_extensions_arr->len; i++) {
2060 /*
2061 * Is this a capture file, rather than one of the
2062 * other random file types we can read?
2063 */
2064 if (file_type_extensions[i].is_capture_file) {
2065 /*
2066 * Yes. Add all this file extension type's
2067 * extensions, with compressed variants.
2068 */
2069 extensions = add_extensions_for_file_extensions_type(i,
2070 extensions, compression_type_extensions);
2071 }
2072 }
2073
2074 g_slist_free(compression_type_extensions);
2075
2076 return g_slist_reverse(extensions);
2077}
2078
2079/* Return a list of all extensions that are used by all file types that
2080 * we can read, including compressed extensions, e.g. not just "pcap" but
2081 * also "pcap.gz" if we can read gzipped files.
2082 *
2083 * "File type" means "include file types that correspond to collections
2084 * of network packets, as well as file types that store data that just
2085 * happens to be transported over protocols such as HTTP but that aren't
2086 * collections of network packets, and plain text files".
2087 *
2088 * All strings in the list are allocated with g_malloc() and must be freed
2089 * with g_free().
2090 *
2091 * This is used to get the "base name" for a file, by stripping off
2092 * compressed-file extensions and extensions that correspond to file
2093 * types that we know about.
2094 */
2095GSList *
2096wtap_get_all_file_extensions_list(void)
2097{
2098 GSList *extensions, *compression_type_extensions;
2099
2100 extensions = NULL((void*)0); /* empty list, to start with */
2101
2102 /*
2103 * Get compression-type extensions, if any.
2104 */
2105 compression_type_extensions = ws_get_all_compression_type_extensions_list();
2106
2107 for (int ft = 0; ft < (int)file_type_subtype_table_arr->len; ft++) {
2108 extensions = add_extensions_for_file_type_subtype(ft, extensions,
2109 compression_type_extensions);
2110 }
2111
2112 g_slist_free(compression_type_extensions);
2113
2114 return g_slist_reverse(extensions);
2115}
2116
2117/*
2118 * Free a list returned by wtap_get_file_extension_type_extensions(),
2119 * wtap_get_all_capture_file_extensions_list, wtap_get_file_extensions_list(),
2120 * or wtap_get_all_file_extensions_list().
2121 */
2122void
2123wtap_free_extensions_list(GSList *extensions)
2124{
2125 GSList *extension;
2126
2127 for (extension = extensions; extension != NULL((void*)0);
2128 extension = g_slist_next(extension)((extension) ? (((GSList *)(extension))->next) : ((void*)0
))
) {
2129 g_free(extension->data);
2130 }
2131 g_slist_free(extensions);
2132}
2133
2134/*
2135 * Return the default file extension to use with the specified file type
2136 * and subtype; that's just the extension, without any ".".
2137 */
2138const char *
2139wtap_default_file_extension(int file_type_subtype)
2140{
2141 if (file_type_subtype < 0 ||
2142 file_type_subtype >= (int)file_type_subtype_table_arr->len)
2143 return NULL((void*)0);
2144 else
2145 return file_type_subtype_table[file_type_subtype].default_file_extension;
2146}
2147
2148/*
2149 * Return whether we know how to write the specified file type.
2150 */
2151bool_Bool
2152wtap_dump_can_open(int file_type_subtype)
2153{
2154 if (file_type_subtype < 0 ||
2155 file_type_subtype >= (int)file_type_subtype_table_arr->len ||
2156 file_type_subtype_table[file_type_subtype].dump_open == NULL((void*)0))
2157 return false0;
2158
2159 return true1;
2160}
2161
2162/*
2163 * Return whether we know how to write a compressed file of the specified
2164 * file type.
2165 */
2166#if defined (HAVE_ZLIB1) || defined (HAVE_ZLIBNG) || defined (HAVE_LZ4FRAME_H1)
2167bool_Bool
2168wtap_dump_can_compress(int file_type_subtype)
2169{
2170 /*
2171 * If this is an unknown file type, or if we have to
2172 * seek when writing out a file with this file type,
2173 * return false.
2174 */
2175 if (file_type_subtype < 0 ||
2176 file_type_subtype >= (int)file_type_subtype_table_arr->len ||
2177 file_type_subtype_table[file_type_subtype].writing_must_seek)
2178 return false0;
2179
2180 return true1;
2181}
2182#else
2183bool_Bool
2184wtap_dump_can_compress(int file_type_subtype _U___attribute__((unused)))
2185{
2186 return false0;
2187}
2188#endif
2189
2190static bool_Bool wtap_dump_open_finish(wtap_dumper *wdh, int *err,
2191 char **err_info);
2192
2193static WFILE_T wtap_dump_file_open(const wtap_dumper *wdh, const char *filename);
2194static WFILE_T wtap_dump_file_fdopen(const wtap_dumper *wdh, int fd);
2195static int wtap_dump_file_close(wtap_dumper *wdh);
2196static bool_Bool wtap_dump_fix_idb(wtap_dumper *wdh, wtap_block_t idb, int *err);
2197
2198static wtap_dumper *
2199wtap_dump_init_dumper(int file_type_subtype, ws_compression_type compression_type,
2200 const wtap_dump_params *params, int *err)
2201{
2202 wtap_dumper *wdh;
2203 wtap_block_t descr, file_int_data;
2204 wtapng_if_descr_mandatory_t *descr_mand, *file_int_data_mand;
2205 GArray *interfaces = params->idb_inf ? params->idb_inf->interface_data : NULL((void*)0);
4
Assuming field 'idb_inf' is non-null
5
'?' condition is true
2206
2207 /* Can we write files of this file type/subtype?
2208 *
2209 * This will fail if file_type_subtype isn't a valid
2210 * file type/subtype value, so, if it doesn't fail,
2211 * we know file_type_subtype is within the bounds of
2212 * the table of file types/subtypes.
2213 */
2214 if (!wtap_dump_can_open(file_type_subtype)) {
6
Taking false branch
2215 /* Invalid type, or type we don't know how to write. */
2216 *err = WTAP_ERR_UNWRITABLE_FILE_TYPE-7;
2217 return NULL((void*)0);
2218 }
2219
2220 /* OK, we know how to write that file type/subtype; can we write
2221 * the specified encapsulation type in that file type/subtype?
2222 */
2223 *err = (*file_type_subtype_table[file_type_subtype].can_write_encap)(params->encap);
2224 /* if the err said to check wslua's can_write_encap, try that */
2225 if (*err == WTAP_ERR_CHECK_WSLUA-23
7
Assuming the condition is false
2226 && file_type_subtype_table[file_type_subtype].wslua_info != NULL((void*)0)
2227 && file_type_subtype_table[file_type_subtype].wslua_info->wslua_can_write_encap != NULL((void*)0)) {
2228
2229 *err = (*file_type_subtype_table[file_type_subtype].wslua_info->wslua_can_write_encap)(params->encap, file_type_subtype_table[file_type_subtype].wslua_info->wslua_data);
2230 }
2231
2232 if (*err != 0) {
8
Assuming the condition is false
2233 /* No, we can't. */
2234 return NULL((void*)0);
2235 }
2236
2237 /* Check whether we can open a capture file with that file type
2238 * and that encapsulation, and, if the compression type isn't
2239 * "uncompressed", whether we can write a *compressed* file
2240 * of that file type.
2241 * If we're doing compression, can this file type/subtype be
2242 written in compressed form?
2243 *
2244 * (The particular type doesn't matter - if the file can't
2245 * be written 100% sequentially, we can't compress it,
2246 * because we can't go back and overwrite something we've
2247 * already written.
2248 */
2249 if (compression_type != WS_FILE_UNCOMPRESSED &&
9
Assuming 'compression_type' is equal to WS_FILE_UNCOMPRESSED
2250 !wtap_dump_can_compress(file_type_subtype)) {
2251 *err = WTAP_ERR_COMPRESSION_NOT_SUPPORTED-17;
2252 return NULL((void*)0);
2253 }
2254
2255 /* Allocate a data structure for the output stream. */
2256 wdh = g_new0(wtap_dumper, 1)((wtap_dumper *) g_malloc0_n ((1), sizeof (wtap_dumper)));
10
Memory is allocated
2257 if (wdh == NULL((void*)0)) {
11
Assuming 'wdh' is not equal to NULL
12
Taking false branch
2258 *err = errno(*__errno_location ());
2259 return NULL((void*)0);
2260 }
2261
2262 wdh->file_type_subtype = file_type_subtype;
2263 wdh->snaplen = params->snaplen;
2264 wdh->file_encap = params->encap;
2265 wdh->compression_type = compression_type;
2266 wdh->wslua_data = NULL((void*)0);
2267 wdh->shb_iface_to_global = params->shb_iface_to_global;
2268 wdh->interface_data = g_array_new(false0, false0, sizeof(wtap_block_t));
2269
2270 /* Set Section Header Block data */
2271 wdh->shb_hdrs = params->shb_hdrs;
2272 /* Set Name Resolution Block data */
2273 wdh->nrbs_growing = params->nrbs_growing;
2274 /* Set Interface Description Block data */
2275 if (interfaces && interfaces->len) {
13
Assuming 'interfaces' is non-null
14
Assuming field 'len' is not equal to 0
15
Taking true branch
2276 if (!params->dont_copy_idbs) { /* XXX */
16
Assuming field 'dont_copy_idbs' is false
17
Taking true branch
2277 unsigned itf_count;
2278
2279 /* Note: this memory is owned by wtap_dumper and will become
2280 * invalid after wtap_dump_close. */
2281 for (itf_count = 0; itf_count
17.1
'itf_count' is < field 'len'
< interfaces->len; itf_count++) {
18
Loop condition is true. Entering loop body
2282 file_int_data = g_array_index(interfaces, wtap_block_t, itf_count)(((wtap_block_t*) (void *) (interfaces)->data) [(itf_count
)])
;
2283 file_int_data_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(file_int_data);
2284 descr = wtap_block_make_copy(file_int_data);
2285 if ((params->encap != WTAP_ENCAP_PER_PACKET-1) && (params->encap != file_int_data_mand->wtap_encap)) {
19
Assuming the condition is false
2286 descr_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(descr);
2287 descr_mand->wtap_encap = params->encap;
2288 }
2289 if (!wtap_dump_fix_idb(wdh, descr, err)) {
20
Taking true branch
2290 return NULL((void*)0);
21
Potential leak of memory pointed to by 'wdh'
2291 }
2292 g_array_append_val(wdh->interface_data, descr)g_array_append_vals (wdh->interface_data, &(descr), 1);
2293 }
2294 }
2295 } else if (params->encap != WTAP_ENCAP_NONE-2 && params->encap != WTAP_ENCAP_PER_PACKET-1) {
2296 /* Generate a fake IDB if we don't have one, unless the
2297 * file encapsulation is none. (WTAP_ENCAP_NONE either
2298 * means that there are no interfaces, or they will be
2299 * provided later when reading the file in single-pass mode.)
2300 *
2301 * For WTAP_ENCAP_PER_PACKET, we'll have to generate IDBs
2302 * from packet records as they come in. (pcapng does this now.)
2303 *
2304 * XXX File types should provide their own IDBs (possibly
2305 * fake ones generated by wtap_add_generated_idb()), in
2306 * order to support being used as inputs for mergecap where
2307 * pcapng is the output.
2308 */
2309 descr = wtap_dump_params_generate_idb(params);
2310 g_array_append_val(wdh->interface_data, descr)g_array_append_vals (wdh->interface_data, &(descr), 1);
2311 }
2312 /* Set Decryption Secrets Blocks */
2313 wdh->dsbs_initial = params->dsbs_initial;
2314 wdh->dsbs_growing = params->dsbs_growing;
2315 /* Set Sysdig meta events */
2316 wdh->mevs_growing = params->mevs_growing;
2317 /* Set DPIBs */
2318 wdh->dpibs_growing = params->dpibs_growing;
2319 return wdh;
2320}
2321
2322wtap_dumper *
2323wtap_dump_open(const char *filename, int file_type_subtype,
2324 ws_compression_type compression_type, const wtap_dump_params *params,
2325 int *err, char **err_info)
2326{
2327 wtap_dumper *wdh;
2328 WFILE_T fh;
2329
2330 *err = 0;
2331 *err_info = NULL((void*)0);
2332
2333 /* Allocate and initialize a data structure for the output stream. */
2334 wdh = wtap_dump_init_dumper(file_type_subtype, compression_type, params,
2335 err);
2336 if (wdh == NULL((void*)0))
2337 return NULL((void*)0);
2338
2339 /* In case "fopen()" fails but doesn't set "errno", set "errno"
2340 to a generic "the open failed" error. */
2341 errno(*__errno_location ()) = WTAP_ERR_CANT_OPEN-6;
2342 fh = wtap_dump_file_open(wdh, filename);
2343 if (fh == NULL((void*)0)) {
2344 *err = errno(*__errno_location ());
2345 g_free(wdh);
2346 return NULL((void*)0); /* can't create file */
2347 }
2348 wdh->fh = fh;
2349
2350 if (!wtap_dump_open_finish(wdh, err, err_info)) {
2351 /* Get rid of the file we created; we couldn't finish
2352 opening it. */
2353 wtap_dump_file_close(wdh);
2354 ws_unlinkunlink(filename);
2355 g_free(wdh);
2356 return NULL((void*)0);
2357 }
2358 return wdh;
2359}
2360
2361wtap_dumper *
2362wtap_dump_open_tempfile(const char *tmpdir, char **filenamep, const char *pfx,
2363 int file_type_subtype, ws_compression_type compression_type,
2364 const wtap_dump_params *params, int *err, char **err_info)
2365{
2366 int fd;
2367 const char *ext;
2368 char sfx[16];
2369 wtap_dumper *wdh;
2370 WFILE_T fh;
2371
2372 /* No path name for the temporary file yet. */
2373 *filenamep = NULL((void*)0);
2374
2375 *err = 0;
2376 *err_info = NULL((void*)0);
2377
2378 /* Allocate and initialize a data structure for the output stream. */
2379 wdh = wtap_dump_init_dumper(file_type_subtype, compression_type, params,
2380 err);
2381 if (wdh == NULL((void*)0))
2382 return NULL((void*)0);
2383
2384 /* Choose an appropriate suffix for the file */
2385 ext = wtap_default_file_extension(file_type_subtype);
2386 if (ext == NULL((void*)0))
2387 ext = "tmp";
2388 sfx[0] = '.';
2389 sfx[1] = '\0';
2390 (void) g_strlcat(sfx, ext, 16);
2391
2392 /* Choose a random name for the file */
2393 fd = create_tempfile(tmpdir, filenamep, pfx, sfx, NULL((void*)0));
2394 if (fd == -1) {
2395 *err = WTAP_ERR_CANT_OPEN-6;
2396 g_free(wdh);
2397 return NULL((void*)0); /* can't create file */
2398 }
2399
2400 /* In case "fopen()" fails but doesn't set "errno", set "errno"
2401 to a generic "the open failed" error. */
2402 errno(*__errno_location ()) = WTAP_ERR_CANT_OPEN-6;
2403 fh = wtap_dump_file_fdopen(wdh, fd);
2404 if (fh == NULL((void*)0)) {
2405 *err = errno(*__errno_location ());
2406 ws_closeclose(fd);
2407 g_free(wdh);
2408 return NULL((void*)0); /* can't create file */
2409 }
2410 wdh->fh = fh;
2411
2412 if (!wtap_dump_open_finish(wdh, err, err_info)) {
2413 /* Get rid of the file we created; we couldn't finish
2414 opening it. */
2415 wtap_dump_file_close(wdh);
2416 ws_unlinkunlink(*filenamep);
2417 g_free(wdh);
2418 return NULL((void*)0);
2419 }
2420 return wdh;
2421}
2422
2423wtap_dumper *
2424wtap_dump_fdopen(int fd, int file_type_subtype, ws_compression_type compression_type,
2425 const wtap_dump_params *params, int *err, char **err_info)
2426{
2427 wtap_dumper *wdh;
2428 WFILE_T fh;
2429
2430 *err = 0;
2431 *err_info = NULL((void*)0);
2432
2433 /* Allocate and initialize a data structure for the output stream. */
2434 wdh = wtap_dump_init_dumper(file_type_subtype, compression_type, params,
3
Calling 'wtap_dump_init_dumper'
2435 err);
2436 if (wdh == NULL((void*)0))
2437 return NULL((void*)0);
2438
2439 /* In case "fopen()" fails but doesn't set "errno", set "errno"
2440 to a generic "the open failed" error. */
2441 errno(*__errno_location ()) = WTAP_ERR_CANT_OPEN-6;
2442 fh = wtap_dump_file_fdopen(wdh, fd);
2443 if (fh == NULL((void*)0)) {
2444 *err = errno(*__errno_location ());
2445 g_free(wdh);
2446 return NULL((void*)0); /* can't create standard I/O stream */
2447 }
2448 wdh->fh = fh;
2449
2450 if (!wtap_dump_open_finish(wdh, err, err_info)) {
2451 wtap_dump_file_close(wdh);
2452 g_free(wdh);
2453 return NULL((void*)0);
2454 }
2455 return wdh;
2456}
2457
2458wtap_dumper *
2459wtap_dump_open_stdout(int file_type_subtype, ws_compression_type compression_type,
2460 const wtap_dump_params *params, int *err, char **err_info)
2461{
2462 int new_fd;
2463 wtap_dumper *wdh;
2464
2465 /*
2466 * Duplicate the file descriptor, so that we can close the
2467 * wtap_dumper handle the same way we close any other
2468 * wtap_dumper handle, without closing the standard output.
2469 */
2470 new_fd = ws_dupdup(1);
2471 if (new_fd == -1) {
1
Taking false branch
2472 /* dup failed */
2473 *err = errno(*__errno_location ());
2474 return NULL((void*)0);
2475 }
2476#ifdef _WIN32
2477 /*
2478 * Put the new descriptor into binary mode.
2479 *
2480 * XXX - even if the file format we're writing is a text
2481 * format?
2482 */
2483 if (_setmode(new_fd, O_BINARY0) == -1) {
2484 /* "Should not happen" */
2485 *err = errno(*__errno_location ());
2486 ws_closeclose(new_fd);
2487 return NULL((void*)0);
2488 }
2489#endif
2490
2491 wdh = wtap_dump_fdopen(new_fd, file_type_subtype, compression_type,
2
Calling 'wtap_dump_fdopen'
2492 params, err, err_info);
2493 if (wdh == NULL((void*)0)) {
2494 /* Failed; close the new FD */
2495 ws_closeclose(new_fd);
2496 return NULL((void*)0);
2497 }
2498 return wdh;
2499}
2500
2501static bool_Bool
2502wtap_dump_open_finish(wtap_dumper *wdh, int *err, char **err_info)
2503{
2504 int fd;
2505 bool_Bool cant_seek;
2506
2507 /* Can we do a seek on the file descriptor?
2508 If not, note that fact. */
2509 if (wdh->compression_type != WS_FILE_UNCOMPRESSED) {
2510 cant_seek = true1;
2511 } else {
2512 fd = ws_filenofileno((FILE *)wdh->fh);
2513 if (ws_lseek64lseek(fd, 1, SEEK_CUR1) == (off_t) -1)
2514 cant_seek = true1;
2515 else {
2516 /* Undo the seek. */
2517 ws_lseek64lseek(fd, 0, SEEK_SET0);
2518 cant_seek = false0;
2519 }
2520 }
2521
2522 /* If this file type requires seeking, and we can't seek, fail. */
2523 if (file_type_subtype_table[wdh->file_type_subtype].writing_must_seek && cant_seek) {
2524 *err = WTAP_ERR_CANT_WRITE_TO_PIPE-5;
2525 return false0;
2526 }
2527
2528 /* Set wdh with wslua data if any - this is how we pass the data
2529 * to the file writer.
2530 */
2531 if (file_type_subtype_table[wdh->file_type_subtype].wslua_info)
2532 wdh->wslua_data = file_type_subtype_table[wdh->file_type_subtype].wslua_info->wslua_data;
2533
2534 /* Now try to open the file for writing. */
2535 if (!(*file_type_subtype_table[wdh->file_type_subtype].dump_open)(wdh, err,
2536 err_info)) {
2537 return false0;
2538 }
2539
2540 return true1; /* success! */
2541}
2542
2543/* XXX - Temporary hack to deal with nstime_t, and thus wtap_rec and libwiretap
2544 * in general, not storing precision greater than nanoseconds yet. Despite
2545 * whatever precision an IDB claims, we can't write finer than nanosecond.
2546 * Eventually this should be removed.
2547 * Fix a given IDB to indicate no greater than nanosecond precision. */
2548static bool_Bool
2549wtap_dump_fix_idb(wtap_dumper *wdb _U___attribute__((unused)), wtap_block_t idb, int *err)
2550{
2551 wtapng_if_descr_mandatory_t *idb_mand;
2552 int64_t tsoffset;
2553 idb_mand = (wtapng_if_descr_mandatory_t*)wtap_block_get_mandatory_data(idb);
2554
2555 /*
2556 * nstime_t only stores nanoseconds, so instead of claiming false
2557 * precision, fix things up.
2558 */
2559 if (idb_mand->time_units_per_second > 1000000000) {
2560 ws_warning("original time precision reduced to nanoseconds")do { if (1) { ws_log_full("Wiretap", LOG_LEVEL_WARNING, "wiretap/file_access.c"
, 2560, __func__, "original time precision reduced to nanoseconds"
); } } while (0)
;
2561 idb_mand->time_units_per_second = 1000000000;
2562 switch (wtap_block_set_uint8_option_value(idb, OPT_IDB_TSRESOL9, 9)) {
2563 case WTAP_OPTTYPE_SUCCESS:
2564 break;
2565 case WTAP_OPTTYPE_NOT_FOUND:
2566 // This "should not" happen, because no if_tsresol means 6,
2567 // and time_units_per_second should be 1000000;
2568 if (wtap_block_add_uint8_option(idb, OPT_IDB_TSRESOL9, 9) == WTAP_OPTTYPE_SUCCESS) {
2569 break;
2570 }
2571 /* FALLTHROUGH */
2572 default:
2573 // These "should not" happen either.
2574 *err = WTAP_ERR_INTERNAL-21;
2575 return false0;
2576 }
2577 }
2578
2579 /*
2580 * Since we're not writing more than nanosecond resolution, if_tsoffset
2581 * isn't necessary, as anything we can store in absolute timestamps in
2582 * Wireshark records we can write to a file without an offset (unless
2583 * we have 32-bit time_t, but that's rare these days.) So we remove it
2584 * here, though in the long term we should keep it.
2585 */
2586 if (wtap_block_get_int64_option_value(idb, OPT_IDB_TSOFFSET14, &tsoffset) == WTAP_OPTTYPE_SUCCESS) {
2587 wtap_block_remove_option(idb, OPT_IDB_TSOFFSET14);
2588 }
2589
2590 return true1;
2591}
2592
2593bool_Bool
2594wtap_dump_add_idb(wtap_dumper *wdh, wtap_block_t idb, int *err,
2595 char **err_info)
2596{
2597 wtap_block_t idb_copy;
2598
2599 if (wdh->subtype_add_idb == NULL((void*)0)) {
2600 /* Not supported. */
2601 *err = WTAP_ERR_UNWRITABLE_REC_TYPE-24;
2602 *err_info = g_strdup("Adding IDBs isn't supported by this file type")g_strdup_inline ("Adding IDBs isn't supported by this file type"
)
;
2603 return false0;
2604 }
2605
2606 /*
2607 * Add a copy of this IDB to our array of IDBs.
2608 */
2609 idb_copy = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
2610 wtap_block_copy(idb_copy, idb);
2611 g_array_append_val(wdh->interface_data, idb_copy)g_array_append_vals (wdh->interface_data, &(idb_copy),
1)
;
2612
2613 if (!wtap_dump_fix_idb(wdh, idb_copy, err)) {
2614 *err_info = ws_strdup_printf("pcapng: failed to lower time resolution to nanoseconds")wmem_strdup_printf(((void*)0), "pcapng: failed to lower time resolution to nanoseconds"
)
;
2615 return false0;
2616 }
2617
2618 *err = 0;
2619 *err_info = NULL((void*)0);
2620 return (wdh->subtype_add_idb)(wdh, idb, err, err_info);
2621}
2622
2623bool_Bool
2624wtap_dump(wtap_dumper *wdh, const wtap_rec *rec, int *err, char **err_info)
2625{
2626 *err = 0;
2627 *err_info = NULL((void*)0);
2628 return (wdh->subtype_write)(wdh, rec, err, err_info);
2629}
2630
2631bool_Bool
2632wtap_dump_flush(wtap_dumper *wdh, int *err)
2633{
2634 switch (wdh->compression_type) {
2635#if defined (HAVE_ZLIB1) || defined (HAVE_ZLIBNG)
2636 case WS_FILE_GZIP_COMPRESSED:
2637 if (gzwfile_flush((GZWFILE_T)wdh->fh) == -1) {
2638 *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
2639 return false0;
2640 }
2641 break;
2642#endif
2643#ifdef HAVE_LZ4FRAME_H1
2644 case WS_FILE_LZ4_COMPRESSED:
2645 if (lz4wfile_flush((LZ4WFILE_T)wdh->fh) == -1) {
2646 *err = lz4wfile_geterr((LZ4WFILE_T)wdh->fh);
2647 return false0;
2648 }
2649 break;
2650#endif /* HAVE_LZ4FRAME_H */
2651 default:
2652 if (fflush((FILE *)wdh->fh) == EOF(-1)) {
2653 *err = errno(*__errno_location ());
2654 return false0;
2655 }
2656 }
2657 return true1;
2658}
2659
2660bool_Bool
2661wtap_dump_close(wtap_dumper *wdh, bool_Bool *needs_reload,
2662 int *err, char **err_info)
2663{
2664 bool_Bool ret = true1;
2665
2666 *err = 0;
2667 *err_info = NULL((void*)0);
2668 if (wdh->subtype_finish != NULL((void*)0)) {
2669 /* There's a finish routine for this dump stream. */
2670 if (!(wdh->subtype_finish)(wdh, err, err_info))
2671 ret = false0;
2672 }
2673 errno(*__errno_location ()) = WTAP_ERR_CANT_CLOSE-11;
2674 if (wtap_dump_file_close(wdh) == EOF(-1)) {
2675 if (ret) {
2676 /* The per-format finish function succeeded,
2677 but the stream close didn't. Save the
2678 reason why, if our caller asked for it. */
2679 if (err != NULL((void*)0))
2680 *err = errno(*__errno_location ());
2681 }
2682 ret = false0;
2683 }
2684 if (needs_reload != NULL((void*)0))
2685 *needs_reload = wdh->needs_reload;
2686 g_free(wdh->priv);
2687 wtap_block_array_free(wdh->interface_data);
2688 wtap_block_array_unref(wdh->dsbs_initial);
2689 g_free(wdh);
2690 return ret;
2691}
2692
2693int
2694wtap_dump_file_type_subtype(const wtap_dumper *wdh)
2695{
2696 return wdh->file_type_subtype;
2697}
2698
2699int64_t
2700wtap_get_bytes_dumped(const wtap_dumper *wdh)
2701{
2702 return wdh->bytes_dumped;
2703}
2704
2705void
2706wtap_set_bytes_dumped(wtap_dumper *wdh, int64_t bytes_dumped)
2707{
2708 wdh->bytes_dumped = bytes_dumped;
2709}
2710
2711bool_Bool
2712wtap_addrinfo_list_empty(const addrinfo_lists_t *addrinfo_lists)
2713{
2714 return (addrinfo_lists == NULL((void*)0)) ||
2715 ((addrinfo_lists->ipv4_addr_list == NULL((void*)0)) &&
2716 (addrinfo_lists->ipv6_addr_list == NULL((void*)0)));
2717}
2718
2719bool_Bool
2720wtap_dump_set_addrinfo_list(wtap_dumper *wdh, addrinfo_lists_t *addrinfo_lists)
2721{
2722 if (!wdh || wdh->file_type_subtype < 0 ||
2723 wdh->file_type_subtype >= (int)file_type_subtype_table_arr->len ||
2724 wtap_file_type_subtype_supports_block(wdh->file_type_subtype, WTAP_BLOCK_NAME_RESOLUTION) == BLOCK_NOT_SUPPORTED)
2725 return false0;
2726 wdh->addrinfo_lists = addrinfo_lists;
2727 return true1;
2728}
2729
2730void
2731wtap_dump_discard_name_resolution(wtap_dumper *wdh)
2732{
2733 /* As below for DSBs. */
2734 if (wdh->nrbs_growing) {
2735 /*
2736 * Pretend we've written all of them.
2737 */
2738 wdh->nrbs_growing_written = wdh->nrbs_growing->len;
2739 }
2740}
2741
2742void
2743wtap_dump_discard_decryption_secrets(wtap_dumper *wdh)
2744{
2745 /*
2746 * This doesn't free the data, as it might be pointed to
2747 * from other structures; it merely marks all of them as
2748 * having been written to the file, so that they don't
2749 * get written by wtap_dump().
2750 *
2751 * XXX - our APIs for dealing with some metadata, such as
2752 * resolved names, decryption secrets, and interface
2753 * statistics is not very well oriented towards one-pass
2754 * programs; this needs to be cleaned up. See bug 15502.
2755 */
2756 if (wdh->dsbs_growing) {
2757 /*
2758 * Pretend we've written all of them.
2759 */
2760 wdh->dsbs_growing_written = wdh->dsbs_growing->len;
2761 }
2762}
2763
2764void
2765wtap_dump_discard_sysdig_meta_events(wtap_dumper *wdh)
2766{
2767 /* As above for DSBs. */
2768 if (wdh->mevs_growing) {
2769 /*
2770 * Pretend we've written all of them.
2771 */
2772 wdh->mevs_growing_written = wdh->mevs_growing->len;
2773 }
2774}
2775
2776/* internally open a file for writing (compressed or not) */
2777static WFILE_T
2778wtap_dump_file_open(const wtap_dumper *wdh, const char *filename)
2779{
2780 switch (wdh->compression_type) {
2781#if defined (HAVE_ZLIB1) || defined (HAVE_ZLIBNG)
2782 case WS_FILE_GZIP_COMPRESSED:
2783 return gzwfile_open(filename);
2784#endif /* defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) */
2785#ifdef HAVE_LZ4FRAME_H1
2786 case WS_FILE_LZ4_COMPRESSED:
2787 return lz4wfile_open(filename);
2788#endif /* HAVE_LZ4FRAME_H */
2789 default:
2790 return ws_fopenfopen(filename, "wb");
2791 }
2792}
2793
2794/* internally open a file for writing (compressed or not) */
2795static WFILE_T
2796wtap_dump_file_fdopen(const wtap_dumper *wdh, int fd)
2797{
2798 switch (wdh->compression_type) {
2799#if defined (HAVE_ZLIB1) || defined (HAVE_ZLIBNG)
2800 case WS_FILE_GZIP_COMPRESSED:
2801 return gzwfile_fdopen(fd);
2802#endif /* defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG) */
2803#ifdef HAVE_LZ4FRAME_H1
2804 case WS_FILE_LZ4_COMPRESSED:
2805 return lz4wfile_fdopen(fd);
2806#endif /* HAVE_LZ4FRAME_H */
2807 default:
2808 return ws_fdopenfdopen(fd, "wb");
2809 }
2810}
2811
2812/* internally writing raw bytes (compressed or not). Updates wdh->bytes_dumped on success */
2813bool_Bool
2814wtap_dump_file_write(wtap_dumper *wdh, const void *buf, size_t bufsize, int *err)
2815{
2816 size_t nwritten;
2817
2818 switch (wdh->compression_type) {
2819#if defined (HAVE_ZLIB1) || defined (HAVE_ZLIBNG)
2820 case WS_FILE_GZIP_COMPRESSED:
2821 nwritten = gzwfile_write((GZWFILE_T)wdh->fh, buf, (unsigned int) bufsize);
2822 /*
2823 * gzwfile_write() returns 0 on error.
2824 */
2825 if (nwritten == 0) {
2826 *err = gzwfile_geterr((GZWFILE_T)wdh->fh);
2827 return false0;
2828 }
2829 break;
2830#endif
2831#ifdef HAVE_LZ4FRAME_H1
2832 case WS_FILE_LZ4_COMPRESSED:
2833 nwritten = lz4wfile_write((LZ4WFILE_T)wdh->fh, buf, bufsize);
2834 /*
2835 * lz4wfile_write() returns 0 on error.
2836 */
2837 if (nwritten == 0) {
2838 *err = lz4wfile_geterr((LZ4WFILE_T)wdh->fh);
2839 return false0;
2840 }
2841 break;
2842#endif /* HAVE_LZ4FRAME_H */
2843 default:
2844 errno(*__errno_location ()) = WTAP_ERR_CANT_WRITE-10;
2845 nwritten = fwrite(buf, 1, bufsize, (FILE *)wdh->fh);
2846 /*
2847 * At least according to the macOS man page,
2848 * this can return a short count on an error.
2849 */
2850 if (nwritten != bufsize) {
2851 if (ferror((FILE *)wdh->fh))
2852 *err = errno(*__errno_location ());
2853 else
2854 *err = WTAP_ERR_SHORT_WRITE-14;
2855 return false0;
2856 }
2857 }
2858 wdh->bytes_dumped += bufsize;
2859 return true1;
2860}
2861
2862/* internally close a file for writing (compressed or not) */
2863static int
2864wtap_dump_file_close(wtap_dumper *wdh)
2865{
2866 switch (wdh->compression_type) {
2867#if defined (HAVE_ZLIB1) || defined (HAVE_ZLIBNG)
2868 case WS_FILE_GZIP_COMPRESSED:
2869 return gzwfile_close((GZWFILE_T)wdh->fh);
2870#endif
2871#ifdef HAVE_LZ4FRAME_H1
2872 case WS_FILE_LZ4_COMPRESSED:
2873 return lz4wfile_close((LZ4WFILE_T)wdh->fh);
2874#endif /* HAVE_LZ4FRAME_H */
2875 default:
2876 return fclose((FILE *)wdh->fh);
2877 }
2878}
2879
2880int64_t
2881wtap_dump_file_seek(wtap_dumper *wdh, int64_t offset, int whence, int *err)
2882{
2883#if defined (HAVE_ZLIB1) || defined (HAVE_ZLIBNG) || defined (HAVE_LZ4FRAME_H1)
2884 if (wdh->compression_type != WS_FILE_UNCOMPRESSED) {
2885 *err = WTAP_ERR_CANT_SEEK_COMPRESSED-19;
2886 return -1;
2887 } else
2888#endif
2889 {
2890 if (-1 == ws_fseek64fseeko((FILE *)wdh->fh, offset, whence)) {
2891 *err = errno(*__errno_location ());
2892 return -1;
2893 } else
2894 {
2895 return 0;
2896 }
2897 }
2898}
2899
2900int64_t
2901wtap_dump_file_tell(wtap_dumper *wdh, int *err)
2902{
2903 int64_t rval;
2904#if defined (HAVE_ZLIB1) || defined (HAVE_ZLIBNG) || defined (HAVE_LZ4FRAME_H1)
2905 if (wdh->compression_type != WS_FILE_UNCOMPRESSED) {
2906 *err = WTAP_ERR_CANT_SEEK_COMPRESSED-19;
2907 return -1;
2908 } else
2909#endif
2910 {
2911 if (-1 == (rval = ws_ftell64ftello((FILE *)wdh->fh))) {
2912 *err = errno(*__errno_location ());
2913 return -1;
2914 } else
2915 {
2916 return rval;
2917 }
2918 }
2919}
2920
2921void
2922cleanup_open_routines(void)
2923{
2924 unsigned i;
2925 struct open_info *i_open;
2926
2927 if (open_routines != NULL((void*)0) && open_info_arr) {
2928 for (i = 0, i_open = open_routines; i < open_info_arr->len; i++, i_open++) {
2929 if (i_open->extensions != NULL((void*)0))
2930 g_strfreev(i_open->extensions_set);
2931 }
2932
2933 g_array_free(open_info_arr, true1);
2934 open_info_arr = NULL((void*)0);
2935 }
2936}
2937
2938/*
2939 * Allow built-in file handlers (but *not* plugin file handlers!) to
2940 * register a "backwards-compatibility" name and file type value, to
2941 * put in the Lua wtap_filetypes table.
2942 *
2943 * This is only to be used as long as we have that table; new Lua
2944 * code should use wtap_name_to_file_type_subtype() to look up
2945 * file types by their name, just as C code should.
2946 *
2947 * The backwards-compatibility names are the old WTAP_FILE_TYPE_SUBTYPE_
2948 * #define name, with WTAP_FILE_TYPE_SUBTYPE_ removed.
2949 */
2950
2951static GArray *backwards_compatibility_lua_names;
2952
2953void
2954// NOLINTNEXTLINE(misc-no-recursion)
2955wtap_register_backwards_compatibility_lua_name(const char *name, int ft)
2956{
2957 struct backwards_compatibiliity_lua_name entry;
2958
2959 /*
2960 * Create the table if it doesn't already exist.
2961 * Use the same size as we do for the file type/subtype table.
2962 */
2963 if (backwards_compatibility_lua_names == NULL((void*)0)) {
2964 backwards_compatibility_lua_names = g_array_sized_new(false0,
2965 true1, sizeof(struct backwards_compatibiliity_lua_name),
2966 wtap_module_count*2);
2967
2968 /*
2969 * Extra backwards compatibility hack - add entries
2970 * for time stamp precision values(!), as well as
2971 * for "UNKNOWN" and types that don't yet register
2972 * themselves.
2973 *
2974 * If new WS_TSPREC_ value are added, don't bother
2975 * adding them to this table; any Lua program that
2976 * would use them should use the wtap_tsprecs type.
2977 *
2978 * (Recursion: see "recursion".)
2979 */
2980 wtap_register_backwards_compatibility_lua_name("TSPREC_SEC",
2981 WTAP_TSPREC_SEC0);
2982 wtap_register_backwards_compatibility_lua_name("TSPREC_DSEC",
2983 WTAP_TSPREC_100_MSEC1);
2984 wtap_register_backwards_compatibility_lua_name("TSPREC_CSEC",
2985 WTAP_TSPREC_10_MSEC2);
2986 wtap_register_backwards_compatibility_lua_name("TSPREC_MSEC",
2987 WTAP_TSPREC_MSEC3);
2988 wtap_register_backwards_compatibility_lua_name("TSPREC_USEC",
2989 WTAP_TSPREC_USEC6);
2990 wtap_register_backwards_compatibility_lua_name("TSPREC_NSEC",
2991 WTAP_TSPREC_NSEC9);
2992 wtap_register_backwards_compatibility_lua_name("UNKNOWN",
2993 WTAP_FILE_TYPE_SUBTYPE_UNKNOWN-1);
2994 }
2995 entry.name = name;
2996 entry.ft = ft;
2997 g_array_append_val(backwards_compatibility_lua_names, entry)g_array_append_vals (backwards_compatibility_lua_names, &
(entry), 1)
;
2998}
2999
3000const GArray *
3001get_backwards_compatibility_lua_table(void)
3002{
3003 return backwards_compatibility_lua_names;
3004}
3005
3006/*
3007 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3008 *
3009 * Local variables:
3010 * c-basic-offset: 8
3011 * tab-width: 8
3012 * indent-tabs-mode: t
3013 * End:
3014 *
3015 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
3016 * :indentSize=8:tabSize=8:noTabs=false:
3017 */