Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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