Sfoglia il codice sorgente

i.group: fit long names to fancy file listing (#1818)

Addresses failure to list files with long names and
-Wformat-overflow= warnings.

There are two ways to list files in a group with i.group, a fancy one
with -l and a raw one with -lg. The fancy one is limited to a 80
character column, with angle bracket format: <mapname@mapset>. Before
this commit, if this "fancy" formatted string would exceed 80 char,
then buffer overflow occurs. With this commit, in the rare (theoretical)
occasion with very long mapname and/or mapset, they may be truncated
if needed (to fit in 80 chars).

Example of truncation in case of long map name:

ifonlythisisalandsatfilewithaveryverylongnameandagainifonlythisisalandsatfilewithaveryverylongnamePERMANENT

becomes:
<ifonlythisisalandsatfilewithaveryverylongnameandagainifonly...@PERMANENT>
nilason 3 anni fa
parent
commit
4c7db5b215
3 ha cambiato i file con 93 aggiunte e 56 eliminazioni
  1. 1 0
      include/grass/defs/imagery.h
  2. 64 28
      lib/imagery/list_gp.c
  3. 28 28
      lib/imagery/list_subgp.c

+ 1 - 0
include/grass/defs/imagery.h

@@ -100,6 +100,7 @@ int I_iclass_write_signatures(struct Signature *, const char *);
 /* list_gp.c */
 /* list_gp.c */
 int I_list_group(const char *, const struct Ref *, FILE *);
 int I_list_group(const char *, const struct Ref *, FILE *);
 int I_list_group_simple(const struct Ref *, FILE *);
 int I_list_group_simple(const struct Ref *, FILE *);
+void I__list_group_name_fit(char *, const char *, const char *);
 
 
 /* list_subgp.c */
 /* list_subgp.c */
 char ** I_list_subgroups(const char *, int *);
 char ** I_list_subgroups(const char *, int *);

+ 64 - 28
lib/imagery/list_gp.c

@@ -1,15 +1,15 @@
 /*!
 /*!
-  \file list_gp.c
-  
-  \brief Imagery Library - List group
-  
-  (C) 2001-2008 by the GRASS Development Team
-  
-  This program is free software under the GNU General Public License
-  (>=v2). Read the file COPYING that comes with GRASS for details.
-  
-  \author USA CERL
-*/
+   \file list_gp.c
+
+   \brief Imagery Library - List group
+
+   (C) 2001-2008 by the GRASS Development Team
+
+   This program is free software under the GNU General Public License
+   (>=v2). Read the file COPYING that comes with GRASS for details.
+
+   \author USA CERL
+ */
 
 
 #include <string.h>
 #include <string.h>
 #include <grass/imagery.h>
 #include <grass/imagery.h>
@@ -31,30 +31,31 @@ int I_list_group(const char *group, const struct Ref *ref, FILE * fd)
     int max;
     int max;
 
 
     if (ref->nfiles <= 0) {
     if (ref->nfiles <= 0) {
-	fprintf(fd, _("group <%s> is empty\n"), group);
-	return 0;
+        fprintf(fd, _("group <%s> is empty\n"), group);
+        return 0;
     }
     }
     max = 0;
     max = 0;
     for (i = 0; i < ref->nfiles; i++) {
     for (i = 0; i < ref->nfiles; i++) {
-	sprintf(buf, "<%s@%s>", ref->file[i].name, ref->file[i].mapset);
-	len = strlen(buf) + 4;
-	if (len > max)
-	    max = len;
+        I__list_group_name_fit(buf, ref->file[i].name, ref->file[i].mapset);
+        len = strlen(buf) + 4;
+        if (len > max)
+            max = len;
     }
     }
-    fprintf(fd, _("group <%s> references the following raster maps\n"), group);
+    fprintf(fd, _("group <%s> references the following raster maps\n"),
+            group);
     fprintf(fd, "-------------\n");
     fprintf(fd, "-------------\n");
     tot_len = 0;
     tot_len = 0;
     for (i = 0; i < ref->nfiles; i++) {
     for (i = 0; i < ref->nfiles; i++) {
-	sprintf(buf, "<%s@%s>", ref->file[i].name, ref->file[i].mapset);
-	tot_len += max;
-	if (tot_len > 78) {
-	    fprintf(fd, "\n");
-	    tot_len = max;
-	}
-	fprintf(fd, "%-*s", max, buf);
+        I__list_group_name_fit(buf, ref->file[i].name, ref->file[i].mapset);
+        tot_len += max;
+        if (tot_len > 78) {
+            fprintf(fd, "\n");
+            tot_len = max;
+        }
+        fprintf(fd, "%-*s", max, buf);
     }
     }
     if (tot_len)
     if (tot_len)
-	fprintf(fd, "\n");
+        fprintf(fd, "\n");
     fprintf(fd, "-------------\n");
     fprintf(fd, "-------------\n");
 
 
     return 0;
     return 0;
@@ -75,10 +76,45 @@ int I_list_group_simple(const struct Ref *ref, FILE * fd)
     int i;
     int i;
 
 
     if (ref->nfiles <= 0)
     if (ref->nfiles <= 0)
-	return 0;
+        return 0;
 
 
     for (i = 0; i < ref->nfiles; i++)
     for (i = 0; i < ref->nfiles; i++)
-	fprintf(fd, "%s@%s\n", ref->file[i].name, ref->file[i].mapset);
+        fprintf(fd, "%s@%s\n", ref->file[i].name, ref->file[i].mapset);
 
 
     return 0;
     return 0;
 }
 }
+
+/*!
+ * \brief Formats map name to fit in a 80 column layout
+ *
+ * Results in a map name in the "<map@mapset>" form.
+ * If necessary truncates relevant part(s) and denotes
+ * with ellipsis, e.g. "<verylongmapname...@mapset>".
+ *
+ * \param[out] buf formatted map name
+ * \param name map name
+ * \param mapset mapset name
+ */
+void I__list_group_name_fit(char *buf, const char *name, const char *mapset)
+{
+    char *frmt;
+    char fr[32];
+    int name_length = (int)strlen(name);
+    int mapset_length = (int)strlen(mapset);
+
+    if (name_length + mapset_length + 3 < 75) {
+        frmt = "<%s@%s>";
+    }
+    else if (name_length > 35 && mapset_length > 35) {
+        frmt = "<%.33s...@%.32s...>";
+    }
+    else if (name_length > 35) {
+        sprintf(fr, "<%%.%ds...@%%s>", 68 - mapset_length);
+        frmt = fr;
+    }
+    else {
+        sprintf(fr, "<%%s@%%.%ds...>", 68 - name_length);
+        frmt = fr;
+    }
+    snprintf(buf, 75, frmt, name, mapset);
+}

+ 28 - 28
lib/imagery/list_subgp.c

@@ -17,8 +17,8 @@
 
 
 char **list_subgroups(const char *group, const char *mapset, int *subgs_num)
 char **list_subgroups(const char *group, const char *mapset, int *subgs_num)
 {
 {
-    /* Unlike I_list_subgroup and I_list_subgroup_simple this function 
-       returns array of subgroup names, it does not use fprintf. 
+    /* Unlike I_list_subgroup and I_list_subgroup_simple this function
+       returns array of subgroup names, it does not use fprintf.
        This approach should make the function usable in more cases. */
        This approach should make the function usable in more cases. */
 
 
     char **subgs;
     char **subgs;
@@ -29,13 +29,13 @@ char **list_subgroups(const char *group, const char *mapset, int *subgs_num)
     *subgs_num = 0;
     *subgs_num = 0;
 
 
     if (I_find_group2(group, mapset) == 0)
     if (I_find_group2(group, mapset) == 0)
-	return NULL;
+        return NULL;
 
 
     sprintf(buf, "group/%s/subgroup", group);
     sprintf(buf, "group/%s/subgroup", group);
     G_file_name(path, buf, "", mapset);
     G_file_name(path, buf, "", mapset);
 
 
     if (G_lstat(path, &sb) || !S_ISDIR(sb.st_mode))
     if (G_lstat(path, &sb) || !S_ISDIR(sb.st_mode))
-	return NULL;
+        return NULL;
 
 
     subgs = G_ls2(path, subgs_num);
     subgs = G_ls2(path, subgs_num);
     return subgs;
     return subgs;
@@ -43,7 +43,7 @@ char **list_subgroups(const char *group, const char *mapset, int *subgs_num)
 
 
 /*!
 /*!
  * \brief Get list of subgroups which a group contatins.
  * \brief Get list of subgroups which a group contatins.
- *  
+ *
  * \param group group name
  * \param group group name
  * \param[out] subgs_num number of subgroups which the group contains
  * \param[out] subgs_num number of subgroups which the group contains
  * \return array of subgroup names
  * \return array of subgroup names
@@ -51,20 +51,21 @@ char **list_subgroups(const char *group, const char *mapset, int *subgs_num)
 
 
 char **I_list_subgroups(const char *group, int *subgs_num)
 char **I_list_subgroups(const char *group, int *subgs_num)
 {
 {
-    
+
     return list_subgroups(group, G_mapset(), subgs_num);
     return list_subgroups(group, G_mapset(), subgs_num);
 }
 }
 
 
 /*!
 /*!
  * \brief Get list of subgroups which a group contatins.
  * \brief Get list of subgroups which a group contatins.
- *  
+ *
  * \param group group name
  * \param group group name
  * \param mapset mapset name
  * \param mapset mapset name
  * \param[out] subgs_num number of subgroups which the group contains
  * \param[out] subgs_num number of subgroups which the group contains
  * \return array of subgroup names
  * \return array of subgroup names
  */
  */
 
 
-char **I_list_subgroups2(const char *group, const char *mapset, int *subgs_num)
+char **I_list_subgroups2(const char *group, const char *mapset,
+                         int *subgs_num)
 {
 {
     return list_subgroups(group, mapset, subgs_num);
     return list_subgroups(group, mapset, subgs_num);
 }
 }
@@ -78,8 +79,8 @@ char **I_list_subgroups2(const char *group, const char *mapset, int *subgs_num)
  * \param fd where to print (typically stdout)
  * \param fd where to print (typically stdout)
  * \return 0
  * \return 0
  */
  */
-int I_list_subgroup(const char *group,
-		    const char *subgroup, const struct Ref *ref, FILE * fd)
+int I_list_subgroup(const char *group, const char *subgroup,
+                    const struct Ref *ref, FILE * fd)
 {
 {
     char buf[80];
     char buf[80];
     int i;
     int i;
@@ -87,34 +88,33 @@ int I_list_subgroup(const char *group,
     int max;
     int max;
 
 
     if (ref->nfiles <= 0) {
     if (ref->nfiles <= 0) {
-	fprintf(fd, _("subgroup <%s> of group <%s> is empty\n"),
-		subgroup, group);
-	return 0;
+        fprintf(fd, _("subgroup <%s> of group <%s> is empty\n"),
+                subgroup, group);
+        return 0;
     }
     }
     max = 0;
     max = 0;
     for (i = 0; i < ref->nfiles; i++) {
     for (i = 0; i < ref->nfiles; i++) {
-	sprintf(buf, "<%s@%s>", ref->file[i].name, ref->file[i].mapset);
-	len = strlen(buf) + 4;
-	if (len > max)
-	    max = len;
+        I__list_group_name_fit(buf, ref->file[i].name, ref->file[i].mapset);
+        len = strlen(buf) + 4;
+        if (len > max)
+            max = len;
     }
     }
     fprintf(fd,
     fprintf(fd,
-	    _
-	    ("subgroup <%s> of group <%s> references the following raster maps\n"),
-	    subgroup, group);
+            _("subgroup <%s> of group <%s> references the following raster maps\n"),
+            subgroup, group);
     fprintf(fd, "-------------\n");
     fprintf(fd, "-------------\n");
     tot_len = 0;
     tot_len = 0;
     for (i = 0; i < ref->nfiles; i++) {
     for (i = 0; i < ref->nfiles; i++) {
-	sprintf(buf, "<%s@%s>", ref->file[i].name, ref->file[i].mapset);
-	tot_len += max;
-	if (tot_len > 78) {
-	    fprintf(fd, "\n");
-	    tot_len = max;
-	}
-	fprintf(fd, "%-*s", max, buf);
+        I__list_group_name_fit(buf, ref->file[i].name, ref->file[i].mapset);
+        tot_len += max;
+        if (tot_len > 78) {
+            fprintf(fd, "\n");
+            tot_len = max;
+        }
+        fprintf(fd, "%-*s", max, buf);
     }
     }
     if (tot_len)
     if (tot_len)
-	fprintf(fd, "\n");
+        fprintf(fd, "\n");
     fprintf(fd, "-------------\n");
     fprintf(fd, "-------------\n");
 
 
     return 0;
     return 0;