From 9d308df13271a852aee7d46c65432fa84145ea31 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 9 May 2012 23:53:16 -0700 Subject: maint: handle file sizes more reliably Problem reported by Samuel Thibault in . * NEWS: Document this. * src/dd.c (skip): Handle skipping past EOF on shared or typed memory objects the same way as with regular files. (dd_copy): It's OK to truncate shared memory objects. * src/du.c (duinfo_add): Check for overflow. (print_only_size): Report overflow. (process_file): Ignore negative file sizes in the --apparent-size case. * src/od.c (skip): Fix comment about st_size. * src/split.c (main): * src/truncate.c (do_ftruncate, main): On files where st_size is not portable, fall back on using lseek with SEEK_END to determine the size. Although strictly speaking POSIX says the behavior is implementation-defined, in practice if lseek returns a nonnegative value it's a reasonable one to use for the file size. * src/system.h (usable_st_size): Symlinks have reliable st_size too. * tests/misc/truncate-dir-fail: Don't assume that getting the size of a dir is not allowed, as it's now allowed on many platforms, e.g., GNU/Linux. --- src/split.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src/split.c') diff --git a/src/split.c b/src/split.c index 062aedea9..53ee2719d 100644 --- a/src/split.c +++ b/src/split.c @@ -1069,7 +1069,7 @@ main (int argc, char **argv) static char const multipliers[] = "bEGKkMmPTYZ0"; int c; int digits_optind = 0; - off_t file_size; + off_t file_size IF_LINT (= 0); initialize_main (&argc, &argv); set_program_name (argv[0]); @@ -1340,12 +1340,18 @@ main (int argc, char **argv) if (in_blk_size == 0) in_blk_size = io_blksize (stat_buf); - /* stat.st_size is valid only for regular files. For others, use 0. */ - file_size = S_ISREG (stat_buf.st_mode) ? stat_buf.st_size : 0; - if (split_type == type_chunk_bytes || split_type == type_chunk_lines) { off_t input_offset = lseek (STDIN_FILENO, 0, SEEK_CUR); + if (usable_st_size (&stat_buf)) + file_size = stat_buf.st_size; + else if (0 <= input_offset) + { + file_size = lseek (STDIN_FILENO, 0, SEEK_END); + input_offset = (file_size < 0 + ? file_size + : lseek (STDIN_FILENO, input_offset, SEEK_SET)); + } if (input_offset < 0) error (EXIT_FAILURE, 0, _("%s: cannot determine file size"), quote (infile)); -- cgit v1.2.3-54-g00ecf