Bug Summary

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