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