Bug Summary

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