GRASS GIS 8 Programmer's Manual 8.2.0(2022)-exported
mkstemp.c
Go to the documentation of this file.
1/*!
2 * \file lib/gis/mkstemp.c
3 *
4 * \brief GIS Library - Temporary file functions.
5 *
6 * (C) 2014 by the GRASS Development Team
7 *
8 * This program is free software under the GNU General Public License
9 * (>=v2). Read the file COPYING that comes with GRASS for details.
10 *
11 * \author Glynn Clements
12 */
13
14#include <stdio.h>
15#include <string.h>
16#include <errno.h>
17#include <unistd.h>
18#include <fcntl.h>
19#include <grass/gis.h>
20#include <grass/glocale.h>
21
22#define MAX_REPLACE 5
23
24static int next(char **replace, int num_replace)
25{
26 int i;
27
28 for (i = 0; i < num_replace; i++) {
29 char *p = replace[i];
30 if (*p < 'z') {
31 (*p)++;
32 return 1;
33 }
34 else
35 *p = 'a';
36 }
37
38 return 0;
39}
40
41static int G__mkstemp(char *template, int flags, int mode)
42{
43 char *replace[MAX_REPLACE];
44 int num_replace = 0;
45 char *ptr = template;
46 int fd;
47
48 while (num_replace < MAX_REPLACE) {
49 char *p = strchr(ptr, 'X');
50 if (!p)
51 break;
52 replace[num_replace++] = p;
53 *p = 'a';
54 ptr = p + 1;
55 }
56
57 if (!num_replace)
58 return -1;
59
60 for (;;) {
61 if (!next(replace, num_replace))
62 return -1;
63
64 if (access(template, F_OK) == 0)
65 continue;
66
67 if (!flags)
68 return 0;
69
70 fd = open(template, flags, mode);
71 if (fd < 0) {
72 if (errno == EEXIST)
73 continue;
74 return -1;
75 }
76
77 return fd;
78 }
79
80 return -1;
81}
82
83
84/*!
85 * \brief Opens a temporary file.
86 *
87 * This routine opens the file.
88 *
89 * The last two take the arguments "flags" and "mode". "flags" should be
90 * O_WRONLY or O_RDWR, plus any other desired flags (e.g. O_APPEND).
91 * "mode" is the file mode (0666 would be typical).
92 *
93 * The functions does not use the PID, although the caller can do so.
94 *
95 * In theory, up to 26^5 (= ~12 million) filenames will be attempted
96 * until it finds one which doesn't exist.
97 *
98 * <b>Note:</b> <i>G_mktemp()</i> as such it is prone to race
99 * conditions (some other process may create that file after G_mktemp()
100 * returns).
101 *
102 * \return file name
103 */
104char *G_mktemp(char *template)
105{
106 return G__mkstemp(template, 0, 0) < 0 ? NULL : template;
107}
108
109/*!
110 * \brief Returns a file descriptor.
111 *
112 * This routine opens the file and returns a descriptor.
113 *
114 * The last two take the arguments "flags" and "mode". "flags" should be
115 * O_WRONLY or O_RDWR, plus any other desired flags (e.g. O_APPEND).
116 * "mode" is the file mode (0666 would be typical).
117 *
118 * The functions does not use the PID, although the caller can do so.
119 *
120 * In theory, up to 26^5 (= ~12 million) filenames will be attempted
121 * until it finds one which doesn't exist.
122 *
123 *
124 * \return file descriptor
125 */
126
127int G_mkstemp(char *template, int flags, int mode)
128{
129
130 switch (flags & O_ACCMODE) {
131 case O_RDONLY:
132 G_fatal_error(_("Attempt to create read-only temporary file"));
133 return -1;
134 case O_WRONLY:
135 case O_RDWR:
136 break;
137 default:
138 G_fatal_error(_("Unrecognised access mode: %o"), flags & O_ACCMODE);
139 return -1;
140 }
141
142 return G__mkstemp(template, flags | O_CREAT | O_EXCL, mode);
143}
144
145/*!
146 * \brief Returns a file descriptor.
147 *
148 * This routine opens the file and returns a FILE*.
149 *
150 * The last two take the arguments "flags" and "mode". "flags" should be
151 * O_WRONLY or O_RDWR, plus any other desired flags (e.g. O_APPEND).
152 * "mode" is the file mode (0666 would be typical).
153 *
154 * The functions does not use the PID, although the caller can do so.
155 *
156 * In theory, up to 26^5 (= ~12 million) filenames will be attempted
157 * until it finds one which doesn't exist.
158 *
159 * \return FILE*
160 */
161
162FILE *G_mkstemp_fp(char *template, int flags, int mode)
163{
164 const char *fmode = ((flags & O_ACCMODE) == O_RDWR)
165 ? ((flags & O_APPEND) ? "a+" : "w+")
166 : ((flags & O_APPEND) ? "a" : "w");
167 int fd = G_mkstemp(template, flags, mode);
168 if (fd < 0)
169 return NULL;
170 return fdopen(fd, fmode);
171}
#define NULL
Definition: ccmath.h:32
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition: gis/error.c:160
#define MAX_REPLACE
Definition: mkstemp.c:22
FILE * G_mkstemp_fp(char *template, int flags, int mode)
Returns a file descriptor.
Definition: mkstemp.c:162
char * G_mktemp(char *template)
Opens a temporary file.
Definition: mkstemp.c:104
int G_mkstemp(char *template, int flags, int mode)
Returns a file descriptor.
Definition: mkstemp.c:127