-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmkfile.sh
121 lines (101 loc) · 3.2 KB
/
mkfile.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/bin/sh
# (c) Mingye Wang <[email protected]>
# 2016-02-25 @ https://github.com/AOSC-Dev/scriptlets/blob/master/mkfile.sh
# (c) Steve Parker, http://steve-parker.org/
# 2010-03-19 @ http://steve-parker.org/code/sh/mkfile.sh.txt
# Licensed under the GPL Version 2
# wrapper for dd and fallocate to act like Solaris' mkfile utility.
die(){ printf 'mkfile: error: %s' "$1"; exit "${2-1}"; }
usage()
{
echo "\
Usage: mkfile [ -qnvp ] [-m MODE] [ -i INFILE ] [ -b BS ] size[bkgtpe] FILES...
mkfile -?
blocksize is 1048576 bytes by default. By default, the remainder from size%bs
is added with an additional dd pass in copy mode.
The \`b' suffix denotes block numbers; for compatibility, the default blocksize
used for this calculation is 512."
}
usage_more(){
usage
echo "Options:
-q Turn off verbose output. This is the default.
-v Turn on verbose output (looks like '{fn} {n}bytes @ {mode} -> {exit}')
-b BS Sets blocksize for copy/pipe as well as for size calculation.
-i FILE Sets the input file for dd (\`copy' mode only).
-m MODE Sets the operation mode. Possible values are:
copy dd-from-infile. Creates a regular file, slow. Default.
seek dd-seek. Creates a sparse file (bad for swap), fast. See -n.
alloc fallocate. Creates a regular file, fast.
redir printf-pat-redir. Creates a regular file, slow.
-p PAT The byte pattern to use in pipe mode. Do not use NUL bytes.
".
}
humanreadable ()
{
multiplier=1
case $1 in
*b) multiplier=$hbs ;; # blocks (tricky, right?)
*k) multiplier=$((1<<10)) ;;
*m) multiplier=$((1<<20)) ;;
*g) multiplier=$((1<<30)) ;;
# warning: extended-precision POSIX shells only (e.g. bash on amd64)
*t) multiplier=$((1<<40)) ;;
*p) multiplier=$((1<<50)) ;;
*e) multiplier=$((1<<60)) ;;
# for z and y, consider
esac
numeric=${1%[bkmgtpe]}
printf "$((multiplier * numeric))"
}
bs=1048576 # bigger, better, faster!
hbs=512 # the bs used for humanreadable, in order to respect 'mkfile'.
quiet=0
method=copy # copy/seek/alloc
noremain=0
verbose=0
keepgoing=0
INFILE=/dev/zero
while getopts 'i:b:m:qnavr?' opt
do
case $opt in
b) bs=$OPTARG hbs=$bs ;;
i) INFILE=$OPTARG;;
q) verbose=0 ;;
k) keepgoing=1 ;;
n) method=seek ;; # dd seek-only
m) method=optarg ;;
r) noremain=1 ;; # ignore (size % bs) difference
v) verbose=1 ;; # %s %llu bytes stdout; METHOD stderr; \n stdout.
\?) usage_more; exit ;;
*) usage; exit 2 ;;
esac
done
shift $((OPTIND-2))
if [ -z "$1" ]; then
die "No size specificed"
fi
if [ -z "$2" ]; then
echo "ERROR: No filename specificed"
fi
SIZE=`humanreadable $1` || die "Invalid
FILENAME="$2"
BS=`humanreadable $bs`
COUNT=`expr $SIZE / $BS`
CHECK=`expr $COUNT \* $BS`
if [ "$CHECK" -ne "$SIZE" ]; then
echo "Warning: Due to the blocksize requested, the file created will be `expr $COUNT \* $BS` bytes and not $SIZE bytes"
fi
echo -en "Creating $SIZE byte file $FILENAME...."
dd if=$INFILE bs=$BS count=$COUNT of="$FILENAME" 2>/dev/null
ddresult=$?
if [ "$quiet" -ne "1" ]; then
# We all know that you're goint to do this next - let's do it for you:
if [ "$ddresult" -eq "0" ]; then
echo "Finished:"
else
echo "An error occurred. dd returned code $ddresult."
fi
ls -l "$FILENAME" && ls -lh "$FILENAME"
fi
exit $ddresult