source: trunk/third/evolution/e-util/e-mktemp.c @ 18142

Revision 18142, 5.5 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18141, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 *  Authors: Jeffrey Stedfast <fejj@ximian.com>
4 *
5 *  Copyright 2001 Ximian, Inc. (www.ximian.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2 of the GNU General Public
9 * License as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include <glib.h>
28#include <sys/stat.h>
29#include <sys/types.h>
30#include <stdlib.h>
31#include <string.h>
32#include <fcntl.h>
33#include <unistd.h>
34#include <dirent.h>
35#include <errno.h>
36
37#ifdef ENABLE_THREADS
38#include <pthread.h>
39#endif
40
41#include "e-mktemp.h"
42
43
44static gboolean initialized = FALSE;
45static GSList *temp_files = NULL;
46static GSList *temp_dirs = NULL;
47#ifdef ENABLE_THREADS
48static pthread_mutex_t temp_files_lock = PTHREAD_MUTEX_INITIALIZER;
49static pthread_mutex_t temp_dirs_lock = PTHREAD_MUTEX_INITIALIZER;
50#define TEMP_FILES_LOCK() pthread_mutex_lock (&temp_files_lock)
51#define TEMP_FILES_UNLOCK() pthread_mutex_unlock (&temp_files_lock)
52#define TEMP_DIRS_LOCK() pthread_mutex_lock (&temp_dirs_lock)
53#define TEMP_DIRS_UNLOCK() pthread_mutex_unlock (&temp_dirs_lock)
54#else
55#define TEMP_FILES_LOCK()
56#define TEMP_FILES_UNLOCK()
57#define TEMP_DIRS_LOCK()
58#define TEMP_DIRS_UNLOCK()
59#endif /* ENABLE_THREADS */
60
61
62static GString *
63get_path (gboolean make)
64{
65        GString *path;
66       
67        path = g_string_new ("/tmp/evolution-");
68        g_string_sprintfa (path, "%d-%d", (int) getuid (), (int) getpid ());
69       
70        if (make) {
71                int ret;
72               
73                /* shoot now, ask questions later */
74                ret = mkdir (path->str, S_IRWXU);
75                if (ret == -1) {
76                        if (errno == EEXIST) {
77                                struct stat st;
78                               
79                                if (stat (path->str, &st) == -1) {
80                                        /* reset errno */
81                                        errno = EEXIST;
82                                        g_string_free (path, TRUE);
83                                        return NULL;
84                                }
85                               
86                                /* make sure this is a directory and belongs to us... */
87                                if (!S_ISDIR (st.st_mode) || st.st_uid != getuid ()) {
88                                        /* eek! this is bad... */
89                                        g_string_free (path, TRUE);
90                                        return NULL;
91                                }
92                        } else {
93                                /* some other error...do not pass go, do not collect $200 */
94                                g_string_free (path, TRUE);
95                                return NULL;
96                        }
97                }
98        }
99       
100        return path;
101}
102
103static void
104e_mktemp_cleanup (void)
105{
106        GString *path;
107        GSList *node;
108       
109        TEMP_FILES_LOCK ();
110        if (temp_files) {
111                node = temp_files;
112                while (node) {
113                        unlink (node->data);
114                        g_free (node->data);
115                        node = node->next;
116                }
117                g_slist_free (temp_files);
118                temp_files = NULL;
119        }
120        TEMP_FILES_UNLOCK ();
121       
122        TEMP_DIRS_LOCK ();
123        if (temp_dirs) {
124                node = temp_dirs;
125                while (node) {
126                        /* perform the equivalent of a rm -rf */
127                        struct dirent *dent;
128                        DIR *dir;
129                       
130                        /* first empty out this directory of it's files... */
131                        dir = opendir (node->data);
132                        if (dir) {
133                                while ((dent = readdir (dir)) != NULL) {
134                                        /* yea...so if we contain
135                                           subdirectories this won't work, but
136                                           it shouldn't so we won't
137                                           bother caring... */
138                                        if (strcmp (dent->d_name, ".") && strcmp (dent->d_name, ".."))
139                                                unlink (dent->d_name);
140                                }
141                                closedir (dir);
142                        }
143                       
144                        /* ...then rmdir the directory */
145                        rmdir (node->data);
146                        g_free (node->data);
147                        node = node->next;
148                }
149                g_slist_free (temp_dirs);
150                temp_dirs = NULL;
151        }
152        TEMP_DIRS_UNLOCK ();
153       
154        path = get_path (FALSE);
155        rmdir (path->str);
156       
157        g_string_free (path, TRUE);
158}
159
160
161const char *
162e_mktemp (const char *template)
163{
164        GString *path;
165        char *ret;
166       
167        path = get_path (TRUE);
168        if (!path)
169                return NULL;
170       
171        g_string_append_c (path, '/');
172        if (template)
173                g_string_append (path, template);
174        else
175                g_string_append (path, "unknown-XXXXXX");
176       
177        ret = mktemp (path->str);
178        if (ret) {
179                TEMP_FILES_LOCK ();
180                if (!initialized) {
181                        g_atexit (e_mktemp_cleanup);
182                        initialized = TRUE;
183                }
184                temp_files = g_slist_prepend (temp_files, ret);
185                g_string_free (path, FALSE);
186                TEMP_FILES_UNLOCK ();
187        } else {
188                g_string_free (path, TRUE);
189        }
190       
191        return ret;
192}
193
194
195int
196e_mkstemp (const char *template)
197{
198        GString *path;
199        int fd;
200       
201        path = get_path (TRUE);
202        if (!path)
203                return -1;
204       
205        g_string_append_c (path, '/');
206        if (template)
207                g_string_append (path, template);
208        else
209                g_string_append (path, "unknown-XXXXXX");
210       
211        fd = mkstemp (path->str);
212        if (fd != -1) {
213                TEMP_FILES_LOCK ();
214                if (!initialized) {
215                        g_atexit (e_mktemp_cleanup);
216                        initialized = TRUE;
217                }
218                temp_files = g_slist_prepend (temp_files, path->str);
219                g_string_free (path, FALSE);
220                TEMP_FILES_UNLOCK ();
221        } else {
222                g_string_free (path, TRUE);
223        }
224       
225        return fd;
226}
227
228
229const char *
230e_mkdtemp (const char *template)
231{
232        GString *path;
233        char *tmpdir;
234       
235        path = get_path (TRUE);
236        if (!path)
237                return NULL;
238       
239        g_string_append_c (path, '/');
240        if (template)
241                g_string_append (path, template);
242        else
243                g_string_append (path, "unknown-XXXXXX");
244       
245#ifdef HAVE_MKDTEMP
246        tmpdir = mkdtemp (path->str);
247#else
248        tmpdir = mktemp (path->str);
249        if (tmpdir) {
250                if (mkdir (tmpdir, S_IRWXU) == -1)
251                        tmpdir = NULL;
252        }
253#endif
254       
255        if (tmpdir) {
256                TEMP_DIRS_LOCK ();
257                if (!initialized) {
258                        g_atexit (e_mktemp_cleanup);
259                        initialized = TRUE;
260                }
261                temp_dirs = g_slist_prepend (temp_dirs, tmpdir);
262                g_string_free (path, FALSE);
263                TEMP_DIRS_UNLOCK ();
264        } else {
265                g_string_free (path, TRUE);
266        }
267       
268        return tmpdir;
269}
Note: See TracBrowser for help on using the repository browser.