GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
find_file.c
Go to the documentation of this file.
1 /*!
2  \file lib/gis/find_file.c
3 
4  \brief GIS library - Find GRASS data base files
5 
6  (C) 2001-2009 by the GRASS Development Team
7 
8  This program is free software under the
9  GNU General Public License (>=v2).
10  Read the file COPYING that comes with GRASS
11  for details.
12 
13  \author Original author CERL
14  */
15 
16 #include <string.h>
17 #include <unistd.h>
18 #include <grass/gis.h>
19 #include <grass/glocale.h>
20 
21 static const char *find_element(int misc, const char *dir, const char *element)
22 {
23  static const char *cell_elements[] = {
24  "cellhd",
25  "cell",
26  "cats",
27  "colr",
28  "hist",
29  "cell_misc",
30  "fcell",
31  "g3dcell",
32  NULL
33  };
34  static const char *dig_elements[] = {
35  "dig",
36  "dig_att",
37  "dig_plus",
38  "dig_cats",
39  "dig_misc",
40  "reg",
41  NULL
42  };
43  const char *search = misc ? dir : element;
44  int i;
45 
46  for (i = 1; cell_elements[i]; i++)
47  if (strcmp(search, cell_elements[i]) == 0)
48  return cell_elements[0];
49  for (i = 1; dig_elements[i]; i++)
50  if (strcmp(search, dig_elements[i]) == 0)
51  return dig_elements[0];
52  return element;
53 }
54 
55 static const char *find_file(int misc, const char *dir,
56  const char *element, const char *name,
57  const char *mapset)
58 {
59  char path[GPATH_MAX];
60  char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
61  const char *pname, *pmapset;
62  int n;
63 
64  if (*name == 0)
65  return NULL;
66  *path = 0;
67 
68  /*
69  * if name is in the fully qualified format, split it into
70  * name, mapset (overrides what was in mapset)
71  */
72  if (G_name_is_fully_qualified(name, xname, xmapset)) {
73  pname = xname;
74  pmapset = xmapset;
75  }
76  else {
77  pname = name;
78  pmapset = mapset;
79  }
80 
81  if (strcmp(element, "vector") == 0 &&
82  pmapset && strcasecmp(pmapset, "ogr") == 0) {
83  /* don't check for virtual OGR mapset */
84  return G_store(pmapset);
85  }
86 
87  /*
88  * reject illegal names and mapsets
89  */
90  if (G_legal_filename(pname) == -1)
91  return NULL;
92 
93  if (pmapset && *pmapset && G_legal_filename(pmapset) == -1)
94  return NULL;
95 
96  /*
97  * if no specific mapset is to be searched
98  * then search all mapsets in the mapset search list
99  */
100  if (pmapset == NULL || *pmapset == 0) {
101  int cnt = 0;
102  const char *pselmapset = NULL;
103  const char *pelement = find_element(misc, dir, element);
104 
105  for (n = 0; (pmapset = G_get_mapset_name(n)); n++) {
106  if (misc && element == pelement)
107  G_file_name_misc(path, dir, pelement, pname, pmapset);
108  else
109  G_file_name(path, pelement, pname, pmapset);
110  if (access(path, 0) == 0) {
111  if (!pselmapset)
112  pselmapset = pmapset;
113  else if (element == pelement)
114  G_important_message(_("Data element '%s/%s' was found in more mapsets (also found in <%s>)"),
115  element, pname, pmapset);
116  cnt++;
117  }
118  }
119  if (cnt > 0) {
120  if (misc)
121  G_file_name_misc(path, dir, element, pname, pselmapset);
122  else
123  G_file_name(path, element, name, pselmapset);
124  if (access(path, 0) == 0) {
125  /* If the same name exists in more mapsets and print a warning */
126  if (cnt > 1 && element == pelement)
127  G_important_message(_("Using <%s@%s>..."),
128  pname, pselmapset);
129 
130  return G_store(pselmapset);
131  }
132  }
133  }
134  /*
135  * otherwise just look for the file in the specified mapset.
136  * since the name may have been qualified, mapset may point
137  * to the xmapset, so we must should it to
138  * permanent storage via G_store().
139  */
140  else {
141  if (misc)
142  G_file_name_misc(path, dir, element, pname, pmapset);
143  else
144  G_file_name(path, element, pname, pmapset);
145 
146  if (access(path, 0) == 0)
147  return G_store(pmapset);
148  }
149 
150  return NULL;
151 }
152 
153 
154 
155 static const char *find_file1(
156  int misc,
157  const char *dir,
158  const char *element, char *name, const char *mapset)
159 {
160  char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
161  const char *pname, *pmapset;
162  const char *mp;
163 
164  if (G_name_is_fully_qualified(name, xname, xmapset)) {
165  pname = xname;
166  pmapset = xmapset;
167  }
168  else {
169  pname = name;
170  pmapset = mapset;
171  }
172 
173  mp = find_file(misc, dir, element, pname, pmapset);
174 
175  if (mp && name != pname)
176  strcpy(name, pname);
177 
178  return mp;
179 }
180 
181 /*!
182  * \brief Searches for a file from the mapset search list or in a
183  * specified mapset.
184  *
185  * Returns the mapset name where the file was found.
186  *
187  * If the user specifies a fully qualified element (name@mapset)
188  * which exists, then G_find_file() modifies "name"
189  * by removing the "@mapset" part.
190  *
191  * Rejects all names that begin with "."
192  *
193  * If <i>name</i> is of the form nnn in ppp then only mapset ppp
194  * is searched.
195  *
196  * \param element database element (eg, "cell", "cellhd", "colr", etc)
197  * \param name file name to look for
198  * \param mapset mapset to search. if mapset is "" will search in mapset search list
199  *
200  * \return pointer to a string with name of mapset where file was
201  * found, or NULL if not found
202  */
203 const char *G_find_file(const char *element, char *name, const char *mapset)
204 {
205  return find_file1(0, NULL, element, name, mapset);
206 }
207 
208 /*!
209  * \brief Searches for a misc file from the mapset search list or in a
210  * specified mapset.
211  *
212  * Returns the mapset name where the misc file was found.
213  * Paths to misc files currently follow structure:
214  * mapset/dir/name/element
215  *
216  * \param dir file directory
217  * \param element database element (eg, "cell", "cellhd", "colr", etc)
218  * \param name file name to look for
219  * \param mapset mapset to search. if mapset is "" will search in mapset search list
220  *
221  * \return pointer to a string with name of mapset where file was
222  * found, or NULL if not found
223  */
224 const char *G_find_file_misc(const char *dir,
225  const char *element, char *name, const char *mapset)
226 {
227  return find_file1(1, dir, element, name, mapset);
228 }
229 
230 /*!
231  * \brief Searches for a file from the mapset search list or in a
232  * specified mapset. (look but don't touch)
233  *
234  * Returns the mapset name where the file was found.
235  *
236  * Exactly the same as G_find_file() except that if <i>name</i> is in
237  * the form "<i>name@mapset</i>", and is found, G_find_file2() will
238  * not alter <i>name</i> by removing the "@<i>mapset</i>" part.
239  *
240  * Rejects all names that begin with "."
241  *
242  * \param element database element (eg, "cell", "cellhd", "colr", etc)
243  * \param name file name to look for
244  * \param mapset mapset to search. if mapset is "" will search in mapset search list
245  *
246  * \return pointer to a string with name of mapset where file was
247  * found, or NULL if not found
248  */
249 const char *G_find_file2(const char *element, const char *name, const char *mapset)
250 {
251  return find_file(0, NULL, element, name, mapset);
252 }
253 
254 /*!
255  * \brief Searches for a misc file from the mapset search list or in a
256  * specified mapset. (look but don't touch)
257  *
258  * Returns the mapset name where the misc file was found.
259  * Paths to misc files currently follow structure:
260  * mapset/dir/name/element
261  *
262  * \param dir file directory
263  * \param element database element (eg, "cell", "cellhd", "colr", etc)
264  * \param name file name to look for
265  * \param mapset mapset to search. if mapset is "" will search in mapset search list
266  *
267  * \return pointer to a string with name of mapset where file was
268  * found, or NULL if not found
269  */
270 const char *G_find_file2_misc(const char *dir,
271  const char *element,
272  const char *name, const char *mapset)
273 {
274  return find_file(1, dir, element, name, mapset);
275 }
char * G_file_name_misc(char *, const char *, const char *, const char *, const char *)
Builds full path names to GIS misc data files.
Definition: file_name.c:101
char * G_file_name(char *, const char *, const char *, const char *)
Builds full path names to GIS data files.
Definition: file_name.c:61
void void void G_important_message(const char *,...) __attribute__((format(printf
#define GMAPSET_MAX
Definition: gis.h:178
const char * G_find_file2_misc(const char *dir, const char *element, const char *name, const char *mapset)
Searches for a misc file from the mapset search list or in a specified mapset. (look but don&#39;t touch)...
Definition: find_file.c:270
const char * G_find_file(const char *element, char *name, const char *mapset)
Searches for a file from the mapset search list or in a specified mapset.
Definition: find_file.c:203
#define NULL
Definition: ccmath.h:32
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:180
const char * G_find_file_misc(const char *dir, const char *element, char *name, const char *mapset)
Searches for a misc file from the mapset search list or in a specified mapset.
Definition: find_file.c:224
#define GNAME_MAX
Definition: gis.h:177
Definition: path.h:16
#define _(str)
Definition: glocale.h:10
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
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
const char * G_find_file2(const char *element, const char *name, const char *mapset)
Searches for a file from the mapset search list or in a specified mapset. (look but don&#39;t touch) ...
Definition: find_file.c:249
const char * G_get_mapset_name(int)
Get name of the n&#39;th mapset from the current mapset search path.
Definition: mapset_nme.c:44