builddisk
9.03 KB
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
#!/usr/local/bin/perl5 -w
#
# This program generates a command script for the 'mkfs' utility.
# It adds two significant features:
#
# - hides the challenging, unforgiving mkfs command syntax
# - directory expansion, either single-level or recursive
#
#
# See the companion file 'commented-profile.bld' for input description.
open(STDOUT, ">$ARGV[1]") if $ARGV[1];
select(STDOUT); $| = 1; # To unbuffer output. Useful for debugging.
$block_count = 0;
$default_size = 100000;
sub convertPerm {
my(@perm) = split('', $_[0]);
my($octal) = 0;
my($i);
@perm = reverse(@perm);
for ($i = 0; $i < 3; $i++) {
$octal += 2 ** $i if $perm[$i] ne '-';
}
$octal;
}
#
# code from here to the end rewritten by jchapin to allow
# relocating directories, and excluding directories and their
# children from the middle of a recursive tree descent, and creating
# directories on new fs that don't exist on old fs.
# See main for new input format.
#
# Subtle, important change due to this: we now iterate over
# TARGET files, not files in the source file system, except when
# processing the contents of a directory.
#
# output_from_local and output_no_local print an output line
# and answer whether the output was a directory or not. Side effect
# is to increment block_count.
sub output_from_local {
my($targetbase) = $_[0];
my($fulllocal) = $_[1];
my(@lsEntry) = split(/[ ,]+/, " " . $_[2]);
# add space so all lines will have
# initial spaces and indexes will work
my($tabs) = $_[3];
# workaround a bizarre bug: cannot output filenames starting with :
# because it is the comment character
if ($targetbase =~ /^:/o) {
print STDERR "Cannot output $targetbase ($fulllocal) initial ':'.\n";
return 0;
}
my(@perm) = unpack("aa3a3a3", $lsEntry[2]); # parse permissions
my($type) = $perm[0];
my($major,$minor);
if ($type =~ /[cb]/) { # character or block dev file
$major = $lsEntry[6];
$minor = $lsEntry[7];
}
$setuid = ($perm[1] =~ /[sS]/ ? 'u' : '-'); # set if setuid or setgid
$setgid = ($perm[2] =~ /[sS]/ ? 'g' : '-'); # bits are set
print " " x $tabs;
print "$targetbase ", $type, $setuid, $setgid;
print &convertPerm($perm[1]), &convertPerm($perm[2]),
&convertPerm($perm[3]), " $lsEntry[4] $lsEntry[5]";
if ($type =~ /[cb]/) {
print " $major $minor";
} elsif ($type eq 'l') {
print " $lsEntry[12]";
} elsif ($type eq '-') {
print " $fulllocal";
}
$block_count += $lsEntry[1];
print "\n";
return ($type eq 'd');
}
sub output_no_local {
my($targetbase) = $_[0];
my($action) = $_[1];
my($linkfield) = $_[2];
my($tabs) = $_[3];
if ($targetbase =~ /^:/o) {
print STDERR "Cannot output target $targetbase -- initial ':'.\n";
return 0;
}
print " " x $tabs;
if ($action eq "e") {
print "$targetbase d--755 0 0\n";
} elsif ($action eq "n") {
print "$targetbase ---644 0 0 /dev/null\n";
} elsif ($action eq "l") {
print "$targetbase l--644 0 0 $linkfield\n";
} else {
die "bad output_no_local: $targetbase $action $linkfield $tabs\n";
}
# assume one block for each directory, link, empty file
$block_count += 1;
return ($action eq "e");
}
sub filename {
my(@lsEntry) = split(/[ ,]+/, " " . $_[0]);
my(@perm) = unpack("aa3a3a3", $lsEntry[2]); # parse permissions
my($type) = $perm[0];
if ($type =~ /[cb]/o) {
return $lsEntry[11];
} else {
return $lsEntry[10];
}
}
sub extend_name {
my($path) = $_[0];
my($base) = $_[1];
if ($path eq "/") {
return $path . $base;
} else {
return $path . "/" . $base;
}
}
sub output_dir {
my($fulltarget) = $_[0];
my($fulllocal) = $_[1];
my($action) = $_[2];
my($tabs) = $_[3];
if ($action eq "r" || $action eq "a") {
# need to expand filenames. Only process those names not
# explicitly specified in input spec.
if (-d $fulllocal) {
my(@listing) = `/bin/ls -Anls $fulllocal`;
foreach $line (@listing[1..$#listing]) {
chomp($line);
my($childname) = &filename($line);
#print "Processing $childname\n";
my($targetchildname) = &extend_name($fulltarget, $childname);
my($localchildname) = &extend_name($fulllocal, $childname);
if (! $what{$targetchildname}) {
if (-r $localchildname || ! -f $localchildname) {
my($was_directory) = &output_from_local($childname,
$localchildname,
$line, $tabs);
if ($was_directory) {
if ($action eq "r") {
&output_dir($targetchildname,
$localchildname,
$action,
$tabs+1);
}
print " " x ($tabs+1), "\$\n";
}
} else {
print STDERR "$localchildname unreadable, skipped\n";
}
}
}
}
}
# now process explicitly specified child directories and files
if ($fulltarget && $children{$fulltarget}) {
#print STDERR "###$fulltarget\n$children{$fulltarget}####\n";
my(@listing) = split(/\s+/o, $children{$fulltarget});
foreach $line (@listing) {
#if( defined $line ) {
# print STDERR "%%% $line DO $what{$line} %%%\n";
#} else {
# print "Line UNDEF!\n";
# print STDERR "###$fulltarget\n$children{$fulltarget}####\n";
# print join("\t", @listing);
#}
my($childaction) = $what{$line};
next if $childaction eq "x";
my($childname) = substr($line, rindex($line, "/")+1);
#print STDERR "Processing2 $childname\n";
my($targetchildname) = $line;
my($localchildname) = $localname{$line};
my($was_directory) = 0;
if ($childaction eq "l" || ! -e $localchildname) {
$was_directory = &output_no_local($childname,
$childaction,
$localchildname,
$tabs);
} else {
if (-r $localchildname || ! -f $localchildname) {
my($lsout) = `/bin/ls -Anlsd $localchildname`;
chop($lsout);
$was_directory = &output_from_local($childname,
$localchildname,
$lsout,
$tabs);
} else {
print STDERR "$localchildname unreadable, skipped\n";
}
}
if ($was_directory) {
&output_dir($targetchildname,
$localchildname,
$childaction,
$tabs+1);
print " " x ($tabs+1), "\$\n";
}
}
}
}
#
# begin main program
#
# initialize the filespec list
open(FILELIST, $ARGV[0]);
while (<FILELIST>) {
($targetfile, $what_to_do, $localfile) = split;
next if (!$targetfile || ($targetfile =~ /^\#/)) ;
die "all input lines must specify what_to_do field" if ! $what_to_do;
if (! $localfile) {
$localfile = $targetfile;
}
$what{$targetfile} = $what_to_do;
#if( defined $what_to_do ) {
# print STDERR "^^^ $targetfile DO $what_to_do ^^^\n";
#} else {
# print STDERR "What_to_do UNDEF\n";
#}
$localname{$targetfile} = $localfile;
if ($targetfile ne "/") {
$target_parent = substr($targetfile, 0, rindex($targetfile,'/'));
if (! $target_parent) {
$target_parent = "/";
}
if (! $children{$target_parent}) {
# $children{$target_parent} = "";
$children{$target_parent} = $targetfile;
} else {
$children{$target_parent} .= " " . $targetfile;
}
}
}
close(FILELIST);
print "fakedisk\n";
print "$default_size 80\n";
print "d--777 0 0\n";
&output_dir("/", $localname{"/"}, $what{"/"}, 1);
print " ", "\$\n";
print ":\tFile system tree done.\n";
print ":\tApproximate block count: $block_count\n";
if ($block_count > $default_size) {
# print STDERR "Warning: block count $block_count > specified size $default_size.\n";
# print STDERR "Edit output file before running mkfs!\n";
}
close(STDOUT);
#print STDERR "Mkfs script created. Remember to change size of disk (second line) to match\n";
#print STDERR "actual block count of disk (printed at end of file).\n"