#!/bin/sh - # # sparsecheck -- Check files for their sparseness # # Copyright (C) 2007 by Oliver Fromme # All rights reserved. Standard 2-clause BSD license and disclaimer applies. # # Usage: sparsecheck [ ... | ...] # # For every file given on the command line, one line is printed: # # # # For example: # # = 100.00% 149708196 testboot.iso.gz # < 35.04% 261844112 torrent-download.tar.bz2 # # is a single character: "<" if the file is sparse, else "=". # is the percentage of file allocation. 100% if not sparse. # is the (logical) size of the file in bytes. # is the file name. # # Only plain files are displayed, because other types of files cannot # be sparse. If directory names are given on the command line, the # files in those directories are examined. If nothing is given at # all, the files in the current directory are examined. # # Note: This script assumes a UFS block size of 16 KB, # which is the default on FreeBSD for several years. # Tested on FreeBSD 4 (UFS1) and FreeBSD 6 (UFS2). # # if [ $# -gt 0 ]; then find "$@" -depth -2 -type f -print0 else find . -depth 1 -type f -print0 fi \ | xargs -0 stat -f '%Hp %z %b %N' -- \ | awk ' BEGIN { bsize = 16 * 1024 blkfac = bsize / 512 i1limit = 12 i1multi = 2048 i2limit = i1limit + i1multi i2multi = i1multi * i1multi } # # The following function calculates the number of blocks # required for alloacting bytes. This formular has # been tested with UFS and UFS2 and should work with files # up to 64 GB. Beyond that it might be off by one block, # but I have not been able to test that (it should not # matter much anyway, because the difference is way below # 0.01%). # function BlkAlloc(s) { b = int((s + bsize - 1) / bsize) if (b > i1limit) { i = int((b - i1limit) / i1multi) + 1 if (b > i2limit) i += int((b - i2limit) / i2multi) + 1 return b + i } else return b } { if ($1 != "10") next nam = $0 sub(/^[^ ]+ [^ ]+ [^ ]+ /, "", nam) siz = $2 blk = int(($3 + blkfac - 1) / blkfac) epc = BlkAlloc(siz) if (epc) per = (blk * 100) / epc else per = 100 printf "%s %6.2f%% %11d %s\n", (blk < epc) ? "<" : "=", per, siz, nam } ' #--