GRASS GIS 8 Programmer's Manual  8.2.1dev(2022)-31a672db8
manage_signatures.c
Go to the documentation of this file.
1 /*!
2  \file lib/imagery/manage_sinatures.c
3 
4  \brief Imagery Library - Signature file management functions
5 
6  (C) 2021 by Maris Nartiss and 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  \author Maris Nartiss
12  */
13 
14 #include <unistd.h>
15 #include <string.h>
16 
17 #include <grass/gis.h>
18 #include <grass/imagery.h>
19 #include <grass/glocale.h>
20 
21 /*!
22  \brief Get signature directory
23 
24  The directory will be in a form "signatures/<type>".
25 
26  \param dir [GNAME_MAX] allocated string buffer
27  \param type I_SIGFILE_TYPE
28  */
29 void I_get_signatures_dir(char *dir, I_SIGFILE_TYPE type)
30 {
31  if (type == I_SIGFILE_TYPE_SIG) {
32  sprintf(dir, "signatures%csig", HOST_DIRSEP);
33  }
34  else if (type == I_SIGFILE_TYPE_SIGSET) {
35  sprintf(dir, "signatures%csigset", HOST_DIRSEP);
36  }
37  else {
38  G_fatal_error("Programming error: unknown signature file type");
39  }
40 }
41 
42 /*!
43  \brief Make signature dir
44 
45  Creates directories for storage of signature files of specified type.
46  E.g. "<location>/<mapset>/signatures/<type>/"
47 
48  \param type I_SIGFILE_TYPE
49  */
51 {
52  char dir[GNAME_MAX];
53 
54  G_make_mapset_object_group("signatures");
55  I_get_signatures_dir(dir, type);
57 }
58 
59 static int list_by_type(I_SIGFILE_TYPE, const char *, int, char ***);
60 
61 /*!
62  * \brief Remove a signature file
63  *
64  * If removal fails, prints a warning and returns 1.
65  * It is safe to pass fully qualified names.
66  *
67  * \param type I_SIGFILE_TYPE signature type
68  * \param name of signature to remove
69  * \return 0 on success
70  * \return 1 on failure
71  */
72 int I_signatures_remove(I_SIGFILE_TYPE type, const char *name)
73 {
74  char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
75  char dir[GNAME_MAX];
76 
77  G_debug(1, "I_signatures_remove(%d, %s);", type, name);
78 
79  /* Remove only if file is in the current mapset */
80  if (G_name_is_fully_qualified(name, xname, xmapset) &&
81  strcmp(xmapset, G_mapset()) != 0) {
82  G_warning(_("%s is not in the current mapset (%s)"), name,
83  G_mapset());
84  return 1;
85  }
86  if (I_find_signature2(type, name, G_mapset())) {
87  I_get_signatures_dir(dir, type);
88  if (G_remove(dir, name) == 1) {
89  G_verbose_message(_("%s removed"), name);
90  return 0;
91  }
92  G_warning(_("Unable to remove %s signature"), name);
93  }
94  else
95  G_warning(_("%s is missing"), name);
96  return 1;
97 }
98 
99 /*!
100  * \brief Copy a signature file
101  *
102  * If copy fails, prints warning messages and returns 1.
103  * It is safe to pass fully qualified names.
104  *
105  * \param type I_SIGFILE_TYPE signature type
106  * \param name of old signature
107  * \param mapset of old signature
108  * \param name of new signature
109  * \return 0 on success
110  * \return 1 on failure
111  */
112 int I_signatures_copy(I_SIGFILE_TYPE type, const char *old_name,
113  const char *old_mapset, const char *new_name)
114 {
115  char sname[GNAME_MAX], tname[GNAME_MAX], tmapset[GMAPSET_MAX],
116  xmapset[GMAPSET_MAX];
117  char dir[GNAME_MAX];
118  const char *smapset;
119  char old_path[GPATH_MAX], new_path[GPATH_MAX];
120 
121  G_debug(1, "I_signatures_copy(%d, %s@%s, %s);", type, old_name,
122  old_mapset, new_name);
123 
124  /* Copy only if mapset of new name is the current mapset */
125  if (G_name_is_fully_qualified(new_name, tname, tmapset)) {
126  if (strcmp(tmapset, G_mapset()) != 0) {
127  G_warning(_("%s is not in the current mapset (%s)"), new_name,
128  G_mapset());
129  return 1;
130  }
131  }
132  else
133  strcat(tname, new_name);
134 
135  smapset = I_find_signature2(type, old_name, old_mapset);
136  if (!smapset) {
137  G_warning(_("%s is missing"), old_name);
138  return 1;
139  }
140  G_unqualified_name(old_name, NULL, sname, xmapset);
141 
142  I_make_signatures_dir(type);
143 
144  I_get_signatures_dir(dir, type);
145  /* Note – we need whole directory not just an element in it thus
146  G_file_name and not G_file_name_misc */
147  G_file_name(old_path, dir, sname, smapset);
148  G_file_name(new_path, dir, tname, G_mapset());
149 
150  if (G_recursive_copy(old_path, new_path) != 0) {
151  G_warning(_("Unable to copy <%s> to current mapset as <%s>"),
152  G_fully_qualified_name(old_name, smapset), tname);
153  return 1;
154  }
155  return 0;
156 }
157 
158 /*!
159  * \brief Rename a signature file
160  *
161  * If rename fails, prints warning messages and returns 1.
162  * It is safe to pass fully qualified names.
163  *
164  * \param type I_SIGFILE_TYPE signature type
165  * \param name of old signature
166  * \param name of new signature
167  * \return 0 on success
168  * \return 1 on failure
169  */
170 int I_signatures_rename(I_SIGFILE_TYPE type, const char *old_name,
171  const char *new_name)
172 {
173  char sname[GNAME_MAX], tname[GNAME_MAX], tmapset[GMAPSET_MAX];
174  char dir[GNAME_MAX];
175  const char *smapset;
176  char old_path[GPATH_MAX], new_path[GPATH_MAX];
177 
178  G_debug(1, "I_signatures_rename(%d, %s, %s);", type, old_name, new_name);
179 
180  /* Rename only if source and destination mapset is the current mapset */
181  if (G_name_is_fully_qualified(old_name, sname, tmapset)) {
182  if (strcmp(tmapset, G_mapset()) != 0) {
183  G_warning(_("%s is not in the current mapset (%s)"), old_name,
184  G_mapset());
185  return 1;
186  }
187  }
188  else
189  strcat(sname, old_name);
190  if (G_name_is_fully_qualified(new_name, tname, tmapset)) {
191  if (strcmp(tmapset, G_mapset()) != 0) {
192  G_warning(_("%s is not in the current mapset (%s)"), new_name,
193  G_mapset());
194  return 1;
195  }
196  }
197  else
198  strcat(tname, new_name);
199 
200  smapset = I_find_signature2(type, old_name, tmapset);
201  if (!smapset) {
202  G_warning(_("%s is missing"), old_name);
203  return 1;
204  }
205 
206  I_get_signatures_dir(dir, type);
207  /* Note – we need whole directory not just an element in it thus
208  G_file_name and not G_file_name_misc */
209  G_file_name(old_path, dir, sname, tmapset);
210  G_file_name(new_path, dir, tname, tmapset);
211 
212  if (G_rename_file(old_path, new_path) != 0) {
213  G_warning(_("Unable to rename <%s> to <%s>"), old_name, new_name);
214  return 1;
215  }
216  return 0;
217 }
218 
219 /*!
220  * \brief Get list of existing signatures by type
221  *
222  * Fills passed list with fully qualified names of existing signatures.
223  *
224  * If no mapset is passed, all mapsets in the search path are used.
225  * If no signatures are found, returns 0 and list is set to NULL.
226  *
227  * The function will assign memory for the list. It is up to callee to
228  * free the memory of each list item and the list itself.
229  *
230  * \param type I_SIGFILE_TYPE signature type
231  * \param mapset optional mapset to search in or NULL
232  * \param pointer to array of found signature strings or NULL if none found
233  * \return count of signature strings in the array
234  */
235 int I_signatures_list_by_type(I_SIGFILE_TYPE type, const char *mapset,
236  char ***out_list)
237 {
238  int base = 0;
239 
240  *out_list = NULL;
241  if (mapset == NULL) {
242  for (int n = 0; (mapset = G_get_mapset_name(n)); n++) {
243  base += list_by_type(type, mapset, base, out_list);
244  }
245  }
246  else {
247  base += list_by_type(type, mapset, base, out_list);
248  }
249 
250  return base;
251 }
252 
253 /*!
254  * \brief Free memory allocated by I_signatures_list_by_type
255  *
256  * Calls G_free for all list items returned by I_signatures_list_by_type()
257  * Sets pointer to NULL to prevent accidental use after free.
258  *
259  * \param int Return value of I_signatures_list_by_type()
260  * \param pointer to array filled by I_signatures_list_by_type()
261  */
263 {
264  for (int n = 0; n < count; n++) {
265  G_free((*list)[n]);
266  }
267  G_free(*list);
268  *list = NULL;
269 }
270 
271 static int list_by_type(I_SIGFILE_TYPE type, const char *mapset, int base,
272  char ***out_list)
273 {
274  int count = 0;
275  char path[GPATH_MAX];
276  char dir[GNAME_MAX];
277  char **dirlist;
278 
279  I_get_signatures_dir(dir, type);
280  G_file_name(path, dir, "", mapset);
281 
282  if (access(path, 0) != 0) {
283  return count;
284  }
285 
286  dirlist = G_ls2(path, &count);
287  if (count == 0)
288  return count;
289 
290  /* Make items fully qualified names */
291  int mapset_len = strlen(mapset);
292 
293  *out_list =
294  (char **)G_realloc(*out_list, (base + count) * sizeof(char *));
295  for (int i = 0; i < count; i++) {
296  (*out_list)[base + i] =
297  (char *)G_malloc((strlen(dirlist[i]) + 1 + mapset_len + 1) *
298  sizeof(char));
299  sprintf((*out_list)[base + i], "%s@%s", dirlist[i], mapset);
300  }
301 
302  return count;
303 }
const char * I_find_signature2(I_SIGFILE_TYPE, const char *, const char *)
Find mapset containing signature (look but don&#39;t touch)
Definition: imagery/find.c:240
#define G_malloc(n)
Definition: defs/gis.h:112
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_remove(const char *, const char *)
Remove a database file.
Definition: remove.c:44
void I_make_signatures_dir(I_SIGFILE_TYPE type)
Make signature dir.
#define GMAPSET_MAX
Definition: gis.h:178
int I_signatures_rename(I_SIGFILE_TYPE type, const char *old_name, const char *new_name)
Rename a signature file.
int G_rename_file(const char *, const char *)
Rename a file or a directory in the filesystem.
Definition: rename.c:32
int G_unqualified_name(const char *, const char *, char *, char *)
Returns unqualified map name (without @ mapset)
Definition: nme_in_mps.c:134
void I_free_signatures_list(int count, char ***list)
Free memory allocated by I_signatures_list_by_type.
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:149
int count
char ** G_ls2(const char *, int *)
Stores a sorted directory listing in an array.
Definition: ls.c:95
#define NULL
Definition: ccmath.h:32
#define HOST_DIRSEP
Definition: gis.h:223
char * G_fully_qualified_name(const char *, const char *)
Get fully qualified element name.
Definition: nme_in_mps.c:101
int G_recursive_copy(const char *, const char *)
Copy recursively source directory to destination directory.
Definition: copy_dir.c:70
#define GPATH_MAX
Definition: gis.h:180
void I_get_signatures_dir(char *dir, I_SIGFILE_TYPE type)
Get signature directory.
const char * G_mapset(void)
Get current mapset name.
Definition: gis/mapset.c:33
Definition: manage.h:4
#define GNAME_MAX
Definition: gis.h:177
void G_warning(const char *,...) __attribute__((format(printf
Definition: path.h:16
int I_signatures_copy(I_SIGFILE_TYPE type, const char *old_name, const char *old_mapset, const char *new_name)
Copy a signature file.
#define G_realloc(p, n)
Definition: defs/gis.h:114
#define _(str)
Definition: glocale.h:10
const char * name
Definition: named_colr.c:7
int I_signatures_list_by_type(I_SIGFILE_TYPE type, const char *mapset, char ***out_list)
Get list of existing signatures by type.
int G_name_is_fully_qualified(const char *, char *, char *)
Check if map name is fully qualified (map @ mapset)
Definition: nme_in_mps.c:36
void void G_verbose_message(const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
int G_make_mapset_object_group(const char *)
Create directory for group of elements of a given type.
Definition: mapset_msc.c:74
const char * G_get_mapset_name(int)
Get name of the n&#39;th mapset from the current mapset search path.
Definition: mapset_nme.c:44
I_SIGFILE_TYPE
Definition: imagery.h:202
int I_signatures_remove(I_SIGFILE_TYPE type, const char *name)
Remove a signature file.