GRASS GIS 8 Programmer's Manual 8.2.0(2022)-exported
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
21static 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
55static 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
155static 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 */
203const 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 */
224const 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 */
249const 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 */
270const 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}
#define NULL
Definition: ccmath.h:32
char * G_file_name(char *path, const char *element, const char *name, const char *mapset)
Builds full path names to GIS data files.
Definition: file_name.c:61
char * G_file_name_misc(char *path, const char *dir, const char *element, const char *name, const char *mapset)
Builds full path names to GIS misc data files.
Definition: file_name.c:101
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:249
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
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: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
void G_important_message(const char *msg,...)
Print a message to stderr even in brief mode (verbosity=1)
Definition: gis/error.c:131
int G_legal_filename(const char *s)
Check for legal database file name.
Definition: legal_name.c:34
const char * G_get_mapset_name(int n)
Get name of the n'th mapset from the current mapset search path.
Definition: mapset_nme.c:44
const char * name
Definition: named_colr.c:7
int G_name_is_fully_qualified(const char *fullname, char *name, char *mapset)
Check if map name is fully qualified (map @ mapset)
Definition: nme_in_mps.c:36
char * G_store(const char *s)
Copy string to allocated memory.
Definition: strings.c:87
Definition: lidar.h:87
Definition: path.h:16