GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-6da4f45b8e
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] = {'\0'};
187  char *p;
188  const char *element;
189 
190  element = p_element;
191  if (*element == 0)
192  return 0;
193 
194  strncpy(path, p_path, GPATH_MAX - 1);
195  p = path;
196  while (*p)
197  p++;
198  /* add trailing slash if missing */
199  --p;
200  if (*p++ != '/') {
201  *p++ = '/';
202  *p = 0;
203  }
204 
205  /* now append element, one directory at a time, to path */
206  while (1) {
207  if (*element == '/' || *element == 0) {
208  *p = 0;
209  char *msg = NULL;
210 
211  if (access(path, 0) != 0) {
212  /* Assuming that directory does not exist. */
213  if (G_mkdir(path) != 0) {
214  msg = G_store(strerror(errno));
215  }
216  }
217  if (access(path, 0) != 0 || (msg && !race_ok)) {
218  /* Directory is not accessible even after attempt to create it.
219  */
220  if (msg) {
221  /* Error already happened when mkdir. */
223  _("Unable to make mapset element %s (%s): %s"),
224  p_element, path, strerror(errno));
225  }
226  else {
227  /* Access error is not related to mkdir. */
229  _("Unable to access mapset element %s (%s): %s"),
230  p_element, path, strerror(errno));
231  }
232  }
233  if (*element == 0)
234  return 1;
235  }
236  *p++ = *element++;
237  }
238 }
239 
240 int make_mapset_element(const char *p_path, const char *p_element)
241 {
242  return make_mapset_element_impl(p_path, p_element, false);
243 }
244 
245 int make_mapset_element_no_fail_on_race(const char *p_path,
246  const char *p_element)
247 {
248  return make_mapset_element_impl(p_path, p_element, true);
249 }
250 
251 /*!
252  \brief Create misc element in the current mapset.
253 
254  \param dir directory path (e.g., `cell_misc`)
255  \param name element to be created in mapset (e.g., `elevation`)
256 
257  \return 0 no element defined
258  \return 1 on success
259  */
260 int G__make_mapset_element_misc(const char *dir, const char *name)
261 {
262  return G_make_mapset_dir_object(dir, name);
263 }
264 
265 static int check_owner(const struct stat *info)
266 {
267 #if defined(__MINGW32__) || defined(SKIP_MAPSET_OWN_CHK)
268  return 1;
269 #else
270  const char *check = getenv("GRASS_SKIP_MAPSET_OWNER_CHECK");
271 
272  if (check && *check)
273  return 1;
274  if (info->st_uid != getuid())
275  return 0;
276  if (info->st_uid != geteuid())
277  return 0;
278  return 1;
279 #endif
280 }
281 
282 /*!
283  \brief Check for user mapset permission
284 
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  */
291 int G_mapset_permissions(const char *mapset)
292 {
293  char path[GPATH_MAX];
294  struct stat info;
295 
296  G_file_name(path, "", "", mapset);
297 
298  if (G_stat(path, &info) != 0)
299  return -1;
300  if (!S_ISDIR(info.st_mode))
301  return -1;
302 
303  if (!check_owner(&info))
304  return 0;
305 
306  return 1;
307 }
308 
309 /*!
310  \brief Check for user mapset permission
311 
312  \param gisdbase full path to GISDBASE
313  \param location location name
314  \param mapset mapset name
315 
316  \return 1 mapset exists, and user has permission
317  \return 0 mapset exists, BUT user denied permission
318  \return -1 mapset does not exist
319  */
320 int G_mapset_permissions2(const char *gisdbase, const char *location,
321  const char *mapset)
322 {
323  char path[GPATH_MAX];
324  struct stat info;
325 
326  sprintf(path, "%s/%s/%s", gisdbase, location, mapset);
327 
328  if (G_stat(path, &info) != 0)
329  return -1;
330  if (!S_ISDIR(info.st_mode))
331  return -1;
332 
333  if (!check_owner(&info))
334  return 0;
335 
336  return 1;
337 }
#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:260
int G_mapset_permissions2(const char *gisdbase, const char *location, const char *mapset)
Check for user mapset permission.
Definition: mapset_msc.c:320
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:291
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