]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
df: support different file system encodings when not using tty
authorPádraig Brady <P@draigBrady.com>
Sun, 3 Mar 2019 22:35:18 +0000 (14:35 -0800)
committerPádraig Brady <P@draigBrady.com>
Mon, 4 Mar 2019 06:31:08 +0000 (22:31 -0800)
* src/df.c (replace_problematic_chars): A new wrapper to be
more conservative in our replacement when not connected to a tty.
* tests/df/problematic-chars.sh: Add a test case.

src/df.c
tests/df/problematic-chars.sh

index 1eb7bcd47933dbb4387dbc9404f7f54255676652..041f2820d66dc7115840780c597c52e436c7196b 100644 (file)
--- a/src/df.c
+++ b/src/df.c
@@ -23,6 +23,7 @@
 #include <sys/types.h>
 #include <getopt.h>
 #include <assert.h>
+#include <c-ctype.h>
 #include <wchar.h>
 #include <wctype.h>
 
@@ -273,10 +274,26 @@ static struct option const long_options[] =
   {NULL, 0, NULL, 0}
 };
 
+/* Replace problematic chars with '?'.
+   Since only control characters are currently considered,
+   this should work in all encodings.  */
+
+static void
+replace_control_chars (char *cell)
+{
+  char *p = cell;
+  while (*p)
+    {
+      if (c_iscntrl (to_uchar (*p)))
+        *p = '?';
+      p++;
+    }
+}
+
 /* Replace problematic chars with '?'.  */
 
 static void
-hide_problematic_chars (char *cell)
+replace_invalid_chars (char *cell)
 {
   char *srcend = cell + strlen (cell);
   char *dst = cell;
@@ -310,6 +327,17 @@ hide_problematic_chars (char *cell)
   *dst = '\0';
 }
 
+static void
+replace_problematic_chars (char *cell)
+{
+  static int tty_out = -1;
+  if (tty_out < 0)
+    tty_out = isatty (STDOUT_FILENO);
+
+  (tty_out ? replace_invalid_chars : replace_control_chars) (cell) ;
+}
+
+
 /* Dynamically allocate a row of pointers in TABLE, which
    can then be accessed with standard 2D array notation.  */
 
@@ -591,7 +619,7 @@ get_header (void)
       if (!cell)
         xalloc_die ();
 
-      hide_problematic_chars (cell);
+      replace_problematic_chars (cell);
 
       table[nrows - 1][col] = cell;
 
@@ -1205,7 +1233,7 @@ get_dev (char const *disk, char const *mount_point, char const* file,
       if (!cell)
         assert (!"empty cell");
 
-      hide_problematic_chars (cell);
+      replace_problematic_chars (cell);
       size_t cell_width = mbswidth (cell, 0);
       columns[col]->width = MAX (columns[col]->width, cell_width);
       table[nrows - 1][col] = cell;
index 34e743bdccb9b150f78b5ee6d15623f90babb833..181149f574e60fa3b0dc17005422c845a82bc853 100755 (executable)
 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
 
 . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
-print_ver_ df
+print_ver_ df printf
 require_root_
 
+
+# Ensure a new line in a mount point only outputs a single line
+
 mnt='mount
 point'
 
 cwd=$(pwd)
-cleanup_() { cd /; umount "$cwd/$mnt"; }
+cleanup_() { umount "$cwd/$mnt"; }
 
 skip=0
 # Create a file system, then mount it.
@@ -33,14 +36,30 @@ dd if=/dev/zero of=blob bs=8192 count=200 > /dev/null 2>&1 \
 mkdir "$mnt"                                 || skip=1
 mkfs -t ext2 -F blob \
   || skip_ "failed to create ext2 file system"
-
 mount -oloop blob "$mnt"                     || skip=1
-
 test $skip = 1 \
   && skip_ "insufficient mount/ext2 support"
-
 test $(df "$mnt" | wc -l) = 2 || fail=1
-
 test "$fail" = 1 && dump_mount_list_
 
+
+# Ensure mount points not matching the current user encoding are output
+
+unset LC_ALL
+f=$LOCALE_FR_UTF8
+: ${LOCALE_FR_UTF8=none}
+if test "$LOCALE_FR_UTF8" != "none"; then
+
+  cleanup_ || framework_failure_
+
+  # Create a non UTF8 mount point
+  mnt="$(env printf 'm\xf3unt p\xf3int')"
+  mkdir "$mnt" || framework_failure_
+  mount -oloop blob "$mnt" || skip_ "unable to mount $mnt"
+
+  LC_ALL=$f df --output=target "$mnt" > df.out || fail=1
+  test "$(basename "$(tail -n1 df.out)")" = "$mnt" || fail=1
+fi
+
+
 Exit $fail