GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
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 <i>mapset</i>
31  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,
53  const char *name, const char *mapset, 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(_("G__open(read): mapset <%s> doesn't match xmapset <%s>"),
69  mapset, xmapset);
70  return -1;
71  }
72  name = xname;
73  mapset = xmapset;
74  }
75 
76  if (!is_tmp) {
77  mapset = G_find_file2(element, name, mapset);
78 
79  if (!mapset)
80  return -1;
81 
82  G_file_name(path, element, name, mapset);
83  }
84  else {
85  G_file_name_tmp(path, element, name, mapset);
86  }
87 
88  if ((fd = open(path, 0)) < 0)
89  G_warning(_("G__open(read): Unable to open '%s': %s"),
90  path, strerror(errno));
91  return fd;
92  }
93  /* WRITE */
94  if (mode == 1 || mode == 2) {
95  mapset = G_mapset();
96  if (G_name_is_fully_qualified(name, xname, xmapset)) {
97  if (strcmp(xmapset, mapset) != 0) {
98  G_warning(_("G__open(write): xmapset <%s> != G_mapset() <%s>"),
99  xmapset, mapset);
100  return -1;
101  }
102  name = xname;
103  }
104 
105  if (*name && G_legal_filename(name) == -1)
106  return -1;
107 
108  if (!is_tmp)
109  G_file_name(path, element, name, mapset);
110  else
111  G_file_name_tmp(path, element, name, mapset);
112 
113  if (mode == 1 || access(path, 0) != 0) {
114  if (is_tmp)
115  G_make_mapset_element_tmp(element);
116  else
117  G_make_mapset_element(element);
118  close(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666));
119  }
120 
121  if ((fd = open(path, mode)) < 0)
122  G_warning(_("G__open(write): Unable to open '%s': %s"),
123  path, strerror(errno));
124  return fd;
125  }
126  return -1;
127 }
128 
129 /*!
130  \brief Open a new database file
131 
132  Creates <i>name</i> in the current mapset and opens it
133  for write only.
134 
135  The database file <i>name</i> under the <i>element</i> in the
136  current mapset is created and opened for writing (but not reading).
137  The UNIX open() routine is used to open the file. If the file does
138  not exist, -1 is returned. Otherwise the file is positioned at the
139  end of the file and the file descriptor from the open() is returned.
140 
141  \param element database element name
142  \param name map file name
143 
144  \return open file descriptor (int)
145  \return -1 could not open
146 */
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 /*!
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 /*!
204  \brief Open a new database file
205 
206  The database file <i>name</i> under the <i>element</i> in the
207  current mapset is created and opened for writing (but not reading).
208  The UNIX fopen() routine, with "w" write mode, is used to open the
209  file. If the file does not exist, the NULL pointer is
210  returned. Otherwise the file is positioned at the end of the file
211  and the file descriptor from the fopen() is returned.
212 
213  \param element database element name
214  \param name map file name
215 
216  \return open file descriptor (FILE *)
217  \return NULL on error
218  */
219 
220 FILE *G_fopen_new(const char *element, const char *name)
221 {
222  int fd;
223 
224  fd = G__open(element, name, G_mapset(), 1);
225  if (fd < 0) {
226  G_debug(1, "G_fopen_new(): element = %s, name = %s : NULL",
227  element, name);
228  return (FILE *) 0;
229  }
230 
231  G_debug(2, "\tfile open: new (mode = w)");
232  return fdopen(fd, "w");
233 }
234 
235 
236 /*!
237  \brief Open a database file for reading
238 
239  The database file <i>name</i> under the <i>element</i> in the
240  specified <i>mapset</i> is opened for reading (but not for writing).
241  The UNIX fopen() routine, with "r" read mode, is used to open the
242  file. If the file does not exist, the NULL pointer is
243  returned. Otherwise the file descriptor from the fopen() is
244  returned.
245 
246  \param element database element name
247  \param name map file name
248  \param mapset mapset name containing map <i>name</i>
249 
250  \return open file descriptor (FILE *)
251  \return NULL on error
252 */
253 FILE *G_fopen_old(const char *element, const char *name, const char *mapset)
254 {
255  int fd;
256 
257  fd = G__open(element, name, mapset, 0);
258  if (fd < 0)
259  return (FILE *) NULL;
260 
261  G_debug(2, "\tfile open: read (mode = r)");
262  return fdopen(fd, "r");
263 }
264 
265 /*!
266  \brief Open a database file for update (append mode)
267 
268  The database file <i>name</i> under the <i>element</i> in the
269  current mapset is opened for for writing. The UNIX fopen() routine,
270  with "a" append mode, is used to open the file. If the file does not
271  exist, the NULL pointer is returned. Otherwise the file descriptor
272  from the fopen() is returned.
273 
274  \param element database element name
275  \param name map file name
276 
277  \return open file descriptor (FILE *)
278  \return NULL on error
279 */
280 FILE *G_fopen_append(const char *element, const char *name)
281 {
282  int fd;
283 
284  fd = G__open(element, name, G_mapset(), 2);
285  if (fd < 0)
286  return (FILE *) 0;
287  lseek(fd, 0L, SEEK_END);
288 
289  G_debug(2, "\tfile open: append (mode = a)");
290  return fdopen(fd, "a");
291 }
292 
293 /*!
294  \brief Open a database file for update (r+ mode)
295 
296  The database file <i>name</i> under the <i>element</i> in the
297  current mapset is opened for for writing. The UNIX fopen() routine,
298  with "r+" append mode, is used to open the file. If the file does not
299  exist, the NULL pointer is returned. Otherwise the file descriptor
300  from the fopen() is returned.
301 
302  \param element database element name
303  \param name map file name
304 
305  \return open file descriptor (FILE *)
306  \return NULL on error
307 */
308 FILE *G_fopen_modify(const char *element, const char *name)
309 {
310  int fd;
311 
312  fd = G__open(element, name, G_mapset(), 2);
313  if (fd < 0)
314  return (FILE *) 0;
315  lseek(fd, 0L, SEEK_END);
316 
317  G_debug(2, "\tfile open: modify (mode = r+)");
318  return fdopen(fd, "r+");
319 }
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&#39;t touch) ...
Definition: find_file.c:247
char * G_file_name(char *, const char *, const char *, const char *)
Builds full path names to GIS data files.
Definition: file_name.c:38
#define GMAPSET_MAX
Definition: gis.h:168
FILE * G_fopen_modify(const char *element, const char *name)
Open a database file for update (r+ mode)
Definition: gis/open.c:308
#define NULL
Definition: ccmath.h:32
int G_make_mapset_element_tmp(const char *)
Create element in the temporary directory.
Definition: mapset_msc.c:56
Definition: lidar.h:86
int G_legal_filename(const char *)
Check for legal database file name.
Definition: legal_name.c:34
#define GPATH_MAX
Definition: gis.h:170
int G_open_update(const char *element, const char *name)
Open a database file for update.
Definition: gis/open.c:191
int G_open_old(const char *element, const char *name, const char *mapset)
Open a database file for reading.
Definition: gis/open.c:170
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:80
FILE * G_fopen_new(const char *element, const char *name)
Open a new database file.
Definition: gis/open.c:220
const char * G_mapset(void)
Get current mapset name.
Definition: gis/mapset.c:33
int G_open_new(const char *element, const char *name)
Open a new database file.
Definition: gis/open.c:148
#define GNAME_MAX
Definition: gis.h:167
void G_warning(const char *,...) __attribute__((format(printf
Definition: path.h:16
#define _(str)
Definition: glocale.h:10
void G__check_gisinit(void)
Checks to see if GIS engine is initialized.
Definition: gisinit.c:100
int G_make_mapset_element(const char *)
Create element in the current mapset.
Definition: mapset_msc.c:38
FILE * G_fopen_append(const char *element, const char *name)
Open a database file for update (append mode)
Definition: gis/open.c:280
FILE * G_fopen_old(const char *element, const char *name, const char *mapset)
Open a database file for reading.
Definition: gis/open.c:253
const char * name
Definition: named_colr.c:7
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
int G_debug(int, const char *,...) __attribute__((format(printf