summaryrefslogtreecommitdiff
path: root/wsutil/tempfile.c
diff options
context:
space:
mode:
authorJeff Morriss <jeff.morriss.ws@gmail.com>2013-06-26 01:14:35 +0000
committerJeff Morriss <jeff.morriss.ws@gmail.com>2013-06-26 01:14:35 +0000
commitbbf6a3766e65ebc66f06f936e530e79ec2d5b31b (patch)
tree36807307f1569f29471ae157dcc82141c422a1ad /wsutil/tempfile.c
parent3ab335948b76b1a87fd0c193050673ffd37c9a86 (diff)
downloadwireshark-bbf6a3766e65ebc66f06f936e530e79ec2d5b31b.tar.gz
Move tempfile.{h,c} into wsutil.
svn path=/trunk/; revision=50163
Diffstat (limited to 'wsutil/tempfile.c')
-rw-r--r--wsutil/tempfile.c279
1 files changed, 279 insertions, 0 deletions
diff --git a/wsutil/tempfile.c b/wsutil/tempfile.c
new file mode 100644
index 0000000000..2fab0df257
--- /dev/null
+++ b/wsutil/tempfile.c
@@ -0,0 +1,279 @@
+/* tempfile.c
+ * Routines to create temporary files
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+#endif
+
+#ifdef _WIN32
+#include <process.h> /* For getpid() */
+#endif
+
+#include "tempfile.h"
+#include <wsutil/file_util.h>
+
+#ifndef __set_errno
+#define __set_errno(x) errno=(x)
+#endif
+
+#define INITIAL_PATH_SIZE 128
+#define TMP_FILE_SUFFIX "XXXXXX"
+
+#ifndef HAVE_MKSTEMP
+/* Generate a unique temporary file name from TEMPLATE.
+ The last six characters of TEMPLATE must be TMP_FILE_SUFFIX;
+ they are replaced with a string that makes the filename unique.
+ Returns a file descriptor open on the file for reading and writing. */
+static int
+mkstemp (char *template)
+{
+ static const char letters[]
+ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ size_t len;
+ size_t i;
+
+ len = strlen (template);
+ if (len < 6 || strcmp (&template[len - 6], TMP_FILE_SUFFIX))
+ {
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ if (g_snprintf (&template[len - 5], 6, "%.5u",
+ (unsigned int) getpid () % 100000) != 5)
+ /* Inconceivable lossage. */
+ return -1;
+
+ for (i = 0; i < sizeof (letters); ++i)
+ {
+ int fd;
+
+ template[len - 6] = letters[i];
+
+ fd = ws_open (template, O_RDWR|O_BINARY|O_CREAT|O_EXCL, 0600);
+ if (fd >= 0)
+ return fd;
+ }
+
+ /* We return the null string if we can't find a unique file name. */
+
+ template[0] = '\0';
+ return -1;
+}
+
+#endif /* HAVE_MKSTEMP */
+
+#ifndef HAVE_MKDTEMP
+/* Generate a unique temporary directory name from TEMPLATE.
+ The last six characters of TEMPLATE must be TMP_FILE_SUFFIX;
+ they are replaced with a string that makes the filename unique.
+ Returns 0 on success or -1 on error (from mkdir(2)). */
+char *
+mkdtemp (char *template)
+{
+ static const char letters[]
+ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ size_t len;
+ size_t i;
+
+ len = strlen (template);
+ if (len < 6 || strcmp (&template[len - 6], TMP_FILE_SUFFIX))
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ if (g_snprintf (&template[len - 5], 6, "%.5u",
+ (unsigned int) getpid () % 100000) != 5)
+ /* Inconceivable lossage. */
+ return NULL;
+
+ for (i = 0; i < sizeof (letters); ++i)
+ {
+ int ret;
+
+ template[len - 6] = letters[i];
+
+ ret = ws_mkdir(template, 0700);
+ if (ret >= 0)
+ return template;
+ }
+
+ /* We return the null string if we can't find a unique file name. */
+
+ template[0] = '\0';
+ return NULL;
+}
+
+#endif /* HAVE_MKDTEMP */
+
+#define MAX_TEMPFILES 3
+
+/**
+ * Create a tempfile with the given prefix (e.g. "wireshark").
+ *
+ * @param namebuf If not NULL, receives the full path of the temp file.
+ * Should NOT be freed.
+ * @param pfx A prefix for the temporary file.
+ * @return The file descriptor of the new tempfile, from mkstemp().
+ * @todo Switch from mkstemp() to something like mkstemps(), so the caller
+ * can optionally indicate that part of the pfx is actually a suffix,
+ * such as "pcap" or "pcapng".
+ */
+int
+create_tempfile(char **namebuf, const char *pfx)
+{
+ static struct _tf {
+ char *path;
+ unsigned long len;
+ } tf[MAX_TEMPFILES];
+ static int idx;
+
+ const char *tmp_dir;
+ int old_umask;
+ int fd;
+ time_t current_time;
+ char timestr[14 + 1];
+ gchar *tmp_file;
+ gchar *safe_pfx;
+ gchar sep[2] = {0, 0};
+
+ /* The characters in "delimiters" come from:
+ * http://msdn.microsoft.com/en-us/library/aa365247%28VS.85%29.aspx.
+ * Add to the list as necessary for other OS's.
+ */
+ const gchar *delimiters = "<>:\"/\\|?*"
+ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a"
+ "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14"
+ "\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
+
+ /* Sanitize the pfx to resolve bug 7877 */
+ safe_pfx = g_strdup(pfx);
+ safe_pfx = g_strdelimit(safe_pfx, delimiters, '-');
+
+ idx = (idx + 1) % MAX_TEMPFILES;
+
+ /*
+ * Allocate the buffer if it's not already allocated.
+ */
+ if (tf[idx].path == NULL) {
+ tf[idx].len = INITIAL_PATH_SIZE;
+ tf[idx].path = (char *)g_malloc(tf[idx].len);
+ }
+
+ /*
+ * We can't use get_tempfile_path here because we're called from dumpcap.c.
+ */
+ tmp_dir = g_get_tmp_dir();
+
+#ifdef _WIN32
+ _tzset();
+#endif
+ current_time = time(NULL);
+ strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", localtime(&current_time));
+ sep[0] = G_DIR_SEPARATOR;
+ tmp_file = g_strconcat(tmp_dir, sep, safe_pfx, "_", timestr, "_", TMP_FILE_SUFFIX, NULL);
+ g_free(safe_pfx);
+ if (strlen(tmp_file) > tf[idx].len) {
+ tf[idx].len = (int)strlen(tmp_file) + 1;
+ tf[idx].path = (char *)g_realloc(tf[idx].path, tf[idx].len);
+ }
+ g_strlcpy(tf[idx].path, tmp_file, tf[idx].len);
+ g_free(tmp_file);
+
+ if (namebuf) {
+ *namebuf = tf[idx].path;
+ }
+ /* The Single UNIX Specification doesn't say that "mkstemp()"
+ creates the temporary file with mode rw-------, so we
+ won't assume that all UNIXes will do so; instead, we set
+ the umask to 0077 to take away all group and other
+ permissions, attempt to create the file, and then put
+ the umask back. */
+ old_umask = umask(0077);
+ fd = mkstemp(tf[idx].path);
+ umask(old_umask);
+ return fd;
+}
+
+/**
+ * Create a directory with the given prefix (e.g. "wireshark"). The path
+ * is created using g_get_tmp_dir and mkdtemp.
+ *
+ * @param namebuf
+ * @param pfx A prefix for the temporary directory.
+ * @return The temporary directory path on success, or NULL on failure.
+ * Must NOT be freed.
+ */
+const char *
+create_tempdir(char **namebuf, const char *pfx)
+{
+ static char *td_path[3];
+ static int td_path_len[3];
+ static int idx;
+ const char *tmp_dir;
+
+ idx = (idx + 1) % 3;
+
+ /*
+ * Allocate the buffer if it's not already allocated.
+ */
+ if (td_path[idx] == NULL) {
+ td_path_len[idx] = INITIAL_PATH_SIZE;
+ td_path[idx] = (char *)g_malloc(td_path_len[idx]);
+ }
+
+ /*
+ * We can't use get_tempfile_path here because we're called from dumpcap.c.
+ */
+ tmp_dir = g_get_tmp_dir();
+
+ while (g_snprintf(td_path[idx], td_path_len[idx], "%s%c%s" TMP_FILE_SUFFIX, tmp_dir, G_DIR_SEPARATOR, pfx) > td_path_len[idx]) {
+ td_path_len[idx] *= 2;
+ td_path[idx] = (char *)g_realloc(td_path[idx], td_path_len[idx]);
+ }
+
+ if (namebuf) {
+ *namebuf = td_path[idx];
+ }
+ return mkdtemp(td_path[idx]);
+}