add an initscript
[openwrt.git] / obsolete-buildroot / sources / genext2fs.patch
1 diff -urN genext2fs-1.3.orig/Makefile genext2fs-1.3/Makefile
2 --- genext2fs-1.3.orig/Makefile 1969-12-31 17:00:00.000000000 -0700
3 +++ genext2fs-1.3/Makefile 2003-04-21 01:41:42.000000000 -0600
4 @@ -0,0 +1,46 @@
5 +CC=gcc
6 +CFLAGS=-Wall -O0 -g
7 +
8 +SRC=genext2fs.c
9 +OBJS=$(patsubst %.c,%.o, $(SRC))
10 +
11 +all: genext2fs
12 +INSTALL=install
13 +
14 +genext2fs: $(OBJS)
15 + $(CC) $(CFLAGS) -o $@ $(OBJS) -o $@
16 +
17 +$(OBJS): %.o : %.c
18 + $(CC) $(CFLAGS) -c $< -o $@
19 +
20 +$(OBJS): Makefile
21 +
22 +install:
23 + $(INSTALL) -d $(DESTDIR)/usr/bin/
24 + $(INSTALL) -m 755 genext2fs $(DESTDIR)/usr/bin/
25 + $(INSTALL) -d $(DESTDIR)/usr/share/man/man8/
26 + $(INSTALL) -m 644 genext2fs.8 $(DESTDIR)/usr/share/man/man8/
27 +
28 +clean:
29 + rm -rf *.o *.a core genext2fs
30 + rm -rf test ext2.img
31 +
32 +check: all
33 + mkdir -p test
34 + dd if=/dev/zero of=test/zero count=1
35 + ./genext2fs -b 4096 -d test ext2.img
36 +
37 + md5=`md5sum ext2.img | cut -f 1 -d " "`; \
38 + if [ "$$md5" != "89471302d95f96a76fbb2cff98182cde" ] ; then \
39 + echo "test failed."; \
40 + else \
41 + echo "test succeeded."; \
42 + fi
43 +
44 +# test genext2fs by creating the image and comparing checksums
45 +test: all
46 + sh ./test.sh
47 +
48 +# test genext2fs by actually mounting the created image.
49 +test-mount: all
50 + sudo sh ./test-mount.sh
51 diff -urN genext2fs-1.3.orig/debian/changelog genext2fs-1.3/debian/changelog
52 --- genext2fs-1.3.orig/debian/changelog 1969-12-31 17:00:00.000000000 -0700
53 +++ genext2fs-1.3/debian/changelog 2003-04-21 01:41:42.000000000 -0600
54 @@ -0,0 +1,17 @@
55 +genext2fs (1.3-2) unstable; urgency=low
56 +
57 + * apply fix from upstream cvs that appears to fix endian bug
58 + (closes: #122411)
59 + * mention filesystem size limit in manpage (closes: #122729)
60 + * mention that hard links are not supported in manpage
61 + (closes: #155464)
62 + * add sanity check at the end of the build
63 +
64 + -- David Kimdon <dwhedon@debian.org> Fri, 8 Mar 2002 23:17:36 -0800
65 +
66 +genext2fs (1.3-1) unstable; urgency=low
67 +
68 + * Initial Release. (closes: #105263)
69 +
70 + -- David Kimdon <dwhedon@debian.org> Sat, 14 Jul 2001 13:24:49 -0700
71 +
72 diff -urN genext2fs-1.3.orig/debian/control genext2fs-1.3/debian/control
73 --- genext2fs-1.3.orig/debian/control 1969-12-31 17:00:00.000000000 -0700
74 +++ genext2fs-1.3/debian/control 2003-04-21 01:41:42.000000000 -0600
75 @@ -0,0 +1,19 @@
76 +Source: genext2fs
77 +Section: admin
78 +Priority: optional
79 +Maintainer: David Kimdon <dwhedon@debian.org>
80 +Build-Depends: debhelper (>> 3.0.0)
81 +Standards-Version: 3.5.2
82 +
83 +Package: genext2fs
84 +Architecture: any
85 +Depends: ${shlibs:Depends}
86 +Description: ext2 filesystem generator for embedded systems
87 + `genext2fs' is meant to generate an ext2 filesystem
88 + as a normal (non-root) user. It doesn't require you to mount
89 + the image file to copy files on it. It doesn't even require
90 + you to be the superuser to make device nodes.
91 + .
92 + Warning ! `genext2fs' has been designed for embedded
93 + systems. As such, it will generate a filesystem for single-user
94 + usage: all files/directories/etc... will belong to UID/GID 0
95 diff -urN genext2fs-1.3.orig/debian/copyright genext2fs-1.3/debian/copyright
96 --- genext2fs-1.3.orig/debian/copyright 1969-12-31 17:00:00.000000000 -0700
97 +++ genext2fs-1.3/debian/copyright 2003-04-21 01:41:42.000000000 -0600
98 @@ -0,0 +1,15 @@
99 +This package was debianized by David Kimdon <dwhedon@debian.org> on
100 +Sat, 14 Jul 2001 13:24:49 -0700.
101 +
102 +It was downloaded from http://freshmeat.net/projects/genext2fs/
103 +Upstream Author(s): Xavier Bestel <xbestel@aplio.fr>
104 +
105 +Copyright (C) 2000 Xavier Bestel <xavier.bestel@free.fr>
106 +
107 +This program is free software; you can redistribute it and/or
108 +modify it under the terms of the GNU General Public License
109 +as published by the Free Software Foundation; version
110 +2 of the License.
111 +
112 +On Debian systems, the complete text of the GNU General Public
113 +License can be found in /usr/share/common-licenses/GPL file.
114 diff -urN genext2fs-1.3.orig/debian/rules genext2fs-1.3/debian/rules
115 --- genext2fs-1.3.orig/debian/rules 1969-12-31 17:00:00.000000000 -0700
116 +++ genext2fs-1.3/debian/rules 2003-04-21 01:41:42.000000000 -0600
117 @@ -0,0 +1,70 @@
118 +#!/usr/bin/make -f
119 +# Sample debian/rules that uses debhelper.
120 +# GNU copyright 1997 to 1999 by Joey Hess.
121 +
122 +# Uncomment this to turn on verbose mode.
123 +#export DH_VERBOSE=1
124 +
125 +# This is the debhelper compatability version to use.
126 +export DH_COMPAT=2
127 +
128 +configure: configure-stamp
129 +configure-stamp:
130 + dh_testdir
131 + # Add here commands to configure the package.
132 + # ./configure --prefix=/usr --mandir=/usr/share/man/
133 +
134 + touch configure-stamp
135 +
136 +build: configure-stamp build-stamp
137 +build-stamp:
138 + dh_testdir
139 +
140 + # Add here commands to compile the package.
141 + $(MAKE)
142 + $(MAKE) check
143 +
144 + touch build-stamp
145 +
146 +clean:
147 + dh_testdir
148 + dh_testroot
149 + rm -f build-stamp configure-stamp
150 +
151 + # Add here commands to clean up after the build process.
152 + -$(MAKE) clean
153 +
154 + dh_clean
155 +
156 +install: build
157 + dh_testdir
158 + dh_testroot
159 + dh_clean -k
160 + dh_installdirs
161 +
162 + # Add here commands to install the package into debian/genext2fs.
163 + $(MAKE) install DESTDIR=`pwd`/debian/genext2fs
164 +
165 +
166 +# Build architecture-independent files here.
167 +binary-indep: build install
168 +# We have nothing to do by default.
169 +
170 +# Build architecture-dependent files here.
171 +binary-arch: build install
172 + dh_testdir
173 + dh_testroot
174 + dh_installdocs
175 + dh_installchangelogs
176 + dh_link
177 + dh_strip
178 + dh_compress
179 + dh_fixperms
180 + dh_installdeb
181 + dh_shlibdeps
182 + dh_gencontrol
183 + dh_md5sums
184 + dh_builddeb
185 +
186 +binary: binary-indep binary-arch
187 +.PHONY: build clean binary-indep binary-arch binary install configure
188 diff -urN genext2fs-1.3.orig/dev.txt genext2fs-1.3/dev.txt
189 --- genext2fs-1.3.orig/dev.txt 2000-09-28 09:03:19.000000000 -0600
190 +++ genext2fs-1.3/dev.txt 1969-12-31 17:00:00.000000000 -0700
191 @@ -1,94 +0,0 @@
192 -drwx /dev
193 -crw- 10,190 /dev/lcd
194 -crw- 10,191 /dev/splc781
195 -crw- 4,0 /dev/console
196 -crw- 5,64 /dev/cua0
197 -crw- 5,65 /dev/cua1
198 -crw- 5,66 /dev/cua2
199 -crw- 5,70 /dev/cua6
200 -crw- 5,71 /dev/cua7
201 -crw- 5,72 /dev/cua8
202 -crw- 5,73 /dev/cua9
203 -crw- 29,0 /dev/fb0
204 -crw- 29,32 /dev/fb1
205 -crw- 1,2 /dev/kmem
206 -crw- 1,1 /dev/mem
207 -crw- 1,3 /dev/null
208 -crw- 2,2 /dev/ptyp2
209 -crw- 2,3 /dev/ptyp3
210 -crw- 2,5 /dev/ptyp5
211 -crw- 2,4 /dev/ptyp4
212 -crw- 10,178 /dev/triokb
213 -crw- 2,0 /dev/ptyp0
214 -crw- 2,6 /dev/ptyp6
215 -crw- 2,7 /dev/ptyp7
216 -crw- 2,8 /dev/ptyp8
217 -crw- 2,9 /dev/ptyp9
218 -crw- 2,10 /dev/ptypa
219 -crw- 2,11 /dev/ptypb
220 -crw- 2,12 /dev/ptypc
221 -crw- 2,13 /dev/ptypd
222 -crw- 2,14 /dev/ptype
223 -crw- 2,15 /dev/ptypf
224 -brw- 1,0 /dev/ram0
225 -brw- 1,1 /dev/ram1
226 -brw- 1,2 /dev/ram2
227 -brw- 1,3 /dev/ram3
228 -br-- 31,0 /dev/rom0
229 -brw- 31,1 /dev/rom1
230 -brw- 31,2 /dev/rom2
231 -brw- 31,3 /dev/rom3
232 -crw- 5,0 /dev/tty
233 -crw- 4,0 /dev/tty0
234 -crwx 4,1 /dev/tty1
235 -crwx 4,2 /dev/tty2
236 -crwx 4,3 /dev/tty3
237 -crwx 4,4 /dev/tty4
238 -crw- 4,5 /dev/tty5
239 -crwx 4,6 /dev/tty6
240 -crw- 4,7 /dev/tty7
241 -crw- 4,8 /dev/tty8
242 -crw- 4,9 /dev/tty9
243 -crw- 4,64 /dev/ttyS0
244 -crw- 4,65 /dev/ttyS1
245 -crw- 4,66 /dev/ttyS2
246 -crw- 4,67 /dev/ttyS3
247 -crw- 4,68 /dev/ttyS4
248 -crw- 4,69 /dev/ttyS5
249 -crw- 4,70 /dev/ttyS6
250 -crw- 4,71 /dev/ttyS7
251 -crw- 4,72 /dev/ttyS8
252 -crw- 4,73 /dev/ttyS9
253 -crw- 3,0 /dev/ttyp0
254 -crw- 3,1 /dev/ttyp1
255 -crw- 3,2 /dev/ttyp2
256 -crw- 3,3 /dev/ttyp3
257 -crw- 3,4 /dev/ttyp4
258 -crw- 3,5 /dev/ttyp5
259 -crw- 3,6 /dev/ttyp6
260 -crw- 3,7 /dev/ttyp7
261 -crw- 3,8 /dev/ttyp8
262 -crw- 3,9 /dev/ttyp9
263 -crw- 3,10 /dev/ttypa
264 -crw- 3,11 /dev/ttypb
265 -crw- 3,12 /dev/ttypc
266 -crw- 3,13 /dev/ttypd
267 -crw- 3,14 /dev/ttype
268 -crw- 3,15 /dev/ttypf
269 -crw- 1,5 /dev/zero
270 -crwx 10,111 /dev/dtedrv
271 -crwx 4,110 /dev/ttyM
272 -crw- 77,1 /dev/tssnd
273 -crw- 77,2 /dev/tstone
274 -crw- 2,1 /dev/ptyp1
275 -crwx 10,180 /dev/triohook
276 -crw- 90,0 /dev/mtd0
277 -brw- 44,0 /dev/ftl0
278 -crw- 10,175 /dev/tporta
279 -crw- 10,176 /dev/tportb
280 -crwx 10,100 /dev/softmodem
281 -crwx 10,101 /dev/softmodem_signals
282 -crwx 10,181 /dev/triovoice
283 -crw- 5,67 /dev/cua3
284 -crw- 5,68 /dev/cua4
285 -crw- 5,69 /dev/cua5
286 diff -urN genext2fs-1.3.orig/device_table.txt genext2fs-1.3/device_table.txt
287 --- genext2fs-1.3.orig/device_table.txt 1969-12-31 17:00:00.000000000 -0700
288 +++ genext2fs-1.3/device_table.txt 2003-04-21 01:41:42.000000000 -0600
289 @@ -0,0 +1,129 @@
290 +# When building a target filesystem, it is desirable to not have to
291 +# become root and then run 'mknod' a thousand times. Using a device
292 +# table you can create device nodes and directories "on the fly".
293 +#
294 +# This is a sample device table file for use with genext2fs. You can
295 +# do all sorts of interesting things with a device table file. For
296 +# example, if you want to adjust the permissions on a particular file
297 +# you can just add an entry like:
298 +# /sbin/foobar f 2755 0 0 - - - - -
299 +# and (assuming the file /sbin/foobar exists) it will be made setuid
300 +# root (regardless of what its permissions are on the host filesystem.
301 +# Furthermore, you can use a single table entry to create a many device
302 +# minors. For example, if I wanted to create /dev/hda and /dev/hda[0-15]
303 +# I could just use the following two table entries:
304 +# /dev/hda b 640 0 0 3 0 0 0 -
305 +# /dev/hda b 640 0 0 3 1 1 1 15
306 +#
307 +# Device table entries take the form of:
308 +# <name> <type> <mode> <uid> <gid> <major> <minor> <start> <inc> <count>
309 +# where name is the file name, type can be one of:
310 +# f A regular file
311 +# d Directory
312 +# c Character special device file
313 +# b Block special device file
314 +# p Fifo (named pipe)
315 +# uid is the user id for the target file, gid is the group id for the
316 +# target file. The rest of the entries (major, minor, etc) apply only
317 +# to device special files.
318 +
319 +# Have fun
320 +# -Erik Andersen <andersen@codepoet.org>
321 +#
322 +
323 +#<name> <type> <mode> <uid> <gid> <major> <minor> <start> <inc> <count>
324 +/dev d 755 0 0 - - - - -
325 +/dev/mem c 640 0 0 1 1 0 0 -
326 +/dev/kmem c 640 0 0 1 2 0 0 -
327 +/dev/null c 640 0 0 1 3 0 0 -
328 +/dev/zero c 640 0 0 1 5 0 0 -
329 +/dev/random c 640 0 0 1 8 0 0 -
330 +/dev/urandom c 640 0 0 1 9 0 0 -
331 +/dev/tty c 666 0 0 5 0 0 0 -
332 +/dev/tty c 666 0 0 4 0 0 1 6
333 +/dev/console c 640 0 0 5 1 0 0 -
334 +/dev/ram b 640 0 0 1 1 0 0 -
335 +/dev/ram b 640 0 0 1 0 0 1 4
336 +/dev/loop b 640 0 0 7 0 0 1 2
337 +/dev/ptmx c 666 0 0 5 2 0 0 -
338 +#/dev/ttyS c 640 0 0 4 64 0 1 4
339 +#/dev/psaux c 640 0 0 10 1 0 0 -
340 +#/dev/rtc c 640 0 0 10 135 0 0 -
341 +
342 +# Adjust permissions on some normal files
343 +#/etc/shadow f 600 0 0 - - - - -
344 +#/bin/tinylogin f 4755 0 0 - - - - -
345 +
346 +# User-mode Linux stuff
347 +/dev/ubda b 640 0 0 98 0 0 0 -
348 +/dev/ubda b 640 0 0 98 1 1 1 15
349 +
350 +# IDE Devices
351 +/dev/hda b 640 0 0 3 0 0 0 -
352 +/dev/hda b 640 0 0 3 1 1 1 15
353 +/dev/hdb b 640 0 0 3 64 0 0 -
354 +/dev/hdb b 640 0 0 3 65 1 1 15
355 +#/dev/hdc b 640 0 0 22 0 0 0 -
356 +#/dev/hdc b 640 0 0 22 1 1 1 15
357 +#/dev/hdd b 640 0 0 22 64 0 0 -
358 +#/dev/hdd b 640 0 0 22 65 1 1 15
359 +#/dev/hde b 640 0 0 33 0 0 0 -
360 +#/dev/hde b 640 0 0 33 1 1 1 15
361 +#/dev/hdf b 640 0 0 33 64 0 0 -
362 +#/dev/hdf b 640 0 0 33 65 1 1 15
363 +#/dev/hdg b 640 0 0 34 0 0 0 -
364 +#/dev/hdg b 640 0 0 34 1 1 1 15
365 +#/dev/hdh b 640 0 0 34 64 0 0 -
366 +#/dev/hdh b 640 0 0 34 65 1 1 15
367 +
368 +# SCSI Devices
369 +#/dev/sda b 640 0 0 8 0 0 0 -
370 +#/dev/sda b 640 0 0 8 1 1 1 15
371 +#/dev/sdb b 640 0 0 8 16 0 0 -
372 +#/dev/sdb b 640 0 0 8 17 1 1 15
373 +#/dev/sdc b 640 0 0 8 32 0 0 -
374 +#/dev/sdc b 640 0 0 8 33 1 1 15
375 +#/dev/sdd b 640 0 0 8 48 0 0 -
376 +#/dev/sdd b 640 0 0 8 49 1 1 15
377 +#/dev/sde b 640 0 0 8 64 0 0 -
378 +#/dev/sde b 640 0 0 8 65 1 1 15
379 +#/dev/sdf b 640 0 0 8 80 0 0 -
380 +#/dev/sdf b 640 0 0 8 81 1 1 15
381 +#/dev/sdg b 640 0 0 8 96 0 0 -
382 +#/dev/sdg b 640 0 0 8 97 1 1 15
383 +#/dev/sdh b 640 0 0 8 112 0 0 -
384 +#/dev/sdh b 640 0 0 8 113 1 1 15
385 +#/dev/sg c 640 0 0 21 0 0 1 15
386 +#/dev/scd b 640 0 0 11 0 0 1 15
387 +#/dev/st c 640 0 0 9 0 0 1 8
388 +#/dev/nst c 640 0 0 9 128 0 1 8
389 +#/dev/st c 640 0 0 9 32 1 1 4
390 +#/dev/st c 640 0 0 9 64 1 1 4
391 +#/dev/st c 640 0 0 9 96 1 1 4
392 +
393 +# Floppy disk devices
394 +#/dev/fd b 640 0 0 2 0 0 1 2
395 +#/dev/fd0d360 b 640 0 0 2 4 0 0 -
396 +#/dev/fd1d360 b 640 0 0 2 5 0 0 -
397 +#/dev/fd0h1200 b 640 0 0 2 8 0 0 -
398 +#/dev/fd1h1200 b 640 0 0 2 9 0 0 -
399 +#/dev/fd0u1440 b 640 0 0 2 28 0 0 -
400 +#/dev/fd1u1440 b 640 0 0 2 29 0 0 -
401 +#/dev/fd0u2880 b 640 0 0 2 32 0 0 -
402 +#/dev/fd1u2880 b 640 0 0 2 33 0 0 -
403 +
404 +# All the proprietary cdrom devices in the world
405 +#/dev/aztcd b 640 0 0 29 0 0 0 -
406 +#/dev/bpcd b 640 0 0 41 0 0 0 -
407 +#/dev/capi20 c 640 0 0 68 0 0 1 2
408 +#/dev/cdu31a b 640 0 0 15 0 0 0 -
409 +#/dev/cdu535 b 640 0 0 24 0 0 0 -
410 +#/dev/cm206cd b 640 0 0 32 0 0 0 -
411 +#/dev/sjcd b 640 0 0 18 0 0 0 -
412 +#/dev/sonycd b 640 0 0 15 0 0 0 -
413 +#/dev/gscd b 640 0 0 16 0 0 0 -
414 +#/dev/sbpcd b 640 0 0 25 0 0 0 -
415 +#/dev/sbpcd b 640 0 0 25 0 0 1 4
416 +#/dev/mcd b 640 0 0 23 0 0 0 -
417 +#/dev/optcd b 640 0 0 17 0 0 0 -
418 +
419 diff -urN genext2fs-1.3.orig/genext2fs.8 genext2fs-1.3/genext2fs.8
420 --- genext2fs-1.3.orig/genext2fs.8 1969-12-31 17:00:00.000000000 -0700
421 +++ genext2fs-1.3/genext2fs.8 2003-04-21 01:41:42.000000000 -0600
422 @@ -0,0 +1,125 @@
423 +.\" Hey, EMACS: -*- nroff -*-
424 +.\" First parameter, NAME, should be all caps
425 +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
426 +.\" other parameters are allowed: see man(7), man(1)
427 +.TH GENEXT2FS 8 "July 14, 2001"
428 +.\" Please adjust this date whenever revising the manpage.
429 +.\"
430 +.\" Some roff macros, for reference:
431 +.\" .nh disable hyphenation
432 +.\" .hy enable hyphenation
433 +.\" .ad l left justify
434 +.\" .ad b justify to both left and right margins
435 +.\" .nf disable filling
436 +.\" .fi enable filling
437 +.\" .br insert line break
438 +.\" .sp <n> insert n+1 empty lines
439 +.\" for manpage-specific macros, see man(7)
440 +.SH NAME
441 +genext2fs \- ext2 filesystem generator for embedded systems
442 +.SH SYNOPSIS
443 +.B genext2fs
444 +.RI [ options ] " image"
445 +.SH DESCRIPTION
446 +\fBgenext2fs\fP generates an ext2 filesystem
447 +as a normal (non-root) user. It doesn't require you to mount
448 +the image file to copy files on it. It doesn't even require
449 +you to be the superuser to make device nodes.
450 +.SH OPTIONS
451 +.TP
452 +.BI -x \ image
453 +Use this image as a starting point
454 +.TP
455 +.BI -d \ directory
456 +Add this directory as source
457 +.TP
458 +.BI -f \ FILE
459 +.TP
460 +.BI -D \ FILE
461 +Uses the named FILE as a device table file, to create device
462 +nodes and directories "on the fly".
463 +.TP
464 +.BI -b \ blocks
465 +Size in blocks
466 +.TP
467 +.BI -i \ inodes
468 +Number of inodes
469 +.TP
470 +.BI -r \ reserved
471 +Number of reserved blocks
472 +.TP
473 +.BI -g \ path
474 +Generate a block map file for this path
475 +.TP
476 +.BI -e \ value
477 +Fill unallocated blocks with value
478 +.TP
479 +.BI -z
480 +Make files with holes
481 +.TP
482 +.BI -U
483 +Squash owners making all files be owned by root
484 +.TP
485 +.BI -P
486 +Squash permissions on all files
487 +.TP
488 +.BI -q
489 +Squash permissions and owners (same as -P -U)
490 +.TP
491 +.BI -v
492 +Print resulting filesystem structure
493 +.TP
494 +.BI -h
495 +Display help
496 +.TP
497 +.SH EXAMPLES
498 +
499 +.EX
500 +.B
501 + genext2fs -b 1440 -d src /dev/fd0
502 +.EE
503 +
504 +All files in the
505 +.I src
506 +directory will be written to
507 +.B /dev/fd0
508 +as a new ext2 filesystem image. You can then mount the floppy as
509 +usual.
510 +
511 +.EX
512 +.B
513 + genext2fs -b 1024 -d src -D device_table.txt flashdisk.img
514 +.EE
515 +
516 +This example builds a filesystem from all the files in
517 +.I src
518 +, then device nodes are created based on the content the device_table file
519 +.I dev.txt.
520 +An example device file follows:
521 +
522 +.EX
523 + #<name> <type> <mode> <uid> <gid> <major> <minor> <start> <inc> <count>
524 + /dev d 755 0 0 - - - - -
525 + /dev/mem c 640 0 0 1 1 0 0 -
526 + /dev/tty c 666 0 0 5 0 0 0 -
527 + /dev/tty c 666 0 0 4 0 0 1 6
528 + /dev/loop b 640 0 0 7 0 0 1 2
529 + /dev/hda b 640 0 0 3 0 0 0 -
530 + /dev/hda b 640 0 0 3 1 1 1 16
531 +.EE
532 +
533 +This device table creates the /dev directory, a character device
534 +node /dev/mem (major 1, minor 1), it also creates /dev/tty,
535 +/dev/tty[0-5], /dev/loop[0-1], /dev/hda, and /dev/hda0 to /dev/hda15
536 +.SH BUGS
537 +\fBgenext2fs\fP does not support hard links. Hard links present in the input
538 +tree will be represented as separate files in the ext2 image.
539 +
540 +.SH SEE ALSO
541 +.BR mkfs (8),
542 +.BR genromfs (8),
543 +.BR mkisofs (8).
544 +.br
545 +.SH AUTHOR
546 +This manual page was written by David Kimdon <dwhedon@debian.org>,
547 +for the Debian GNU/Linux system (but may be used by others).
548 diff -urN genext2fs-1.3.orig/genext2fs.c genext2fs-1.3/genext2fs.c
549 --- genext2fs-1.3.orig/genext2fs.c 2001-06-18 02:11:32.000000000 -0600
550 +++ genext2fs-1.3/genext2fs.c 2003-04-21 01:48:35.000000000 -0600
551 @@ -1,3 +1,4 @@
552 +/* vi: set sw=8 ts=8: */
553 // genext2fs.c
554 //
555 // ext2 filesystem generator for embedded systems
556 @@ -26,6 +27,22 @@
557 // Bugfix: getcwd values for Solaris xavier.gueguen@col.bsf.alcatel.fr
558 // Bugfix: ANSI scanf for non-GNU C xavier.gueguen@col.bsf.alcatel.fr
559 // 28 Jun 2001 Bugfix: getcwd differs for Solaris/GNU mike@sowbug.com
560 +// 23 Mar 2002 Bugfix: test for IFCHR or IFBLK was flawed
561 +// 10 Oct 2002 Added comments,makefile targets, vsundar@ixiacom.com
562 +// endianess swap assert check.
563 +// Copyright (C) 2002 Ixia communications
564 +// 12 Oct 2002 Added support for triple indirection vsundar@ixiacom.com
565 +// Copyright (C) 2002 Ixia communications
566 +// 14 Oct 2002 Added support for groups vsundar@ixiacom.com
567 +// Copyright (C) 2002 Ixia communications
568 +// 5 Jan 2003 Bugfixes: reserved inodes should be set vsundar@usc.edu
569 +// only in the first group; directory names
570 +// need to be null padded at the end; and
571 +// number of blocks per group should be a
572 +// multiple of 8. Updated md5 values.
573 +// 6 Jan 2003 Erik Andersen <andersee@debian.org> added
574 +// mkfs.jffs2 compatible device table support,
575 +// along with -q, -P, -U
576
577
578 // `genext2fs' is a mean to generate an ext2 filesystem
579 @@ -33,10 +50,6 @@
580 // the image file to copy files on it. It doesn't even require
581 // you to be the superuser to make device nodes.
582 //
583 -// Warning ! `genext2fs' has been designed for embedded
584 -// systems. As such, it will generate a filesystem for single-user
585 -// usage: all files/directories/etc... will belong to UID/GID 0
586 -//
587 // Example usage:
588 //
589 // # genext2fs -b 1440 -d srcdir /dev/fd0
590 @@ -45,21 +58,15 @@
591 // a new ext2 filesystem image. You can then mount the floppy as
592 // usual.
593 //
594 -// # genext2fs -b 1024 -d builddir -f devices.txt flashdisk.img
595 +// # genext2fs -b 1024 -d builddir -D device_table.txt flashdisk.img
596 //
597 // This one would build a filesystem from all the files in builddir,
598 -// then would read a devices list and make apropriate nodes. The
599 -// format for the device list is:
600 -//
601 -// drwx /dev
602 -// crw- 10,190 /dev/lcd
603 -// brw- 1,0 /dev/ram0
604 -//
605 -// This device list builds the /dev directory, a character device
606 -// node /dev/lcd (major 10, minor 190) and a block device node
607 -// /dev/ram0 (major 1, minor 0)
608 +// then would read the device_table.txt file and make apropriate nodes.
609 +// The format for the device table file is covered in detail in the sample
610 +// device_table.txt file provided with the genext2fs source.
611
612
613 +#define _GNU_SOURCE
614 #include <stdio.h>
615 #include <stdlib.h>
616 #include <string.h>
617 @@ -67,6 +74,11 @@
618 #include <stdarg.h>
619 #include <unistd.h>
620 #include <sys/stat.h>
621 +#include <assert.h>
622 +#include <time.h>
623 +#include <ctype.h>
624 +#include <errno.h>
625 +#include <fcntl.h>
626
627
628
629 @@ -76,10 +88,14 @@
630 #define BLOCKSIZE 1024
631 #define BLOCKS_PER_GROUP 8192
632 #define BYTES_PER_INODE (8*BLOCKSIZE)
633 +/* Percentage of blocks that are reserved.*/
634 #define RESERVED_INODES 5/100
635
636
637 // inode block size (why is it != BLOCKSIZE ?!?)
638 +/* The field i_blocks in the ext2 inode stores the number of data blocks
639 + but in terms of 512 bytes. That is what INODE_BLOCKSIZE represents.
640 + INOBLK is the number of such blocks in an actual disk block */
641
642 #define INODE_BLOCKSIZE 512
643 #define INOBLK (BLOCKSIZE / INODE_BLOCKSIZE)
644 @@ -147,6 +163,39 @@
645
646 #define OP_HOLES 0x01 // make files with holes
647
648 +/* Defines for accessing group details */
649 +
650 +// Number of groups in the filesystem
651 +#define GRP_NBGROUPS(fs) ( ((fs)->sb.s_blocks_count-1)/(fs)->sb.s_blocks_per_group )
652 +
653 +// Get group block bitmap (bbm) given the group number
654 +#define GRP_GET_GROUP_BBM(fs,grp) ( get_blk((fs),(fs)->gd[(grp)].bg_block_bitmap) )
655 +
656 +// Get group inode bitmap (ibm) given the group number
657 +#define GRP_GET_GROUP_IBM(fs,grp) ( get_blk((fs),(fs)->gd[(grp)].bg_inode_bitmap) )
658 +
659 +// Given an inode number find the group it belongs to
660 +#define GRP_GROUP_OF_INODE(fs,nod) ( ((nod)-1) / (fs)->sb.s_inodes_per_group)
661 +
662 +//Given an inode number get the inode bitmap that covers it
663 +#define GRP_GET_INODE_BITMAP(fs,nod) \
664 + ( GRP_GET_GROUP_IBM((fs),GRP_GROUP_OF_INODE((fs),(nod))) )
665 +
666 +//Given an inode number find its offset within the inode bitmap that covers it
667 +#define GRP_IBM_OFFSET(fs,nod) \
668 + ( (nod) - GRP_GROUP_OF_INODE((fs),(nod))*(fs)->sb.s_inodes_per_group )
669 +
670 +// Given a block number find the group it belongs to
671 +#define GRP_GROUP_OF_BLOCK(fs,blk) ( ((blk)-1) / (fs)->sb.s_blocks_per_group)
672 +
673 +//Given a block number get the block bitmap that covers it
674 +#define GRP_GET_BLOCK_BITMAP(fs,blk) \
675 + ( GRP_GET_GROUP_BBM((fs),GRP_GROUP_OF_BLOCK((fs),(blk))) )
676 +
677 +//Given a block number find its offset within the block bitmap that covers it
678 +#define GRP_BBM_OFFSET(fs,blk) \
679 + ( (blk) - GRP_GROUP_OF_BLOCK((fs),(blk))*(fs)->sb.s_blocks_per_group )
680 +
681
682 // used types
683
684 @@ -287,7 +336,6 @@
685 {
686 groupdescriptor_decl
687 uint32 bg_reserved[3];
688 - uint32 bg_pad_to_bk[(BLOCKSIZE-32)/sizeof(uint32)];
689 } groupdescriptor;
690
691 typedef struct
692 @@ -304,6 +352,32 @@
693
694 typedef uint8 block[BLOCKSIZE];
695
696 +/* blockwalker fields:
697 + The blockwalker is used to access all the blocks of a file (including
698 + the indirection blocks) through repeated calls to walk_bw.
699 +
700 + bpdir -> index into the inode->i_block[]. Indicates level of indirection.
701 + bnum -> total number of blocks so far accessed. including indirection
702 + blocks.
703 + bpind,bpdind,bptind -> index into indirection blocks.
704 +
705 + bpind, bpdind, bptind do *NOT* index into single, double and triple
706 + indirect blocks resp. as you might expect from their names. Instead
707 + they are in order the 1st, 2nd & 3rd index to be used
708 +
709 + As an example..
710 + To access data block number 70000:
711 + bpdir: 15 (we are doing triple indirection)
712 + bpind: 0 ( index into the triple indirection block)
713 + bpdind: 16 ( index into the double indirection block)
714 + bptind: 99 ( index into the single indirection block)
715 + 70000 = 12 + 256 + 256*256 + 16*256 + 100 (indexing starts from zero)
716 +
717 + So,for double indirection bpind will index into the double indirection
718 + block and bpdind into the single indirection block. For single indirection
719 + only bpind will be used.
720 +*/
721 +
722 typedef struct
723 {
724 uint32 bnum;
725 @@ -313,15 +387,14 @@
726 uint32 bptind;
727 } blockwalker;
728
729 +
730 +/* Filesystem structure that support groups */
731 #if BLOCKSIZE == 1024
732 typedef struct
733 {
734 block zero; // The famous block 0
735 superblock sb; // The superblock
736 - groupdescriptor gd; // The group desciptor
737 - block bbm; // The block bitmap
738 - block ibm; // The inode bitmap
739 - inode itab[0]; // The inode table
740 + groupdescriptor gd[0]; // The group descriptors
741 } filesystem;
742 #else
743 #error UNHANDLED BLOCKSIZE
744 @@ -389,25 +462,113 @@
745 #undef udecl32
746 #undef utdecl32
747
748 -char * argv0;
749 +static char * app_name;
750 +static int squash_uids = 0;
751 +static int squash_perms = 0;
752 +static const char *const memory_exhausted = "memory exhausted";
753
754 // error (un)handling
755 -inline void errexit(const char *fmt, ...)
756 +static void verror_msg(const char *s, va_list p)
757 {
758 - va_list ap;
759 - fprintf(stderr, "%s: ", argv0);
760 - va_start(ap, fmt);
761 - vfprintf(stderr, fmt, ap);
762 - va_end(ap);
763 - fprintf(stderr, "\n");
764 - exit(1);
765 + fflush(stdout);
766 + fprintf(stderr, "%s: ", app_name);
767 + vfprintf(stderr, s, p);
768 +}
769 +static void error_msg(const char *s, ...)
770 +{
771 + va_list p;
772 + va_start(p, s);
773 + verror_msg(s, p);
774 + va_end(p);
775 + putc('\n', stderr);
776 +}
777 +
778 +static void error_msg_and_die(const char *s, ...)
779 +{
780 + va_list p;
781 + va_start(p, s);
782 + verror_msg(s, p);
783 + va_end(p);
784 + putc('\n', stderr);
785 + exit(EXIT_FAILURE);
786 +}
787 +
788 +static void vperror_msg(const char *s, va_list p)
789 +{
790 + int err = errno;
791 + if (s == 0)
792 + s = "";
793 + verror_msg(s, p);
794 + if (*s)
795 + s = ": ";
796 + fprintf(stderr, "%s%s\n", s, strerror(err));
797 +}
798 +
799 +#if 0
800 +static void perror_msg(const char *s, ...)
801 +{
802 + va_list p;
803 + va_start(p, s);
804 + vperror_msg(s, p);
805 + va_end(p);
806 +}
807 +#endif
808 +static void perror_msg_and_die(const char *s, ...)
809 +{
810 + va_list p;
811 + va_start(p, s);
812 + vperror_msg(s, p);
813 + va_end(p);
814 + exit(EXIT_FAILURE);
815 }
816
817 -inline void pexit(const char * fname)
818 +static FILE *xfopen(const char *path, const char *mode)
819 {
820 - fprintf(stderr, "%s: ", argv0);
821 - perror(fname);
822 - exit(1);
823 + FILE *fp;
824 + if ((fp = fopen(path, mode)) == NULL)
825 + perror_msg_and_die("%s", path);
826 + return fp;
827 +}
828 +
829 +static char *xstrdup(const char *s)
830 +{
831 + char *t;
832 +
833 + if (s == NULL)
834 + return NULL;
835 + t = strdup(s);
836 + if (t == NULL)
837 + error_msg_and_die(memory_exhausted);
838 + return t;
839 +}
840 +
841 +extern void *xrealloc(void *ptr, size_t size)
842 +{
843 + ptr = realloc(ptr, size);
844 + if (ptr == NULL && size != 0)
845 + error_msg_and_die(memory_exhausted);
846 + return ptr;
847 +}
848 +
849 +static char *xreadlink(const char *path)
850 +{
851 + static const int GROWBY = 80; /* how large we will grow strings by */
852 +
853 + char *buf = NULL;
854 + int bufsize = 0, readsize = 0;
855 +
856 + do {
857 + buf = xrealloc(buf, bufsize += GROWBY);
858 + readsize = readlink(path, buf, bufsize); /* 1st try */
859 + if (readsize == -1) {
860 + perror_msg_and_die("%s:%s", app_name, path);
861 + }
862 + }
863 + while (bufsize < readsize + 1);
864 +
865 + buf[readsize] = '\0';
866 +
867 + return buf;
868 }
869
870 // printf helper macro
871 @@ -423,7 +584,7 @@
872 {
873 }
874
875 -// rounds a quantity up to a blocksize
876 +/* Rounds qty upto a multiple of siz. siz should be a power of 2 */
877 uint32 rndup(uint32 qty, uint32 siz)
878 {
879 return (qty + (siz - 1)) & ~(siz - 1);
880 @@ -444,7 +605,13 @@
881 // return a given inode from a filesystem
882 inline inode * get_nod(filesystem *fs, uint32 nod)
883 {
884 - return &fs->itab[nod-1];
885 + int grp,offset;
886 + inode *itab;
887 +
888 + offset = GRP_IBM_OFFSET(fs,nod);
889 + grp = GRP_GROUP_OF_INODE(fs,nod);
890 + itab = (inode *)get_blk(fs, fs->gd[grp].bg_inode_table);
891 + return itab+offset-1;
892 }
893
894 // allocate a given block/inode in the bitmap
895 @@ -479,29 +646,57 @@
896 }
897
898 // allocate a block
899 -uint32 alloc_blk(filesystem *fs)
900 +uint32 alloc_blk(filesystem *fs, uint32 nod)
901 {
902 - uint32 bk;
903 - if(!(bk = allocate(fs->bbm, 0)))
904 - errexit("couldn't allocate a block (no free space)");
905 - if(!(fs->gd.bg_free_blocks_count--))
906 - errexit("group descr. free blocks count == 0 (corrupted fs?)");
907 + uint32 bk=0;
908 + uint32 grp,nbgroups;
909 +
910 + grp = nod/fs->sb.s_inodes_per_group;
911 + nbgroups = ( fs->sb.s_blocks_count - fs->sb.s_first_data_block + fs->sb.s_blocks_per_group -1 ) /
912 + fs->sb.s_blocks_per_group;
913 + if(!(bk = allocate(get_blk(fs,fs->gd[grp].bg_block_bitmap), 0))) {
914 + for(grp=0;grp<nbgroups && !bk;grp++)
915 + bk=allocate(get_blk(fs,fs->gd[grp].bg_block_bitmap),0);
916 + grp--;
917 + }
918 + if (!bk)
919 + error_msg_and_die("couldn't allocate a block (no free space)");
920 + if(!(fs->gd[grp].bg_free_blocks_count--))
921 + error_msg_and_die("group descr %d. free blocks count == 0 (corrupted fs?)",grp);
922 if(!(fs->sb.s_free_blocks_count--))
923 - errexit("superblock free blocks count == 0 (corrupted fs?)");
924 - return bk;
925 + error_msg_and_die("superblock free blocks count == 0 (corrupted fs?)");
926 + return fs->sb.s_blocks_per_group*grp + bk;
927 }
928
929 // allocate an inode
930 uint32 alloc_nod(filesystem *fs)
931 {
932 - uint32 nod;
933 - if(!(nod = allocate(fs->ibm, 0)))
934 - errexit("couldn't allocate an inode (no free inode)");
935 - if(!(fs->gd.bg_free_inodes_count--))
936 - errexit("group descr. free blocks count == 0 (corrupted fs?)");
937 + uint32 nod=0,best_group=0;
938 + uint32 grp,nbgroups,avefreei;
939 +
940 + nbgroups = ( fs->sb.s_blocks_count - fs->sb.s_first_data_block + fs->sb.s_blocks_per_group -1 ) /
941 + fs->sb.s_blocks_per_group;
942 +
943 + /* Distribute inodes amongst all the blocks */
944 + /* For every block group with more than average number of free inodes */
945 + /* find the one with the most free blocks and allocate node there */
946 + /* Idea from find_group_dir in fs/ext2/ialloc.c in 2.4.19 kernel */
947 + /* We do it for all inodes. */
948 + avefreei = fs->sb.s_free_inodes_count / nbgroups;
949 + for(grp=0;grp<nbgroups && !nod;grp++) {
950 + if (fs->gd[grp].bg_free_inodes_count < avefreei)
951 + continue;
952 + if (!best_group ||
953 + fs->gd[grp].bg_free_blocks_count > fs->gd[best_group].bg_free_blocks_count)
954 + best_group = grp;
955 + }
956 + if (!(nod = allocate(get_blk(fs,fs->gd[best_group].bg_inode_bitmap),0)))
957 + error_msg_and_die("couldn't allocate an inode (no free inode)");
958 + if(!(fs->gd[best_group].bg_free_inodes_count--))
959 + error_msg_and_die("group descr. free blocks count == 0 (corrupted fs?)");
960 if(!(fs->sb.s_free_inodes_count--))
961 - errexit("superblock free blocks count == 0 (corrupted fs?)");
962 - return nod;
963 + error_msg_and_die("superblock free blocks count == 0 (corrupted fs?)");
964 + return fs->sb.s_inodes_per_group*best_group+nod;
965 }
966
967 // print a bitmap allocation
968 @@ -546,14 +741,14 @@
969 {
970 bkref = &get_nod(fs, nod)->i_block[bw->bpdir = 0];
971 if(extend) // allocate first block
972 - *bkref = hole ? 0 : alloc_blk(fs);
973 + *bkref = hole ? 0 : alloc_blk(fs,nod);
974 }
975 // direct block
976 else if(bw->bpdir < EXT2_NDIR_BLOCKS)
977 {
978 bkref = &get_nod(fs, nod)->i_block[++bw->bpdir];
979 if(extend) // allocate block
980 - *bkref = hole ? 0 : alloc_blk(fs);
981 + *bkref = hole ? 0 : alloc_blk(fs,nod);
982 }
983 // first block in indirect block
984 else if(bw->bpdir == EXT2_NDIR_BLOCKS)
985 @@ -562,11 +757,11 @@
986 bw->bpdir = EXT2_IND_BLOCK;
987 bw->bpind = 0;
988 if(extend) // allocate indirect block
989 - get_nod(fs, nod)->i_block[bw->bpdir] = alloc_blk(fs);
990 + get_nod(fs, nod)->i_block[bw->bpdir] = alloc_blk(fs,nod);
991 b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
992 bkref = &b[bw->bpind];
993 if(extend) // allocate first block
994 - *bkref = hole ? 0 : alloc_blk(fs);
995 + *bkref = hole ? 0 : alloc_blk(fs,nod);
996 }
997 // block in indirect block
998 else if((bw->bpdir == EXT2_IND_BLOCK) && (bw->bpind < BLOCKSIZE/4 - 1))
999 @@ -575,7 +770,7 @@
1000 b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
1001 bkref = &b[bw->bpind];
1002 if(extend) // allocate block
1003 - *bkref = hole ? 0 : alloc_blk(fs);
1004 + *bkref = hole ? 0 : alloc_blk(fs,nod);
1005 }
1006 // first block in first indirect block in first double indirect block
1007 else if(bw->bpdir == EXT2_IND_BLOCK)
1008 @@ -585,14 +780,14 @@
1009 bw->bpind = 0;
1010 bw->bpdind = 0;
1011 if(extend) // allocate double indirect block
1012 - get_nod(fs, nod)->i_block[bw->bpdir] = alloc_blk(fs);
1013 + get_nod(fs, nod)->i_block[bw->bpdir] = alloc_blk(fs,nod);
1014 b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
1015 if(extend) // allocate first indirect block
1016 - b[bw->bpind] = alloc_blk(fs);
1017 + b[bw->bpind] = alloc_blk(fs,nod);
1018 b = (uint32*)get_blk(fs, b[bw->bpind]);
1019 bkref = &b[bw->bpdind];
1020 if(extend) // allocate first block
1021 - *bkref = hole ? 0 : alloc_blk(fs);
1022 + *bkref = hole ? 0 : alloc_blk(fs,nod);
1023 }
1024 // block in indirect block in double indirect block
1025 else if((bw->bpdir == EXT2_DIND_BLOCK) && (bw->bpdind < BLOCKSIZE/4 - 1))
1026 @@ -602,7 +797,7 @@
1027 b = (uint32*)get_blk(fs, b[bw->bpind]);
1028 bkref = &b[bw->bpdind];
1029 if(extend) // allocate block
1030 - *bkref = hole ? 0 : alloc_blk(fs);
1031 + *bkref = hole ? 0 : alloc_blk(fs,nod);
1032 }
1033 // first block in indirect block in double indirect block
1034 else if((bw->bpdir == EXT2_DIND_BLOCK) && (bw->bpind < BLOCKSIZE/4 - 1))
1035 @@ -612,20 +807,100 @@
1036 bw->bpind++;
1037 b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
1038 if(extend) // allocate indirect block
1039 - b[bw->bpind] = alloc_blk(fs);
1040 + b[bw->bpind] = alloc_blk(fs,nod);
1041 b = (uint32*)get_blk(fs, b[bw->bpind]);
1042 bkref = &b[bw->bpdind];
1043 if(extend) // allocate first block
1044 - *bkref = hole ? 0 : alloc_blk(fs);
1045 + *bkref = hole ? 0 : alloc_blk(fs,nod);
1046 + }
1047 +
1048 + /* Adding support for triple indirection */
1049 + /* Just starting triple indirection. Allocate the indirection
1050 + blocks and the first data block
1051 + */
1052 + else if (bw->bpdir == EXT2_DIND_BLOCK)
1053 + {
1054 + bw->bnum += 3;
1055 + bw->bpdir = EXT2_TIND_BLOCK;
1056 + bw->bpind = 0;
1057 + bw->bpdind = 0;
1058 + bw->bptind = 0;
1059 + if(extend) // allocate triple indirect block
1060 + get_nod(fs, nod)->i_block[bw->bpdir] = alloc_blk(fs,nod);
1061 + b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
1062 + if(extend) // allocate first double indirect block
1063 + b[bw->bpind] = alloc_blk(fs,nod);
1064 + b = (uint32*)get_blk(fs, b[bw->bpind]);
1065 + if(extend) // allocate first indirect block
1066 + b[bw->bpdind] = alloc_blk(fs,nod);
1067 + b = (uint32*)get_blk(fs, b[bw->bpdind]);
1068 + bkref = &b[bw->bptind];
1069 + if(extend) // allocate first data block
1070 + *bkref = hole ? 0 : alloc_blk(fs,nod);
1071 + }
1072 + /* Still processing a single indirect block down the indirection
1073 + chain.Allocate a data block for it
1074 + */
1075 + else if ( (bw->bpdir == EXT2_TIND_BLOCK) &&
1076 + (bw->bptind < BLOCKSIZE/4 -1) )
1077 + {
1078 + bw->bptind++;
1079 + b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
1080 + b = (uint32*)get_blk(fs, b[bw->bpind]);
1081 + b = (uint32*)get_blk(fs, b[bw->bpdind]);
1082 + bkref = &b[bw->bptind];
1083 + if(extend) // allocate data block
1084 + *bkref = hole ? 0 : alloc_blk(fs,nod);
1085 + }
1086 + /* Finished processing a single indirect block. But still in the
1087 + same double indirect block. Allocate new single indirect block
1088 + for it and a data block
1089 + */
1090 + else if ( (bw->bpdir == EXT2_TIND_BLOCK) &&
1091 + (bw->bpdind < BLOCKSIZE/4 -1) )
1092 + {
1093 + bw->bnum++;
1094 + bw->bptind = 0;
1095 + bw->bpdind++;
1096 + b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
1097 + b = (uint32*)get_blk(fs, b[bw->bpind]);
1098 + if (extend) // allocate single indirect block
1099 + b[bw->bpdind] = alloc_blk(fs,nod);
1100 + b = (uint32*)get_blk(fs, b[bw->bpdind]);
1101 + bkref = &b[bw->bptind];
1102 + if(extend) // allocate first data block
1103 + *bkref = hole ? 0 : alloc_blk(fs,nod);
1104 + }
1105 + /* Finished processing a double indirect block. Allocate the next
1106 + double indirect block and the single,data blocks for it
1107 + */
1108 + else if ( (bw->bpdir == EXT2_TIND_BLOCK) &&
1109 + (bw->bpind < BLOCKSIZE/4 - 1) )
1110 + {
1111 + bw->bnum += 2;
1112 + bw->bpdind = 0;
1113 + bw->bptind = 0;
1114 + bw->bpind++;
1115 + b = (uint32*)get_blk(fs, get_nod(fs, nod)->i_block[bw->bpdir]);
1116 + if(extend) // allocate double indirect block
1117 + b[bw->bpind] = alloc_blk(fs,nod);
1118 + b = (uint32*)get_blk(fs, b[bw->bpind]);
1119 + if(extend) // allocate single indirect block
1120 + b[bw->bpdind] = alloc_blk(fs,nod);
1121 + b = (uint32*)get_blk(fs, b[bw->bpdind]);
1122 + bkref = &b[bw->bptind];
1123 + if(extend) // allocate first block
1124 + *bkref = hole ? 0 : alloc_blk(fs,nod);
1125 }
1126 - // I don't do triple indirect - it's such a small filesystem ...
1127 else
1128 - errexit("file too big ! blocks list for inode %d extends past double indirect blocks!", nod);
1129 + error_msg_and_die("file too big !");
1130 + /* End change for walking triple indirection */
1131 +
1132 if(*bkref)
1133 {
1134 bw->bnum++;
1135 - if(!allocated(fs->bbm, *bkref))
1136 - errexit("[block %d of inode %d is unallocated !]", *bkref, nod);
1137 + if(!allocated(GRP_GET_BLOCK_BITMAP(fs,*bkref), GRP_BBM_OFFSET(fs,*bkref)))
1138 + error_msg_and_die("[block %d of inode %d is unallocated !]", *bkref, nod);
1139 }
1140 if(extend)
1141 get_nod(fs, nod)->i_blocks = bw->bnum * INOBLK;
1142 @@ -663,23 +938,40 @@
1143 }
1144
1145 // link an entry (inode #) to a directory
1146 -void add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name)
1147 +void add2dir(filesystem *fs, uint32 dnod, uint32 nod, const char* name, uint32 mode, uid_t uid, gid_t gid, time_t ctime)
1148 {
1149 blockwalker bw;
1150 uint32 bk;
1151 uint8 *b;
1152 directory *d;
1153 int reclen, nlen;
1154 - if((get_nod(fs, dnod)->i_mode & FM_IFMT) != FM_IFDIR)
1155 - errexit("can't add '%s' to a non-directory", name);
1156 + inode *node;
1157 + inode *pnode;
1158 +
1159 + /* Squash all permissions so files are owned by root
1160 + * and file permissions have group/other perms removed */
1161 + if (squash_uids) {
1162 + uid = gid = 0;
1163 + }
1164 + if (squash_perms) {
1165 + if (!S_ISLNK(mode)) {
1166 + mode &= ~(S_IWGRP | S_IWOTH);
1167 + mode &= ~(S_ISUID | S_ISGID);
1168 + }
1169 + }
1170 +
1171 + pnode = get_nod(fs, dnod);
1172 +
1173 + if(!S_ISDIR(pnode->i_mode))
1174 + error_msg_and_die("can't add '%s' to a non-directory", name);
1175 if(!*name)
1176 - errexit("bad name '%s' (not meaningful)", name);
1177 + error_msg_and_die("bad name '%s' (not meaningful)", name);
1178 if(strchr(name, '/'))
1179 - errexit("bad name '%s' (contains a slash)", name);
1180 + error_msg_and_die("bad name '%s' (contains a slash)", name);
1181 nlen = strlen(name);
1182 reclen = sizeof(directory) + rndup(nlen, 4);
1183 if(reclen > BLOCKSIZE)
1184 - errexit("bad name '%s' (too long)", name);
1185 + error_msg_and_die("bad name '%s' (too long)", name);
1186 init_bw(fs, dnod, &bw);
1187 while((bk = walk_bw(fs, dnod, &bw, 0, 0)) != WALK_END) // for all blocks in dir
1188 {
1189 @@ -691,9 +983,16 @@
1190 if((!d->d_inode) && (d->d_rec_len >= reclen))
1191 {
1192 d->d_inode = nod;
1193 - get_nod(fs, nod)->i_links_count++;
1194 + node = get_nod(fs, nod);
1195 + node->i_links_count++;
1196 d->d_name_len = nlen;
1197 - strncpy(d->d_name, name, nlen);
1198 + strncpy(d->d_name, name, rndup(nlen,4));
1199 + node->i_mode = mode;
1200 + node->i_uid = uid;
1201 + node->i_gid = gid;
1202 + node->i_atime = ctime;
1203 + node->i_ctime = ctime;
1204 + node->i_mtime = ctime;
1205 return;
1206 }
1207 // if entry with enough room (last one?), shrink it & use it
1208 @@ -705,9 +1004,16 @@
1209 d = (directory*) (((int8*)d) + d->d_rec_len);
1210 d->d_rec_len = reclen;
1211 d->d_inode = nod;
1212 - get_nod(fs, nod)->i_links_count++;
1213 + node = get_nod(fs, nod);
1214 + node->i_links_count++;
1215 d->d_name_len = nlen;
1216 - strncpy(d->d_name, name, nlen);
1217 + strncpy(d->d_name, name, rndup(nlen,4));
1218 + node->i_mode = mode;
1219 + node->i_uid = uid;
1220 + node->i_gid = gid;
1221 + node->i_atime = ctime;
1222 + node->i_ctime = ctime;
1223 + node->i_mtime = ctime;
1224 return;
1225 }
1226 }
1227 @@ -716,10 +1022,17 @@
1228 b = get_workblk();
1229 d = (directory*)b;
1230 d->d_inode = nod;
1231 - get_nod(fs, nod)->i_links_count++;
1232 + node = get_nod(fs, nod);
1233 + node->i_links_count++;
1234 d->d_rec_len = BLOCKSIZE;
1235 d->d_name_len = nlen;
1236 - strncpy(d->d_name, name, nlen);
1237 + strncpy(d->d_name, name, rndup(nlen,4));
1238 + node->i_mode = mode;
1239 + node->i_uid = uid;
1240 + node->i_gid = gid;
1241 + node->i_atime = ctime;
1242 + node->i_ctime = ctime;
1243 + node->i_mtime = ctime;
1244 extend_blk(fs, dnod, b, 1);
1245 get_nod(fs, dnod)->i_size += BLOCKSIZE;
1246 free_workblk(b);
1247 @@ -747,7 +1060,7 @@
1248 // find the inode of a full path
1249 uint32 find_path(filesystem *fs, uint32 nod, const char * name)
1250 {
1251 - char *p, *n, *n2 = strdup(name);
1252 + char *p, *n, *n2 = xstrdup(name);
1253 n = n2;
1254 while(*n == '/')
1255 {
1256 @@ -770,27 +1083,32 @@
1257 }
1258
1259 // make a full-fledged directory (i.e. with "." & "..")
1260 -uint32 mkdir_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode)
1261 +uint32 mkdir_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode,
1262 + uid_t uid, gid_t gid, time_t ctime)
1263 {
1264 uint32 nod;
1265 if((nod = find_dir(fs, parent_nod, name)))
1266 return nod;
1267 nod = alloc_nod(fs);
1268 - get_nod(fs, nod)->i_mode = FM_IFDIR | mode;
1269 - add2dir(fs, parent_nod, nod, name);
1270 - add2dir(fs, nod, nod, ".");
1271 - add2dir(fs, nod, parent_nod, "..");
1272 - fs->gd.bg_used_dirs_count++;
1273 + if (!(mode & FM_IFDIR))
1274 + mode |= FM_IFDIR;
1275 + add2dir(fs, parent_nod, nod, name, mode, uid, gid, ctime);
1276 + add2dir(fs, nod, nod, ".", mode, uid, gid, ctime);
1277 + add2dir(fs, nod, parent_nod, "..", mode, uid, gid, ctime);
1278 + fs->gd[GRP_GROUP_OF_INODE(fs,nod)].bg_used_dirs_count++;
1279 return nod;
1280 }
1281
1282 // make a symlink
1283 -uint32 mklink_fs(filesystem *fs, uint32 parent_nod, const char *name, size_t size, uint8 * b)
1284 +uint32 mklink_fs(filesystem *fs, uint32 parent_nod, const char *name, size_t size,
1285 + uint8 * b, uid_t uid, gid_t gid, time_t ctime)
1286 {
1287 + uint32 mode;
1288 uint32 nod = alloc_nod(fs);
1289 + mode = FM_IFLNK | FM_IRWXU | FM_IRWXG | FM_IRWXO;
1290 get_nod(fs, nod)->i_mode = FM_IFLNK | FM_IRWXU | FM_IRWXG | FM_IRWXO;
1291 get_nod(fs, nod)->i_size = size;
1292 - add2dir(fs, parent_nod, nod, name);
1293 + add2dir(fs, parent_nod, nod, name, mode, uid, gid, ctime);
1294 if(size <= 4 * (EXT2_TIND_BLOCK+1))
1295 {
1296 strncpy((char*)get_nod(fs, nod)->i_block, (char*)b, size);
1297 @@ -801,15 +1119,15 @@
1298 }
1299
1300 // make a file from a FILE*
1301 -uint32 mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, size_t size, FILE *f)
1302 +uint32 mkfile_fs(filesystem *fs, uint32 parent_nod, const char *name, uint32 mode, size_t size, FILE *f, uid_t uid, gid_t gid, time_t ctime)
1303 {
1304 uint8 * b;
1305 uint32 nod = alloc_nod(fs);
1306 - get_nod(fs, nod)->i_mode = FM_IFREG | mode;
1307 + mode |= FM_IFREG;
1308 get_nod(fs, nod)->i_size = size;
1309 - add2dir(fs, parent_nod, nod, name);
1310 + add2dir(fs, parent_nod, nod, name, mode, uid, gid, ctime);
1311 if(!(b = (uint8*)malloc(rndup(size, BLOCKSIZE))))
1312 - errexit("not enough mem to read file '%s'", name);
1313 + error_msg_and_die("not enough mem to read file '%s'", name);
1314 memset(b, 0,rndup(size, BLOCKSIZE));
1315 if(f)
1316 fread(b, size, 1, f);
1317 @@ -824,6 +1142,15 @@
1318 uint32 get_mode(struct stat *st)
1319 {
1320 uint32 mode = 0;
1321 +
1322 + /* Squash file permissions as needed */
1323 + if (squash_perms) {
1324 + if (!S_ISLNK(mode)) {
1325 + st->st_mode &= ~(S_IWGRP | S_IWOTH);
1326 + st->st_mode &= ~(S_ISUID | S_ISGID);
1327 + }
1328 + }
1329 +
1330 if(st->st_mode & S_IRUSR)
1331 mode |= FM_IRUSR | FM_IRGRP | FM_IROTH;
1332 if(st->st_mode & S_IWUSR)
1333 @@ -833,30 +1160,17 @@
1334 return mode;
1335 }
1336
1337 -// retrieves a mode info from a string
1338 -uint32 get_modestr(const char *p)
1339 -{
1340 - uint32 mode = 0;
1341 - if(p[0] == 'r')
1342 - mode |= FM_IRUSR | FM_IRGRP | FM_IROTH;
1343 - if(p[1] == 'w')
1344 - mode |= FM_IWUSR | FM_IWGRP | FM_IWOTH;
1345 - if(p[2] == 'x' || p[2] == 's')
1346 - mode |= FM_IXUSR | FM_IXGRP | FM_IXOTH;
1347 - return mode;
1348 -}
1349 -
1350 // basename of a path - free me
1351 char * basename(const char * fullpath)
1352 {
1353 char * p = strrchr(fullpath, '/');
1354 - return strdup(p ? p + 1 : fullpath);
1355 + return xstrdup(p ? p + 1 : fullpath);
1356 }
1357
1358 // dirname of a path - free me
1359 char * dirname(const char * fullpath)
1360 {
1361 - char * p, * n = strdup(fullpath);
1362 + char * p, * n = xstrdup(fullpath);
1363 if((p = strrchr(n, '/')))
1364 *(p+1) = 0;
1365 else
1366 @@ -864,66 +1178,6 @@
1367 return n;
1368 }
1369
1370 -// adds entries to the filesystem from a text file
1371 -void add2fs_from_file(filesystem *fs, uint32 this_nod, FILE * fh)
1372 -{
1373 - uint32 mode;
1374 - uint32 nod, nod2;
1375 - char cmod[11], *path, *name, *dir;
1376 - int major, minor;
1377 - while(fscanf(fh, "%10s", cmod))
1378 - {
1379 - if(feof(fh))
1380 - break;
1381 - mode = get_modestr(cmod + 1);
1382 - switch(*cmod)
1383 - {
1384 - case 'd':
1385 - fscanf(fh, "%" SCANF_PREFIX "s\n", SCANF_STRING(path));
1386 - break;
1387 - case 'c':
1388 - mode |= FM_IFCHR;
1389 - fscanf(fh, "%i, %i %" SCANF_PREFIX "s\n", &major, &minor, SCANF_STRING(path));
1390 - break;
1391 - case 'b':
1392 - mode |= FM_IFBLK;
1393 - fscanf(fh, "%i, %i %" SCANF_PREFIX "s\n", &major, &minor, SCANF_STRING(path));
1394 - break;
1395 - case '#':
1396 - while(fgetc(fh) != '\n');
1397 - continue;
1398 - default:
1399 - errexit("malformed text input file");
1400 - }
1401 - name = basename(path);
1402 - dir = dirname(path);
1403 - free(path);
1404 - if(!(nod = find_path(fs, this_nod, dir)))
1405 - errexit("can't find directory '%s' to create '%s''", dir, name);
1406 - free(dir);
1407 - if((!strcmp(name, ".")) || (!strcmp(name, "..")))
1408 - {
1409 - free(name);
1410 - continue;
1411 - }
1412 - switch(*cmod)
1413 - {
1414 - case 'd':
1415 - mkdir_fs(fs, nod, name, mode);
1416 - break;
1417 - case 'c':
1418 - case 'b':
1419 - nod2 = alloc_nod(fs);
1420 - get_nod(fs, nod2)->i_mode = mode;
1421 - ((uint8*)get_nod(fs, nod2)->i_block)[0] = minor;
1422 - ((uint8*)get_nod(fs, nod2)->i_block)[1] = major;
1423 - add2dir(fs, nod, nod2, name);
1424 - break;
1425 - }
1426 - free(name);
1427 - }
1428 -}
1429 -
1430 // adds a tree of entries to the filesystem from current dir
1431 void add2fs_from_dir(filesystem *fs, uint32 this_nod)
1432 {
1433 @@ -934,7 +1188,7 @@
1434 struct stat st;
1435 uint8 *b;
1436 if(!(dh = opendir(".")))
1437 - pexit(".");
1438 + perror_msg_and_die(".");
1439 while((dent = readdir(dh)))
1440 {
1441 if((!strcmp(dent->d_name, ".")) || (!strcmp(dent->d_name, "..")))
1442 @@ -948,31 +1202,27 @@
1443 get_nod(fs, nod)->i_mode = (((st.st_mode & S_IFMT) == S_IFCHR) ? FM_IFCHR : FM_IFBLK) | get_mode(&st);
1444 ((uint8*)get_nod(fs, nod)->i_block)[0] = (st.st_rdev & 0xff);
1445 ((uint8*)get_nod(fs, nod)->i_block)[1] = (st.st_rdev >> 8);
1446 - add2dir(fs, this_nod, nod, dent->d_name);
1447 + add2dir(fs, this_nod, nod, dent->d_name, st.st_mode, st.st_uid, st.st_gid, st.st_ctime);
1448 break;
1449 case S_IFLNK:
1450 - if(!(b = (uint8*)malloc(rndup(st.st_size, BLOCKSIZE))))
1451 - errexit("out of memory");
1452 - if(readlink(dent->d_name, (char*)b, st.st_size) < 0)
1453 - pexit(dent->d_name);
1454 - mklink_fs(fs, this_nod, dent->d_name, st.st_size, b);
1455 + b = xreadlink(dent->d_name);
1456 + mklink_fs(fs, this_nod, dent->d_name, st.st_size, b, st.st_uid, st.st_gid, st.st_ctime);
1457 free(b);
1458 break;
1459 case S_IFREG:
1460 - if(!(fh = fopen(dent->d_name, "r")))
1461 - pexit(dent->d_name);
1462 - mkfile_fs(fs, this_nod, dent->d_name, get_mode(&st), st.st_size, fh);
1463 + fh = xfopen(dent->d_name, "r");
1464 + mkfile_fs(fs, this_nod, dent->d_name, st.st_mode, st.st_size, fh, st.st_uid, st.st_gid, st.st_ctime);
1465 fclose(fh);
1466 break;
1467 case S_IFDIR:
1468 - nod = mkdir_fs(fs, this_nod, dent->d_name, get_mode(&st));
1469 + nod = mkdir_fs(fs, this_nod, dent->d_name, st.st_mode, st.st_uid, st.st_gid, st.st_ctime);
1470 if(chdir(dent->d_name) < 0)
1471 - pexit(dent->d_name);
1472 + perror_msg_and_die(dent->d_name);
1473 add2fs_from_dir(fs, nod);
1474 chdir("..");
1475 break;
1476 default:
1477 - fprintf(stderr, "ignoring entry %s", dent->d_name);
1478 + error_msg("ignoring entry %s", dent->d_name);
1479 }
1480 }
1481 closedir(dh);
1482 @@ -981,9 +1231,11 @@
1483 // endianness swap of x-indirect blocks
1484 void swap_goodblocks(filesystem *fs, inode *nod)
1485 {
1486 - int i;
1487 + int i,j,done=0;
1488 + uint32 *b,*b2;
1489 +
1490 int nblk = nod->i_blocks / INOBLK;
1491 - if((nod->i_size && !nblk) || (nod->i_mode & (FM_IFBLK | FM_IFCHR)))
1492 + if((nod->i_size && !nblk) || ((nod->i_mode & FM_IFBLK) == FM_IFBLK) || ((nod->i_mode & FM_IFCHR) == FM_IFCHR))
1493 for(i = 0; i <= EXT2_TIND_BLOCK; i++)
1494 nod->i_block[i] = swab32(nod->i_block[i]);
1495 if(nblk <= EXT2_IND_BLOCK)
1496 @@ -991,20 +1243,55 @@
1497 swap_block(get_blk(fs, nod->i_block[EXT2_IND_BLOCK]));
1498 if(nblk <= EXT2_IND_BLOCK + BLOCKSIZE/4)
1499 return;
1500 + /* Currently this will fail b'cos the number of blocks as stored
1501 + in i_blocks also includes the indirection blocks (see
1502 + walk_bw). But this function assumes that i_blocks only
1503 + stores the count of data blocks ( Actually according to
1504 + "Understanding the Linux Kernel" (Table 17-3 p502 1st Ed)
1505 + i_blocks IS supposed to store the count of data blocks). so
1506 + with a file of size 268K nblk would be 269.The above check
1507 + will be false even though double indirection hasn't been
1508 + started.This is benign as 0 means block 0 which has been
1509 + zeroed out and therefore points back to itself from any offset
1510 + */
1511 + assert(nod->i_block[EXT2_DIND_BLOCK] != 0);
1512 for(i = 0; i < BLOCKSIZE/4; i++)
1513 + /* Should this be...
1514 + if(nblk > EXT2_IND_BLOCK + BLOCKSIZE/4 + (BLOCKSIZE/4)*i )
1515 + */
1516 if(nblk > EXT2_IND_BLOCK + BLOCKSIZE/4 + i)
1517 swap_block(get_blk(fs, ((uint32*)get_blk(fs, nod->i_block[EXT2_DIND_BLOCK]))[i]));
1518 swap_block(get_blk(fs, nod->i_block[EXT2_DIND_BLOCK]));
1519 if(nblk <= EXT2_IND_BLOCK + BLOCKSIZE/4 + BLOCKSIZE/4 * BLOCKSIZE/4)
1520 return;
1521 - errexit("too big file on the filesystem");
1522 + /* Adding support for triple indirection */
1523 + b = (uint32*)get_blk(fs,nod->i_block[EXT2_TIND_BLOCK]);
1524 + for(i=0;i < BLOCKSIZE/4 && !done ; i++) {
1525 + b2 = (uint32*)get_blk(fs,b[i]);
1526 + for(j=0; j<BLOCKSIZE/4;j++) {
1527 + if (nblk > ( EXT2_IND_BLOCK + BLOCKSIZE/4 +
1528 + (BLOCKSIZE/4)*(BLOCKSIZE/4) +
1529 + i*(BLOCKSIZE/4)*(BLOCKSIZE/4) +
1530 + j*(BLOCKSIZE/4)) )
1531 + swap_block(get_blk(fs,b2[j]));
1532 + else {
1533 + done = 1;
1534 + break;
1535 + }
1536 + }
1537 + swap_block((uint8 *)b2);
1538 + }
1539 + swap_block((uint8 *)b);
1540 + return;
1541 }
1542
1543 void swap_badblocks(filesystem *fs, inode *nod)
1544 {
1545 - int i;
1546 + int i,j,done=0;
1547 + uint32 *b,*b2;
1548 +
1549 int nblk = nod->i_blocks / INOBLK;
1550 - if((nod->i_size && !nblk) || (nod->i_mode & (FM_IFBLK | FM_IFCHR)))
1551 + if((nod->i_size && !nblk) || ((nod->i_mode & FM_IFBLK) == FM_IFBLK) || ((nod->i_mode & FM_IFCHR) == FM_IFCHR))
1552 for(i = 0; i <= EXT2_TIND_BLOCK; i++)
1553 nod->i_block[i] = swab32(nod->i_block[i]);
1554 if(nblk <= EXT2_IND_BLOCK)
1555 @@ -1012,13 +1299,34 @@
1556 swap_block(get_blk(fs, nod->i_block[EXT2_IND_BLOCK]));
1557 if(nblk <= EXT2_IND_BLOCK + BLOCKSIZE/4)
1558 return;
1559 + /* See comment in swap_goodblocks */
1560 + assert(nod->i_block[EXT2_DIND_BLOCK] != 0);
1561 swap_block(get_blk(fs, nod->i_block[EXT2_DIND_BLOCK]));
1562 for(i = 0; i < BLOCKSIZE/4; i++)
1563 + /* See comment in swap_goodblocks */
1564 if(nblk > EXT2_IND_BLOCK + BLOCKSIZE/4 + i)
1565 swap_block(get_blk(fs, ((uint32*)get_blk(fs, nod->i_block[EXT2_DIND_BLOCK]))[i]));
1566 if(nblk <= EXT2_IND_BLOCK + BLOCKSIZE/4 + BLOCKSIZE/4 * BLOCKSIZE/4)
1567 return;
1568 - errexit("too big file on the filesystem");
1569 + /* Adding support for triple indirection */
1570 + b = (uint32*)get_blk(fs,nod->i_block[EXT2_TIND_BLOCK]);
1571 + swap_block((uint8 *)b);
1572 + for(i=0;i < BLOCKSIZE/4 && !done ; i++) {
1573 + b2 = (uint32*)get_blk(fs,b[i]);
1574 + swap_block((uint8 *)b2);
1575 + for(j=0; j<BLOCKSIZE/4;j++) {
1576 + if (nblk > ( EXT2_IND_BLOCK + BLOCKSIZE/4 +
1577 + (BLOCKSIZE/4)*(BLOCKSIZE/4) +
1578 + i*(BLOCKSIZE/4)*(BLOCKSIZE/4) +
1579 + j*(BLOCKSIZE/4)) )
1580 + swap_block(get_blk(fs,b2[j]));
1581 + else {
1582 + done = 1;
1583 + break;
1584 + }
1585 + }
1586 + }
1587 + return;
1588 }
1589
1590 // endianness swap of the whole filesystem
1591 @@ -1045,7 +1353,8 @@
1592 swap_goodblocks(fs, nod);
1593 swap_nod(nod);
1594 }
1595 - swap_gd(&fs->gd);
1596 + for(i=0;i<GRP_NBGROUPS(fs);i++)
1597 + swap_gd(&(fs->gd[i]));
1598 swap_sb(&fs->sb);
1599 }
1600
1601 @@ -1053,7 +1362,8 @@
1602 {
1603 int i;
1604 swap_sb(&fs->sb);
1605 - swap_gd(&fs->gd);
1606 + for(i=0;i<GRP_NBGROUPS(fs);i++)
1607 + swap_gd(&(fs->gd[i]));
1608 for(i = 1; i < fs->sb.s_inodes_count; i++)
1609 {
1610 inode *nod = get_nod(fs, i);
1611 @@ -1084,53 +1394,118 @@
1612 directory *d;
1613 uint8 * b;
1614 uint32 nod;
1615 + uint32 nbgroups,nbinodes_per_group,overhead_per_group,free_blocks,
1616 + free_blocks_per_group,nbblocks_per_group;
1617 + uint32 gd,itbl,ibmpos,bbmpos,itblpos;
1618 + int j;
1619 + uint8 *bbm,*ibm;
1620 + inode *itab0;
1621
1622 if(nbblocks < 16) // totally arbitrary
1623 - errexit("too small filesystem");
1624 - if(nbblocks >BLOCKS_PER_GROUP) // I build only one group
1625 - errexit("too big filesystem");
1626 + error_msg_and_die("too small filesystem");
1627 +
1628 + /* nbblocks is the total number of blocks in the system. First
1629 + * calculate how much overhead blocks - inode table blocks,bitmap
1630 + * blocks,group descriptor blocks etc. - are needed assuming each
1631 + * group has BLOCKS_PER_GROUP blocks.Then recalculate nbblocks with
1632 + * this figure. Each group has the same number of blocks. So the fs
1633 + * has a size atleast the given value but usually rounded off to a i
1634 + * higher number.
1635 + */
1636 + nbgroups = rndup(nbblocks,BLOCKS_PER_GROUP)/ BLOCKS_PER_GROUP;
1637 + nbinodes_per_group = nbinodes/nbgroups +1;
1638 + nbinodes_per_group = rndup(nbinodes_per_group, BLOCKSIZE/sizeof(inode));
1639 + if (nbinodes_per_group < 16)
1640 + nbinodes_per_group = 16; //minimum number b'cos the first 10 are reserved
1641 + overhead_per_group = 3 /*super block,ibm,bbm*/
1642 + + /* No. of blocks that the inodes occupy */
1643 + nbinodes_per_group *sizeof(inode)/BLOCKSIZE
1644 + + /* No. of blocks that group descriptors occupy */
1645 + rndup(nbgroups*sizeof(groupdescriptor),BLOCKSIZE)/BLOCKSIZE;
1646 + free_blocks = nbblocks - overhead_per_group * nbgroups - 1 /*boot block */;
1647 + free_blocks_per_group = free_blocks/nbgroups;
1648 + if (free_blocks > free_blocks_per_group * nbgroups)
1649 + free_blocks_per_group++;
1650 + nbblocks_per_group = free_blocks_per_group + overhead_per_group;
1651 + /* e2fsck complains if nbblocks_per_group is not a multiple of 8 */
1652 + nbblocks_per_group = rndup(nbblocks_per_group,8);
1653 + free_blocks_per_group = nbblocks_per_group - overhead_per_group;
1654 + if (nbblocks_per_group > BLOCKS_PER_GROUP) {
1655 + /* Can this happen ? */
1656 + nbblocks_per_group = BLOCKS_PER_GROUP;
1657 + free_blocks_per_group = nbblocks_per_group - overhead_per_group;
1658 + }
1659 + nbblocks = nbblocks_per_group * nbgroups + 1;
1660 +
1661 +
1662 if(!(fs = (filesystem*)calloc(nbblocks, BLOCKSIZE)))
1663 - errexit("not enough memory for filesystem");
1664 + error_msg_and_die("not enough memory for filesystem");
1665
1666 // create the superblock for an empty filesystem
1667 - fs->sb.s_inodes_count = rndup(nbinodes, BLOCKSIZE/sizeof(inode));
1668 + fs->sb.s_inodes_count = nbinodes_per_group * nbgroups;
1669 fs->sb.s_blocks_count = nbblocks;
1670 fs->sb.s_r_blocks_count = nbresrvd;
1671 - fs->sb.s_free_blocks_count = nbblocks;
1672 + fs->sb.s_free_blocks_count = free_blocks_per_group*nbgroups;
1673 fs->sb.s_free_inodes_count = fs->sb.s_inodes_count - EXT2_FIRST_INO + 1;
1674 fs->sb.s_first_data_block = (BLOCKSIZE == 1024);
1675 fs->sb.s_log_block_size = BLOCKSIZE >> 11;
1676 fs->sb.s_log_frag_size = BLOCKSIZE >> 11;
1677 - fs->sb.s_blocks_per_group = BLOCKS_PER_GROUP;
1678 - fs->sb.s_frags_per_group = BLOCKS_PER_GROUP;
1679 - fs->sb.s_inodes_per_group = fs->sb.s_inodes_count;
1680 + fs->sb.s_blocks_per_group = nbblocks_per_group;
1681 + fs->sb.s_frags_per_group = nbblocks_per_group;
1682 + fs->sb.s_inodes_per_group = nbinodes_per_group;
1683 fs->sb.s_magic = EXT2_MAGIC_NUMBER;
1684
1685 // set up groupdescriptors
1686 - fs->sb.s_free_blocks_count -= 5 + fs->sb.s_inodes_count * sizeof(inode) / BLOCKSIZE;
1687 - fs->gd.bg_free_blocks_count = fs->sb.s_free_blocks_count;
1688 - fs->gd.bg_free_inodes_count = fs->sb.s_free_inodes_count;
1689 - fs->gd.bg_used_dirs_count = 1;
1690 - fs->gd.bg_block_bitmap = 3;
1691 - fs->gd.bg_inode_bitmap = 4;
1692 - fs->gd.bg_inode_table = 5;
1693 -
1694 - // mark non-filesystem blocks and inodes as allocated
1695 - for(i = fs->sb.s_blocks_count; i <= BLOCKSIZE * 8; i++)
1696 - allocate(fs->bbm, i);
1697 - for(i = fs->sb.s_inodes_count + 1; i <= BLOCKSIZE * 8; i++)
1698 - allocate(fs->ibm, i);
1699 -
1700 - // mark system blocsk and inodes as allocated
1701 - for(i = 1; i <= 4 + fs->sb.s_inodes_count * sizeof(inode) / BLOCKSIZE; i++)
1702 - allocate(fs->bbm, i);
1703 - for(i = 1; i < EXT2_FIRST_INO; i++)
1704 - allocate(fs->ibm, i);
1705 -
1706 - // make root inode and directory
1707 - fs->itab[EXT2_ROOT_INO-1].i_mode = FM_IFDIR | FM_IRWXU | FM_IRWXG | FM_IRWXO;
1708 - fs->itab[EXT2_ROOT_INO-1].i_size = BLOCKSIZE;
1709 - fs->itab[EXT2_ROOT_INO-1].i_links_count = 2;
1710 + gd = rndup(nbgroups*sizeof(groupdescriptor),BLOCKSIZE)/BLOCKSIZE;
1711 + itbl = nbinodes_per_group*sizeof(inode)/BLOCKSIZE;
1712 + for(i = 0,bbmpos=2+gd,ibmpos=3+gd,itblpos =4+gd;
1713 + i<nbgroups;
1714 + i++, bbmpos += nbblocks_per_group,ibmpos += nbblocks_per_group,
1715 + itblpos += nbblocks_per_group) {
1716 +
1717 + fs->gd[i].bg_free_blocks_count = free_blocks_per_group;
1718 + fs->gd[i].bg_free_inodes_count = nbinodes_per_group;
1719 + fs->gd[i].bg_used_dirs_count = 0;
1720 + fs->gd[i].bg_block_bitmap = bbmpos;
1721 + fs->gd[i].bg_inode_bitmap = ibmpos;
1722 + fs->gd[i].bg_inode_table = itblpos;
1723 + }
1724 +
1725 + /* Mark non-filesystem blocks and inodes as allocated */
1726 + /* Mark system blocks and inodes as allocated */
1727 + for(i = 0; i<nbgroups;i++) {
1728 +
1729 + /* Block bitmap */
1730 + bbm = get_blk(fs,fs->gd[i].bg_block_bitmap);
1731 + //non-filesystem blocks.
1732 + for(j=fs->sb.s_blocks_per_group + 1; j <= BLOCKSIZE * 8; j++)
1733 + allocate(bbm, j);
1734 + //system blocks
1735 + for(j = 1; j <= 3+gd+itbl; j++)
1736 + allocate(bbm, j);
1737 +
1738 + /* Inode bitmap */
1739 + ibm = get_blk(fs,fs->gd[i].bg_inode_bitmap);
1740 + //non-filesystem inodes
1741 + for(j = fs->sb.s_inodes_per_group+1; j <= BLOCKSIZE * 8; j++)
1742 + allocate(ibm, j);
1743 + }
1744 +
1745 + /* We have groups now. Add the root filesystem in group 0 */
1746 + /* Also allocate the system inodes in group 0 and update */
1747 + /* directory count and inode count for group 0 */
1748 +
1749 + ibm = get_blk(fs,fs->gd[0].bg_inode_bitmap);
1750 + for(j = 1; j < EXT2_FIRST_INO; j++) {
1751 + allocate(ibm, j);
1752 + fs->gd[0].bg_free_inodes_count--;
1753 + }
1754 + fs->gd[0].bg_used_dirs_count = 1;
1755 + itab0 = (inode *)get_blk(fs,fs->gd[0].bg_inode_table);
1756 + itab0[EXT2_ROOT_INO-1].i_mode = FM_IFDIR | FM_IRWXU | FM_IRWXG | FM_IRWXO;
1757 + itab0[EXT2_ROOT_INO-1].i_size = BLOCKSIZE;
1758 + itab0[EXT2_ROOT_INO-1].i_links_count = 2;
1759 +
1760 b = get_workblk();
1761 d = (directory*)b;
1762 d->d_inode = EXT2_ROOT_INO;
1763 @@ -1147,9 +1522,14 @@
1764 // make lost+found directory and reserve blocks
1765 if(fs->sb.s_r_blocks_count)
1766 {
1767 - nod = mkdir_fs(fs, EXT2_ROOT_INO, "lost+found", FM_IRWXU | FM_IRWXG | FM_IRWXO);
1768 + nod = mkdir_fs(fs, EXT2_ROOT_INO, "lost+found", S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, 0, 0, time(NULL));
1769 memset(b, 0, BLOCKSIZE);
1770 ((directory*)b)->d_rec_len = BLOCKSIZE;
1771 + /* We run into problems with e2fsck if directory lost+found grows
1772 + * bigger than this. Need to find out why this happens - sundar
1773 + */
1774 + if (fs->sb.s_r_blocks_count > 2049 )
1775 + fs->sb.s_r_blocks_count=2049;
1776 for(i = 1; i < fs->sb.s_r_blocks_count; i++)
1777 extend_blk(fs, nod, b, 1);
1778 get_nod(fs, nod)->i_size = fs->sb.s_r_blocks_count * BLOCKSIZE;
1779 @@ -1170,24 +1550,24 @@
1780 // loads a filesystem from disk
1781 filesystem * load_fs(FILE * fh, int swapit)
1782 {
1783 - size_t fssize;
1784 + size_t fssize = 0;
1785 filesystem *fs;
1786 if((fseek(fh, 0, SEEK_END) < 0) || ((fssize = ftell(fh)) < 0))
1787 - pexit("input filesystem image");
1788 + perror_msg_and_die("input filesystem image");
1789 rewind(fh);
1790 fssize = (fssize + BLOCKSIZE - 1) / BLOCKSIZE;
1791 if(fssize < 16) // totally arbitrary
1792 - errexit("too small filesystem");
1793 - if(fssize > BLOCKS_PER_GROUP) // I build only one group
1794 - errexit("too big filesystem");
1795 + error_msg_and_die("too small filesystem");
1796 +/* if(fssize > BLOCKS_PER_GROUP) // I build only one group
1797 + error_msg_and_die("too big filesystem"); */
1798 if(!(fs = (filesystem*)calloc(fssize, BLOCKSIZE)))
1799 - errexit("not enough memory for filesystem");
1800 + error_msg_and_die("not enough memory for filesystem");
1801 if(fread(fs, BLOCKSIZE, fssize, fh) != fssize)
1802 - pexit("input filesystem image");
1803 + perror_msg_and_die("input filesystem image");
1804 if(swapit)
1805 swap_badfs(fs);
1806 if(fs->sb.s_rev_level || (fs->sb.s_magic != EXT2_MAGIC_NUMBER))
1807 - errexit("not a suitable ext2 filesystem");
1808 + error_msg_and_die("not a suitable ext2 filesystem");
1809 return fs;
1810 }
1811
1812 @@ -1230,9 +1610,9 @@
1813 while((bk = walk_bw(fs, nod, &bw, 0, 0)) != WALK_END)
1814 {
1815 if(fsize <= 0)
1816 - errexit("wrong size while saving inode %d", nod);
1817 + error_msg_and_die("wrong size while saving inode %d", nod);
1818 if(fwrite(get_blk(fs, bk), (fsize > BLOCKSIZE) ? BLOCKSIZE : fsize, 1, f) != 1)
1819 - errexit("error while saving inode %d", nod);
1820 + error_msg_and_die("error while saving inode %d", nod);
1821 fsize -= BLOCKSIZE;
1822 }
1823 }
1824 @@ -1250,7 +1630,7 @@
1825 {
1826 int i, j;
1827 if(fsize <= 0)
1828 - errexit("wrong size while saving inode %d", nod);
1829 + error_msg_and_die("wrong size while saving inode %d", nod);
1830 b = get_blk(fs, bk);
1831 for(i = 0; i < 64; i++)
1832 {
1833 @@ -1406,7 +1786,7 @@
1834 s = (nod >= EXT2_FIRST_INO) ? "normal" : "unknown reserved";
1835 }
1836 printf("inode %d (%s, %d links): ", nod, s, get_nod(fs, nod)->i_links_count);
1837 - if(!allocated(fs->ibm, nod))
1838 + if(!allocated(GRP_GET_INODE_BITMAP(fs,nod), GRP_IBM_OFFSET(fs,nod)))
1839 {
1840 printf("unallocated\n");
1841 return;
1842 @@ -1440,24 +1820,46 @@
1843 default:
1844 list_blocks(fs, nod);
1845 }
1846 + printf("Done with inode %d\n",nod);
1847 }
1848
1849 // describes various fields in a filesystem
1850 void print_fs(filesystem *fs)
1851 {
1852 - int i;
1853 - printf("%d blocks (%d free, %d reserved), first data block: %d\n", fs->sb.s_blocks_count, fs->sb.s_free_blocks_count, fs->sb.s_r_blocks_count, fs->sb.s_first_data_block);
1854 - printf("%d inodes (%d free)\n", fs->sb.s_inodes_count, fs->sb.s_free_inodes_count);
1855 - printf("block size = %d, frag size = %d\n", fs->sb.s_log_block_size ? (fs->sb.s_log_block_size << 11) : 1024, fs->sb.s_log_frag_size ? (fs->sb.s_log_frag_size << 11) : 1024);
1856 - printf("%d blocks per group, %d frags per group, %d inodes per group\n", fs->sb.s_blocks_per_group, fs->sb.s_frags_per_group, fs->sb.s_inodes_per_group);
1857 - printf("block bitmap: block %d, inode bitmap: block %d, inode table: block %d\n", fs->gd.bg_block_bitmap, fs->gd.bg_inode_bitmap, fs->gd.bg_inode_table);
1858 - printf("block bitmap allocation:\n");
1859 - print_bm(fs->bbm, fs->sb.s_blocks_count);
1860 - printf("inode bitmap allocation:\n");
1861 - print_bm(fs->ibm, fs->sb.s_inodes_count);
1862 - for(i=1; i<=fs->sb.s_inodes_count; i++)
1863 - if(allocated(fs->ibm, i))
1864 - print_inode(fs, i);
1865 + int i,j;
1866 + uint8 *ibm;
1867 +
1868 + printf("%d blocks (%d free, %d reserved), first data block: %d\n",
1869 + fs->sb.s_blocks_count, fs->sb.s_free_blocks_count,
1870 + fs->sb.s_r_blocks_count, fs->sb.s_first_data_block);
1871 + printf("%d inodes (%d free)\n", fs->sb.s_inodes_count,
1872 + fs->sb.s_free_inodes_count);
1873 + printf("block size = %d, frag size = %d\n",
1874 + fs->sb.s_log_block_size ? (fs->sb.s_log_block_size << 11) : 1024,
1875 + fs->sb.s_log_frag_size ? (fs->sb.s_log_frag_size << 11) : 1024);
1876 + printf("Number of groups: %d\n",GRP_NBGROUPS(fs));
1877 + printf("%d blocks per group,%d frags per group,%d inodes per group\n",
1878 + fs->sb.s_blocks_per_group, fs->sb.s_frags_per_group,
1879 + fs->sb.s_inodes_per_group);
1880 + printf("Size of inode table: %d blocks\n",
1881 + fs->sb.s_inodes_per_group * sizeof(inode)/BLOCKSIZE);
1882 + for (i = 0; i < GRP_NBGROUPS(fs); i++) {
1883 + printf("Group No: %d\n", i);
1884 + printf("block bitmap: block %d,inode bitmap: block %d, inode table: block %d\n",
1885 + fs->gd[i].bg_block_bitmap, fs->gd[i].bg_inode_bitmap,
1886 + fs->gd[i].bg_inode_table);
1887 + printf("Free blocks count: %d\n",fs->gd[i].bg_free_blocks_count);
1888 + printf("Free inodes count: %d\n",fs->gd[i].bg_free_inodes_count);
1889 + printf("Used dir count: %d\n",fs->gd[i].bg_used_dirs_count);
1890 + printf("block bitmap allocation:\n");
1891 + print_bm(GRP_GET_GROUP_BBM(fs, i),fs->sb.s_blocks_per_group);
1892 + printf("inode bitmap allocation:\n");
1893 + ibm = GRP_GET_GROUP_IBM(fs, i);
1894 + print_bm(ibm, fs->sb.s_inodes_per_group);
1895 + for (j = 1; j <= fs->sb.s_inodes_per_group; j++)
1896 + if (allocated(ibm, j))
1897 + print_inode(fs, i*fs->sb.s_inodes_per_group + j);
1898 + }
1899 }
1900
1901 void dump_fs(filesystem *fs, FILE * fh, int swapit)
1902 @@ -1467,31 +1869,234 @@
1903 if(swapit)
1904 swap_goodfs(fs);
1905 if(fwrite(fs, BLOCKSIZE, nbblocks, fh) < nbblocks)
1906 - pexit("output filesystem image");
1907 + perror_msg_and_die("output filesystem image");
1908 if(swapit)
1909 swap_badfs(fs);
1910 }
1911
1912 +/* device table entries take the form of:
1913 + <path> <type> <mode> <uid> <gid> <major> <minor> <start> <inc> <count>
1914 + /dev/mem c 640 0 0 1 1 0 0 -
1915 +
1916 + type can be one of:
1917 + f A regular file
1918 + d Directory
1919 + c Character special device file
1920 + b Block special device file
1921 + p Fifo (named pipe)
1922 +
1923 + I don't bother with symlinks (permissions are irrelevant), hard
1924 + links (special cases of regular files), or sockets (why bother).
1925 +
1926 + Regular files must exist in the target root directory. If a char,
1927 + block, fifo, or directory does not exist, it will be created.
1928 +*/
1929 +static int interpret_table_entry(filesystem *fs, char *line)
1930 +{
1931 + char type, *name = NULL, *tmp, *dir, *bname;
1932 + unsigned long mode = 0755, uid = 0, gid = 0, major = 0, minor = 0;
1933 + unsigned long start = 0, increment = 1, count = 0;
1934 + inode *entry;
1935 + uint32 nod, parent;
1936 +
1937 + if (sscanf (line, "%" SCANF_PREFIX "s %c %lo %lu %lu %lu %lu %lu %lu %lu",
1938 + SCANF_STRING(name), &type, &mode, &uid, &gid, &major, &minor,
1939 + &start, &increment, &count) < 0)
1940 + {
1941 + return 1;
1942 + }
1943 +
1944 + if (!strcmp(name, "/")) {
1945 + error_msg_and_die("Device table entries require absolute paths");
1946 + }
1947 +
1948 + /* Check if this file already exists... */
1949 + switch (type) {
1950 + case 'd':
1951 + mode |= S_IFDIR;
1952 + break;
1953 + case 'f':
1954 + mode |= S_IFREG;
1955 + break;
1956 + case 'p':
1957 + mode |= S_IFIFO;
1958 + break;
1959 + case 'c':
1960 + mode |= S_IFCHR;
1961 + break;
1962 + case 'b':
1963 + mode |= S_IFBLK;
1964 + break;
1965 + default:
1966 + error_msg_and_die("Unsupported file type");
1967 + }
1968 + nod = 0;
1969 + if (count==0)
1970 + nod = find_path(fs, EXT2_ROOT_INO, name);
1971 + if (nod) {
1972 + /* Ok, we just need to fixup an existing entry
1973 + * and we will be all done... */
1974 + entry = get_nod(fs, nod);
1975 + entry->i_uid = uid;
1976 + entry->i_gid = gid;
1977 + entry->i_mode = mode;
1978 + if (major) {
1979 + dev_t rdev = makedev(major, minor);
1980 + ((uint8*)entry->i_block)[0] = (rdev & 0xff);
1981 + ((uint8*)entry->i_block)[1] = (rdev >> 8);
1982 + }
1983 + } else {
1984 + /* Try and find our parent now */
1985 + tmp = xstrdup(name);
1986 + dir = dirname(tmp);
1987 + parent = find_path(fs, EXT2_ROOT_INO, dir);
1988 + free(tmp);
1989 + if (!parent) {
1990 + error_msg ("skipping device_table entry '%s': no parent directory!", name);
1991 + free(name);
1992 + return 1;
1993 + }
1994 +
1995 + tmp = xstrdup(name);
1996 + bname = xstrdup(basename(tmp));
1997 + free(tmp);
1998 + switch (type) {
1999 + case 'd':
2000 + mkdir_fs(fs, parent, bname, mode|FM_IFDIR, uid, gid, time(NULL));
2001 + break;
2002 + case 'f':
2003 +#if 0
2004 + {
2005 + // This is a bit odd.. This will try to include
2006 + // the file of the same name from your _build_
2007 + // system... Probably a very bad idea....
2008 + struct stat st;
2009 + FILE *fh = xfopen(name, "r");
2010 + lstat(name, &st);
2011 + mkfile_fs(fs, parent, bname, mode|FM_IFREG, st.st_size, fh, uid, gid, st.st_ctime);
2012 + fclose(fh);
2013 + }
2014 +#else
2015 + error_msg("ignoring entry %s", name);
2016 +#endif
2017 + break;
2018 + case 'p':
2019 + error_msg("ignoring entry %s", name);
2020 + break;
2021 + case 'c':
2022 + case 'b':
2023 + if (count > 0) {
2024 + dev_t rdev;
2025 + char *dname;
2026 + unsigned long i;
2027 + for (i = start; i < count; i++) {
2028 + asprintf(&dname, "%s%lu", bname, i);
2029 + nod = find_path(fs, EXT2_ROOT_INO, dname);
2030 + if (nod) {
2031 + /* We just need to fixup an existing entry */
2032 + entry = get_nod(fs, nod);
2033 + } else {
2034 + nod = alloc_nod(fs);
2035 + add2dir(fs, parent, nod, dname, mode, uid, gid, time(NULL));
2036 + entry = get_nod(fs, nod);
2037 + }
2038 + entry->i_uid = uid;
2039 + entry->i_gid = gid;
2040 + entry->i_mode = mode;
2041 + rdev = makedev(major, minor + (i * increment - start));
2042 + ((uint8*)entry->i_block)[0] = (rdev & 0xff);
2043 + ((uint8*)entry->i_block)[1] = (rdev >> 8);
2044 + free(dname);
2045 + }
2046 + } else {
2047 + dev_t rdev = makedev(major, minor);
2048 + nod = alloc_nod(fs);
2049 + add2dir(fs, parent, nod, bname, mode, uid, gid, time(NULL));
2050 + entry = get_nod(fs, nod);
2051 + ((uint8*)entry->i_block)[0] = (rdev & 0xff);
2052 + ((uint8*)entry->i_block)[1] = (rdev >> 8);
2053 + }
2054 + break;
2055 + default:
2056 + error_msg_and_die("Unsupported file type");
2057 + }
2058 + free(bname);
2059 + }
2060 + free(name);
2061 + return 0;
2062 +}
2063 +
2064 +static int parse_device_table(filesystem *root, FILE * file)
2065 +{
2066 + char *line;
2067 + int status = 0;
2068 + size_t length = 0;
2069 +
2070 + /* Turn off squash, since we must ensure that values
2071 + * entered via the device table are not squashed */
2072 + squash_uids = 0;
2073 + squash_perms = 0;
2074 +
2075 + /* Looks ok so far. The general plan now is to read in one
2076 + * line at a time, check for leading comment delimiters ('#'),
2077 + * then try and parse the line as a device table. If we fail
2078 + * to parse things, try and help the poor fool to fix their
2079 + * device table with a useful error msg... */
2080 + line = NULL;
2081 + while (getline(&line, &length, file) != -1) {
2082 + /* First trim off any whitespace */
2083 + int len = strlen(line);
2084 +
2085 + /* trim trailing whitespace */
2086 + while (len > 0 && isspace(line[len - 1]))
2087 + line[--len] = '\0';
2088 + /* trim leading whitespace */
2089 + memmove(line, &line[strspn(line, " \n\r\t\v")], len);
2090 +
2091 + /* How long are we after trimming? */
2092 + len = strlen(line);
2093 +
2094 + /* If this is NOT a comment line, try to interpret it */
2095 + if (len && *line != '#') {
2096 + if (interpret_table_entry(root, line))
2097 + status = 1;
2098 + }
2099 +
2100 + free(line);
2101 + line = NULL;
2102 + }
2103 + fclose(file);
2104 +
2105 + return status;
2106 +}
2107 +
2108 +/*
2109 +Local Variables:
2110 +c-file-style: "linux"
2111 +c-basic-offset: 4
2112 +tab-width: 4
2113 +End:
2114 +*/
2115 +
2116 void showhelp(void)
2117 {
2118 fprintf(stderr, "Usage: %s [options] image\n"
2119 "Create an ext2 filesystem image from directories/files\n\n"
2120 - " -x image Use this image as a starting point\n"
2121 - " -d directory Add this directory as source\n"
2122 - " -f file Add nodes (e.g. devices) from this spec file\n"
2123 - " -b blocks Size in blocks\n"
2124 - " -i inodes Number of inodes\n"
2125 - " -r reserved Number of reserved blocks\n"
2126 - " -g path Generate a block map file for this path\n"
2127 - " -e value Fill unallocated blocks with value\n"
2128 - " -z Make files with holes\n"
2129 - " -v Print resulting filesystem structure\n"
2130 - " -h Show this help\n\n"
2131 - "Example of spec file:\n"
2132 - "drwx /dev\n"
2133 - "crw- 10,190 /dev/lcd\n"
2134 - "brw- 1,0 /dev/ram0\n\n"
2135 - "Report bugs to xavier.bestel@free.fr\n", argv0);
2136 + " -x image Use this image as a starting point\n"
2137 + " -d directory Add this directory as source\n"
2138 + " -b blocks Size in blocks\n"
2139 + " -i inodes Number of inodes\n"
2140 + " -r reserved Number of reserved blocks\n"
2141 + " -g path Generate a block map file for this path\n"
2142 + " -e value Fill unallocated blocks with value\n"
2143 + " -z Make files with holes\n"
2144 + " -D,-f Use the named FILE as a device table file\n"
2145 + " -q Squash permissions and owners making all files be owned by root\n"
2146 + " -U Squash owners making all files be owned by root\n"
2147 + " -P Squash permissions on all files\n"
2148 + " -v Print resulting filesystem structure\n"
2149 + " -h Show this help\n\n"
2150 + "Report bugs to xavier.bestel@free.fr\n", app_name);
2151 }
2152
2153 #define MAX_DOPT 128
2154 @@ -1521,21 +2126,17 @@
2155 filesystem *fs;
2156 int i;
2157 int c;
2158 + struct stat sb;
2159 + FILE *devtable = NULL;
2160
2161 - argv0 = argv[0];
2162 - if(argc <= 1)
2163 - {
2164 - showhelp();
2165 - exit(1);
2166 - }
2167 - while((c = getopt(argc, argv, "x:f:d:b:i:r:g:e:zvh")) != EOF)
2168 + app_name = argv[0];
2169 + while((c = getopt(argc, argv, "x:d:b:i:r:g:e:zvhD:f:qUP")) != EOF)
2170 switch(c)
2171 {
2172 case 'x':
2173 fsin = optarg;
2174 break;
2175 case 'd':
2176 - case 'f':
2177 dopt[didx++] = optarg;
2178 break;
2179 case 'b':
2180 @@ -1556,6 +2157,24 @@
2181 case 'z':
2182 holes = 1;
2183 break;
2184 + case 'f':
2185 + case 'D':
2186 + devtable = xfopen(optarg, "r");
2187 + if (fstat(fileno(devtable), &sb) < 0)
2188 + perror_msg_and_die(optarg);
2189 + if (sb.st_size < 10)
2190 + error_msg_and_die("%s: not a proper device table file", optarg);
2191 + break;
2192 + case 'q':
2193 + squash_uids = 1;
2194 + squash_perms = 1;
2195 + break;
2196 + case 'U':
2197 + squash_uids = 1;
2198 + break;
2199 + case 'P':
2200 + squash_perms = 1;
2201 + break;
2202 case 'v':
2203 verbose = 1;
2204 break;
2205 @@ -1566,16 +2185,14 @@
2206 exit(1);
2207 }
2208 if(optind < (argc - 1))
2209 - errexit("too many arguments");
2210 + error_msg_and_die("too many arguments");
2211 if(optind == (argc - 1))
2212 fsout = argv[optind];
2213 if(fsin)
2214 {
2215 if(strcmp(fsin, "-"))
2216 {
2217 - FILE * fh = fopen(fsin, "r");
2218 - if(!fh)
2219 - pexit(fsin);
2220 + FILE * fh = xfopen(fsin, "r");
2221 fs = load_fs(fh, bigendian);
2222 fclose(fh);
2223 }
2224 @@ -1585,7 +2202,7 @@
2225 else
2226 {
2227 if(nbblocks == -1)
2228 - errexit("filesystem size unspecified");
2229 + error_msg_and_die("filesystem size unspecified");
2230 if(nbinodes == -1)
2231 nbinodes = nbblocks * BLOCKSIZE / rndup(BYTES_PER_INODE, BLOCKSIZE);
2232 if(nbresrvd == -1)
2233 @@ -1595,35 +2212,30 @@
2234 for(i = 0; i < didx; i++)
2235 {
2236 struct stat st;
2237 - FILE *fh;
2238 char *pdir;
2239 stat(dopt[i], &st);
2240 switch(st.st_mode & S_IFMT)
2241 {
2242 - case S_IFREG:
2243 - if(!(fh = fopen(dopt[i], "r")))
2244 - pexit(dopt[i]);
2245 - add2fs_from_file(fs, EXT2_ROOT_INO, fh);
2246 - fclose(fh);
2247 - break;
2248 case S_IFDIR:
2249 if(!(pdir = getcwd(0, GETCWD_SIZE)))
2250 - pexit(dopt[i]);
2251 + perror_msg_and_die(dopt[i]);
2252 if(chdir(dopt[i]) < 0)
2253 - pexit(dopt[i]);
2254 + perror_msg_and_die(dopt[i]);
2255 add2fs_from_dir(fs, EXT2_ROOT_INO);
2256 if(chdir(pdir) < 0)
2257 - pexit(pdir);
2258 + perror_msg_and_die(pdir);
2259 free(pdir);
2260 break;
2261 default:
2262 - errexit("%s in neither a file nor a directory", dopt[i]);
2263 + error_msg_and_die("%s is neither a file nor a directory", dopt[i]);
2264 }
2265 }
2266 if(emptyval)
2267 for(i = 1; i < fs->sb.s_blocks_count; i++)
2268 - if(!allocated(fs->bbm, i))
2269 + if(!allocated(GRP_GET_BLOCK_BITMAP(fs,i),GRP_BBM_OFFSET(fs,i)))
2270 memset(get_blk(fs, i), emptyval, BLOCKSIZE);
2271 + if(devtable)
2272 + parse_device_table(fs, devtable);
2273 if(verbose)
2274 print_fs(fs);
2275 for(i = 0; i < gidx; i++)
2276 @@ -1633,21 +2245,18 @@
2277 char *p;
2278 FILE *fh;
2279 if(!(nod = find_path(fs, EXT2_ROOT_INO, gopt[i])))
2280 - errexit("path %s not found in filesystem", gopt[i]);
2281 + error_msg_and_die("path %s not found in filesystem", gopt[i]);
2282 while((p = strchr(gopt[i], '/')))
2283 *p = '_';
2284 snprintf(fname, MAX_FILENAME-1, "%s.blk", gopt[i]);
2285 - if(!(fh = fopen(fname, "w")))
2286 - pexit(fname);
2287 + fh = xfopen(fname, "w");
2288 fprintf(fh, "%d:", get_nod(fs, nod)->i_size);
2289 flist_blocks(fs, nod, fh);
2290 fclose(fh);
2291 }
2292 if(strcmp(fsout, "-"))
2293 {
2294 - FILE * fh = fopen(fsout, "w");
2295 - if(!fh)
2296 - pexit(fsout);
2297 + FILE * fh = xfopen(fsout, "w");
2298 dump_fs(fs, fh, bigendian);
2299 fclose(fh);
2300 }
2301 diff -urN genext2fs-1.3.orig/test-mount.sh genext2fs-1.3/test-mount.sh
2302 --- genext2fs-1.3.orig/test-mount.sh 1969-12-31 17:00:00.000000000 -0700
2303 +++ genext2fs-1.3/test-mount.sh 2003-04-21 01:41:42.000000000 -0600
2304 @@ -0,0 +1,96 @@
2305 +#!/bin/sh
2306 +set -e
2307 +
2308 +cleanup () {
2309 + set +e
2310 + umount mnt 2>/dev/null
2311 + rm -rf mnt ext2.img lsout fout test 2>/dev/null
2312 +}
2313 +
2314 +# dtest - Uses the -d directory option of genext2fs
2315 +# Creates an image with a file of given size and verifies it
2316 +# Usage: dtest file-size number-of-blocks
2317 +dtest () {
2318 + size=$1; blocks=$2;fname=$size
2319 + echo "Testing with file of size $size "
2320 + mkdir -p test
2321 + cd test
2322 + dd if=/dev/zero of=file.$1 bs=1 count=$size
2323 + cd ..
2324 + ./genext2fs -b $blocks -d test ext2.img
2325 + md5=`md5sum ext2.img | cut -f1 -d " "`
2326 + if ! /sbin/e2fsck -fn ext2.img ; then
2327 + echo "fsck failed"
2328 + echo FAILED
2329 + cleanup
2330 + exit 1
2331 + fi
2332 + mkdir -p mnt
2333 + if ! mount -t ext2 -o loop ext2.img mnt; then
2334 + echo FAILED
2335 + cleanup
2336 + exit 1
2337 + fi
2338 + if (! [ -f mnt/file.$fname ]) || \
2339 + [ $fname != "`ls -al mnt | grep file.$fname |awk '{print $5}'`" ] ; then
2340 + echo FAILED
2341 + cleanup
2342 + exit 1
2343 + fi
2344 + echo PASSED "(md5 checksum for the image: $md5)"
2345 + cleanup
2346 +}
2347 +
2348 +# ftest - Uses the -f spec-file option of genext2fs
2349 +# Creates an image with the devices mentioned in the given spec
2350 +# file and verifies it
2351 +# Usage: ftest spec-file number-of-blocks
2352 +ftest () {
2353 + fname=$1; blocks=$2;
2354 + echo "Testing with devices file $fname"
2355 + ./genext2fs -b $blocks -f $fname ext2.img
2356 + md5=`md5sum ext2.img | cut -f 1 -d " "`
2357 + if ! /sbin/e2fsck -fn ext2.img ; then
2358 + echo "fsck failed"
2359 + echo FAILED
2360 + cleanup
2361 + exit 1
2362 + fi
2363 + mkdir -p mnt
2364 + if ! mount -t ext2 -o loop ext2.img mnt; then
2365 + echo FAILED
2366 + cleanup
2367 + exit 1
2368 + fi
2369 + if ! [ -d mnt/dev ] ; then
2370 + echo FAILED
2371 + cleanup
2372 + exit 1
2373 + fi
2374 + cat dev.txt | grep ^[bc] | \
2375 + awk '{print $1substr($1,2)substr($1,2),$2,$3}'| \
2376 + sort -d -k3.6 > fout
2377 + ls -al mnt/dev | grep ^[bc] | \
2378 + awk '{ print $1,$5$6,"/dev/"$10}' | \
2379 + sort -d -k3.6 > lsout
2380 + if ! diff fout lsout ; then
2381 + echo FAILED
2382 + cleanup
2383 + exit 1
2384 + fi
2385 + echo PASSED "(md5 checksum for the image: $md5)"
2386 + cleanup
2387 +}
2388 +
2389 +dtest 0 4096
2390 +dtest 0 8193
2391 +dtest 0 8194
2392 +dtest 1 4096
2393 +dtest 12288 4096
2394 +dtest 274432 4096
2395 +dtest 8388608 9000
2396 +dtest 16777216 20000
2397 +
2398 +ftest dev.txt 4096
2399 +
2400 +exit 0
2401 diff -urN genext2fs-1.3.orig/test.sh genext2fs-1.3/test.sh
2402 --- genext2fs-1.3.orig/test.sh 1969-12-31 17:00:00.000000000 -0700
2403 +++ genext2fs-1.3/test.sh 2003-04-21 01:41:42.000000000 -0600
2404 @@ -0,0 +1,53 @@
2405 +#!/bin/sh
2406 +set -e
2407 +
2408 +# dtest - Uses the -d directory option of genext2fs
2409 +# Creates an image with a file of given size and verifies it
2410 +# Usage: dtest file-size number-of-blocks correct-checksum
2411 +dtest () {
2412 + size=$1; blocks=$2; checksum=$3
2413 + echo "Testing with file of size $size "
2414 + mkdir -p test
2415 + cd test
2416 + dd if=/dev/zero of=file.$1 bs=1 count=$size
2417 + cd ..
2418 + ./genext2fs -b $blocks -d test ext2.img
2419 + md5=`md5sum ext2.img | cut -d" " -f1`
2420 + rm -rf ext2.img test
2421 + if [ $md5 == $checksum ] ; then
2422 + echo PASSED
2423 + else
2424 + echo FAILED
2425 + exit 1
2426 + fi
2427 +}
2428 +
2429 +# ftest - Uses the -f spec-file option of genext2fs
2430 +# Creates an image with the devices mentioned in the given spec
2431 +# file and verifies it
2432 +# Usage: ftest spec-file number-of-blocks correct-checksum
2433 +ftest () {
2434 + fname=$1; blocks=$2; checksum=$3
2435 + echo "Testing with devices file $fname"
2436 + ./genext2fs -b $blocks -f $fname ext2.img
2437 + md5=`md5sum ext2.img | cut -d" " -f1`
2438 + rm -rf ext2.img
2439 + if [ $md5 == $checksum ] ; then
2440 + echo PASSED
2441 + else
2442 + echo FAILED
2443 + exit 1
2444 + fi
2445 +}
2446 +
2447 +dtest 0 4096 491a43ab93c2e5c186c9f1f72d88e5c5
2448 +dtest 0 8193 6289224f0b7f151994479ba156c43505
2449 +dtest 0 8194 3272c43c25e8d0c3768935861a643a65
2450 +dtest 1 4096 5ee24486d33af88c63080b09d8cadfb5
2451 +dtest 12288 4096 494498364defdc27b2770d1f9c1e3387
2452 +dtest 274432 4096 65c4bd8d30bf563fa5434119a12abff1
2453 +dtest 8388608 9000 9a49b0461ee236b7fd7c452fb6a1f2dc
2454 +dtest 16777216 20000 91e16429c901b68d30f783263f0611b7
2455 +
2456 +ftest dev.txt 4096 921ee9343b0759e16ad8d979d7dd16ec
2457 +exit 0
This page took 0.162505 seconds and 5 git commands to generate.