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