summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2018-07-24 19:16:27 -0400
committerTavian Barnes <tavianator@tavianator.com>2018-07-24 19:16:27 -0400
commit199063ab53cbae3b3be199ff902f9f2d001d1058 (patch)
treee533572ad08648917322e35a05fd1465f99bae6b
parent86f0049bff0c8c802bb07fcb52ae468608ec0920 (diff)
downloadbfs-199063ab53cbae3b3be199ff902f9f2d001d1058.tar.xz
stat: Don't assume blocks are 512 bytes
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 <sys/param.h> if available. Also, for -printf '%S', print 1 instead of NaN for empty files with no blocks.
-rw-r--r--eval.c4
-rw-r--r--printf.c14
-rw-r--r--stat.h12
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 <sys/param.h>
#include <sys/types.h>
+#include <sys/stat.h>
#include <time.h>
/**
@@ -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. */