GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
Loading...
Searching...
No Matches
gis/open.c
Go to the documentation of this file.
1/*!
2 * \file lib/gis/open.c
3 *
4 * \brief GIS Library - Open file functions
5 *
6 * SPDX-FileCopyrightText: 1999-2015 GRASS Development Team
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 *
9 * \author USACERL and many others
10 */
11
12#include <grass/config.h>
13#include <errno.h>
14#include <string.h>
15
16#include <unistd.h>
17#include <fcntl.h>
18
19#include <grass/gis.h>
20#include <grass/glocale.h>
21
22#include "gis_local_proto.h"
23
24/*!
25 \brief Lowest level open routine.
26
27 Opens the file <i>name</i> in <i>element</i> ("cell", etc.) in mapset
28 <i>mapset</i> according to the i/o <i>mode</i>.
29
30 - mode = 0 (read) will look for <i>name</i> in <i>mapset</i> and
31 open the file for read only the file must exist
32
33 - mode = 1 (write) will create an empty file <i>name</i> in the
34 current mapset and open the file for write only
35 <i>mapset</i> ignored
36
37 - mode = 2 (read and write) will open a file in the current mapset
38 for reading and writing creating a new file if
39 necessary <i>mapset</i> ignored
40
41 \param element database element name
42 \param name map file name
43 \param mapset mapset containing map <i>name</i>
44 \param mode r/w mode 0=read, 1=write, 2=read/write
45
46 \return open file descriptor (int)
47 \return -1 could not open
48 */
49static int G__open(const char *element, const char *name, const char *mapset,
50 int mode)
51{
52 int fd;
53 int is_tmp;
54 char path[GPATH_MAX];
56
58
59 is_tmp = (element && strncmp(element, ".tmp", 4) == 0);
60
61 /* READ */
62 if (mode == 0) {
64 if (*mapset && strcmp(xmapset, mapset) != 0) {
66 _("G__open(read): mapset <%s> doesn't match xmapset <%s>"),
67 mapset, xmapset);
68 return -1;
69 }
70 name = xname;
71 mapset = xmapset;
72 }
73
74 if (!is_tmp) {
75 mapset = G_find_file2(element, name, mapset);
76
77 if (!mapset)
78 return -1;
79
80 G_file_name(path, element, name, mapset);
81 }
82 else {
84 }
85
86 if ((fd = open(path, 0)) < 0)
87 G_warning(_("G__open(read): Unable to open '%s': %s"), path,
89 return fd;
90 }
91 /* WRITE */
92 if (mode == 1 || mode == 2) {
93 mapset = G_mapset();
95 if (strcmp(xmapset, mapset) != 0) {
96 G_warning(_("G__open(write): xmapset <%s> != G_mapset() <%s>"),
97 xmapset, mapset);
98 return -1;
99 }
100 name = xname;
101 }
102
103 if (*name && G_legal_filename(name) == -1)
104 return -1;
105
106 if (!is_tmp)
107 G_file_name(path, element, name, mapset);
108 else
109 G_file_name_tmp(path, element, name, mapset);
110
111 if (mode == 1 || access(path, 0) != 0) {
112 if (is_tmp)
114 else
116 close(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666));
117 }
118
119 if ((fd = open(path, mode)) < 0)
120 G_warning(_("G__open(write): Unable to open '%s': %s"), path,
121 strerror(errno));
122 return fd;
123 }
124 return -1;
125}
126
127/*!
128 \brief Open a new database file
129
130 Creates <i>name</i> in the current mapset and opens it
131 for write only.
132
133 The database file <i>name</i> under the <i>element</i> in the
134 current mapset is created and opened for writing (but not reading).
135 The UNIX open() routine is used to open the file. If the file does
136 not exist, -1 is returned. Otherwise the file is positioned at the
137 end of the file and the file descriptor from the open() is returned.
138
139 \param element database element name
140 \param name map file name
141
142 \return open file descriptor (int)
143 \return -1 could not open
144 */
145int G_open_new(const char *element, const char *name)
146{
147 return G__open(element, name, G_mapset(), 1);
148}
149
150/*!
151 \brief Open a database file for reading
152
153 The database file <i>name</i> under the <i>element</i> in the
154 specified <i>mapset</i> is opened for reading (but not for writing).
155 The UNIX open() routine is used to open the file. If the file does
156 not exist, -1 is returned. Otherwise the file descriptor from the
157 open() is returned.
158
159 \param element database element name
160 \param name map file name
161 \param mapset mapset containing map <i>name</i>
162
163 \return open file descriptor (int)
164 \return -1 could not open
165 */
166int G_open_old(const char *element, const char *name, const char *mapset)
167{
168 return G__open(element, name, mapset, 0);
169}
170
171/*!
172 \brief Open a database file for update
173
174 The database file <i>name</i> under the <i>element</i> in the
175 current mapset is opened for reading and writing. The UNIX open()
176 routine is used to open the file. If the file does not exist, -1 is
177 returned. Otherwise the file is positioned at the end of the file
178 and the file descriptor from the open() is returned.
179
180 \param element database element name
181 \param name map file name
182
183 \return open file descriptor (int)
184 \return -1 could not open
185 */
186int G_open_update(const char *element, const char *name)
187{
188 int fd;
189
190 fd = G__open(element, name, G_mapset(), 2);
191 if (fd >= 0)
192 if (lseek(fd, 0L, SEEK_END) == -1) {
193 int err = errno;
194 G_warning(_("File read/write operation failed: %s (%d)"),
195 strerror(err), err);
196 return -1;
197 }
198
199 return fd;
200}
201
202/*!
203 \brief Open a new database file
204
205 The database file <i>name</i> under the <i>element</i> in the
206 current mapset is created and opened for writing (but not reading).
207 The UNIX fopen() routine, with "w" write mode, is used to open the
208 file. If the file does not exist, the NULL pointer is
209 returned. Otherwise the file is positioned at the end of the file
210 and the file descriptor from the fopen() is returned.
211
212 \param element database element name
213 \param name map file name
214
215 \return open file descriptor (FILE *)
216 \return NULL on error
217 */
218FILE *G_fopen_new(const char *element, const char *name)
219{
220 int fd;
221
222 fd = G__open(element, name, G_mapset(), 1);
223 if (fd < 0) {
224 G_debug(1, "G_fopen_new(): element = %s, name = %s : NULL", element,
225 name);
226 return (FILE *)0;
227 }
228
229 G_debug(2, "\tfile open: new (mode = w)");
230 return fdopen(fd, "w");
231}
232
233/*!
234 \brief Open a database file for reading
235
236 The database file <i>name</i> under the <i>element</i> in the
237 specified <i>mapset</i> is opened for reading (but not for writing).
238 The UNIX fopen() routine, with "r" read mode, is used to open the
239 file. If the file does not exist, the NULL pointer is
240 returned. Otherwise the file descriptor from the fopen() is
241 returned.
242
243 \param element database element name
244 \param name map file name
245 \param mapset mapset name containing map <i>name</i>
246
247 \return open file descriptor (FILE *)
248 \return NULL on error
249 */
250FILE *G_fopen_old(const char *element, const char *name, const char *mapset)
251{
252 int fd;
253
254 fd = G__open(element, name, mapset, 0);
255 if (fd < 0)
256 return (FILE *)NULL;
257
258 G_debug(2, "\tfile open: read (mode = r)");
259 return fdopen(fd, "r");
260}
261
262/*!
263 \brief Open a database file for update (append mode)
264
265 The database file <i>name</i> under the <i>element</i> in the
266 current mapset is opened for for writing. The UNIX fopen() routine,
267 with "a" append mode, is used to open the file. If the file does not
268 exist, the NULL pointer is returned. Otherwise the file descriptor
269 from the fopen() is returned.
270
271 \param element database element name
272 \param name map file name
273
274 \return open file descriptor (FILE *)
275 \return NULL on error
276 */
277FILE *G_fopen_append(const char *element, const char *name)
278{
279 int fd;
280
281 fd = G__open(element, name, G_mapset(), 2);
282 if (fd < 0)
283 return (FILE *)0;
284 if (lseek(fd, 0L, SEEK_END) == -1) {
285 int err = errno;
286 G_warning(_("File read/write operation failed: %s (%d)"), strerror(err),
287 err);
288 return NULL;
289 }
290
291 G_debug(2, "\tfile open: append (mode = a)");
292 return fdopen(fd, "a");
293}
294
295/*!
296 \brief Open a database file for update (r+ mode)
297
298 The database file <i>name</i> under the <i>element</i> in the
299 current mapset is opened for for writing. The UNIX fopen() routine,
300 with "r+" append mode, is used to open the file. If the file does not
301 exist, the NULL pointer is returned. Otherwise the file descriptor
302 from the fopen() is returned.
303
304 \param element database element name
305 \param name map file name
306
307 \return open file descriptor (FILE *)
308 \return NULL on error
309 */
310FILE *G_fopen_modify(const char *element, const char *name)
311{
312 int fd;
313
314 fd = G__open(element, name, G_mapset(), 2);
315 if (fd < 0)
316 return (FILE *)0;
317 if (lseek(fd, 0L, SEEK_END) == -1) {
318 int err = errno;
319 G_warning(_("File read/write operation failed: %s (%d)"), strerror(err),
320 err);
321 return NULL;
322 }
323
324 G_debug(2, "\tfile open: modify (mode = r+)");
325 return fdopen(fd, "r+");
326}
#define NULL
Definition ccmath.h:32
int G_name_is_fully_qualified(const char *, char *, char *)
Check if map name is fully qualified (map @ mapset)
Definition nme_in_mps.c:34
void G_warning(const char *,...) __attribute__((format(printf
int G_legal_filename(const char *)
Check for legal database file name.
Definition legal_name.c:32
int G_make_mapset_object_group(const char *)
Create directory for group of elements of a given type.
Definition mapset_msc.c:73
char * G_file_name(char *, const char *, const char *, const char *)
Builds full path names to GIS data files.
Definition file_name.c:59
const char * G_find_file2(const char *, const char *, const char *)
Searches for a file from the mapset search list or in a specified mapset. (look but don't touch)
Definition find_file.c:230
int G_make_mapset_object_group_tmp(const char *)
Create directory for type of objects in the temporary directory.
Definition mapset_msc.c:152
char * G_file_name_tmp(char *, const char *, const char *, const char *)
Builds full path names to GIS data files in temporary directory (for internal use only)
Definition file_name.c:123
int G_debug(int, const char *,...) __attribute__((format(printf
const char * G_mapset(void)
Get current mapset name.
Definition gis/mapset.c:31
Header file for msvc/fcntl.c.
#define open
Definition fcntl.h:32
FILE * G_fopen_append(const char *element, const char *name)
Open a database file for update (append mode)
Definition gis/open.c:277
int G_open_new(const char *element, const char *name)
Open a new database file.
Definition gis/open.c:145
int G_open_update(const char *element, const char *name)
Open a database file for update.
Definition gis/open.c:186
FILE * G_fopen_modify(const char *element, const char *name)
Open a database file for update (r+ mode)
Definition gis/open.c:310
FILE * G_fopen_old(const char *element, const char *name, const char *mapset)
Open a database file for reading.
Definition gis/open.c:250
FILE * G_fopen_new(const char *element, const char *name)
Open a new database file.
Definition gis/open.c:218
int G_open_old(const char *element, const char *name, const char *mapset)
Open a database file for reading.
Definition gis/open.c:166
#define GMAPSET_MAX
Definition gis.h:194
#define GPATH_MAX
Definition gis.h:196
#define GNAME_MAX
Definition gis.h:193
void G__check_gisinit(void)
Checks to see if GIS engine is initialized.
Definition gisinit.c:146
#define _(str)
Definition glocale.h:10
const char * name
Definition named_colr.c:6
#define fdopen
Definition stdio.h:6
Definition path.h:15
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
#define access
Definition unistd.h:7
#define close
Definition unistd.h:8