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