summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2011-11-11 23:21:13 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2011-11-11 23:21:50 -0800
commit448718c123838891500afa7fbda06335e7258592 (patch)
tree8c0bb1d206db461f72cd4a192e0a439d980466c9
parent1d9fe527a0ff85ca757a74338c5f1b523473b377 (diff)
downloadcoreutils-448718c123838891500afa7fbda06335e7258592.tar.xz
ls: -k no longer affects -l's file sizes
This fixes an incompatibility with POSIX 2008 and with BSD. Problem reported by Abdallah Clark (Bug#9939) via Alan Curry (Bug#10016). * NEWS: Document this. * doc/coreutils.texi (General output formatting): Document the new -k behavior, and --kibibytes. * src/ls.c (file_human_output_opts): New static var. (long_options, usage): Add --kibibytes. (decode_switches, gobble_file, print_long_format): Implement the new -k behavior. * tests/ls/block-size: New file. * tests/Makefile.am (TESTS): Add it.
-rw-r--r--NEWS7
-rw-r--r--doc/coreutils.texi15
-rw-r--r--src/ls.c51
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/ls/block-size173
5 files changed, 226 insertions, 21 deletions
diff --git a/NEWS b/NEWS
index 081989dd4..1b0f2f5e9 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,13 @@ GNU coreutils NEWS -*- outline -*-
** Bug fixes
+ ls's -k option no longer affects how ls -l outputs file sizes.
+ It now affects only the per-directory block counts written by -l,
+ and the sizes written by -s. This is for compatibility with BSD
+ and with POSIX 2008. Because -k is no longer equivalent to
+ --block-size=1KiB, a new long option --kibibyte stands for -k.
+ [bug introduced in coreutils-4.5.4]
+
rm -rf DIR would fail with "Device or resource busy" on Cygwin with NWFS
and NcFsd file systems. This did not affect Unix/Linux-based kernels.
[bug introduced in coreutils-8.0, when rm began using fts]
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 2c33fe8b5..453144046 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -7127,10 +7127,19 @@ Append @samp{*} for executable regular files, otherwise behave as for
@end table
@item -k
+@itemx --kibibytes
@opindex -k
-Print file sizes in 1024-byte blocks, overriding the default block
-size (@pxref{Block size}).
-This option is equivalent to @option{--block-size=1K}.
+@opindex --kibibytes
+Set the default block size to its normal value of 1024 bytes,
+overriding any contrary specification in environment variables
+(@pxref{Block size}). This option is in turn overridden by the
+@option{--block-size}, @option{-h} or @option{--human-readable}, and
+@option{--si} options.
+
+The @option{-k} or @option{--kibibytes} option affects the
+per-directory block count written by the @option{-l} and similar
+options, and the size written by the @option{-s} or @option{--size}
+option. It does not affect the file size written by @option{-l}.
@item -m
@itemx --format=commas
diff --git a/src/ls.c b/src/ls.c
index 1b0c250d7..b8a09b3df 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -479,13 +479,14 @@ static bool numeric_ids;
static bool print_block_size;
-/* Human-readable options for output. */
+/* Human-readable options for output, when printing block counts. */
static int human_output_opts;
-/* The units to use when printing sizes other than file sizes. */
+/* The units to use when printing block counts. */
static uintmax_t output_block_size;
/* Likewise, but for file sizes. */
+static int file_human_output_opts;
static uintmax_t file_output_block_size = 1;
/* Follow the output with a special string. Using this format,
@@ -809,6 +810,7 @@ static struct option const long_options[] =
GROUP_DIRECTORIES_FIRST_OPTION},
{"human-readable", no_argument, NULL, 'h'},
{"inode", no_argument, NULL, 'i'},
+ {"kibibytes", no_argument, NULL, 'k'},
{"numeric-uid-gid", no_argument, NULL, 'n'},
{"no-group", no_argument, NULL, 'G'},
{"hide-control-chars", no_argument, NULL, 'q'},
@@ -1512,8 +1514,8 @@ decode_switches (int argc, char **argv)
{
char *time_style_option = NULL;
- /* Record whether there is an option specifying sort type. */
bool sort_type_specified = false;
+ bool kibibytes_specified = false;
qmark_funny_chars = false;
@@ -1582,14 +1584,6 @@ decode_switches (int argc, char **argv)
}
}
- {
- char const *ls_block_size = getenv ("LS_BLOCK_SIZE");
- human_options (ls_block_size,
- &human_output_opts, &output_block_size);
- if (ls_block_size || getenv ("BLOCK_SIZE"))
- file_output_block_size = output_block_size;
- }
-
line_length = 80;
{
char const *p = getenv ("COLUMNS");
@@ -1689,7 +1683,8 @@ decode_switches (int argc, char **argv)
break;
case 'h':
- human_output_opts = human_autoscale | human_SI | human_base_1024;
+ file_human_output_opts = human_output_opts =
+ human_autoscale | human_SI | human_base_1024;
file_output_block_size = output_block_size = 1;
break;
@@ -1698,8 +1693,7 @@ decode_switches (int argc, char **argv)
break;
case 'k':
- human_output_opts = 0;
- file_output_block_size = output_block_size = 1024;
+ kibibytes_specified = true;
break;
case 'l':
@@ -1937,12 +1931,14 @@ decode_switches (int argc, char **argv)
&output_block_size);
if (e != LONGINT_OK)
xstrtol_fatal (e, oi, 0, long_options, optarg);
+ file_human_output_opts = human_output_opts;
file_output_block_size = output_block_size;
}
break;
case SI_OPTION:
- human_output_opts = human_autoscale | human_SI;
+ file_human_output_opts = human_output_opts =
+ human_autoscale | human_SI;
file_output_block_size = output_block_size = 1;
break;
@@ -1959,6 +1955,23 @@ decode_switches (int argc, char **argv)
}
}
+ if (! output_block_size)
+ {
+ char const *ls_block_size = getenv ("LS_BLOCK_SIZE");
+ human_options (ls_block_size,
+ &human_output_opts, &output_block_size);
+ if (ls_block_size || getenv ("BLOCK_SIZE"))
+ {
+ file_human_output_opts = human_output_opts;
+ file_output_block_size = output_block_size;
+ }
+ if (kibibytes_specified)
+ {
+ human_output_opts = 0;
+ output_block_size = 1024;
+ }
+ }
+
max_idx = MAX (1, line_length / MIN_COLUMN_WIDTH);
filename_quoting_options = clone_quoting_options (NULL);
@@ -3025,7 +3038,8 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
{
char buf[LONGEST_HUMAN_READABLE + 1];
uintmax_t size = unsigned_file_size (f->stat.st_size);
- int len = mbswidth (human_readable (size, buf, human_output_opts,
+ int len = mbswidth (human_readable (size, buf,
+ file_human_output_opts,
1, file_output_block_size),
0);
if (file_size_width < len)
@@ -3767,7 +3781,8 @@ print_long_format (const struct fileinfo *f)
(! f->stat_ok
? "?"
: human_readable (unsigned_file_size (f->stat.st_size),
- hbuf, human_output_opts, 1, file_output_block_size));
+ hbuf, file_human_output_opts, 1,
+ file_output_block_size));
int pad;
for (pad = file_size_width - mbswidth (size, 0); 0 < pad; pad--)
*p++ = ' ';
@@ -4672,7 +4687,7 @@ Mandatory arguments to long options are mandatory for short options too.\n\
-i, --inode print the index number of each file\n\
-I, --ignore=PATTERN do not list implied entries matching shell PATTERN\
\n\
- -k like --block-size=1K\n\
+ -k, --kibibytes use 1024-byte blocks\n\
"), stdout);
fputs (_("\
-l use a long listing format\n\
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5021c1844..64366a491 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -415,6 +415,7 @@ TESTS = \
ln/slash-decorated-nonexistent-dest \
ln/target-1 \
ls/abmon-align \
+ ls/block-size \
ls/color-clear-to-eol \
ls/color-dtype-dir \
ls/color-norm \
diff --git a/tests/ls/block-size b/tests/ls/block-size
new file mode 100644
index 000000000..16ede04b7
--- /dev/null
+++ b/tests/ls/block-size
@@ -0,0 +1,173 @@
+#!/bin/sh
+# Exercise ls --block-size and related options.
+
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../src
+print_ver_ ls
+
+TZ=UTC0
+export TZ
+
+mkdir sub
+cd sub
+
+for size in 1024 4096 262144; do
+ echo foo | dd conv=sync bs=$size >file$size || fail=1
+done
+touch -d '2001-01-01 00:00' file* || fail=1
+
+size_etc='s/[^ ]* *[^ ]* *[^ ]* *[^ ]* *//'
+
+ls -l * | sed "$size_etc" >../out || fail=1
+POSIXLY_CORRECT=1 ls -l * | sed "$size_etc" >>../out || fail=1
+POSIXLY_CORRECT=1 ls -k -l * | sed "$size_etc" >>../out || fail=1
+
+for var in BLOCKSIZE BLOCK_SIZE LS_BLOCK_SIZE; do
+ for blocksize in 1 512 1K 1KiB; do
+ (eval $var=$blocksize && export $var &&
+ ls -l * &&
+ ls -l -k * &&
+ ls -l -k --block-size=$blocksize *
+ ) | sed "$size_etc" >>../out || fail=1
+ done
+done
+
+cd ..
+
+cat >exp <<'EOF'
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+2 Jan 1 2001 file1024
+512 Jan 1 2001 file262144
+8 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1 Jan 1 2001 file1024
+256 Jan 1 2001 file262144
+4 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1 Jan 1 2001 file1024
+256 Jan 1 2001 file262144
+4 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+2 Jan 1 2001 file1024
+512 Jan 1 2001 file262144
+8 Jan 1 2001 file4096
+2 Jan 1 2001 file1024
+512 Jan 1 2001 file262144
+8 Jan 1 2001 file4096
+2 Jan 1 2001 file1024
+512 Jan 1 2001 file262144
+8 Jan 1 2001 file4096
+1 Jan 1 2001 file1024
+256 Jan 1 2001 file262144
+4 Jan 1 2001 file4096
+1 Jan 1 2001 file1024
+256 Jan 1 2001 file262144
+4 Jan 1 2001 file4096
+1 Jan 1 2001 file1024
+256 Jan 1 2001 file262144
+4 Jan 1 2001 file4096
+1 Jan 1 2001 file1024
+256 Jan 1 2001 file262144
+4 Jan 1 2001 file4096
+1 Jan 1 2001 file1024
+256 Jan 1 2001 file262144
+4 Jan 1 2001 file4096
+1 Jan 1 2001 file1024
+256 Jan 1 2001 file262144
+4 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+1024 Jan 1 2001 file1024
+262144 Jan 1 2001 file262144
+4096 Jan 1 2001 file4096
+2 Jan 1 2001 file1024
+512 Jan 1 2001 file262144
+8 Jan 1 2001 file4096
+2 Jan 1 2001 file1024
+512 Jan 1 2001 file262144
+8 Jan 1 2001 file4096
+2 Jan 1 2001 file1024
+512 Jan 1 2001 file262144
+8 Jan 1 2001 file4096
+1 Jan 1 2001 file1024
+256 Jan 1 2001 file262144
+4 Jan 1 2001 file4096
+1 Jan 1 2001 file1024
+256 Jan 1 2001 file262144
+4 Jan 1 2001 file4096
+1 Jan 1 2001 file1024
+256 Jan 1 2001 file262144
+4 Jan 1 2001 file4096
+1 Jan 1 2001 file1024
+256 Jan 1 2001 file262144
+4 Jan 1 2001 file4096
+1 Jan 1 2001 file1024
+256 Jan 1 2001 file262144
+4 Jan 1 2001 file4096
+1 Jan 1 2001 file1024
+256 Jan 1 2001 file262144
+4 Jan 1 2001 file4096
+EOF
+
+compare out exp || fail=1
+
+Exit $fail