GRASS 8 Programmer's Manual 8.6.0dev(2026)-1d1e47ad9d
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 */
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 */
161FILE *G_mkstemp_fp(char *template, int flags, int mode)
162{
163 const char *fmode = ((flags & O_ACCMODE) == O_RDWR)
164 ? ((flags & O_APPEND) ? "a+" : "w+")
165 : ((flags & O_APPEND) ? "a" : "w");
166 int fd = G_mkstemp(template, flags, mode);
167
168 if (fd < 0)
169 return NULL;
170 return fdopen(fd, fmode);
171}
#define NULL
Definition ccmath.h:32
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
Header file for msvc/fcntl.c.
#define O_ACCMODE
Definition fcntl.h:37
#define open
Definition fcntl.h:33
#define _(str)
Definition glocale.h:10
#define MAX_REPLACE
Definition mkstemp.c:22
FILE * G_mkstemp_fp(char *template, int flags, int mode)
Returns a file descriptor.
Definition mkstemp.c:161
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:127
#define fdopen
Definition stdio.h:6
#define access
Definition unistd.h:7
#define F_OK
Definition unistd.h:22