GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-2bdcc05b3a
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 
149 int G_open_new(const char *element, const char *name)
150 {
151  return G__open(element, name, G_mapset(), 1);
152 }
153 
154 /*!
155  \brief Open a database file for reading
156 
157  The database file <i>name</i> under the <i>element</i> in the
158  specified <i>mapset</i> is opened for reading (but not for writing).
159  The UNIX open() routine is used to open the file. If the file does
160  not exist, -1 is returned. Otherwise the file descriptor from the
161  open() is returned.
162 
163  \param element database element name
164  \param name map file name
165  \param mapset mapset containing map <i>name</i>
166 
167  \return open file descriptor (int)
168  \return -1 could not open
169  */
170 int G_open_old(const char *element, const char *name, const char *mapset)
171 {
172  return G__open(element, name, mapset, 0);
173 }
174 
175 /*!
176  \brief Open a database file for update
177 
178  The database file <i>name</i> under the <i>element</i> in the
179  current mapset is opened for reading and writing. The UNIX open()
180  routine is used to open the file. If the file does not exist, -1 is
181  returned. Otherwise the file is positioned at the end of the file
182  and the file descriptor from the open() is returned.
183 
184  \param element database element name
185  \param name map file name
186 
187  \return open file descriptor (int)
188  \return -1 could not open
189  */
190 
191 int G_open_update(const char *element, const char *name)
192 {
193  int fd;
194 
195  fd = G__open(element, name, G_mapset(), 2);
196  if (fd >= 0)
197  lseek(fd, 0L, SEEK_END);
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  */
218 
219 FILE *G_fopen_new(const char *element, const char *name)
220 {
221  int fd;
222 
223  fd = G__open(element, name, G_mapset(), 1);
224  if (fd < 0) {
225  G_debug(1, "G_fopen_new(): element = %s, name = %s : NULL", element,
226  name);
227  return (FILE *)0;
228  }
229 
230  G_debug(2, "\tfile open: new (mode = w)");
231  return fdopen(fd, "w");
232 }
233 
234 /*!
235  \brief Open a database file for reading
236 
237  The database file <i>name</i> under the <i>element</i> in the
238  specified <i>mapset</i> is opened for reading (but not for writing).
239  The UNIX fopen() routine, with "r" read mode, is used to open the
240  file. If the file does not exist, the NULL pointer is
241  returned. Otherwise the file descriptor from the fopen() is
242  returned.
243 
244  \param element database element name
245  \param name map file name
246  \param mapset mapset name containing map <i>name</i>
247 
248  \return open file descriptor (FILE *)
249  \return NULL on error
250  */
251 FILE *G_fopen_old(const char *element, const char *name, const char *mapset)
252 {
253  int fd;
254 
255  fd = G__open(element, name, mapset, 0);
256  if (fd < 0)
257  return (FILE *)NULL;
258 
259  G_debug(2, "\tfile open: read (mode = r)");
260  return fdopen(fd, "r");
261 }
262 
263 /*!
264  \brief Open a database file for update (append mode)
265 
266  The database file <i>name</i> under the <i>element</i> in the
267  current mapset is opened for for writing. The UNIX fopen() routine,
268  with "a" append mode, is used to open the file. If the file does not
269  exist, the NULL pointer is returned. Otherwise the file descriptor
270  from the fopen() is returned.
271 
272  \param element database element name
273  \param name map file name
274 
275  \return open file descriptor (FILE *)
276  \return NULL on error
277  */
278 FILE *G_fopen_append(const char *element, const char *name)
279 {
280  int fd;
281 
282  fd = G__open(element, name, G_mapset(), 2);
283  if (fd < 0)
284  return (FILE *)0;
285  lseek(fd, 0L, SEEK_END);
286 
287  G_debug(2, "\tfile open: append (mode = a)");
288  return fdopen(fd, "a");
289 }
290 
291 /*!
292  \brief Open a database file for update (r+ mode)
293 
294  The database file <i>name</i> under the <i>element</i> in the
295  current mapset is opened for for writing. The UNIX fopen() routine,
296  with "r+" append mode, is used to open the file. If the file does not
297  exist, the NULL pointer is returned. Otherwise the file descriptor
298  from the fopen() is returned.
299 
300  \param element database element name
301  \param name map file name
302 
303  \return open file descriptor (FILE *)
304  \return NULL on error
305  */
306 FILE *G_fopen_modify(const char *element, const char *name)
307 {
308  int fd;
309 
310  fd = G__open(element, name, G_mapset(), 2);
311  if (fd < 0)
312  return (FILE *)0;
313  lseek(fd, 0L, SEEK_END);
314 
315  G_debug(2, "\tfile open: modify (mode = r+)");
316  return fdopen(fd, "r+");
317 }
#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:74
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:153
int G_debug(int, const char *,...) __attribute__((format(printf
FILE * G_fopen_append(const char *element, const char *name)
Open a database file for update (append mode)
Definition: gis/open.c:278
FILE * G_fopen_modify(const char *element, const char *name)
Open a database file for update (r+ mode)
Definition: gis/open.c:306
FILE * G_fopen_new(const char *element, const char *name)
Open a new database file.
Definition: gis/open.c:219
int G_open_new(const char *element, const char *name)
Open a new database file.
Definition: gis/open.c:149
int G_open_update(const char *element, const char *name)
Open a database file for update.
Definition: gis/open.c:191
FILE * G_fopen_old(const char *element, const char *name, const char *mapset)
Open a database file for reading.
Definition: gis/open.c:251
int G_open_old(const char *element, const char *name, const char *mapset)
Open a database file for reading.
Definition: gis/open.c:170
#define GMAPSET_MAX
Definition: gis.h:192
#define GPATH_MAX
Definition: gis.h:194
#define GNAME_MAX
Definition: gis.h:191
void G__check_gisinit(void)
Checks to see if GIS engine is initialized.
Definition: gisinit.c:131
#define _(str)
Definition: glocale.h:10
const char * name
Definition: named_colr.c:6
Definition: lidar.h:85
Definition: path.h:15