GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-9aacb948ba
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 
22 static int make_mapset_element(const char *, const char *);
23 static int make_mapset_element_no_fail_on_race(const char *, const char *);
24 static 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  */
44 int 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  */
74 int 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  */
108 int 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  */
131 int 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  */
153 int G_make_mapset_object_group_tmp(const char *type)
154 {
155  char path[GPATH_MAX];
156 
158  return make_mapset_element_no_fail_on_race(path, type);
159 }
160 
161 /*!
162  \brief Create directory for type of objects in the temporary directory.
163 
164  See G_file_name_basedir() for details.
165 
166  \param type object type (e.g., `cell`)
167 
168  \note
169  Use G_make_mapset_object_group_basedir() for creating common, shared
170  directories for temporary data.
171 
172  \return 0 no element defined
173  \return 1 on success
174  */
175 int G_make_mapset_object_group_basedir(const char *type, const char *basedir)
176 {
177  char path[GPATH_MAX];
178 
179  G_file_name_basedir(path, NULL, NULL, G_mapset(), basedir);
180  return make_mapset_element_no_fail_on_race(path, type);
181 }
182 
183 int make_mapset_element_impl(const char *p_path, const char *p_element,
184  bool race_ok)
185 {
186  char path[GPATH_MAX], *p;
187  const char *element;
188 
189  element = p_element;
190  if (*element == 0)
191  return 0;
192 
193  strncpy(path, p_path, GPATH_MAX);
194  p = path;
195  while (*p)
196  p++;
197  /* add trailing slash if missing */
198  --p;
199  if (*p++ != '/') {
200  *p++ = '/';
201  *p = 0;
202  }
203 
204  /* now append element, one directory at a time, to path */
205  while (1) {
206  if (*element == '/' || *element == 0) {
207  *p = 0;
208  char *msg = NULL;
209 
210  if (access(path, 0) != 0) {
211  /* Assuming that directory does not exist. */
212  if (G_mkdir(path) != 0) {
213  msg = G_store(strerror(errno));
214  }
215  }
216  if (access(path, 0) != 0 || (msg && !race_ok)) {
217  /* Directory is not accessible even after attempt to create it.
218  */
219  if (msg) {
220  /* Error already happened when mkdir. */
222  _("Unable to make mapset element %s (%s): %s"),
223  p_element, path, strerror(errno));
224  }
225  else {
226  /* Access error is not related to mkdir. */
228  _("Unable to access mapset element %s (%s): %s"),
229  p_element, path, strerror(errno));
230  }
231  }
232  if (*element == 0)
233  return 1;
234  }
235  *p++ = *element++;
236  }
237 }
238 
239 int make_mapset_element(const char *p_path, const char *p_element)
240 {
241  return make_mapset_element_impl(p_path, p_element, false);
242 }
243 
244 int make_mapset_element_no_fail_on_race(const char *p_path,
245  const char *p_element)
246 {
247  return make_mapset_element_impl(p_path, p_element, true);
248 }
249 
250 /*!
251  \brief Create misc element in the current mapset.
252 
253  \param dir directory path (e.g., `cell_misc`)
254  \param name element to be created in mapset (e.g., `elevation`)
255 
256  \return 0 no element defined
257  \return 1 on success
258  */
259 int G__make_mapset_element_misc(const char *dir, const char *name)
260 {
261  return G_make_mapset_dir_object(dir, name);
262 }
263 
264 static int check_owner(const struct stat *info)
265 {
266 #if defined(__MINGW32__) || defined(SKIP_MAPSET_OWN_CHK)
267  return 1;
268 #else
269  const char *check = getenv("GRASS_SKIP_MAPSET_OWNER_CHECK");
270 
271  if (check && *check)
272  return 1;
273  if (info->st_uid != getuid())
274  return 0;
275  if (info->st_uid != geteuid())
276  return 0;
277  return 1;
278 #endif
279 }
280 
281 /*!
282  \brief Check for user mapset permission
283 
284  \param mapset mapset name
285 
286  \return 1 mapset exists, and user has permission
287  \return 0 mapset exists, BUT user denied permission
288  \return -1 mapset does not exist
289  */
290 int G_mapset_permissions(const char *mapset)
291 {
292  char path[GPATH_MAX];
293  struct stat info;
294 
295  G_file_name(path, "", "", mapset);
296 
297  if (G_stat(path, &info) != 0)
298  return -1;
299  if (!S_ISDIR(info.st_mode))
300  return -1;
301 
302  if (!check_owner(&info))
303  return 0;
304 
305  return 1;
306 }
307 
308 /*!
309  \brief Check for user mapset permission
310 
311  \param gisdbase full path to GISDBASE
312  \param location location name
313  \param mapset mapset name
314 
315  \return 1 mapset exists, and user has permission
316  \return 0 mapset exists, BUT user denied permission
317  \return -1 mapset does not exist
318  */
319 int G_mapset_permissions2(const char *gisdbase, const char *location,
320  const char *mapset)
321 {
322  char path[GPATH_MAX];
323  struct stat info;
324 
325  sprintf(path, "%s/%s/%s", gisdbase, location, mapset);
326 
327  if (G_stat(path, &info) != 0)
328  return -1;
329  if (!S_ISDIR(info.st_mode))
330  return -1;
331 
332  if (!check_owner(&info))
333  return 0;
334 
335  return 1;
336 }
#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:194
#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:153
int G__make_mapset_element_misc(const char *dir, const char *name)
Create misc element in the current mapset.
Definition: mapset_msc.c:259
int G_mapset_permissions2(const char *gisdbase, const char *location, const char *mapset)
Check for user mapset permission.
Definition: mapset_msc.c:319
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:290
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
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:175
const char * name
Definition: named_colr.c:6
Definition: lidar.h:85
Definition: path.h:15