Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / wsutil / tempfile.c
blob927e64190a08b6b8884dd59ae9d08663eefdf5b3
1 /* tempfile.c
2 * Routines to create temporary files
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
11 #include "config.h"
12 #include "tempfile.h"
14 #include <errno.h>
16 #include "file_util.h"
18 static char *
19 sanitize_prefix(const char *prefix)
21 if (!prefix) {
22 return NULL;
25 /* The characters in "delimiters" come from:
26 * https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions.
27 * Add to the list as necessary for other OS's.
29 const char *delimiters = "<>:\"/\\|?*"
30 "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a"
31 "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
32 "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
34 /* Sanitize the prefix to resolve bug 7877 */
35 char *safe_prefx = g_strdup(prefix);
36 safe_prefx = g_strdelimit(safe_prefx, delimiters, '-');
37 return safe_prefx;
40 /**
41 * Create a tempfile with the given prefix (e.g. "wireshark"). The path
42 * is created using g_file_open_tmp.
44 * @param tempdir [in] If not NULL, the directory in which to create the file.
45 * @param namebuf [in,out] If not NULL, receives the full path of the temp file.
46 * Must be freed.
47 * @param pfx [in] A prefix for the temporary file.
48 * @param sfx [in] A file extension for the temporary file. NULL can be passed
49 * if no file extension is needed
50 * @param err [out] Any error returned by g_file_open_tmp. May be NULL
51 * @return The file descriptor of the new tempfile, from mkstemps().
53 int
54 create_tempfile(const char *tempdir, char **namebuf, const char *pfx, const char *sfx, GError **err)
56 int fd;
57 char *safe_pfx = sanitize_prefix(pfx);
59 if (tempdir == NULL || tempdir[0] == '\0') {
60 /* Use OS default tempdir behaviour */
61 char* filetmpl = ws_strdup_printf("%sXXXXXX%s", safe_pfx ? safe_pfx : "", sfx ? sfx : "");
62 g_free(safe_pfx);
64 fd = g_file_open_tmp(filetmpl, namebuf, err);
65 g_free(filetmpl);
67 else {
68 /* User-specified tempdir.
69 * We don't get libc's help generating a random name here.
71 const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
72 const int32_t a_len = 64;
73 char* filetmpl = NULL;
75 while(1) {
76 g_free(filetmpl);
77 filetmpl = ws_strdup_printf("%s%c%s%c%c%c%c%c%c%s",
78 tempdir,
79 G_DIR_SEPARATOR,
80 safe_pfx ? safe_pfx : "",
81 alphabet[g_random_int_range(0, a_len)],
82 alphabet[g_random_int_range(0, a_len)],
83 alphabet[g_random_int_range(0, a_len)],
84 alphabet[g_random_int_range(0, a_len)],
85 alphabet[g_random_int_range(0, a_len)],
86 alphabet[g_random_int_range(0, a_len)],
87 sfx ? sfx : "");
89 fd = ws_open(filetmpl, O_CREAT|O_EXCL|O_BINARY|O_WRONLY, 0600);
90 if (fd >= 0) {
91 break;
93 if (errno != EEXIST) {
94 g_set_error_literal(err, G_FILE_ERROR,
95 g_file_error_from_errno(errno), g_strerror(errno));
96 g_free(filetmpl);
97 filetmpl = NULL;
98 break;
100 /* Loop continues if error was EEXIST, meaning the file we tried
101 * to make already existed at the destination
105 if (namebuf == NULL) {
106 g_free(filetmpl);
108 else {
109 *namebuf = filetmpl;
111 g_free(safe_pfx);
114 return fd;
117 char *
118 create_tempdir(const char *parent_dir, const char *tmpl, GError **err)
120 if (parent_dir == NULL || parent_dir[0] == '\0') {
121 parent_dir = g_get_tmp_dir();
124 char *safe_pfx = sanitize_prefix(tmpl);
125 if (safe_pfx == NULL) {
126 safe_pfx = g_strdup("wireshark_XXXXXX");
129 char *temp_subdir = g_build_path(G_DIR_SEPARATOR_S, parent_dir, safe_pfx, NULL);
130 g_free(safe_pfx);
131 if (g_mkdtemp(temp_subdir) == NULL)
133 g_free(temp_subdir);
134 g_set_error_literal(err, G_FILE_ERROR,
135 g_file_error_from_errno(errno), g_strerror(errno));
136 return NULL;
139 return temp_subdir;
143 * Editor modelines - https://www.wireshark.org/tools/modelines.html
145 * Local Variables:
146 * c-basic-offset: 2
147 * tab-width: 8
148 * indent-tabs-mode: nil
149 * End:
151 * ex: set shiftwidth=2 tabstop=8 expandtab:
152 * :indentSize=2:tabSize=8:noTabs=true: