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