GRASS 8 Programmer's Manual 8.6.0dev(2026)-c83afef6d3
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 * SPDX-FileCopyrightText: 2014 GRASS Development Team
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 *
9 * \author Glynn Clements
10 */
11
12#include <stdio.h>
13#include <string.h>
14#include <errno.h>
15#include <unistd.h>
16#include <fcntl.h>
17#include <grass/gis.h>
18#include <grass/glocale.h>
19
20#define MAX_REPLACE 5
21
22static int next(char **replace, int num_replace)
23{
24 int i;
25
26 for (i = 0; i < num_replace; i++) {
27 char *p = replace[i];
28
29 if (*p < 'z') {
30 (*p)++;
31 return 1;
32 }
33 else
34 *p = 'a';
35 }
36
37 return 0;
38}
39
40static int G__mkstemp(char *template, int flags, int mode)
41{
42 char *replace[MAX_REPLACE];
43 int num_replace = 0;
44 char *ptr = template;
45 int fd;
46
47 while (num_replace < MAX_REPLACE) {
48 char *p = strchr(ptr, 'X');
49
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 * \brief Opens a temporary file.
85 *
86 * This routine opens the file.
87 *
88 * The last two take the arguments "flags" and "mode". "flags" should be
89 * O_WRONLY or O_RDWR, plus any other desired flags (e.g. O_APPEND).
90 * "mode" is the file mode (0666 would be typical).
91 *
92 * The functions does not use the PID, although the caller can do so.
93 *
94 * In theory, up to 26^5 (= ~12 million) filenames will be attempted
95 * until it finds one which doesn't exist.
96 *
97 * <b>Note:</b> <i>G_mktemp()</i> as such it is prone to race
98 * conditions (some other process may create that file after G_mktemp()
99 * returns).
100 *
101 * \return file name
102 */
103char *G_mktemp(char *template)
104{
105 return G__mkstemp(template, 0, 0) < 0 ? NULL : template;
106}
107
108/*!
109 * \brief Returns a file descriptor.
110 *
111 * This routine opens the file and returns a descriptor.
112 *
113 * The last two take the arguments "flags" and "mode". "flags" should be
114 * O_WRONLY or O_RDWR, plus any other desired flags (e.g. O_APPEND).
115 * "mode" is the file mode (0666 would be typical).
116 *
117 * The functions does not use the PID, although the caller can do so.
118 *
119 * In theory, up to 26^5 (= ~12 million) filenames will be attempted
120 * until it finds one which doesn't exist.
121 *
122 *
123 * \return file descriptor
124 */
125int G_mkstemp(char *template, int flags, int mode)
126{
127
128 switch (flags & O_ACCMODE) {
129 case O_RDONLY:
130 G_fatal_error(_("Attempt to create read-only temporary file"));
131 return -1;
132 case O_WRONLY:
133 case O_RDWR:
134 break;
135 default:
136 G_fatal_error(_("Unrecognised access mode: %o"), flags & O_ACCMODE);
137 return -1;
138 }
139
140 return G__mkstemp(template, flags | O_CREAT | O_EXCL, mode);
141}
142
143/*!
144 * \brief Returns a file descriptor.
145 *
146 * This routine opens the file and returns a FILE*.
147 *
148 * The last two take the arguments "flags" and "mode". "flags" should be
149 * O_WRONLY or O_RDWR, plus any other desired flags (e.g. O_APPEND).
150 * "mode" is the file mode (0666 would be typical).
151 *
152 * The functions does not use the PID, although the caller can do so.
153 *
154 * In theory, up to 26^5 (= ~12 million) filenames will be attempted
155 * until it finds one which doesn't exist.
156 *
157 * \return FILE*
158 */
159FILE *G_mkstemp_fp(char *template, int flags, int mode)
160{
161 const char *fmode = ((flags & O_ACCMODE) == O_RDWR)
162 ? ((flags & O_APPEND) ? "a+" : "w+")
163 : ((flags & O_APPEND) ? "a" : "w");
164 int fd = G_mkstemp(template, flags, mode);
165
166 if (fd < 0)
167 return NULL;
168 return fdopen(fd, fmode);
169}
#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:36
#define open
Definition fcntl.h:32
#define _(str)
Definition glocale.h:10
#define MAX_REPLACE
Definition mkstemp.c:20
FILE * G_mkstemp_fp(char *template, int flags, int mode)
Returns a file descriptor.
Definition mkstemp.c:159
char * G_mktemp(char *template)
Opens a temporary file.
Definition mkstemp.c:103
int G_mkstemp(char *template, int flags, int mode)
Returns a file descriptor.
Definition mkstemp.c:125
#define fdopen
Definition stdio.h:6
#define access
Definition unistd.h:7
#define F_OK
Definition unistd.h:22