diff options
author | Tor Lillqvist <tml@iki.fi> | 2000-11-10 23:43:33 +0000 |
---|---|---|
committer | Tor Lillqvist <tml@src.gnome.org> | 2000-11-10 23:43:33 +0000 |
commit | 997215e7477075bfa05a9f21a639f3d8f74d2144 (patch) | |
tree | f21ad3b01316d5347779becd6e077f236d582fb4 | |
parent | c46b9f34e4ac5f0b869fe6077973336d5e1cead8 (diff) | |
download | glib-997215e7477075bfa05a9f21a639f3d8f74d2144.tar.gz |
New function, suggested by Havoc earlier this month. (g_mkstemp): Use only
2000-11-11 Tor Lillqvist <tml@iki.fi>
* gfileutils.c (g_file_open_tmp): New function, suggested by Havoc
earlier this month.
(g_mkstemp): Use only one case for letters in temp file name, as
this will be used on systems with case-insensitive file systems.
* testglib.c (main): Test g_mkstemp() and g_file_open_tmp().
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 9 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 9 | ||||
-rw-r--r-- | ChangeLog.pre-2-12 | 9 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 9 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 9 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 9 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 9 | ||||
-rw-r--r-- | gfileutils.c | 118 | ||||
-rw-r--r-- | glib.def | 1 | ||||
-rw-r--r-- | glib/gfileutils.c | 118 | ||||
-rw-r--r-- | glib/glib.def | 1 | ||||
-rw-r--r-- | testglib.c | 72 | ||||
-rw-r--r-- | tests/testglib.c | 72 |
14 files changed, 428 insertions, 26 deletions
@@ -1,3 +1,12 @@ +2000-11-11 Tor Lillqvist <tml@iki.fi> + + * gfileutils.c (g_file_open_tmp): New function, suggested by Havoc + earlier this month. + (g_mkstemp): Use only one case for letters in temp file name, as + this will be used on systems with case-insensitive file systems. + + * testglib.c (main): Test g_mkstemp() and g_file_open_tmp(). + 2000-11-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de> * gthreadpool.c: Don't take other threads with other priorities diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 57964146d..acaf5bc5d 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,12 @@ +2000-11-11 Tor Lillqvist <tml@iki.fi> + + * gfileutils.c (g_file_open_tmp): New function, suggested by Havoc + earlier this month. + (g_mkstemp): Use only one case for letters in temp file name, as + this will be used on systems with case-insensitive file systems. + + * testglib.c (main): Test g_mkstemp() and g_file_open_tmp(). + 2000-11-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de> * gthreadpool.c: Don't take other threads with other priorities diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 57964146d..acaf5bc5d 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,12 @@ +2000-11-11 Tor Lillqvist <tml@iki.fi> + + * gfileutils.c (g_file_open_tmp): New function, suggested by Havoc + earlier this month. + (g_mkstemp): Use only one case for letters in temp file name, as + this will be used on systems with case-insensitive file systems. + + * testglib.c (main): Test g_mkstemp() and g_file_open_tmp(). + 2000-11-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de> * gthreadpool.c: Don't take other threads with other priorities diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 57964146d..acaf5bc5d 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,12 @@ +2000-11-11 Tor Lillqvist <tml@iki.fi> + + * gfileutils.c (g_file_open_tmp): New function, suggested by Havoc + earlier this month. + (g_mkstemp): Use only one case for letters in temp file name, as + this will be used on systems with case-insensitive file systems. + + * testglib.c (main): Test g_mkstemp() and g_file_open_tmp(). + 2000-11-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de> * gthreadpool.c: Don't take other threads with other priorities diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 57964146d..acaf5bc5d 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,12 @@ +2000-11-11 Tor Lillqvist <tml@iki.fi> + + * gfileutils.c (g_file_open_tmp): New function, suggested by Havoc + earlier this month. + (g_mkstemp): Use only one case for letters in temp file name, as + this will be used on systems with case-insensitive file systems. + + * testglib.c (main): Test g_mkstemp() and g_file_open_tmp(). + 2000-11-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de> * gthreadpool.c: Don't take other threads with other priorities diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 57964146d..acaf5bc5d 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,12 @@ +2000-11-11 Tor Lillqvist <tml@iki.fi> + + * gfileutils.c (g_file_open_tmp): New function, suggested by Havoc + earlier this month. + (g_mkstemp): Use only one case for letters in temp file name, as + this will be used on systems with case-insensitive file systems. + + * testglib.c (main): Test g_mkstemp() and g_file_open_tmp(). + 2000-11-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de> * gthreadpool.c: Don't take other threads with other priorities diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 57964146d..acaf5bc5d 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,12 @@ +2000-11-11 Tor Lillqvist <tml@iki.fi> + + * gfileutils.c (g_file_open_tmp): New function, suggested by Havoc + earlier this month. + (g_mkstemp): Use only one case for letters in temp file name, as + this will be used on systems with case-insensitive file systems. + + * testglib.c (main): Test g_mkstemp() and g_file_open_tmp(). + 2000-11-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de> * gthreadpool.c: Don't take other threads with other priorities diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 57964146d..acaf5bc5d 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,12 @@ +2000-11-11 Tor Lillqvist <tml@iki.fi> + + * gfileutils.c (g_file_open_tmp): New function, suggested by Havoc + earlier this month. + (g_mkstemp): Use only one case for letters in temp file name, as + this will be used on systems with case-insensitive file systems. + + * testglib.c (main): Test g_mkstemp() and g_file_open_tmp(). + 2000-11-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de> * gthreadpool.c: Don't take other threads with other priorities diff --git a/gfileutils.c b/gfileutils.c index c9c0d9e19..e5cc56aed 100644 --- a/gfileutils.c +++ b/gfileutils.c @@ -518,7 +518,7 @@ g_file_get_contents (const gchar *filename, * 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. @@ -534,7 +534,8 @@ 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; @@ -554,17 +555,17 @@ g_mkstemp (char *tmpl) 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); @@ -581,3 +582,94 @@ g_mkstemp (char *tmpl) return -1; #endif } + +/** + * g_file_open_tmp: + * @template: 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()). + * + * @template should be a string ending with six 'X' characters, as the + * parameter to g_mkstemp() (or mktemp()). 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. + * + * 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. + * + * If some error occurs, @error is set, and -1 is returned. Otherwise, + * the file descriptor to a file opened for reading and writing with + * g_mkstemp() is returned. + **/ +int +g_file_open_tmp (const char *template, + char **name_used, + GError **error) +{ + int retval; + char mytemplate[10]; + char *tmpdir; + char *sep; + char *fulltemplate; + + if (template == NULL) + { + strcpy (mytemplate, ".XXXXXX"); + template = mytemplate; + } + + if (strchr (template, G_DIR_SEPARATOR)) + { + g_set_error (error, + G_FILE_ERROR, + G_FILE_ERROR_FAILED, + _("Template '%s' illegal, should not contain a '%s'"), + template, G_DIR_SEPARATOR_S); + + return -1; + } + + if (strlen (template) < 6 || + strcmp (template + strlen (template) - 6, "XXXXXX") != 0) + { + g_set_error (error, + G_FILE_ERROR, + G_FILE_ERROR_FAILED, + _("Template '%s' doesn end with XXXXXX"), + template); + 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, template, 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; +} @@ -103,6 +103,7 @@ EXPORTS g_file_error_quark g_file_get_contents g_file_test + g_file_open_tmp g_filename_from_utf8 g_filename_to_utf8 g_free diff --git a/glib/gfileutils.c b/glib/gfileutils.c index c9c0d9e19..e5cc56aed 100644 --- a/glib/gfileutils.c +++ b/glib/gfileutils.c @@ -518,7 +518,7 @@ g_file_get_contents (const gchar *filename, * 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. @@ -534,7 +534,8 @@ 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; @@ -554,17 +555,17 @@ g_mkstemp (char *tmpl) 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); @@ -581,3 +582,94 @@ g_mkstemp (char *tmpl) return -1; #endif } + +/** + * g_file_open_tmp: + * @template: 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()). + * + * @template should be a string ending with six 'X' characters, as the + * parameter to g_mkstemp() (or mktemp()). 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. + * + * 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. + * + * If some error occurs, @error is set, and -1 is returned. Otherwise, + * the file descriptor to a file opened for reading and writing with + * g_mkstemp() is returned. + **/ +int +g_file_open_tmp (const char *template, + char **name_used, + GError **error) +{ + int retval; + char mytemplate[10]; + char *tmpdir; + char *sep; + char *fulltemplate; + + if (template == NULL) + { + strcpy (mytemplate, ".XXXXXX"); + template = mytemplate; + } + + if (strchr (template, G_DIR_SEPARATOR)) + { + g_set_error (error, + G_FILE_ERROR, + G_FILE_ERROR_FAILED, + _("Template '%s' illegal, should not contain a '%s'"), + template, G_DIR_SEPARATOR_S); + + return -1; + } + + if (strlen (template) < 6 || + strcmp (template + strlen (template) - 6, "XXXXXX") != 0) + { + g_set_error (error, + G_FILE_ERROR, + G_FILE_ERROR_FAILED, + _("Template '%s' doesn end with XXXXXX"), + template); + 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, template, 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; +} diff --git a/glib/glib.def b/glib/glib.def index 818485869..82642e2dd 100644 --- a/glib/glib.def +++ b/glib/glib.def @@ -103,6 +103,7 @@ EXPORTS g_file_error_quark g_file_get_contents g_file_test + g_file_open_tmp g_filename_from_utf8 g_filename_to_utf8 g_free diff --git a/testglib.c b/testglib.c index cb8f50f2e..3eedc81dd 100644 --- a/testglib.c +++ b/testglib.c @@ -28,6 +28,7 @@ #include <stdio.h> #include <string.h> +#include <errno.h> #include "glib.h" int array[10000]; @@ -349,6 +350,12 @@ main (int argc, guint64 gu64t1 = G_GINT64_CONSTANT(0x1d636b02300a7aa7U), gu64t2 = G_GINT64_CONSTANT(0xa77a0a30026b631dU); #endif + const char hello[] = "Hello, World"; + const int hellolen = sizeof (hello) - 1; + int fd; + char template[10]; + GError *error; + char *name_used; g_print ("TestGLib v%u.%u.%u (i:%u b:%u)\n", glib_major_version, @@ -1085,6 +1092,71 @@ main (int argc, g_print ("current locale: %s\n", g_win32_getlocale ()); #endif + g_print ("checking file functions...\n"); + + strcpy (template, "foobar"); + fd = g_mkstemp (template); + if (fd != -1) + g_print ("g_mkstemp works even if template doesn't end in XXXXXX\n"); + close (fd); + strcpy (template, "fooXXXXXX"); + fd = g_mkstemp (template); + if (fd == -1) + g_print ("g_mkstemp didn't work for template %s\n", template); + i = write (fd, hello, hellolen); + if (i == -1) + g_print ("write() failed: %s\n", g_strerror (errno)); + else if (i != hellolen) + g_print ("write() should have written %d bytes, wrote %d\n", hellolen, i); + + lseek (fd, 0, 0); + i = read (fd, chars, sizeof (chars)); + if (i == -1) + g_print ("read() failed: %s\n", g_strerror (errno)); + else if (i != hellolen) + g_print ("read() should have read %d bytes, got %d\n", hellolen, i); + + chars[i] = 0; + if (strcmp (chars, hello) != 0) + g_print ("wrote '%s', but got '%s'\n", hello, chars); + + close (fd); + remove (template); + + strcpy (template, "zap" G_DIR_SEPARATOR_S "barXXXXXX"); + fd = g_file_open_tmp (template, &name_used, &error); + if (fd != -1) + g_print ("g_file_open_tmp works even if template contains '%s'\n", + G_DIR_SEPARATOR_S); + else + g_print ("g_file_open_tmp correctly returns error: %s\n", + error->message); + close (fd); + g_clear_error (&error); + + strcpy (template, "zapXXXXXX"); + fd = g_file_open_tmp (template, &name_used, &error); + if (fd == -1) + g_print ("g_file_open_tmp didn't work for template '%s': %s\n", + template, error->message); + else + g_print ("g_file_open_tmp for template '%s' used name '%s'\n", + template, name_used); + close (fd); + g_clear_error (&error); + remove (name_used); + + fd = g_file_open_tmp (NULL, &name_used, &error); + if (fd == -1) + g_print ("g_file_open_tmp didn't work for a NULL template: %s\n", + error->message); + else + g_print ("g_file_open_tmp for NULL template used name '%s'\n", + name_used); + close (fd); + g_clear_error (&error); + remove (name_used); + return 0; } diff --git a/tests/testglib.c b/tests/testglib.c index cb8f50f2e..3eedc81dd 100644 --- a/tests/testglib.c +++ b/tests/testglib.c @@ -28,6 +28,7 @@ #include <stdio.h> #include <string.h> +#include <errno.h> #include "glib.h" int array[10000]; @@ -349,6 +350,12 @@ main (int argc, guint64 gu64t1 = G_GINT64_CONSTANT(0x1d636b02300a7aa7U), gu64t2 = G_GINT64_CONSTANT(0xa77a0a30026b631dU); #endif + const char hello[] = "Hello, World"; + const int hellolen = sizeof (hello) - 1; + int fd; + char template[10]; + GError *error; + char *name_used; g_print ("TestGLib v%u.%u.%u (i:%u b:%u)\n", glib_major_version, @@ -1085,6 +1092,71 @@ main (int argc, g_print ("current locale: %s\n", g_win32_getlocale ()); #endif + g_print ("checking file functions...\n"); + + strcpy (template, "foobar"); + fd = g_mkstemp (template); + if (fd != -1) + g_print ("g_mkstemp works even if template doesn't end in XXXXXX\n"); + close (fd); + strcpy (template, "fooXXXXXX"); + fd = g_mkstemp (template); + if (fd == -1) + g_print ("g_mkstemp didn't work for template %s\n", template); + i = write (fd, hello, hellolen); + if (i == -1) + g_print ("write() failed: %s\n", g_strerror (errno)); + else if (i != hellolen) + g_print ("write() should have written %d bytes, wrote %d\n", hellolen, i); + + lseek (fd, 0, 0); + i = read (fd, chars, sizeof (chars)); + if (i == -1) + g_print ("read() failed: %s\n", g_strerror (errno)); + else if (i != hellolen) + g_print ("read() should have read %d bytes, got %d\n", hellolen, i); + + chars[i] = 0; + if (strcmp (chars, hello) != 0) + g_print ("wrote '%s', but got '%s'\n", hello, chars); + + close (fd); + remove (template); + + strcpy (template, "zap" G_DIR_SEPARATOR_S "barXXXXXX"); + fd = g_file_open_tmp (template, &name_used, &error); + if (fd != -1) + g_print ("g_file_open_tmp works even if template contains '%s'\n", + G_DIR_SEPARATOR_S); + else + g_print ("g_file_open_tmp correctly returns error: %s\n", + error->message); + close (fd); + g_clear_error (&error); + + strcpy (template, "zapXXXXXX"); + fd = g_file_open_tmp (template, &name_used, &error); + if (fd == -1) + g_print ("g_file_open_tmp didn't work for template '%s': %s\n", + template, error->message); + else + g_print ("g_file_open_tmp for template '%s' used name '%s'\n", + template, name_used); + close (fd); + g_clear_error (&error); + remove (name_used); + + fd = g_file_open_tmp (NULL, &name_used, &error); + if (fd == -1) + g_print ("g_file_open_tmp didn't work for a NULL template: %s\n", + error->message); + else + g_print ("g_file_open_tmp for NULL template used name '%s'\n", + name_used); + close (fd); + g_clear_error (&error); + remove (name_used); + return 0; } |