#include <unistd.h>
#endif
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <stdlib.h>
#ifdef G_OS_WIN32
#include <io.h>
#define S_ISLNK(x) 0
#endif
-#define _(x) x
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#include "glibintl.h"
/**
* g_file_test:
return q;
}
+/**
+ * g_file_error_from_errno:
+ * @err_no: an "errno" value
+ *
+ * Gets a #GFileError constant based on the passed-in errno.
+ * For example, if you pass in EEXIST this function returns
+ * #G_FILE_ERROR_EXIST. Unlike errno values, you can portably
+ * assume that all #GFileError values will exist.
+ *
+ * Normally a #GFileError value goes into a #GError returned
+ * from a function that manipulates files. So you would use
+ * g_file_error_from_errno() when constructing a #GError.
+ *
+ * Return value: #GFileError corresponding to the given errno
+ **/
GFileError
-g_file_error_from_errno (gint en)
+g_file_error_from_errno (gint err_no)
{
- switch (en)
+ switch (err_no)
{
#ifdef EEXIST
case EEXIST:
struct stat stat_buf;
gint fd;
- fd = open (filename, O_RDONLY);
+ /* O_BINARY useful on Cygwin */
+ fd = open (filename, O_RDONLY|O_BINARY);
if (fd < 0)
{
#endif
}
+/*
+ * mkstemp() implementation is from the GNU C library.
+ * Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
+ */
/**
* g_mkstemp:
+ * @tmpl: template filename
*
- * Open a temporary file
+ * Open a temporary file. See "man mkstemp" on most UNIX-like systems.
+ * This is a portability wrapper, which simply calls mkstemp() on systems
+ * that have it, and implements it in GLib otherwise.
*
* The parameter is a string that should match the rules for mktemp, i.e.
* end in "XXXXXX". The X string will be modified to form the name
* of a file that didn't exist.
*
- * Return value: A file handle (as from open()) to the file file
+ * Return value: A file handle (as from open()) to the file
* opened for reading and writing. The file is opened in binary mode
* on platforms where there is a difference. The file handle should be
* closed with close(). In case of errors, -1 is returned.
- *
- * From the GNU C library.
- * Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
*/
int
g_mkstemp (char *tmpl)
char *XXXXXX;
int count, fd;
static const char letters[] =
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ static const int NLETTERS = sizeof (letters) - 1;
glong value;
GTimeVal tv;
+ static int counter = 0;
len = strlen (tmpl);
if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
/* Get some more or less random data. */
g_get_current_time (&tv);
- value = tv.tv_usec ^ tv.tv_sec;
+ value = (tv.tv_usec ^ tv.tv_sec) + counter++;
for (count = 0; count < 100; value += 7777, ++count)
{
glong v = value;
/* Fill in the random bits. */
- XXXXXX[0] = letters[v % 62];
- v /= 62;
- XXXXXX[1] = letters[v % 62];
- v /= 62;
- XXXXXX[2] = letters[v % 62];
- v /= 62;
- XXXXXX[3] = letters[v % 62];
- v /= 62;
- XXXXXX[4] = letters[v % 62];
- v /= 62;
- XXXXXX[5] = letters[v % 62];
+ XXXXXX[0] = letters[v % NLETTERS];
+ v /= NLETTERS;
+ XXXXXX[1] = letters[v % NLETTERS];
+ v /= NLETTERS;
+ XXXXXX[2] = letters[v % NLETTERS];
+ v /= NLETTERS;
+ XXXXXX[3] = letters[v % NLETTERS];
+ v /= NLETTERS;
+ XXXXXX[4] = letters[v % NLETTERS];
+ v /= NLETTERS;
+ XXXXXX[5] = letters[v % NLETTERS];
fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
return -1;
#endif
}
+
+/**
+ * g_file_open_tmp:
+ * @tmpl: Template for file name, as in g_mkstemp, basename only
+ * @name_used: location to store actual name used
+ * @error: return location for a #GError
+ *
+ * Opens a file for writing in the preferred directory for temporary
+ * files (as returned by g_get_tmp_dir()).
+ *
+ * @tmpl should be a string ending with six 'X' characters, as the
+ * parameter to g_mkstemp() (or mkstemp()). However, unlike these
+ * functions, the template should only be a basename, no directory
+ * components are allowed. If template is NULL, a default template is
+ * used.
+ *
+ * Note that in contrast to g_mkstemp() (and mkstemp()) @tmpl is not
+ * modified, and might thus be a read-only literal string.
+ *
+ * The actual name used is returned in @name_used if non-NULL. This
+ * string should be freed with g_free when not needed any longer.
+ *
+ * Return value: A file handle (as from open()) to the file
+ * opened for reading and writing. The file is opened in binary mode
+ * on platforms where there is a difference. The file handle should be
+ * closed with close(). In case of errors, -1 is returned and
+ * @error will be set.
+ **/
+int
+g_file_open_tmp (const char *tmpl,
+ char **name_used,
+ GError **error)
+{
+ int retval;
+ const char *tmpdir;
+ char *sep;
+ char *fulltemplate;
+
+ if (tmpl == NULL)
+ tmpl = ".XXXXXX";
+
+ if (strchr (tmpl, G_DIR_SEPARATOR)
+#ifdef G_OS_WIN32
+ || strchr (tmpl, '/')
+#endif
+ )
+ {
+ g_set_error (error,
+ G_FILE_ERROR,
+ G_FILE_ERROR_FAILED,
+ _("Template '%s' illegal, should not contain a '%s'"),
+ tmpl, G_DIR_SEPARATOR_S);
+
+ return -1;
+ }
+
+ if (strlen (tmpl) < 6 ||
+ strcmp (tmpl + strlen (tmpl) - 6, "XXXXXX") != 0)
+ {
+ g_set_error (error,
+ G_FILE_ERROR,
+ G_FILE_ERROR_FAILED,
+ _("Template '%s' doesn't end with XXXXXX"),
+ tmpl);
+ return -1;
+ }
+
+ tmpdir = g_get_tmp_dir ();
+
+ if (tmpdir [strlen (tmpdir) - 1] == G_DIR_SEPARATOR)
+ sep = "";
+ else
+ sep = G_DIR_SEPARATOR_S;
+
+ fulltemplate = g_strconcat (tmpdir, sep, tmpl, NULL);
+
+ retval = g_mkstemp (fulltemplate);
+
+ if (retval == -1)
+ {
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ _("Failed to create file '%s': %s"),
+ fulltemplate, strerror (errno));
+ g_free (fulltemplate);
+ return -1;
+ }
+
+ if (name_used)
+ *name_used = fulltemplate;
+ else
+ g_free (fulltemplate);
+
+ return retval;
+}