Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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