Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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