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