Browse Source

Imagery: move signatures to subdirs (#1850)

Imagery: move signature files to a <name>/<element> type directory structure (a.k.a. _misc)

Full path to signature file now is:
location/mapset/signatures/<type>/<name>/<element>

This new structure will allow to store arbitrary number of files for each signature.
None of existing signature types utilizes the new functionality.
Māris Nartišs 3 years ago
parent
commit
fb4a9754ba

+ 1 - 1
gui/wxpython/gui_core/gselect.py

@@ -2835,7 +2835,7 @@ class SignatureSelect(wx.ComboBox):
         count = I_signatures_list_by_type(sig_type, mapset, ctypes.byref(sig_list))
         for n in range(count):
             items.append(decode(sig_list[n]))
-        I_free_signatures_list(count, sig_list)
+        I_free_signatures_list(count, ctypes.byref(sig_list))
 
 
 class SeparatorSelect(wx.ComboBox):

+ 2 - 2
include/grass/defs/imagery.h

@@ -148,8 +148,8 @@ int I_apply_colormap(unsigned char *, unsigned char *, unsigned,  unsigned char
 int I_rasterize(double *, int, unsigned char, struct Cell_head *, unsigned char *);
 
 /* manage_signatures.c */
-void I__get_signatures_element(char *, I_SIGFILE_TYPE);
-void I__make_signatures_element(I_SIGFILE_TYPE);
+void I_get_signatures_dir(char *, I_SIGFILE_TYPE);
+void I_make_signatures_dir(I_SIGFILE_TYPE);
 int I_signatures_remove(I_SIGFILE_TYPE, const char *);
 int I_signatures_copy(I_SIGFILE_TYPE, const char *, const char *, const char *);
 int I_signatures_rename(I_SIGFILE_TYPE, const char *, const char *);

+ 26 - 15
lib/imagery/find.c

@@ -67,7 +67,8 @@ int I_find_group_file(const char *group, const char *file)
  * \param file
  * \return int 1 if file was found, 0 otherwise
  */
-int I_find_group_file2(const char *group, const char *mapset, const char *file)
+int I_find_group_file2(const char *group, const char *mapset,
+                       const char *file)
 {
     if (!I_find_group2(group, mapset))
         return 0;
@@ -107,7 +108,8 @@ int I_find_subgroup(const char *group, const char *subgroup)
  * \param mapset
  * \return int 1 if subrgoup was found, 0 otherwise
  */
-int I_find_subgroup2(const char *group, const char *subgroup, const char *mapset)
+int I_find_subgroup2(const char *group, const char *subgroup,
+                     const char *mapset)
 {
     char element[GNAME_MAX];
 
@@ -142,7 +144,8 @@ int I_find_subgroup_file(const char *group, const char *subgroup,
     if (file == NULL || *file == 0)
         return 0;
 
-    sprintf(element, "subgroup%c%s%c%s", HOST_DIRSEP, subgroup, HOST_DIRSEP, file);
+    sprintf(element, "subgroup%c%s%c%s", HOST_DIRSEP, subgroup, HOST_DIRSEP,
+            file);
     G_debug(5, "I_find_subgroup_file() element: %s", element);
 
     return G_find_file2_misc("group", element, group, G_mapset()) != NULL;
@@ -158,7 +161,7 @@ int I_find_subgroup_file(const char *group, const char *subgroup,
  * \return int 1 if file was found, 0 otherwise
  */
 int I_find_subgroup_file2(const char *group, const char *subgroup,
-                         const char *mapset, const char *file)
+                          const char *mapset, const char *file)
 {
     char element[GNAME_MAX * 2];
 
@@ -169,7 +172,8 @@ int I_find_subgroup_file2(const char *group, const char *subgroup,
     if (file == NULL || *file == 0)
         return 0;
 
-    sprintf(element, "subgroup%c%s%c%s", HOST_DIRSEP, subgroup, HOST_DIRSEP, file);
+    sprintf(element, "subgroup%c%s%c%s", HOST_DIRSEP, subgroup, HOST_DIRSEP,
+            file);
     G_debug(5, "I_find_subgroup_file2() element: %s", element);
 
     return G_find_file2_misc("group", element, group, mapset) != NULL;
@@ -198,14 +202,18 @@ int I_find_subgroup_file2(const char *group, const char *subgroup,
  * \param mapset set NULL to search in all mapsets
  * \return mapset or NULL
  */
-const char *I_find_signature(I_SIGFILE_TYPE type, char *name, const char *mapset) {
-    char selem[GNAME_MAX]; /* 'signatures/type\0' */
+const char *I_find_signature(I_SIGFILE_TYPE type, char *name,
+                             const char *mapset)
+{
+    char sdir[GNAME_MAX];       /* 'signatures/type\0' */
 
-    G_debug(1, "I_find_signature(): type=%d name=%s mapset=%s", type, name, mapset);
+    G_debug(1, "I_find_signature(): type=%d name=%s mapset=%s", type, name,
+            mapset);
 
-    I__get_signatures_element(selem, type);
+    I_get_signatures_dir(sdir, type);
 
-    return G_find_file(selem, name, mapset);
+    /* We do not search for a specific file as file name is up to signature type */
+    return G_find_file(sdir, name, mapset);
 }
 
 /*!
@@ -229,12 +237,15 @@ const char *I_find_signature(I_SIGFILE_TYPE type, char *name, const char *mapset
  * \param mapset set NULL to search in all mapsets
  * \return mapset or NULL
  */
-const char *I_find_signature2(I_SIGFILE_TYPE type, const char *name, const char *mapset) {
-    char selem[GNAME_MAX]; /* 'signatures/type\0' */
+const char *I_find_signature2(I_SIGFILE_TYPE type, const char *name,
+                              const char *mapset)
+{
+    char sdir[GNAME_MAX];       /* 'signatures/type\0' */
 
-    G_debug(1, "I_find_signature2(): type=%d name=%s mapset=%s", type, name, mapset);
+    G_debug(1, "I_find_signature2(): type=%d name=%s mapset=%s", type, name,
+            mapset);
 
-    I__get_signatures_element(selem, type);
+    I_get_signatures_dir(sdir, type);
 
-    return G_find_file2(selem, name, mapset);
+    return G_find_file2(sdir, name, mapset);
 }

+ 42 - 30
lib/imagery/manage_signatures.c

@@ -19,18 +19,20 @@
 #include <grass/glocale.h>
 
 /*!
-  \brief Get signature element (internal use only)
+   \brief Get signature directory
 
-  \param element [GNAME_MAX] allocated string buffer
-  \param type I_SIGFILE_TYPE
-*/
-void I__get_signatures_element(char *element, I_SIGFILE_TYPE type)
+   The directory will be in a form "signatures/<type>".
+
+   \param dir [GNAME_MAX] allocated string buffer
+   \param type I_SIGFILE_TYPE
+ */
+void I_get_signatures_dir(char *dir, I_SIGFILE_TYPE type)
 {
     if (type == I_SIGFILE_TYPE_SIG) {
-        sprintf(element, "signatures%csig", HOST_DIRSEP);
+        sprintf(dir, "signatures%csig", HOST_DIRSEP);
     }
     else if (type == I_SIGFILE_TYPE_SIGSET) {
-        sprintf(element, "signatures%csigset", HOST_DIRSEP);
+        sprintf(dir, "signatures%csigset", HOST_DIRSEP);
     }
     else {
         G_fatal_error("Programming error: unknown signature file type");
@@ -38,16 +40,20 @@ void I__get_signatures_element(char *element, I_SIGFILE_TYPE type)
 }
 
 /*!
-  \brief Make signature element (internal use only)
+   \brief Make signature dir
+
+   Creates directories for storage of signature files of specified type.
+   E.g. "<location>/<mapset>/signatures/<type>/"
 
-  \param type I_SIGFILE_TYPE
-*/
-void I__make_signatures_element(I_SIGFILE_TYPE type)
+   \param type I_SIGFILE_TYPE
+ */
+void I_make_signatures_dir(I_SIGFILE_TYPE type)
 {
-    char element[GNAME_MAX];
+    char dir[GNAME_MAX];
+
     G_make_mapset_object_group("signatures");
-    I__get_signatures_element(element, type);
-    G_make_mapset_object_group(element);
+    I_get_signatures_dir(dir, type);
+    G_make_mapset_object_group(dir);
 }
 
 static int list_by_type(I_SIGFILE_TYPE, const char *, int, char ***);
@@ -66,7 +72,7 @@ static int list_by_type(I_SIGFILE_TYPE, const char *, int, char ***);
 int I_signatures_remove(I_SIGFILE_TYPE type, const char *name)
 {
     char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
-    char element[GNAME_MAX];
+    char dir[GNAME_MAX];
     int ret = 0;
 
     G_debug(1, "I_signatures_remove(%d, %s);", type, name);
@@ -79,8 +85,8 @@ int I_signatures_remove(I_SIGFILE_TYPE type, const char *name)
         return 1;
     }
     if (I_find_signature2(type, name, G_mapset())) {
-        I__get_signatures_element(element, type);
-        if (G_remove(element, name) == 1) {
+        I_get_signatures_dir(dir, type);
+        if (G_remove(dir, name) == 1) {
             G_verbose_message(_("%s removed"), name);
             return 0;
         }
@@ -109,7 +115,7 @@ int I_signatures_copy(I_SIGFILE_TYPE type, const char *old_name,
 {
     char sname[GNAME_MAX], tname[GNAME_MAX], tmapset[GMAPSET_MAX],
         xmapset[GMAPSET_MAX];
-    char element[GNAME_MAX];
+    char dir[GNAME_MAX];
     const char *smapset;
     char old_path[GPATH_MAX], new_path[GPATH_MAX];
 
@@ -134,13 +140,15 @@ int I_signatures_copy(I_SIGFILE_TYPE type, const char *old_name,
     }
     G_unqualified_name(old_name, NULL, sname, xmapset);
 
-    I__make_signatures_element(type);
+    I_make_signatures_dir(type);
 
-    I__get_signatures_element(element, type);
-    G_file_name(old_path, element, sname, smapset);
-    G_file_name(new_path, element, tname, G_mapset());
+    I_get_signatures_dir(dir, type);
+    /* Note – we need whole directory not just an element in it thus
+       G_file_name and not G_file_name_misc */
+    G_file_name(old_path, dir, sname, smapset);
+    G_file_name(new_path, dir, tname, G_mapset());
 
-    if (G_copy_file(old_path, new_path) != 1) {
+    if (G_recursive_copy(old_path, new_path) != 0) {
         G_warning(_("Unable to copy <%s> to current mapset as <%s>"),
                   G_fully_qualified_name(old_name, smapset), tname);
         return 1;
@@ -164,7 +172,7 @@ int I_signatures_rename(I_SIGFILE_TYPE type, const char *old_name,
                         const char *new_name)
 {
     char sname[GNAME_MAX], tname[GNAME_MAX], tmapset[GMAPSET_MAX];
-    char element[GNAME_MAX];
+    char dir[GNAME_MAX];
     const char *smapset;
     char old_path[GPATH_MAX], new_path[GPATH_MAX];
 
@@ -196,9 +204,11 @@ int I_signatures_rename(I_SIGFILE_TYPE type, const char *old_name,
         return 1;
     }
 
-    I__get_signatures_element(element, type);
-    G_file_name(old_path, element, sname, tmapset);
-    G_file_name(new_path, element, tname, tmapset);
+    I_get_signatures_dir(dir, type);
+    /* Note – we need whole directory not just an element in it thus
+       G_file_name and not G_file_name_misc */
+    G_file_name(old_path, dir, sname, tmapset);
+    G_file_name(new_path, dir, tname, tmapset);
 
     if (G_rename_file(old_path, new_path) != 0) {
         G_warning(_("Unable to rename <%s> to <%s>"), old_name, new_name);
@@ -245,6 +255,7 @@ int I_signatures_list_by_type(I_SIGFILE_TYPE type, const char *mapset,
  * \brief Free memory allocated by I_signatures_list_by_type
  *
  * Calls G_free for all list items returned by I_signatures_list_by_type()
+ * Sets pointer to NULL to prevent accidental use after free.
  *
  * \param int Return value of I_signatures_list_by_type()
  * \param pointer to array filled by I_signatures_list_by_type()
@@ -255,6 +266,7 @@ void I_free_signatures_list(int count, char ***list)
         G_free((*list)[n]);
     }
     G_free(*list);
+    *list = NULL;
 }
 
 static int list_by_type(I_SIGFILE_TYPE type, const char *mapset, int base,
@@ -262,11 +274,11 @@ static int list_by_type(I_SIGFILE_TYPE type, const char *mapset, int base,
 {
     int count = 0;
     char path[GPATH_MAX];
-    char element[GNAME_MAX];
+    char dir[GNAME_MAX];
     char **dirlist;
 
-    I__get_signatures_element(element, type);
-    G_file_name(path, element, "", mapset);
+    I_get_signatures_dir(dir, type);
+    G_file_name(path, dir, "", mapset);
 
     if (access(path, 0) != 0) {
         return count;

+ 14 - 9
lib/imagery/sigfile.c

@@ -17,6 +17,9 @@
 /*!
    \brief Create signature file
 
+   Returns a pointer to FILE for writing signature file.
+   Use fclose on the pointer to close after use.
+
    \param name signature filename
 
    \return pointer to FILE
@@ -24,14 +27,13 @@
  */
 FILE *I_fopen_signature_file_new(const char *name)
 {
-    char element[GNAME_MAX];
+    char dir[GNAME_MAX];
     FILE *fd;
 
     /* create sig directory */
-    I__make_signatures_element(I_SIGFILE_TYPE_SIG);
-
-    I__get_signatures_element(element, I_SIGFILE_TYPE_SIG);
-    fd = G_fopen_new(element, name);
+    I_make_signatures_dir(I_SIGFILE_TYPE_SIG);
+    I_get_signatures_dir(dir, I_SIGFILE_TYPE_SIG);
+    fd = G_fopen_new_misc(dir, "sig", name);
 
     return fd;
 }
@@ -39,7 +41,10 @@ FILE *I_fopen_signature_file_new(const char *name)
 /*!
    \brief Open existing signature file
 
-   Use fully qualified names for signatures from other mapsets
+   Use fully qualified names for signatures from other mapsets.
+
+   Returns a pointer to FILE with signature. Use fclose on the pointer
+   after use.
 
    \param name signature filename
 
@@ -49,14 +54,14 @@ FILE *I_fopen_signature_file_new(const char *name)
 FILE *I_fopen_signature_file_old(const char *name)
 {
     char sig_name[GNAME_MAX], sig_mapset[GMAPSET_MAX];
-    char element[GNAME_MAX];
+    char dir[GNAME_MAX];
     FILE *fd;
 
     if (G_unqualified_name(name, NULL, sig_name, sig_mapset) == 0)
         strcpy(sig_mapset, G_mapset());
 
-    I__get_signatures_element(element, I_SIGFILE_TYPE_SIG);
-    fd = G_fopen_old(element, sig_name, sig_mapset);
+    I_get_signatures_dir(dir, I_SIGFILE_TYPE_SIG);
+    fd = G_fopen_old_misc(dir, "sig", sig_name, sig_mapset);
 
     return fd;
 }

+ 172 - 133
lib/imagery/sigset.c

@@ -1,8 +1,8 @@
 #include <string.h>
 #include <stdlib.h>
-#include <grass/imagery.h>
 #include <grass/gis.h>
 #include <grass/glocale.h>
+#include <grass/imagery.h>
 
 static int gettag(FILE *, char *);
 static int get_bandrefs(FILE *, struct SigSet *);
@@ -24,7 +24,7 @@ static double **alloc_matrix(int rows, int cols)
     m = (double **)G_calloc(rows, sizeof(double *));
     m[0] = (double *)G_calloc(rows * cols, sizeof(double));
     for (i = 1; i < rows; i++)
-	m[i] = m[i - 1] + cols;
+        m[i] = m[i - 1] + cols;
 
     return m;
 }
@@ -34,15 +34,15 @@ int I_SigSetNClasses(struct SigSet *S)
     int i, count;
 
     for (i = 0, count = 0; i < S->nclasses; i++)
-	if (S->ClassSig[i].used)
-	    count++;
+        if (S->ClassSig[i].used)
+            count++;
 
     return count;
 }
 
 
 struct ClassData *I_AllocClassData(struct SigSet *S,
-				   struct ClassSig *C, int npixels)
+                                   struct ClassSig *C, int npixels)
 {
     struct ClassData *Data;
 
@@ -80,11 +80,11 @@ struct ClassSig *I_NewClassSig(struct SigSet *S)
     struct ClassSig *Sp;
 
     if (S->nclasses == 0)
-	S->ClassSig = (struct ClassSig *)G_malloc(sizeof(struct ClassSig));
+        S->ClassSig = (struct ClassSig *)G_malloc(sizeof(struct ClassSig));
     else
-	S->ClassSig = (struct ClassSig *)G_realloc((char *)S->ClassSig,
-						   sizeof(struct ClassSig) *
-						   (S->nclasses + 1));
+        S->ClassSig = (struct ClassSig *)G_realloc((char *)S->ClassSig,
+                                                   sizeof(struct ClassSig) *
+                                                   (S->nclasses + 1));
 
     Sp = &S->ClassSig[S->nclasses++];
     Sp->classnum = 0;
@@ -101,22 +101,22 @@ struct SubSig *I_NewSubSig(struct SigSet *S, struct ClassSig *C)
     int i;
 
     if (C->nsubclasses == 0)
-	C->SubSig = (struct SubSig *)G_malloc(sizeof(struct SubSig));
+        C->SubSig = (struct SubSig *)G_malloc(sizeof(struct SubSig));
     else
-	C->SubSig = (struct SubSig *)G_realloc((char *)C->SubSig,
-					       sizeof(struct SubSig) *
-					       (C->nsubclasses + 1));
+        C->SubSig = (struct SubSig *)G_realloc((char *)C->SubSig,
+                                               sizeof(struct SubSig) *
+                                               (C->nsubclasses + 1));
 
     Sp = &C->SubSig[C->nsubclasses++];
     Sp->used = 1;
     Sp->R = (double **)G_calloc(S->nbands, sizeof(double *));
     Sp->R[0] = (double *)G_calloc(S->nbands * S->nbands, sizeof(double));
     for (i = 1; i < S->nbands; i++)
-	Sp->R[i] = Sp->R[i - 1] + S->nbands;
+        Sp->R[i] = Sp->R[i - 1] + S->nbands;
     Sp->Rinv = (double **)G_calloc(S->nbands, sizeof(double *));
     Sp->Rinv[0] = (double *)G_calloc(S->nbands * S->nbands, sizeof(double));
     for (i = 1; i < S->nbands; i++)
-	Sp->Rinv[i] = Sp->Rinv[i - 1] + S->nbands;
+        Sp->Rinv[i] = Sp->Rinv[i - 1] + S->nbands;
     Sp->means = (double *)G_calloc(S->nbands, sizeof(double));
     Sp->N = 0;
     Sp->pi = 0;
@@ -157,53 +157,77 @@ int I_ReadSigSet(FILE * fd, struct SigSet *S)
 
     I_InitSigSet(S, 0);
     while (gettag(fd, tag)) {
-	if (eq(tag, "title:"))
-	    if (get_title(fd, S) != 0)
-            return -1;
-	if (eq(tag, "bandrefs:"))
-        if (get_bandrefs(fd, S) != 0)
-            return -1;
-    if (eq(tag, "class:"))
-	    if (get_class(fd, S) != 0)
-            return -1;
+        if (eq(tag, "title:"))
+            if (get_title(fd, S) != 0)
+                return -1;
+        if (eq(tag, "bandrefs:"))
+            if (get_bandrefs(fd, S) != 0)
+                return -1;
+        if (eq(tag, "class:"))
+            if (get_class(fd, S) != 0)
+                return -1;
     }
-    return 1;			/* for now assume success */
+    return 1;                   /* for now assume success */
 }
 
 static int gettag(FILE * fd, char *tag)
 {
     if (fscanf(fd, "%255s", tag) != 1)
-	return 0;
+        return 0;
     G_strip(tag);
     return 1;
 }
 
 static int get_bandrefs(FILE * fd, struct SigSet *S)
 {
-    char **bandrefs;
-    char *bandrefs_str;
-
-    if (fscanf(fd, "%m[^\n]", &bandrefs_str) != 1) {
-        G_warning(_("Error reading band references from sigset file"));
-        return -1;
+    int n, pos;
+    char c, prev;
+    char bandref[GNAME_MAX];
+
+    /* Read band references and count them to set nbands */
+    n = 0;
+    pos = 0;
+    S->bandrefs = (char **)G_realloc(S->bandrefs, (n + 1) * sizeof(char **));
+    while ((c = (char)fgetc(fd)) != EOF) {
+        if (c == '\n') {
+            if (prev != ' ') {
+                bandref[pos] = '\0';
+                if (strlen(bandref) > 0) {
+                    S->bandrefs[n] = G_store(bandref);
+                    n++;
+                }
+            }
+            S->nbands = n;
+            break;
+        }
+        if (c == ' ') {
+            bandref[pos] = '\0';
+            if (strlen(bandref) > 0) {
+                S->bandrefs[n] = G_store(bandref);
+                n++;
+                /* [n] is 0 based thus: (n + 1) */
+                S->bandrefs =
+                    (char **)G_realloc(S->bandrefs,
+                                       (n + 1) * sizeof(char **));
+            }
+            pos = 0;
+            prev = c;
+            continue;
+        }
+        /* Band references are limited to GNAME_MAX - 1 + \0 in length;
+         * n is 0-based */
+        if (pos == (GNAME_MAX - 2)) {
+            G_warning(_("Invalid signature file: band reference length limit exceeded"));
+            return -1;
+        }
+        bandref[pos] = c;
+        pos++;
+        prev = c;
     }
-
-    G_strip(bandrefs_str);
-    bandrefs = G_tokenize(bandrefs_str, " ");
-    S->nbands = G_number_of_tokens(bandrefs);
     if (!(S->nbands > 0)) {
         G_warning(_("Signature file does not contain bands"));
         return -1;
     }
-    S->bandrefs = (char **)G_realloc(S->bandrefs, S->nbands * sizeof(char **));
-    for (unsigned int i = S->nbands; i--;) {
-        if (strlen(bandrefs[i]) > (GNAME_MAX - 1)) {
-            G_warning(_("Invalid sigset file: band reference length limit exceeded"));
-            return -1;
-        }
-        S->bandrefs[i] = (char *)G_malloc(GNAME_MAX * sizeof(char *));
-        strcpy(S->bandrefs[i], bandrefs[i]);
-    }
 
     return 0;
 }
@@ -228,20 +252,20 @@ static int get_class(FILE * fd, struct SigSet *S)
 
     C = I_NewClassSig(S);
     while (gettag(fd, tag)) {
-	if (eq(tag, "endclass:"))
-	    break;
-	if (eq(tag, "classnum:"))
-	    if (get_classnum(fd, C) != 0)
-            return -1;
-	if (eq(tag, "classtype:"))
-	    if (get_classtype(fd, C) != 0)
-            return -1;
-	if (eq(tag, "classtitle:"))
-	    if (get_classtitle(fd, C) != 0)
-            return -1;
-	if (eq(tag, "subclass:"))
-	    if (get_subclass(fd, S, C) != 0)
-            return -1;
+        if (eq(tag, "endclass:"))
+            break;
+        if (eq(tag, "classnum:"))
+            if (get_classnum(fd, C) != 0)
+                return -1;
+        if (eq(tag, "classtype:"))
+            if (get_classtype(fd, C) != 0)
+                return -1;
+        if (eq(tag, "classtitle:"))
+            if (get_classtitle(fd, C) != 0)
+                return -1;
+        if (eq(tag, "subclass:"))
+            if (get_subclass(fd, S, C) != 0)
+                return -1;
     }
 
     return 0;
@@ -284,17 +308,17 @@ static int get_subclass(FILE * fd, struct SigSet *S, struct ClassSig *C)
     Sp = I_NewSubSig(S, C);
 
     while (gettag(fd, tag)) {
-	if (eq(tag, "endsubclass:"))
-	    break;
-	if (eq(tag, "pi:"))
-	    if (get_subclass_pi(fd, Sp) != 0)
-            return -1;
-	if (eq(tag, "means:"))
-	    if (get_subclass_means(fd, Sp, S->nbands) != 0)
-            return -1;
-	if (eq(tag, "covar:"))
-	    if (get_subclass_covar(fd, Sp, S->nbands) != 0)
-            return -1;
+        if (eq(tag, "endsubclass:"))
+            break;
+        if (eq(tag, "pi:"))
+            if (get_subclass_pi(fd, Sp) != 0)
+                return -1;
+        if (eq(tag, "means:"))
+            if (get_subclass_means(fd, Sp, S->nbands) != 0)
+                return -1;
+        if (eq(tag, "covar:"))
+            if (get_subclass_covar(fd, Sp, S->nbands) != 0)
+                return -1;
     }
 
     return 0;
@@ -313,8 +337,8 @@ static int get_subclass_means(FILE * fd, struct SubSig *Sp, int nbands)
     int i;
 
     for (i = 0; i < nbands; i++)
-	if (fscanf(fd, "%lf", &Sp->means[i]) != 1)
-        return -1;
+        if (fscanf(fd, "%lf", &Sp->means[i]) != 1)
+            return -1;
 
     return 0;
 }
@@ -324,9 +348,9 @@ static int get_subclass_covar(FILE * fd, struct SubSig *Sp, int nbands)
     int i, j;
 
     for (i = 0; i < nbands; i++)
-	for (j = 0; j < nbands; j++)
-	    if (fscanf(fd, "%lf", &Sp->R[i][j]) != 1)
-            return -1;
+        for (j = 0; j < nbands; j++)
+            if (fscanf(fd, "%lf", &Sp->R[i][j]) != 1)
+                return -1;
 
     return 0;
 }
@@ -334,9 +358,9 @@ static int get_subclass_covar(FILE * fd, struct SubSig *Sp, int nbands)
 int I_SetSigTitle(struct SigSet *S, const char *title)
 {
     if (title == NULL)
-	title = "";
+        title = "";
     if (S->title)
-	free(S->title);
+        free(S->title);
     S->title = G_store(title);
 
     return 0;
@@ -345,17 +369,17 @@ int I_SetSigTitle(struct SigSet *S, const char *title)
 const char *I_GetSigTitle(const struct SigSet *S)
 {
     if (S->title)
-	return S->title;
+        return S->title;
     else
-	return "";
+        return "";
 }
 
 int I_SetClassTitle(struct ClassSig *C, const char *title)
 {
     if (title == NULL)
-	title = "";
+        title = "";
     if (C->title)
-	free(C->title);
+        free(C->title);
     C->title = G_store(title);
 
     return 0;
@@ -364,9 +388,9 @@ int I_SetClassTitle(struct ClassSig *C, const char *title)
 const char *I_GetClassTitle(const struct ClassSig *C)
 {
     if (C->title)
-	return C->title;
+        return C->title;
     else
-	return "";
+        return "";
 }
 
 int I_WriteSigSet(FILE * fd, const struct SigSet *S)
@@ -384,34 +408,34 @@ int I_WriteSigSet(FILE * fd, const struct SigSet *S)
     }
     fprintf(fd, "\n");
     for (i = 0; i < S->nclasses; i++) {
-	Cp = &S->ClassSig[i];
-	if (!Cp->used)
-	    continue;
-	if (Cp->nsubclasses <= 0)
-	    continue;
-	fprintf(fd, "class:\n");
-	fprintf(fd, " classnum: %ld\n", Cp->classnum);
-	fprintf(fd, " classtitle: %s\n", I_GetClassTitle(Cp));
-	fprintf(fd, " classtype: %d\n", Cp->type);
-
-	for (j = 0; j < Cp->nsubclasses; j++) {
-	    Sp = &Cp->SubSig[j];
-	    fprintf(fd, " subclass:\n");
-	    fprintf(fd, "  pi: %g\n", Sp->pi);
-	    fprintf(fd, "  means:");
-	    for (b1 = 0; b1 < S->nbands; b1++)
-		fprintf(fd, " %g", Sp->means[b1]);
-	    fprintf(fd, "\n");
-	    fprintf(fd, "  covar:\n");
-	    for (b1 = 0; b1 < S->nbands; b1++) {
-		fprintf(fd, "   ");
-		for (b2 = 0; b2 < S->nbands; b2++)
-		    fprintf(fd, " %g", Sp->R[b1][b2]);
-		fprintf(fd, "\n");
-	    }
-	    fprintf(fd, " endsubclass:\n");
-	}
-	fprintf(fd, "endclass:\n");
+        Cp = &S->ClassSig[i];
+        if (!Cp->used)
+            continue;
+        if (Cp->nsubclasses <= 0)
+            continue;
+        fprintf(fd, "class:\n");
+        fprintf(fd, " classnum: %ld\n", Cp->classnum);
+        fprintf(fd, " classtitle: %s\n", I_GetClassTitle(Cp));
+        fprintf(fd, " classtype: %d\n", Cp->type);
+
+        for (j = 0; j < Cp->nsubclasses; j++) {
+            Sp = &Cp->SubSig[j];
+            fprintf(fd, " subclass:\n");
+            fprintf(fd, "  pi: %g\n", Sp->pi);
+            fprintf(fd, "  means:");
+            for (b1 = 0; b1 < S->nbands; b1++)
+                fprintf(fd, " %g", Sp->means[b1]);
+            fprintf(fd, "\n");
+            fprintf(fd, "  covar:\n");
+            for (b1 = 0; b1 < S->nbands; b1++) {
+                fprintf(fd, "   ");
+                for (b2 = 0; b2 < S->nbands; b2++)
+                    fprintf(fd, " %g", Sp->R[b1][b2]);
+                fprintf(fd, "\n");
+            }
+            fprintf(fd, " endsubclass:\n");
+        }
+        fprintf(fd, "endclass:\n");
     }
 
     return 0;
@@ -448,7 +472,8 @@ int I_WriteSigSet(FILE * fd, const struct SigSet *S)
  * \return NULL successfully sorted
  * \return err_array two comma separated lists of mismatches
  */
-char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R) {
+char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R)
+{
     unsigned int total, complete;
     unsigned int *match1, *match2, mc1, mc2, *new_order;
     double ***new_means, ****new_vars;
@@ -457,12 +482,14 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R) {
     /* Safety measure. Untranslated as this should not happen in production! */
     if (S->nbands < 1 || R->nfiles < 1)
         G_fatal_error("Programming error. Invalid length structs passed to "
-                      "I_sort_signatures_by_bandref(%d, %d);", S->nbands,  R->nfiles);
+                      "I_sort_signatures_by_bandref(%d, %d);", S->nbands,
+                      R->nfiles);
 
     /* Obtain group band references */
     group_bandrefs = (char **)G_malloc(R->nfiles * sizeof(char *));
     for (unsigned int j = R->nfiles; j--;) {
-        group_bandrefs[j] = Rast_read_bandref(R->file[j].name, R->file[j].mapset);
+        group_bandrefs[j] =
+            Rast_read_bandref(R->file[j].name, R->file[j].mapset);
     }
 
     /* If lengths are not equal, there will be a mismatch */
@@ -479,13 +506,19 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R) {
     // new_vars[S.ClassSig[x]][.SubSig[y]][R[band1]][R[band1]]
     new_vars = (double ****)G_malloc(S->nclasses * sizeof(double ***));
     for (unsigned int c = S->nclasses; c--;) {
-        new_means[c] = (double **)G_malloc(S->ClassSig[c].nsubclasses * sizeof(double *));
-        new_vars[c] = (double ***)G_malloc(S->ClassSig[c].nsubclasses * sizeof(double **));
+        new_means[c] =
+            (double **)G_malloc(S->ClassSig[c].nsubclasses *
+                                sizeof(double *));
+        new_vars[c] =
+            (double ***)G_malloc(S->ClassSig[c].nsubclasses *
+                                 sizeof(double **));
         for (unsigned int s = S->ClassSig[c].nsubclasses; s--;) {
             new_means[c][s] = (double *)G_malloc(S->nbands * sizeof(double));
-            new_vars[c][s] = (double **)G_malloc(S->nbands * sizeof(double *));
+            new_vars[c][s] =
+                (double **)G_malloc(S->nbands * sizeof(double *));
             for (unsigned int i = S->nbands; i--;)
-                new_vars[c][s][i] = (double *)G_malloc(S->nbands * sizeof(double));
+                new_vars[c][s][i] =
+                    (double *)G_malloc(S->nbands * sizeof(double));
         }
     }
 
@@ -494,15 +527,15 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R) {
         for (unsigned int i = S->nbands; i--;) {
             if (S->bandrefs[i] && group_bandrefs[j] &&
                 !strcmp(S->bandrefs[i], group_bandrefs[j])) {
-                    if (complete) {
-                        /* Reorder pointers to existing strings only */
-                        new_bandrefs[j] = S->bandrefs[i];
-                        new_order[i] = j;
-                    }
-                    /* Keep a track of matching items for error reporting */
-                    match1[i] = 1;
-                    match2[j] = 1;
-                    break;
+                if (complete) {
+                    /* Reorder pointers to existing strings only */
+                    new_bandrefs[j] = S->bandrefs[i];
+                    new_order[i] = j;
+                }
+                /* Keep a track of matching items for error reporting */
+                match1[i] = 1;
+                match2[j] = 1;
+                break;
             }
         }
     }
@@ -519,7 +552,8 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R) {
                 total = total + strlen(S->bandrefs[i]);
             else
                 total = total + 24;
-            mismatches[0] = (char *)G_realloc(mismatches[0], total * sizeof(char *));
+            mismatches[0] =
+                (char *)G_realloc(mismatches[0], total * sizeof(char *));
             if (mc1)
                 strcat(mismatches[0], ",");
             else
@@ -539,7 +573,8 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R) {
                 total = total + strlen(group_bandrefs[j]);
             else
                 total = total + 24;
-            mismatches[1] = (char *)G_realloc(mismatches[1], total * sizeof(char *));
+            mismatches[1] =
+                (char *)G_realloc(mismatches[1], total * sizeof(char *));
             if (mc2)
                 strcat(mismatches[1], ",");
             else
@@ -558,9 +593,11 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R) {
         for (unsigned int c = S->nclasses; c--;) {
             for (unsigned int s = S->ClassSig[c].nsubclasses; s--;) {
                 for (unsigned int b1 = 0; b1 < S->nbands; b1++) {
-                    new_means[c][s][new_order[b1]] = S->ClassSig[c].SubSig[s].means[b1];
+                    new_means[c][s][new_order[b1]] =
+                        S->ClassSig[c].SubSig[s].means[b1];
                     for (unsigned int b2 = 0; b2 < S->nbands; b2++) {
-                        new_vars[c][s][new_order[b1]][new_order[b2]] = S->ClassSig[c].SubSig[s].R[b1][b2];
+                        new_vars[c][s][new_order[b1]][new_order[b2]] =
+                            S->ClassSig[c].SubSig[s].R[b1][b2];
                     }
                 }
             }
@@ -570,9 +607,11 @@ char **I_SortSigSetByBandref(struct SigSet *S, const struct Ref *R) {
         memcpy(S->bandrefs, new_bandrefs, S->nbands * sizeof(char **));
         for (unsigned int c = S->nclasses; c--;) {
             for (unsigned int s = S->ClassSig[c].nsubclasses; s--;) {
-                memcpy(S->ClassSig[c].SubSig[s].means, new_means[c][s], S->nbands * sizeof(double));
+                memcpy(S->ClassSig[c].SubSig[s].means, new_means[c][s],
+                       S->nbands * sizeof(double));
                 for (unsigned int i = S->nbands; i--;)
-                    memcpy(S->ClassSig[c].SubSig[s].R[i], new_vars[c][s][i], S->nbands * sizeof(double));
+                    memcpy(S->ClassSig[c].SubSig[s].R[i], new_vars[c][s][i],
+                           S->nbands * sizeof(double));
             }
         }
     }

+ 7 - 7
lib/imagery/sigsetfile.c

@@ -27,14 +27,14 @@
  */
 FILE *I_fopen_sigset_file_new(const char *name)
 {
-    char element[GNAME_MAX];
+    char dir[GNAME_MAX];
     FILE *fd;
 
     /* create sig directory */
-    I__make_signatures_element(I_SIGFILE_TYPE_SIGSET);
+    I_make_signatures_dir(I_SIGFILE_TYPE_SIGSET);
 
-    I__get_signatures_element(element, I_SIGFILE_TYPE_SIGSET);
-    fd = G_fopen_new(element, name);
+    I_get_signatures_dir(dir, I_SIGFILE_TYPE_SIGSET);
+    fd = G_fopen_new_misc(dir, "sig", name);
 
     return fd;
 }
@@ -50,14 +50,14 @@ FILE *I_fopen_sigset_file_new(const char *name)
 FILE *I_fopen_sigset_file_old(const char *name)
 {
     char sig_name[GNAME_MAX], sig_mapset[GMAPSET_MAX];
-    char element[GNAME_MAX];
+    char dir[GNAME_MAX];
     FILE *fd;
 
     if (G_unqualified_name(name, NULL, sig_name, sig_mapset) == 0)
         strcpy(sig_mapset, G_mapset());
 
-    I__get_signatures_element(element, I_SIGFILE_TYPE_SIGSET);
-    fd = G_fopen_old(element, sig_name, sig_mapset);
+    I_get_signatures_dir(dir, I_SIGFILE_TYPE_SIGSET);
+    fd = G_fopen_old_misc(dir, "sig", sig_name, sig_mapset);
 
     return fd;
 }

+ 12 - 9
lib/imagery/testsuite/test_imagery_find.py

@@ -9,6 +9,7 @@ Read the file COPYING that comes with GRASS
 for details
 """
 import os
+import shutil
 
 from grass.gunittest.case import TestCase
 from grass.gunittest.main import test
@@ -31,24 +32,26 @@ class FindSignatureTestCase(TestCase):
     def setUpClass(cls):
         cls.mpath = utils.decode(G_mapset_path())
         cls.mapset_name = Mapset().name
+        cls.sigdirs = []
         # As signatures are created directly not via signature creation
         # tools, we must ensure signature directories exist
         os.makedirs(f"{cls.mpath}/signatures/sig/", exist_ok=True)
         os.makedirs(f"{cls.mpath}/signatures/sigset/", exist_ok=True)
         cls.sig_name1 = tempname(10)
-        cls.sigfile_name1 = f"{cls.mpath}/signatures/sigset/{cls.sig_name1}"
-        open(cls.sigfile_name1, "a").close()
+        cls.sig_dir1 = f"{cls.mpath}/signatures/sigset/{cls.sig_name1}"
+        os.makedirs(cls.sig_dir1)
+        cls.sigdirs.append(cls.sig_dir1)
+        open(f"{cls.sig_dir1}/sig", "a").close()
         cls.sig_name2 = tempname(10)
-        cls.sigfile_name2 = f"{cls.mpath}/signatures/sig/{cls.sig_name2}"
-        open(cls.sigfile_name2, "a").close()
+        cls.sig_dir2 = f"{cls.mpath}/signatures/sig/{cls.sig_name2}"
+        os.makedirs(cls.sig_dir2)
+        cls.sigdirs.append(cls.sig_dir2)
+        open(f"{cls.sig_dir2}/sig", "a").close()
 
     @classmethod
     def tearDownClass(cls):
-        try:
-            os.remove(cls.sigfile_name1)
-            os.remove(cls.sigfile_name2)
-        except OSError:
-            pass
+        for d in cls.sigdirs:
+            shutil.rmtree(d, ignore_errors=True)
 
     def test_find_sig(self):
         # Non existing without a mapset

+ 6 - 8
lib/imagery/testsuite/test_imagery_sigfile.py

@@ -11,6 +11,7 @@ for details
 import os
 import stat
 import ctypes
+import shutil
 
 from grass.gunittest.case import TestCase
 from grass.gunittest.main import test
@@ -45,14 +46,11 @@ class SignatureFileTestCase(TestCase):
         cls.mpath = utils.decode(G_mapset_path())
         cls.mapset_name = Mapset().name
         cls.sig_name = tempname(10)
-        cls.sigfile_name = f"{cls.mpath}/signatures/sig/{cls.sig_name}"
+        cls.sig_dir = f"{cls.mpath}/signatures/sig/{cls.sig_name}"
 
     @classmethod
     def tearDownClass(cls):
-        try:
-            os.remove(cls.sigfile_name)
-        except OSError:
-            pass
+        shutil.rmtree(cls.sig_dir, ignore_errors=True)
 
     def test_I_fopen_signature_file_old_fail(self):
         sigfile = I_fopen_signature_file_old(tempname(10))
@@ -81,7 +79,7 @@ class SignatureFileTestCase(TestCase):
 
         # Write signatures to file
         p_new_sigfile = I_fopen_signature_file_new(self.sig_name)
-        sig_stat = os.stat(self.sigfile_name)
+        sig_stat = os.stat(f"{self.sig_dir}/sig")
         self.assertTrue(stat.S_ISREG(sig_stat.st_mode))
         I_write_signatures(p_new_sigfile, ctypes.byref(So))
         self.libc.fclose(p_new_sigfile)
@@ -134,7 +132,7 @@ class SignatureFileTestCase(TestCase):
 
         # Write signatures to file
         p_new_sigfile = I_fopen_signature_file_new(self.sig_name)
-        sig_stat = os.stat(self.sigfile_name)
+        sig_stat = os.stat(f"{self.sig_dir}/sig")
         self.assertTrue(stat.S_ISREG(sig_stat.st_mode))
         I_write_signatures(p_new_sigfile, ctypes.byref(So))
         self.libc.fclose(p_new_sigfile)
@@ -186,7 +184,7 @@ class SignatureFileTestCase(TestCase):
 
         # Write signatures to file
         p_new_sigfile = I_fopen_signature_file_new(self.sig_name)
-        sig_stat = os.stat(self.sigfile_name)
+        sig_stat = os.stat(f"{self.sig_dir}/sig")
         self.assertTrue(stat.S_ISREG(sig_stat.st_mode))
         I_write_signatures(p_new_sigfile, ctypes.byref(So))
         self.libc.fclose(p_new_sigfile)

+ 188 - 129
lib/imagery/testsuite/test_imagery_signature_management.py

@@ -36,21 +36,21 @@ from grass.lib.imagery import (
     I_signatures_rename,
     I_signatures_list_by_type,
     I_free_signatures_list,
-    I__get_signatures_element,
-    I__make_signatures_element,
+    I_get_signatures_dir,
+    I_make_signatures_dir,
 )
 
 
 class GetSignaturesElementTestCase(TestCase):
     def test_get_sig(self):
-        elem = ctypes.create_string_buffer(GNAME_MAX)
-        I__get_signatures_element(elem, I_SIGFILE_TYPE_SIG)
-        self.assertEqual(utils.decode(elem.value), f"signatures{HOST_DIRSEP}sig")
+        cdir = ctypes.create_string_buffer(GNAME_MAX)
+        I_get_signatures_dir(cdir, I_SIGFILE_TYPE_SIG)
+        self.assertEqual(utils.decode(cdir.value), f"signatures{HOST_DIRSEP}sig")
 
     def test_get_sigset(self):
-        elem = ctypes.create_string_buffer(GNAME_MAX)
-        I__get_signatures_element(elem, I_SIGFILE_TYPE_SIGSET)
-        self.assertEqual(utils.decode(elem.value), f"signatures{HOST_DIRSEP}sigset")
+        cdir = ctypes.create_string_buffer(GNAME_MAX)
+        I_get_signatures_dir(cdir, I_SIGFILE_TYPE_SIGSET)
+        self.assertEqual(utils.decode(cdir.value), f"signatures{HOST_DIRSEP}sigset")
 
 
 class MakeSignaturesElementTestCase(TestCase):
@@ -69,23 +69,23 @@ class MakeSignaturesElementTestCase(TestCase):
         shutil.rmtree(cls.tmp_mapset_path, ignore_errors=True)
 
     def test_make_sig(self):
-        I__make_signatures_element(I_SIGFILE_TYPE_SIG)
+        I_make_signatures_dir(I_SIGFILE_TYPE_SIG)
         self.assertTrue(
             os.path.isdir(os.path.join(self.tmp_mapset_path, "signatures", "sig"))
         )
         # There should not be any side effects of calling function multiple times
-        I__make_signatures_element(I_SIGFILE_TYPE_SIG)
+        I_make_signatures_dir(I_SIGFILE_TYPE_SIG)
         self.assertTrue(
             os.path.isdir(os.path.join(self.tmp_mapset_path, "signatures", "sig"))
         )
 
     def test_make_sigset(self):
-        I__make_signatures_element(I_SIGFILE_TYPE_SIGSET)
+        I_make_signatures_dir(I_SIGFILE_TYPE_SIGSET)
         self.assertTrue(
             os.path.isdir(os.path.join(self.tmp_mapset_path, "signatures", "sigset"))
         )
         # There should not be any side effects of calling function multiple times
-        I__make_signatures_element(I_SIGFILE_TYPE_SIGSET)
+        I_make_signatures_dir(I_SIGFILE_TYPE_SIGSET)
         self.assertTrue(
             os.path.isdir(os.path.join(self.tmp_mapset_path, "signatures", "sigset"))
         )
@@ -96,7 +96,7 @@ class SignaturesRemoveTestCase(TestCase):
     def setUpClass(cls):
         cls.mpath = utils.decode(G_mapset_path())
         cls.mapset_name = Mapset().name
-        cls.sigfiles = []
+        cls.sigdirs = []
         # As signatures are created directly not via signature creation
         # tools, we must ensure signature directories exist
         os.makedirs(f"{cls.mpath}/signatures/sig/", exist_ok=True)
@@ -104,27 +104,30 @@ class SignaturesRemoveTestCase(TestCase):
 
     @classmethod
     def tearDownClass(cls):
-        for f in cls.sigfiles:
-            try:
-                os.remove(f)
-            except OSError:
-                pass
+        for d in cls.sigdirs:
+            shutil.rmtree(d, ignore_errors=True)
 
     def test_remove_existing_sig(self):
         # This test will fail if run in PERMANENT!
         # Set up files and mark for clean-up
         sig_name1 = tempname(10)
-        sigfile_name1 = f"{self.mpath}/signatures/sigset/{sig_name1}"
+        sig_dir1 = f"{self.mpath}/signatures/sigset/{sig_name1}"
+        os.makedirs(sig_dir1)
+        self.sigdirs.append(sig_dir1)
+        sigfile_name1 = f"{sig_dir1}/sig"
         open(sigfile_name1, "a").close()
-        self.sigfiles.append(sigfile_name1)
         sig_name2 = tempname(10)
-        sigfile_name2 = f"{self.mpath}/signatures/sig/{sig_name2}"
+        sig_dir2 = f"{self.mpath}/signatures/sig/{sig_name2}"
+        os.makedirs(sig_dir2)
+        self.sigdirs.append(sig_dir2)
+        sigfile_name2 = f"{sig_dir2}/sig"
         open(sigfile_name2, "a").close()
-        self.sigfiles.append(sigfile_name2)
         sig_name3 = tempname(10)
-        sigfile_name3 = f"{self.mpath}/signatures/sig/{sig_name3}"
+        sig_dir3 = f"{self.mpath}/signatures/sig/{sig_name3}"
+        os.makedirs(sig_dir3)
+        self.sigdirs.append(sig_dir3)
+        sigfile_name3 = f"{sig_dir3}/sig"
         open(sigfile_name3, "a").close()
-        self.sigfiles.append(sigfile_name3)
         # Try to remove with wrong type
         ret = I_signatures_remove(I_SIGFILE_TYPE_SIGSET, sig_name2)
         self.assertEqual(ret, 1)
@@ -155,15 +158,19 @@ class SignaturesRemoveTestCase(TestCase):
     def test_remove_nonexisting_sig(self):
         # Set up files and mark for clean-up
         sig_name1 = tempname(10)
-        sigfile_name1 = f"{self.mpath}/signatures/sigset/{sig_name1}"
+        sig_dir1 = f"{self.mpath}/signatures/sigset/{sig_name1}"
+        os.makedirs(sig_dir1)
+        self.sigdirs.append(sig_dir1)
+        sigfile_name1 = f"{sig_dir1}/sig"
         open(sigfile_name1, "a").close()
-        self.sigfiles.append(sigfile_name1)
         sig_name2 = tempname(10)
         # Do not create sig_name2 matching file
         sig_name3 = tempname(10)
-        sigfile_name3 = f"{self.mpath}/signatures/sig/{sig_name3}"
+        sig_dir3 = f"{self.mpath}/signatures/sig/{sig_name3}"
+        os.makedirs(sig_dir3)
+        self.sigdirs.append(sig_dir3)
+        sigfile_name3 = f"{sig_dir3}/sig"
         open(sigfile_name3, "a").close()
-        self.sigfiles.append(sigfile_name3)
         # Now remove one (should fail as file is absent)
         ret = I_signatures_remove(I_SIGFILE_TYPE_SIG, sig_name2)
         self.assertEqual(ret, 1)
@@ -183,17 +190,23 @@ class SignaturesRemoveTestCase(TestCase):
     def test_remove_existing_sigset(self):
         # Set up files and mark for clean-up
         sig_name1 = tempname(10)
-        sigfile_name1 = f"{self.mpath}/signatures/sigset/{sig_name1}"
+        sig_dir1 = f"{self.mpath}/signatures/sigset/{sig_name1}"
+        os.makedirs(sig_dir1)
+        self.sigdirs.append(sig_dir1)
+        sigfile_name1 = f"{sig_dir1}/sig"
         open(sigfile_name1, "a").close()
-        self.sigfiles.append(sigfile_name1)
         sig_name2 = tempname(10)
-        sigfile_name2 = f"{self.mpath}/signatures/sigset/{sig_name2}"
+        sig_dir2 = f"{self.mpath}/signatures/sigset/{sig_name2}"
+        os.makedirs(sig_dir2)
+        self.sigdirs.append(sig_dir2)
+        sigfile_name2 = f"{sig_dir2}/sig"
         open(sigfile_name2, "a").close()
-        self.sigfiles.append(sigfile_name2)
         sig_name3 = tempname(10)
-        sigfile_name3 = f"{self.mpath}/signatures/sig/{sig_name3}"
+        sig_dir3 = f"{self.mpath}/signatures/sig/{sig_name3}"
+        os.makedirs(sig_dir3)
+        self.sigdirs.append(sig_dir3)
+        sigfile_name3 = f"{sig_dir3}/sig"
         open(sigfile_name3, "a").close()
-        self.sigfiles.append(sigfile_name3)
         # Try to remove with wrong type
         ret = I_signatures_remove(I_SIGFILE_TYPE_SIG, sig_name2)
         self.assertEqual(ret, 1)
@@ -224,15 +237,19 @@ class SignaturesRemoveTestCase(TestCase):
     def test_remove_nonexisting_sigset(self):
         # Set up files and mark for clean-up
         sig_name1 = tempname(10)
-        sigfile_name1 = f"{self.mpath}/signatures/sigset/{sig_name1}"
+        sig_dir1 = f"{self.mpath}/signatures/sigset/{sig_name1}"
+        os.makedirs(sig_dir1)
+        self.sigdirs.append(sig_dir1)
+        sigfile_name1 = f"{sig_dir1}/sig"
         open(sigfile_name1, "a").close()
-        self.sigfiles.append(sigfile_name1)
         sig_name2 = tempname(10)
         # Do not create sig_name2 matching file
         sig_name3 = tempname(10)
-        sigfile_name3 = f"{self.mpath}/signatures/sig/{sig_name3}"
+        sig_dir3 = f"{self.mpath}/signatures/sig/{sig_name3}"
+        os.makedirs(sig_dir3)
+        self.sigdirs.append(sig_dir3)
+        sigfile_name3 = f"{sig_dir3}/sig"
         open(sigfile_name3, "a").close()
-        self.sigfiles.append(sigfile_name3)
         # Now remove one (should fail as file doesn't exist)
         ret = I_signatures_remove(I_SIGFILE_TYPE_SIGSET, sig_name2)
         self.assertEqual(ret, 1)
@@ -255,7 +272,7 @@ class SignaturesCopyTestCase(TestCase):
     def setUpClass(cls):
         cls.mpath = utils.decode(G_mapset_path())
         cls.mapset_name = Mapset().name
-        cls.sigfiles = []
+        cls.sigdirs = []
         # As signatures are created directly not via signature creation
         # tools, we must ensure signature directories exist
         os.makedirs(f"{cls.mpath}/signatures/sig/", exist_ok=True)
@@ -266,16 +283,21 @@ class SignaturesCopyTestCase(TestCase):
         cls.src_mapset_path = (
             cls.mpath.rsplit("/", maxsplit=1)[0] + "/" + cls.src_mapset_name
         )
+        # Create fake signature files
         os.makedirs(f"{cls.src_mapset_path}/signatures/sig/")
         cls.src_sig = tempname(10)
-        cls.sigfiles.append(f"{cls.src_mapset_path}/signatures/sig/{cls.src_sig}")
-        f = open(cls.sigfiles[0], "w")
+        cls.src_sig_dir = f"{cls.src_mapset_path}/signatures/sig/{cls.src_sig}"
+        os.makedirs(cls.src_sig_dir)
+        cls.sigdirs.append(cls.src_sig_dir)
+        f = open(f"{cls.src_sig_dir}/sig", "w")
         f.write("A sig file")
         f.close()
         os.makedirs(f"{cls.src_mapset_path}/signatures/sigset/")
         cls.src_sigset = tempname(10)
-        cls.sigfiles.append(f"{cls.src_mapset_path}/signatures/sigset/{cls.src_sigset}")
-        f = open(cls.sigfiles[1], "w")
+        cls.src_sigset_dir = f"{cls.src_mapset_path}/signatures/sigset/{cls.src_sigset}"
+        os.makedirs(cls.src_sigset_dir)
+        cls.sigdirs.append(cls.src_sigset_dir)
+        f = open(f"{cls.src_sigset_dir}/sig", "w")
         f.write("A sigset file")
         f.close()
 
@@ -283,11 +305,8 @@ class SignaturesCopyTestCase(TestCase):
     def tearDownClass(cls):
         # Remove random mapset created during setup
         shutil.rmtree(cls.src_mapset_path, ignore_errors=True)
-        for f in cls.sigfiles:
-            try:
-                os.remove(f)
-            except OSError:
-                pass
+        for d in cls.sigdirs:
+            shutil.rmtree(d, ignore_errors=True)
 
     def test_copy_to_wrong_mapset(self):
         rnd_name = "{0}@{0}".format(tempname(10))
@@ -317,17 +336,18 @@ class SignaturesCopyTestCase(TestCase):
         ret = I_signatures_copy(
             I_SIGFILE_TYPE_SIG, self.src_sig, self.src_mapset_name, dst
         )
-        self.sigfiles.append(f"{self.mpath}/signatures/sig/{dst}")
+        self.sigdirs.append(f"{self.mpath}/signatures/sig/{dst}")
         self.assertEqual(ret, 0)
         ret = I_find_signature(I_SIGFILE_TYPE_SIG, dst, self.mapset_name)
         self.assertTrue(ret)
         ms = utils.decode(ret)
         self.assertEqual(ms, self.mapset_name)
+        self.assertTrue(os.path.isfile(f"{self.mpath}/signatures/sig/{dst}/sig"))
 
     def test_success_fq_sig(self):
-        dst = tempname(10)
-        self.sigfiles.append(f"{self.mpath}/signatures/sig/{dst}")
-        dst = dst + "@" + self.mapset_name
+        dst_name = tempname(10)
+        self.sigdirs.append(f"{self.mpath}/signatures/sig/{dst_name}")
+        dst = dst_name + "@" + self.mapset_name
         ret = I_find_signature(I_SIGFILE_TYPE_SIG, dst, self.mapset_name)
         self.assertFalse(ret)
         ret = I_find_signature(I_SIGFILE_TYPE_SIG, self.src_sig, self.src_mapset_name)
@@ -343,6 +363,7 @@ class SignaturesCopyTestCase(TestCase):
         self.assertTrue(ret)
         ms = utils.decode(ret)
         self.assertEqual(ms, self.mapset_name)
+        self.assertTrue(os.path.isfile(f"{self.mpath}/signatures/sig/{dst_name}/sig"))
 
     def test_success_unqualified_sigset(self):
         dst = tempname(10)
@@ -355,17 +376,18 @@ class SignaturesCopyTestCase(TestCase):
         ret = I_signatures_copy(
             I_SIGFILE_TYPE_SIGSET, self.src_sigset, self.src_mapset_name, dst
         )
-        self.sigfiles.append(f"{self.mpath}/signatures/sigset/{dst}")
+        self.sigdirs.append(f"{self.mpath}/signatures/sigset/{dst}")
         self.assertEqual(ret, 0)
         ret = I_find_signature(I_SIGFILE_TYPE_SIGSET, dst, self.mapset_name)
         self.assertTrue(ret)
         ms = utils.decode(ret)
         self.assertEqual(ms, self.mapset_name)
+        self.assertTrue(os.path.isfile(f"{self.mpath}/signatures/sigset/{dst}/sig"))
 
     def test_success_fq_sigset(self):
-        dst = tempname(10)
-        self.sigfiles.append(f"{self.mpath}/signatures/sigset/{dst}")
-        dst = dst + "@" + self.mapset_name
+        dst_name = tempname(10)
+        self.sigdirs.append(f"{self.mpath}/signatures/sigset/{dst_name}")
+        dst = dst_name + "@" + self.mapset_name
         ret = I_find_signature(I_SIGFILE_TYPE_SIGSET, dst, self.mapset_name)
         self.assertFalse(ret)
         ret = I_find_signature(
@@ -383,6 +405,9 @@ class SignaturesCopyTestCase(TestCase):
         self.assertTrue(ret)
         ms = utils.decode(ret)
         self.assertEqual(ms, self.mapset_name)
+        self.assertTrue(
+            os.path.isfile(f"{self.mpath}/signatures/sigset/{dst_name}/sig")
+        )
 
 
 class SignaturesRenameTestCase(TestCase):
@@ -390,7 +415,7 @@ class SignaturesRenameTestCase(TestCase):
     def setUpClass(cls):
         cls.mpath = utils.decode(G_mapset_path())
         cls.mapset_name = Mapset().name
-        cls.sigfiles = []
+        cls.sigdirs = []
         # As signatures are created directly not via signature creation
         # tools, we must ensure signature directories exist
         os.makedirs(f"{cls.mpath}/signatures/sig/", exist_ok=True)
@@ -398,11 +423,8 @@ class SignaturesRenameTestCase(TestCase):
 
     @classmethod
     def tearDownClass(cls):
-        for f in cls.sigfiles:
-            try:
-                os.remove(f)
-            except OSError:
-                pass
+        for d in cls.sigdirs:
+            shutil.rmtree(d, ignore_errors=True)
 
     def test_rename_from_wrong_mapset(self):
         rnd_name = "{0}@{0}".format(tempname(10))
@@ -424,13 +446,14 @@ class SignaturesRenameTestCase(TestCase):
 
     def test_success_unqualified_sig(self):
         src_sig = tempname(10)
-        sig_file = f"{self.mpath}/signatures/sig/{src_sig}"
-        self.sigfiles.append(sig_file)
-        f = open(sig_file, "w")
+        sig_dir = f"{self.mpath}/signatures/sig/{src_sig}"
+        os.makedirs(sig_dir)
+        self.sigdirs.append(sig_dir)
+        f = open(f"{sig_dir}/sig", "w")
         f.write("A sig file")
         f.close()
         dst = tempname(10)
-        self.sigfiles.append(f"{self.mpath}/signatures/sig/{dst}")
+        self.sigdirs.append(f"{self.mpath}/signatures/sig/{dst}")
         ret = I_find_signature(I_SIGFILE_TYPE_SIG, dst, self.mapset_name)
         self.assertFalse(ret)
         ret = I_find_signature(I_SIGFILE_TYPE_SIG, src_sig, self.mapset_name)
@@ -441,17 +464,19 @@ class SignaturesRenameTestCase(TestCase):
         self.assertTrue(ret)
         ms = utils.decode(ret)
         self.assertEqual(ms, self.mapset_name)
+        self.assertTrue(os.path.isfile(f"{self.mpath}/signatures/sig/{dst}/sig"))
 
     def test_success_fq_sig(self):
         src_sig = tempname(10)
-        sig_file = f"{self.mpath}/signatures/sig/{src_sig}"
-        self.sigfiles.append(sig_file)
-        f = open(sig_file, "w")
+        sig_dir = f"{self.mpath}/signatures/sig/{src_sig}"
+        os.makedirs(sig_dir)
+        self.sigdirs.append(sig_dir)
+        f = open(f"{sig_dir}/sig", "w")
         f.write("A sig file")
         f.close()
-        dst = tempname(10)
-        self.sigfiles.append(f"{self.mpath}/signatures/sig/{dst}")
-        dst = dst + "@" + self.mapset_name
+        dst_name = tempname(10)
+        self.sigdirs.append(f"{self.mpath}/signatures/sig/{dst_name}")
+        dst = dst_name + "@" + self.mapset_name
         ret = I_find_signature(I_SIGFILE_TYPE_SIG, dst, self.mapset_name)
         self.assertFalse(ret)
         ret = I_find_signature(I_SIGFILE_TYPE_SIG, src_sig, self.mapset_name)
@@ -466,16 +491,18 @@ class SignaturesRenameTestCase(TestCase):
         self.assertTrue(ret)
         ms = utils.decode(ret)
         self.assertEqual(ms, self.mapset_name)
+        self.assertTrue(os.path.isfile(f"{self.mpath}/signatures/sig/{dst_name}/sig"))
 
     def test_success_unqualified_sigset(self):
         src_sigset = tempname(10)
-        sigset_file = f"{self.mpath}/signatures/sigset/{src_sigset}"
-        self.sigfiles.append(sigset_file)
-        f = open(sigset_file, "w")
+        sig_dir = f"{self.mpath}/signatures/sigset/{src_sigset}"
+        os.makedirs(sig_dir)
+        self.sigdirs.append(sig_dir)
+        f = open(f"{sig_dir}/sig", "w")
         f.write("A sigset file")
         f.close()
         dst = tempname(10)
-        self.sigfiles.append(f"{self.mpath}/signatures/sigset/{dst}")
+        self.sigdirs.append(f"{self.mpath}/signatures/sigset/{dst}")
         ret = I_find_signature(I_SIGFILE_TYPE_SIGSET, dst, self.mapset_name)
         self.assertFalse(ret)
         ret = I_find_signature(I_SIGFILE_TYPE_SIGSET, src_sigset, self.mapset_name)
@@ -486,17 +513,19 @@ class SignaturesRenameTestCase(TestCase):
         self.assertTrue(ret)
         ms = utils.decode(ret)
         self.assertEqual(ms, self.mapset_name)
+        self.assertTrue(os.path.isfile(f"{self.mpath}/signatures/sigset/{dst}/sig"))
 
     def test_success_fq_sigset(self):
         src_sigset = tempname(10)
-        sigset_file = f"{self.mpath}/signatures/sigset/{src_sigset}"
-        self.sigfiles.append(sigset_file)
-        f = open(sigset_file, "w")
+        sig_dir = f"{self.mpath}/signatures/sigset/{src_sigset}"
+        os.makedirs(sig_dir)
+        self.sigdirs.append(sig_dir)
+        f = open(f"{sig_dir}/sig", "w")
         f.write("A sigset file")
         f.close()
-        dst = tempname(10)
-        self.sigfiles.append(f"{self.mpath}/signatures/sigset/{dst}")
-        dst = dst + "@" + self.mapset_name
+        dst_name = tempname(10)
+        self.sigdirs.append(f"{self.mpath}/signatures/sigset/{dst_name}")
+        dst = dst_name + "@" + self.mapset_name
         ret = I_find_signature(I_SIGFILE_TYPE_SIGSET, dst, self.mapset_name)
         self.assertFalse(ret)
         ret = I_find_signature(I_SIGFILE_TYPE_SIGSET, src_sigset, self.mapset_name)
@@ -511,6 +540,9 @@ class SignaturesRenameTestCase(TestCase):
         self.assertTrue(ret)
         ms = utils.decode(ret)
         self.assertEqual(ms, self.mapset_name)
+        self.assertTrue(
+            os.path.isfile(f"{self.mpath}/signatures/sigset/{dst_name}/sig")
+        )
 
 
 class SignaturesListByTypeTestCase(TestCase):
@@ -519,7 +551,7 @@ class SignaturesListByTypeTestCase(TestCase):
         cls.list_ptr = ctypes.POINTER(ctypes.c_char_p)
         cls.mpath = utils.decode(G_mapset_path())
         cls.mapset_name = Mapset().name
-        cls.sigfiles = []
+        cls.sigdirs = []
         # As signatures are created directly not via signature creation
         # tools, we must ensure signature directories exist
         os.makedirs(f"{cls.mpath}/signatures/sig/", exist_ok=True)
@@ -537,11 +569,8 @@ class SignaturesListByTypeTestCase(TestCase):
     def tearDownClass(cls):
         # Remove random mapset created during setup
         shutil.rmtree(cls.rnd_mapset_path, ignore_errors=True)
-        for f in cls.sigfiles:
-            try:
-                os.remove(f)
-            except OSError:
-                pass
+        for d in cls.sigdirs:
+            shutil.rmtree(d, ignore_errors=True)
 
     def test_no_sigs_at_all(self):
         # There should be no signatures in the mapset with random
@@ -552,63 +581,78 @@ class SignaturesListByTypeTestCase(TestCase):
         )
         self.assertEqual(ret, 0)
         I_free_signatures_list(ret, ctypes.byref(sig_list))
+        ret = I_signatures_list_by_type(
+            I_SIGFILE_TYPE_SIGSET, self.rnd_mapset_name, ctypes.byref(sig_list)
+        )
+        self.assertEqual(ret, 0)
+        I_free_signatures_list(ret, ctypes.byref(sig_list))
 
     def test_sig_in_different_mapset(self):
         # Should return 0 signatures from a different mapset
+        # Sig type
         local_sig = tempname(10)
-        sig_file = f"{self.mpath}/signatures/sig/{local_sig}"
-        self.sigfiles.append(sig_file)
-        f = open(sig_file, "w")
+        sig_dir = f"{self.mpath}/signatures/sig/{local_sig}"
+        os.makedirs(sig_dir)
+        self.sigdirs.append(sig_dir)
+        f = open(f"{sig_dir}/sig", "w")
         f.write("A sig file")
         f.close()
         sig_list = self.list_ptr()
         ret = I_signatures_list_by_type(
             I_SIGFILE_TYPE_SIG, self.rnd_mapset_name, ctypes.byref(sig_list)
         )
-        os.remove(sig_file)
+        shutil.rmtree(sig_dir)
         self.assertEqual(ret, 0)
         I_free_signatures_list(ret, ctypes.byref(sig_list))
+        # SigSet type
         local_sigset = tempname(10)
-        sigset_file = f"{self.mpath}/signatures/sigset/{local_sigset}"
-        self.sigfiles.append(sigset_file)
-        f = open(sigset_file, "w")
+        sig_dir = f"{self.mpath}/signatures/sigset/{local_sigset}"
+        os.makedirs(sig_dir)
+        self.sigdirs.append(sig_dir)
+        f = open(f"{sig_dir}/sig", "w")
         f.write("A sigset file")
         f.close()
         sig_list = self.list_ptr()
         ret = I_signatures_list_by_type(
             I_SIGFILE_TYPE_SIGSET, self.rnd_mapset_name, ctypes.byref(sig_list)
         )
-        os.remove(sigset_file)
+        shutil.rmtree(sig_dir)
         self.assertEqual(ret, 0)
         I_free_signatures_list(ret, ctypes.byref(sig_list))
 
     def test_single_sig(self):
         # Case when only a single signature file is present
+        # Sig type
         rnd_sig = tempname(10)
-        sig_file = f"{self.rnd_mapset_path}/signatures/sig/{rnd_sig}"
-        f = open(sig_file, "w")
+        sig_dir = f"{self.rnd_mapset_path}/signatures/sig/{rnd_sig}"
+        os.makedirs(sig_dir)
+        self.sigdirs.append(sig_dir)
+        f = open(f"{sig_dir}/sig", "w")
         f.write("A sig file")
         f.close()
         sig_list = self.list_ptr()
         ret = I_signatures_list_by_type(
             I_SIGFILE_TYPE_SIG, self.rnd_mapset_name, ctypes.byref(sig_list)
         )
-        os.remove(sig_file)
+        shutil.rmtree(sig_dir)
         self.assertEqual(ret, 1)
         val = utils.decode(sig_list[0])
         self.assertEqual(val, f"{rnd_sig}@{self.rnd_mapset_name}")
         I_free_signatures_list(ret, ctypes.byref(sig_list))
+        # SigSet type
         # SigSet equals sig. Just testing branching inside.
         rnd_sigset = tempname(10)
-        sigset_file = f"{self.rnd_mapset_path}/signatures/sigset/{rnd_sigset}"
-        f = open(sigset_file, "w")
+        sig_dir = f"{self.rnd_mapset_path}/signatures/sigset/{rnd_sigset}"
+        os.makedirs(sig_dir)
+        self.sigdirs.append(sig_dir)
+        f = open(f"{sig_dir}/sig", "w")
         f.write("A sigset file")
         f.close()
         sigset_list = self.list_ptr()
         ret = I_signatures_list_by_type(
             I_SIGFILE_TYPE_SIGSET, self.rnd_mapset_name, ctypes.byref(sigset_list)
         )
-        os.remove(sigset_file)
+        shutil.rmtree(sig_dir)
         self.assertEqual(ret, 1)
         val = utils.decode(sigset_list[0])
         self.assertEqual(val, f"{rnd_sigset}@{self.rnd_mapset_name}")
@@ -616,14 +660,19 @@ class SignaturesListByTypeTestCase(TestCase):
 
     def test_multiple_sigs(self):
         # Should result into a multiple sigs returned
+        # Sig type
         rnd_sig1 = tempname(10)
-        sig_file1 = f"{self.rnd_mapset_path}/signatures/sig/{rnd_sig1}"
-        f = open(sig_file1, "w")
+        sig_dir1 = f"{self.rnd_mapset_path}/signatures/sig/{rnd_sig1}"
+        os.makedirs(sig_dir1)
+        self.sigdirs.append(sig_dir1)
+        f = open(f"{sig_dir1}/sig", "w")
         f.write("A sig file")
         f.close()
         rnd_sig2 = tempname(10)
-        sig_file2 = f"{self.rnd_mapset_path}/signatures/sig/{rnd_sig2}"
-        f = open(sig_file2, "w")
+        sig_dir2 = f"{self.rnd_mapset_path}/signatures/sig/{rnd_sig2}"
+        os.makedirs(sig_dir2)
+        self.sigdirs.append(sig_dir2)
+        f = open(f"{sig_dir2}/sig", "w")
         f.write("A sig file")
         f.close()
         # POINTER(POINTER(c_char))
@@ -631,8 +680,8 @@ class SignaturesListByTypeTestCase(TestCase):
         ret = I_signatures_list_by_type(
             I_SIGFILE_TYPE_SIG, self.rnd_mapset_name, ctypes.byref(sig_list)
         )
-        os.remove(sig_file1)
-        os.remove(sig_file2)
+        shutil.rmtree(sig_dir1)
+        shutil.rmtree(sig_dir2)
         self.assertEqual(ret, 2)
         golden = (
             f"{rnd_sig1}@{self.rnd_mapset_name}",
@@ -641,23 +690,27 @@ class SignaturesListByTypeTestCase(TestCase):
         self.assertIn(utils.decode(sig_list[0]), golden)
         self.assertIn(utils.decode(sig_list[1]), golden)
         I_free_signatures_list(ret, ctypes.byref(sig_list))
-        # Ditto for sigset
+        # SigSet type
         rnd_sigset1 = tempname(10)
-        sigset_file1 = f"{self.rnd_mapset_path}/signatures/sigset/{rnd_sigset1}"
-        f = open(sigset_file1, "w")
+        sig_dir1 = f"{self.rnd_mapset_path}/signatures/sigset/{rnd_sigset1}"
+        os.makedirs(sig_dir1)
+        self.sigdirs.append(sig_dir1)
+        f = open(f"{sig_dir1}/sig", "w")
         f.write("A sigset file")
         f.close()
         rnd_sigset2 = tempname(10)
-        sigset_file2 = f"{self.rnd_mapset_path}/signatures/sigset/{rnd_sigset2}"
-        f = open(sigset_file2, "w")
+        sig_dir2 = f"{self.rnd_mapset_path}/signatures/sigset/{rnd_sigset2}"
+        os.makedirs(sig_dir2)
+        self.sigdirs.append(sig_dir2)
+        f = open(f"{sig_dir2}/sig", "w")
         f.write("A sigset file")
         f.close()
         sigset_list = self.list_ptr()
         ret = I_signatures_list_by_type(
             I_SIGFILE_TYPE_SIGSET, self.rnd_mapset_name, ctypes.byref(sigset_list)
         )
-        os.remove(sigset_file1)
-        os.remove(sigset_file2)
+        shutil.rmtree(sig_dir1)
+        shutil.rmtree(sig_dir2)
         self.assertEqual(ret, 2)
         golden = (
             f"{rnd_sigset1}@{self.rnd_mapset_name}",
@@ -670,16 +723,19 @@ class SignaturesListByTypeTestCase(TestCase):
     def test_multiple_sigs_multiple_mapsets(self):
         # Test searching in multiple mapsets. Identical to SIGSET case
         rnd_sig1 = tempname(10)
-        sig_file1 = f"{self.rnd_mapset_path}/signatures/sig/{rnd_sig1}"
-        f = open(sig_file1, "w")
+        sig_dir1 = f"{self.rnd_mapset_path}/signatures/sig/{rnd_sig1}"
+        os.makedirs(sig_dir1)
+        self.sigdirs.append(sig_dir1)
+        f = open(f"{sig_dir1}/sig", "w")
         f.write("A sig file")
         f.close()
         rnd_sig2 = tempname(10)
-        sig_file2 = f"{self.mpath}/signatures/sig/{rnd_sig2}"
-        f = open(sig_file2, "w")
+        sig_dir2 = f"{self.mpath}/signatures/sig/{rnd_sig2}"
+        os.makedirs(sig_dir2)
+        self.sigdirs.append(sig_dir2)
+        f = open(f"{sig_dir2}/sig", "w")
         f.write("A sig file")
         f.close()
-        self.sigfiles.append(sig_file2)
         sig_list = self.list_ptr()
         ret = I_signatures_list_by_type(
             I_SIGFILE_TYPE_SIG, None, ctypes.byref(sig_list)
@@ -706,8 +762,8 @@ class SignaturesListByTypeTestCase(TestCase):
         )
         grass.run_command("g.mapsets", mapset=self.rnd_mapset_name, operation="remove")
         G_reset_mapsets()
-        os.remove(sig_file1)
-        os.remove(sig_file2)
+        shutil.rmtree(sig_dir1)
+        shutil.rmtree(sig_dir2)
         # There could be more sigs if this is not an empty mapset
         self.assertTrue(ret >= 2)
         ret_list = list(map(utils.decode, sig_list[:ret]))
@@ -718,16 +774,19 @@ class SignaturesListByTypeTestCase(TestCase):
     def test_multiple_sigsets_multiple_mapsets(self):
         # Test searching in multiple mapsets. Identical to SIG case
         rnd_sig1 = tempname(10)
-        sig_file1 = f"{self.rnd_mapset_path}/signatures/sigset/{rnd_sig1}"
-        f = open(sig_file1, "w")
+        sig_dir1 = f"{self.rnd_mapset_path}/signatures/sigset/{rnd_sig1}"
+        os.makedirs(sig_dir1)
+        self.sigdirs.append(sig_dir1)
+        f = open(f"{sig_dir1}/sig", "w")
         f.write("A sigset file")
         f.close()
         rnd_sig2 = tempname(10)
-        sig_file2 = f"{self.mpath}/signatures/sigset/{rnd_sig2}"
-        f = open(sig_file2, "w")
+        sig_dir2 = f"{self.mpath}/signatures/sigset/{rnd_sig2}"
+        os.makedirs(sig_dir2)
+        self.sigdirs.append(sig_dir2)
+        f = open(f"{sig_dir2}/sig", "w")
         f.write("A sigset file")
         f.close()
-        self.sigfiles.append(sig_file2)
         sig_list = self.list_ptr()
         ret = I_signatures_list_by_type(
             I_SIGFILE_TYPE_SIGSET, None, ctypes.byref(sig_list)
@@ -754,8 +813,8 @@ class SignaturesListByTypeTestCase(TestCase):
         )
         grass.run_command("g.mapsets", mapset=self.rnd_mapset_name, operation="remove")
         G_reset_mapsets()
-        os.remove(sig_file1)
-        os.remove(sig_file2)
+        shutil.rmtree(sig_dir1)
+        shutil.rmtree(sig_dir2)
         # There could be more sigs if this is not an empty mapset
         self.assertTrue(ret >= 2)
         ret_list = list(map(utils.decode, sig_list[:ret]))

+ 6 - 8
lib/imagery/testsuite/test_imagery_sigsetfile.py

@@ -11,6 +11,7 @@ for details
 import os
 import stat
 import ctypes
+import shutil
 
 from grass.gunittest.case import TestCase
 from grass.gunittest.main import test
@@ -46,14 +47,11 @@ class SigSetFileTestCase(TestCase):
         cls.mpath = utils.decode(G_mapset_path())
         cls.mapset_name = Mapset().name
         cls.sig_name = tempname(10)
-        cls.sigfile_name = f"{cls.mpath}/signatures/sigset/{cls.sig_name}"
+        cls.sig_dir = f"{cls.mpath}/signatures/sigset/{cls.sig_name}"
 
     @classmethod
     def tearDownClass(cls):
-        try:
-            os.remove(cls.sigfile_name)
-        except OSError:
-            pass
+        shutil.rmtree(cls.sig_dir, ignore_errors=True)
 
     def test_I_fopen_signature_file_old_fail(self):
         sigfile = I_fopen_sigset_file_old(tempname(10))
@@ -85,7 +83,7 @@ class SigSetFileTestCase(TestCase):
 
         # Write signatures to file
         p_new_sigfile = I_fopen_sigset_file_new(self.sig_name)
-        sig_stat = os.stat(self.sigfile_name)
+        sig_stat = os.stat(f"{self.sig_dir}/sig")
         self.assertTrue(stat.S_ISREG(sig_stat.st_mode))
         I_WriteSigSet(p_new_sigfile, ctypes.byref(So))
         self.libc.fclose(p_new_sigfile)
@@ -138,7 +136,7 @@ class SigSetFileTestCase(TestCase):
 
         # Write signatures to file
         p_new_sigfile = I_fopen_sigset_file_new(self.sig_name)
-        sig_stat = os.stat(self.sigfile_name)
+        sig_stat = os.stat(f"{self.sig_dir}/sig")
         self.assertTrue(stat.S_ISREG(sig_stat.st_mode))
         I_WriteSigSet(p_new_sigfile, ctypes.byref(So))
         self.libc.fclose(p_new_sigfile)
@@ -182,7 +180,7 @@ class SigSetFileTestCase(TestCase):
 
         # Write signatures to file
         p_new_sigfile = I_fopen_sigset_file_new(self.sig_name)
-        sig_stat = os.stat(self.sigfile_name)
+        sig_stat = os.stat(f"{self.sig_dir}/sig")
         self.assertTrue(stat.S_ISREG(sig_stat.st_mode))
         I_WriteSigSet(p_new_sigfile, ctypes.byref(So))
         self.libc.fclose(p_new_sigfile)