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
find_element(int misc,const char * dir,const char * element)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
find_file(int misc,const char * dir,const char * element,const char * name,const char * mapset)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
find_file1(int misc,const char * dir,const char * element,char * name,const char * mapset)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 */
G_find_file(const char * element,char * name,const char * mapset)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 file from the mapset search list or in a
210 * specified mapset.
211 *
212 * Returns the mapset name where the file was found.
213 *
214 * \param dir file directory
215 * \param element database element (eg, "cell", "cellhd", "colr", etc)
216 * \param name file name to look for
217 * \param mapset mapset to search. if mapset is "" will search in mapset search list
218 *
219 * \return pointer to a string with name of mapset where file was
220 * found, or NULL if not found
221 */
G_find_file_misc(const char * dir,const char * element,char * name,const char * mapset)222 const char *G_find_file_misc(const char *dir,
223 const char *element, char *name, const char *mapset)
224 {
225 return find_file1(1, dir, element, name, mapset);
226 }
227
228 /*!
229 * \brief Searches for a file from the mapset search list or in a
230 * specified mapset. (look but don't touch)
231 *
232 * Returns the mapset name where the file was found.
233 *
234 * Exactly the same as G_find_file() except that if <i>name</i> is in
235 * the form "<i>name@mapset</i>", and is found, G_find_file2() will
236 * not alter <i>name</i> by removing the "@<i>mapset</i>" part.
237 *
238 * Rejects all names that begin with "."
239 *
240 * \param element database element (eg, "cell", "cellhd", "colr", etc)
241 * \param name file name to look for
242 * \param mapset mapset to search. if mapset is "" will search in mapset search list
243 *
244 * \return pointer to a string with name of mapset where file was
245 * found, or NULL if not found
246 */
G_find_file2(const char * element,const char * name,const char * mapset)247 const char *G_find_file2(const char *element, const char *name, const char *mapset)
248 {
249 return find_file(0, NULL, element, name, mapset);
250 }
251
252 /*!
253 * \brief Searches for a file from the mapset search list or in a
254 * specified mapset. (look but don't touch)
255 *
256 * Returns the mapset name where the file was found.
257 *
258 *
259 * \param dir file directory
260 * \param element database element (eg, "cell", "cellhd", "colr", etc)
261 * \param name file name to look for
262 * \param mapset mapset to search. if mapset is "" will search in mapset search list
263 *
264 * \return pointer to a string with name of mapset where file was
265 * found, or NULL if not found
266 */
G_find_file2_misc(const char * dir,const char * element,const char * name,const char * mapset)267 const char *G_find_file2_misc(const char *dir,
268 const char *element,
269 const char *name, const char *mapset)
270 {
271 return find_file(1, dir, element, name, mapset);
272 }
273