From 199063ab53cbae3b3be199ff902f9f2d001d1058 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 24 Jul 2018 19:16:27 -0400 Subject: stat: Don't assume blocks are 512 bytes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit POSIX says > The unit for the st_blocks member of the stat structure is not defined > within POSIX.1‐2008. and recommends using DEV_BSIZE from if available. Also, for -printf '%S', print 1 instead of NaN for empty files with no blocks. --- eval.c | 4 ++-- printf.c | 14 +++++++++++--- stat.h | 12 +++++++++++- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/eval.c b/eval.c index ff81e92..6731b31 100644 --- a/eval.c +++ b/eval.c @@ -626,7 +626,7 @@ bool eval_fls(const struct expr *expr, struct eval_state *state) { } uintmax_t ino = statbuf->ino; - uintmax_t blocks = (statbuf->blocks + 1)/2; + uintmax_t blocks = ((uintmax_t)statbuf->blocks*BFS_STAT_BLKSIZE + 1023)/1024; char mode[11]; format_mode(statbuf->mode, mode); uintmax_t nlink = statbuf->nlink; @@ -886,7 +886,7 @@ bool eval_sparse(const struct expr *expr, struct eval_state *state) { return false; } - blkcnt_t expected = (statbuf->size + 511)/512; + blkcnt_t expected = (statbuf->size + BFS_STAT_BLKSIZE - 1)/BFS_STAT_BLKSIZE; return statbuf->blocks < expected; } diff --git a/printf.c b/printf.c index 6a87f99..0e9110e 100644 --- a/printf.c +++ b/printf.c @@ -184,7 +184,8 @@ static int bfs_printf_strftime(FILE *file, const struct bfs_printf_directive *di /** %b: blocks */ static int bfs_printf_b(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)ftwbuf->statbuf->blocks); + uintmax_t blocks = ((uintmax_t)ftwbuf->statbuf->blocks*BFS_STAT_BLKSIZE + 511)/512; + BFS_PRINTF_BUF(buf, "%ju", blocks); return fprintf(file, directive->str, buf); } @@ -266,7 +267,8 @@ static int bfs_printf_i(FILE *file, const struct bfs_printf_directive *directive /** %k: 1K blocks */ static int bfs_printf_k(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)(ftwbuf->statbuf->blocks + 1)/2); + uintmax_t blocks = ((uintmax_t)ftwbuf->statbuf->blocks*BFS_STAT_BLKSIZE + 1023)/1024; + BFS_PRINTF_BUF(buf, "%ju", blocks); return fprintf(file, directive->str, buf); } @@ -326,7 +328,13 @@ static int bfs_printf_s(FILE *file, const struct bfs_printf_directive *directive /** %S: sparseness */ static int bfs_printf_S(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - double sparsity = 512.0 * ftwbuf->statbuf->blocks / ftwbuf->statbuf->size; + double sparsity; + const struct bfs_stat *sb = ftwbuf->statbuf; + if (sb->size == 0 && sb->blocks == 0) { + sparsity = 1.0; + } else { + sparsity = (double)BFS_STAT_BLKSIZE*sb->blocks/sb->size; + } return fprintf(file, directive->str, sparsity); } diff --git a/stat.h b/stat.h index d47d248..95c61ec 100644 --- a/stat.h +++ b/stat.h @@ -17,7 +17,9 @@ #ifndef BFS_STAT_H #define BFS_STAT_H +#include #include +#include #include /** @@ -47,6 +49,14 @@ enum bfs_stat_flag { BFS_STAT_BROKEN_OK = 1 << 0, }; +#ifdef DEV_BSIZE +# define BFS_STAT_BLKSIZE DEV_BSIZE +#elif defined(S_BLKSIZE) +# define BFS_STAT_BLKSIZE S_BLKSIZE +#else +# define BFS_STAT_BLKSIZE 512 +#endif + /** * Facade over struct stat. */ @@ -68,7 +78,7 @@ struct bfs_stat { uid_t uid; /** File size in bytes. */ off_t size; - /** Number of 512B blocks allocated. */ + /** Number of disk blocks allocated (of size BFS_STAT_BLKSIZE). */ blkcnt_t blocks; /** Access time. */ -- cgit v1.2.3