GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
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 
48  G_file_name(path, NULL, NULL, G_mapset());
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 
78  G_file_name(path, NULL, NULL, G_mapset());
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 
135  G_file_name_tmp(path, NULL, NULL, G_mapset());
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 
157  G_file_name_tmp(path, NULL, NULL, G_mapset());
158  return make_mapset_element_no_fail_on_race(path, type);
159 }
160 
161 int 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 
212 int 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 
217 int 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  */
232 int G__make_mapset_element_misc(const char *dir, const char *name)
233 {
234  return G_make_mapset_dir_object(dir, name);
235 }
236 
237 static 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  */
262 int 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  */
291 int 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 }
int G_make_mapset_element(const char *p_element)
Create element in the current mapset.
Definition: mapset_msc.c:44
char * G_file_name(char *, const char *, const char *, const char *)
Builds full path names to GIS data files.
Definition: file_name.c:61
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
int G_mapset_permissions(const char *mapset)
Check for user mapset permission.
Definition: mapset_msc.c:262
int G_make_mapset_object_group(const char *type)
Create directory for group of elements of a given type.
Definition: mapset_msc.c:74
#define NULL
Definition: ccmath.h:32
Definition: lidar.h:86
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
#define GPATH_MAX
Definition: gis.h:180
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_stat(const char *, struct stat *)
Get file status.
Definition: paths.c:128
int G__make_mapset_element_misc(const char *dir, const char *name)
Create misc element in the current mapset.
Definition: mapset_msc.c:232
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:126
const char * G_mapset(void)
Get current mapset name.
Definition: gis/mapset.c:33
Definition: path.h:16
int G_mkdir(const char *)
Creates a new directory.
Definition: paths.c:27
#define _(str)
Definition: glocale.h:10
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
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
char * getenv()
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