GRASS GIS 8 Programmer's Manual 8.2.1RC1(2022)-exported
mapset_msc.c
Go to the documentation of this file.
1/*!
2 \file lib/gis/mapset_msc.c
3
4 \brief GIS library - Mapset user permission routines.
5
6 (C) 1999-2014 The GRASS development team
7
8 This program is free software under the GNU General Public License
9 (>=v2). Read the file COPYING that comes with GRASS for details.
10 */
11
12#include <grass/config.h>
13#include <string.h>
14#include <unistd.h>
15#include <stdlib.h>
16#include <errno.h>
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <grass/gis.h>
20#include <grass/glocale.h>
21
22static int make_mapset_element(const char *, const char *);
23static int make_mapset_element_no_fail_on_race(const char *, const char *);
24static int make_mapset_element_impl(const char *, const char *, bool);
25
26/*!
27 \brief Create element in the current mapset.
28
29 Make the specified element in the current mapset will check for the
30 existence of the element and do nothing if it is found so this
31 routine can be called even if the element already exists.
32
33 Calls G_fatal_error() on failure.
34
35 \deprecated
36 This function is deprecated due to confusion in element terminology.
37 Use G_make_mapset_object_group() or G_make_mapset_dir_object() instead.
38
39 \param p_element element to be created in mapset
40
41 \return 0 no element defined
42 \return 1 on success
43 */
44int G_make_mapset_element(const char *p_element)
45{
46 char path[GPATH_MAX];
47
49 return make_mapset_element(path, p_element);
50}
51
52/*!
53 \brief Create directory for group of elements of a given type.
54
55 Creates the specified element directory in the current mapset.
56 It will check for the existence of the element and do nothing
57 if it is found so this routine can be called even if the element
58 already exists to ensure that it exists.
59
60 If creation fails, but the directory exists after the failure,
61 the function reports success. Therefore, two processes creating
62 a directory in this way can work in parallel.
63
64 Calls G_fatal_error() on failure.
65
66 \param type object type (e.g., `cell`)
67
68 \return 0 no element defined
69 \return 1 on success
70
71 \sa G_make_mapset_dir_object()
72 \sa G_make_mapset_object_group_tmp()
73 */
74int G_make_mapset_object_group(const char *type)
75{
76 char path[GPATH_MAX];
77
79 return make_mapset_element_no_fail_on_race(path, type);
80}
81
82/*!
83 \brief Create directory for an object of a given type.
84
85 Creates the specified element directory in the current mapset.
86 It will check for the existence of the element and do nothing
87 if it is found so this routine can be called even if the element
88 already exists to ensure that it exists.
89
90 Any failure to create it, including the case when it exists
91 (i.e., was created by another process after the existence test)
92 is considered a failure because two processes should not attempt
93 to create two objects of the same name (and type).
94
95 This function is for objects which are directories
96 (the function does not create files).
97
98 Calls G_fatal_error() on failure.
99
100 \param type object type (e.g., `vector`)
101 \param name object name (e.g., `bridges`)
102
103 \return 0 no element defined
104 \return 1 on success
105
106 \sa G_make_mapset_object_group()
107 */
108int G_make_mapset_dir_object(const char *type, const char *name)
109{
110 char path[GPATH_MAX];
111
113 G_file_name(path, type, NULL, G_mapset());
114 return make_mapset_element(path, name);
115}
116
117/*!
118 \brief Create element in the temporary directory.
119
120 See G_file_name_tmp() for details.
121
122 \param p_element element to be created in mapset (e.g., `elevation`)
123
124 \note
125 Use G_make_mapset_object_group_tmp() for creating common, shared
126 directories which are for multiple concrete elements (objects).
127
128 \return 0 no element defined
129 \return 1 on success
130 */
131int G_make_mapset_element_tmp(const char *p_element)
132{
133 char path[GPATH_MAX];
134
136 return make_mapset_element(path, p_element);
137}
138
139/*!
140 \brief Create directory for type of objects in the temporary directory.
141
142 See G_file_name_tmp() for details.
143
144 \param type object type (e.g., `cell`)
145
146 \note
147 Use G_make_mapset_object_group_tmp() for creating common, shared
148 directories which are for multiple concrete elements (objects).
149
150 \return 0 no element defined
151 \return 1 on success
152 */
154{
155 char path[GPATH_MAX];
156
158 return make_mapset_element_no_fail_on_race(path, type);
159}
160
161int make_mapset_element_impl(const char *p_path, const char *p_element, bool race_ok)
162{
163 char path[GPATH_MAX], *p;
164 const char *element;
165
166 element = p_element;
167 if (*element == 0)
168 return 0;
169
170 strncpy(path, p_path, GPATH_MAX);
171 p = path;
172 while (*p)
173 p++;
174 /* add trailing slash if missing */
175 --p;
176 if (*p++ != '/') {
177 *p++ = '/';
178 *p = 0;
179 }
180
181 /* now append element, one directory at a time, to path */
182 while (1) {
183 if (*element == '/' || *element == 0) {
184 *p = 0;
185 char *msg = NULL;
186 if (access(path, 0) != 0) {
187 /* Assuming that directory does not exist. */
188 if (G_mkdir(path) != 0) {
189 msg = G_store(strerror(errno));
190 }
191 }
192 if (access(path, 0) != 0 || (msg && !race_ok)) {
193 /* Directory is not accessible even after attempt to create it. */
194 if (msg) {
195 /* Error already happened when mkdir. */
196 G_fatal_error(_("Unable to make mapset element %s (%s): %s"),
197 p_element, path, strerror(errno));
198 }
199 else {
200 /* Access error is not related to mkdir. */
201 G_fatal_error(_("Unable to access mapset element %s (%s): %s"),
202 p_element, path, strerror(errno));
203 }
204 }
205 if (*element == 0)
206 return 1;
207 }
208 *p++ = *element++;
209 }
210}
211
212int make_mapset_element(const char *p_path, const char *p_element)
213{
214 return make_mapset_element_impl(p_path, p_element, false);
215}
216
217int make_mapset_element_no_fail_on_race(const char *p_path, const char *p_element)
218{
219 return make_mapset_element_impl(p_path, p_element, true);
220}
221
222
223/*!
224 \brief Create misc element in the current mapset.
225
226 \param dir directory path (e.g., `cell_misc`)
227 \param name element to be created in mapset (e.g., `elevation`)
228
229 \return 0 no element defined
230 \return 1 on success
231 */
232int G__make_mapset_element_misc(const char *dir, const char *name)
233{
234 return G_make_mapset_dir_object(dir, name);
235}
236
237static int check_owner(const struct stat *info)
238{
239#if defined(__MINGW32__) || defined(SKIP_MAPSET_OWN_CHK)
240 return 1;
241#else
242 const char *check = getenv("GRASS_SKIP_MAPSET_OWNER_CHECK");
243 if (check && *check)
244 return 1;
245 if (info->st_uid != getuid())
246 return 0;
247 if (info->st_uid != geteuid())
248 return 0;
249 return 1;
250#endif
251}
252
253/*!
254 \brief Check for user mapset permission
255
256 \param mapset mapset name
257
258 \return 1 mapset exists, and user has permission
259 \return 0 mapset exists, BUT user denied permission
260 \return -1 mapset does not exist
261 */
262int G_mapset_permissions(const char *mapset)
263{
264 char path[GPATH_MAX];
265 struct stat info;
266
267 G_file_name(path, "", "", mapset);
268
269 if (G_stat(path, &info) != 0)
270 return -1;
271 if (!S_ISDIR(info.st_mode))
272 return -1;
273
274 if (!check_owner(&info))
275 return 0;
276
277 return 1;
278}
279
280/*!
281 \brief Check for user mapset permission
282
283 \param gisdbase full path to GISDBASE
284 \param location location name
285 \param mapset mapset name
286
287 \return 1 mapset exists, and user has permission
288 \return 0 mapset exists, BUT user denied permission
289 \return -1 mapset does not exist
290 */
291int G_mapset_permissions2(const char *gisdbase, const char *location,
292 const char *mapset)
293{
294 char path[GPATH_MAX];
295 struct stat info;
296
297 sprintf(path, "%s/%s/%s", gisdbase, location, mapset);
298
299 if (G_stat(path, &info) != 0)
300 return -1;
301 if (!S_ISDIR(info.st_mode))
302 return -1;
303
304 if (!check_owner(&info))
305 return 0;
306
307 return 1;
308}
#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_tmp(char *path, const char *element, const char *name, const char *mapset)
Builds full path names to GIS data files in temporary directory (for internal use only)
Definition: file_name.c:126
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition: gis/error.c:160
const char * G_mapset(void)
Get current mapset name.
Definition: mapset.c:33
int G_make_mapset_object_group_tmp(const char *type)
Create directory for type of objects in the temporary directory.
Definition: mapset_msc.c:153
int G__make_mapset_element_misc(const char *dir, const char *name)
Create misc element in the current mapset.
Definition: mapset_msc.c:232
int G_mapset_permissions2(const char *gisdbase, const char *location, const char *mapset)
Check for user mapset permission.
Definition: mapset_msc.c:291
int G_make_mapset_object_group(const char *type)
Create directory for group of elements of a given type.
Definition: mapset_msc.c:74
int G_mapset_permissions(const char *mapset)
Check for user mapset permission.
Definition: mapset_msc.c:262
int G_make_mapset_dir_object(const char *type, const char *name)
Create directory for an object of a given type.
Definition: mapset_msc.c:108
int G_make_mapset_element(const char *p_element)
Create element in the current mapset.
Definition: mapset_msc.c:44
int G_make_mapset_element_tmp(const char *p_element)
Create element in the temporary directory.
Definition: mapset_msc.c:131
const char * name
Definition: named_colr.c:7
int G_mkdir(const char *path)
Creates a new directory.
Definition: paths.c:27
int G_stat(const char *file_name, struct stat *buf)
Get file status.
Definition: paths.c:128
char * G_store(const char *s)
Copy string to allocated memory.
Definition: strings.c:87
Definition: lidar.h:87
Definition: path.h:16