Fixing the UniPlus+ root disk fsck by hand (very very long)

From: Ray Arachelian <ray_at_email.domain.hidden>
Date: Tue, 25 Mar 2008 17:05:46 -0400

This is a very long description of my attempts to fix the root disk.

If you want to try it and don't care about the details, (I haven't tried this yet) please break out lisafsh-tool and skip to the very end, then copy the instructions into lisafsh-tool after you've used it to open the root disk.

My interest in providing this very detailed rant is so that there's a record of exactly what I did here, so that incase I've missed something somewhere, it can be found and corrected. It's a very old school kind of thing for us Unix graybeards.

I'm hopeful that this will work, but it might not, YMMV and all that. Someone please try it on a real Lisa - I can't do this now and won't have the time or energy to attempt it until at least the weekend, and even then, I might not be able to do so...

Note that even if I did everything correctly here, there may be further corruption on the disk preventing UniPlus+ from working...

For those of you who want to attempt a fix without worrying about how it works, skip to the bottom... Well, you should at least know how to use lisafsh-tool.

So for the remaining audience of one or two insane enough to follow me into the bowels of the Unix filesystem, here we go...

Here, when I say "we", I'm referring to myself, and the reader who hopefully won't fall asleep while reading this. It's meant to be followed along as an exercise in fixing unix file systems by hand as well as an attempt to get UniPlus+ working. This process might come in handy in fixing other Unix file systems, so you never know - might be worth your time and trouble to understand what is being done here, how and why. It'll be slightly (or vastly) different on other Unixen.

You'll need a compiled lisafsh-tool for your machine (it comes with LisaEm, download: http://lisaem.sunder.net/downloads ) You'll need to know how to use it, so ask it for help after you run it like this: "lisafsh-tool root-filesystem-b.image"

You'll also need the UniPlus+ manuals (see: http://bitsavers.org/pdf/unisoft/ - specifically read page 281 of the UniPlus+ User's Manual Sections 2-6.pdf ) If you've extracted the tar floppies as per my previous post on 3/22, that will also come in handy. If you haven't, do the following:

for i in 0*.image 1*.image; do FILENAME=`echo $i | sed 's/.image//g'`; echo $FILENAME; dd if=${FILENAME}.image bs=1 skip=84 count=409600 of=tmp; dd bs=512 count=800 if=tmp of=${FILENAME}.tar; echo; done; rm tmp

Then, once you have the tar files:

for i in *.tar; do tar xvf $i; done

*BUT* please use a modern tar - some versions of tar are broken and you'll find that the files that start like this /bin/ls will overwrite the ones on your system. GNU tar is what you want. I suspect most modern tars are ok, if you don't know, skip this step, or at least make sure you don't do it as the root user.

The extracted files are useful as there's information under /usr/include and /usr/include/sys that I use. You can skip this step and just take my word for it. (The #define's are gotten from there...)

As a quickie UFS refresher:

the superblock is the thing that defines a unix volume. (forgive my lack of eloquence here) There are typically several copies of this on the disk for safety, but I think there's only one on UniPlus (block #1). Block 0 is empty - it can hold a boot sector, but on UniPlus it does not. On other Unixen, this will be different for certain.

Files are allocated via inodes, the blocks immediately following the superblock contain inodes. inodes contain details such as: is this a directory, file or device?, permissions, owner, group, size, allocated blocks, and dates for creation, modification, and access - not necessarily in that order.

When the list of blocks is too numerous to fit inside a single inode, indirection (single, double, or tripple) is used. that won't be needed here. The files we're restoring are small directories. It's possible that /bin contains more than one directory and that I've missed the second, I don't know for sure, but I suspect it's ok.

Directory entries are normal files, but they contain the file name and more importantly the inode number that contains the directory information about the file.

Using lisafsh tool, I see the following:

uniplus root disk: block 1 is superblock, block 0 is all zeroes superblock has magic #fd187e20 at offset 1f8 in block 1. It's followed by 00 00 00 01 - this probably means a 512 byte block is used.
- this matches the fs(4) man page for UniPlus+

sector 13 is the root dir entry - this has inode's zeroed out for /etc and /bin:

Looking around the disk image some more for text, specifically for things that I'd recognize, here are some more details:

sector 132 is /etc's dir entry
sector 118 is /bin's dir entry (or part of it)
sector 125 is /dev

sector 41 looks to be inittab

Here's the root sector:
(I've put brackets here to highlight the important bits)



Sec 13:(0x000d)

+0 +1 +2 +3 +4 +5 . +6 +7 +8 +9 +a +b
tags: 00 00 00 00 00 00 . 00 00 00 00 00 00 |volid| ?? |fileid|absnext|next|previous

+0 +1 +2 +3 +4 +5 +6 +7 . +8 +9 +a +b +c +d +e +f
0000: 00 02 2e 00 00 00 00 00 . 00 00 00 00 00 00 00 00 | ".
0010: 00 02 2e 2e 00 00 00 00 . 00 00 00 00 00 00 00 00 | "..
0020: 00 1b 69 6e 73 74 61 6c . 6c 00 00 00 00 00 00 00 | ;install
0030: 00 27 69 6e 73 74 61 6c . 6c 2e 32 00 00 00 00 00 | 'install.2
0040: 00 29 69 6e 73 74 61 6c . 6c 5f 69 74 00 00 00 00 | )install_it
0050: [0000]62 69 6e 00 00 00 . 00 00 00 00 00 00 00 00 | bin
0060: [0000]64 65 76 00 00 00 . 00 00 00 00 00 00 00 00 | dev
0070: [0000]65 74 63 00 00 00 . 00 00 00 00 00 00 00 00 | etc
0080: 00 09 74 00 00 00 00 00 . 00 00 00 00 00 00 00 00 | )t
0090: 00 0a 75 73 72 00 00 00 . 00 00 00 00 00 00 00 00 | *usr
00a0: 00 1e 69 6e 73 74 61 6c . 6c 2e 6f 6c 64 00 00 00 | >install.old
00b0: 00 05 69 6e 73 74 61 6c . 6c 5f 69 74 30 00 00 00 | %install_it0
00c0: 00 2c 69 6e 73 74 61 6c . 6c 2e 32 2e 30 00 00 00 | ,install.2.0
00d0: 00 2d 69 6e 73 74 61 6c . 6c 30 00 00 00 00 00 00 | -install0
00e0: 00 00 07 61 30 35 38 30 . 00 00 00 00 00 00 00 00 | 'a0580
00f0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |

So /etc, /dev, and /bin were damaged. :-( It looks like they weren't rm
-rf'ed as the other files are still there, it looks like they were
accidentally deleted.

We know /etc lives at sector 132 (We'd expect /etc to contain passwd, group, mnttab, and other stuff like that.) Some unixen contained binaries in /etc. I think this is one of them - well, at least for the fsck and init programs.)

Sec 132:(0x0084)



+0 +1 +2 +3 +4 +5 . +6 +7 +8 +9 +a +b
tags: 00 00 00 00 00 00 . 00 00 00 00 00 00 |volid| ?? |fileid|absnext|next|previous

+0 +1 +2 +3 +4 +5 +6 +7 . +8 +9 +a +b +c +d +e +f
0000: 00 08 2e 00 00 00 00 00 . 00 00 00 00 00 00 00 00 | (.
0010: 00 02 2e 2e 00 00 00 00 . 00 00 00 00 00 00 00 00 | "..
0020: 00 00 66 73 63 6b 31 62 . 00 00 00 00 00 00 00 00 | fsck1b
0030: 00 1c 67 72 6f 75 70 00 . 00 00 00 00 00 00 00 00 | <group
0040: 00 1d 69 6e 69 74 00 00 . 00 00 00 00 00 00 00 00 | =init
0050: 00 2a 69 6e 69 74 74 61 . 62 00 00 00 00 00 00 00 | *inittab
0060: 00 1f 6d 6b 66 73 31 62 . 00 00 00 00 00 00 00 00 | mkfs1b
0070: 00 20 70 61 73 73 77 64 . 00 00 00 00 00 00 00 00 | passwd
0080: 00 23 69 6f 63 74 6c 2e . 73 79 73 63 6f 6e 00 00 | #ioctl.syscon
0090: 00 26 6d 6e 74 74 61 62 . 00 00 00 00 00 00 00 00 | &mnttab

So lets' find some inodes that are still on the disk..

00 20 is the entry right before passwd - so inode 0x0020 - /etc/passwd's content is at sector 247.
00 1c is the entry right before group - so inode 0x001c - /etc/group's content is at sector 620.

So let's try and see if we can match this to an existing working file. /etc/passwd is very distinctive and easy to find...

According to the man page, the inodes start on block 2, immediately after the superblock and they have a structure similar to this. The numbers are how many bytes:

2 ushort mode
2 short nlinks
2 ushort uid
2 ushort gid
4 off_t size
40 char addr[40] (3 byte groups containing the block #'s in the file.)

4 time_t
4 time_t
4 time_t

above is 64 bytes/inode - so there are 8 inodes per each 512 byte disk sector.

So looking at the directory entry for /etc/passwd, 0x0020 is 32 in decimal. So 32*64=2048. so 2048 bytes after the start of sector 2 puts us in sector 6 (2048/512=4, we start at sector 2, so 2+4=6.)

So this should point to the very first inode on sector 6. Except that it doesn't. :-)

You see, we're off by 1 here. It turns out that inode #0 doesn't exist - it means "deleted file"
So going back to the last inode on sector 5, we see:

(I've put brackets here to highlight the important bits)



Sec 5:(0x0005)

+0 +1 +2 +3 +4 +5 . +6 +7 +8 +9 +a +b
tags: 00 00 00 00 00 00 . 00 00 00 00 00 00 |volid| ?? |fileid|absnext|next|previous

....
mode nlnk uid gid 473bytes sector 583
01c0: [8124][0001][0000][0000][000001d9] [00 02 47]00 | !$ ! !Y "G
01d0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01e0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01f0: 00 00 00 00 37 a1 33 65 . 1b 39 0b d0 1b 39 0b d0 | 7!3e;9+P;9+P

mode=8124: 100444 octal (looks reasonable for /etc/passwd) file has 1 links (itself)
uid=0, gid=0
size=0x1d9 bytes or 473 bytes, perfect (see below) first data sector starts at 0x0247=583

We have a perfect match, the following is indeed the /etc/passwd file. *Bingo*



Sec 583:(0x0247)

+0 +1 +2 +3 +4 +5 . +6 +7 +8 +9 +a +b
tags: 00 00 00 00 00 00 . 00 00 00 00 00 00 |volid| ?? |fileid|absnext|next|previous

+0 +1 +2 +3 +4 +5 +6 +7 . +8 +9 +a +b +c +d +e +f
0000: 72 6f 6f 74 3a 61 4c 62 . 44 50 4f 32 6c 56 2e 69 | root:aLbDPO2lV.i
0010: 70 55 3a 30 3a 30 3a 3a . 2f 3a 2f 62 69 6e 2f 73 | pU:0:0::/:/bin/s
0020: 68 0a 72 6f 6f 74 63 73 . 68 3a 43 4c 42 65 33 31 | h*rootcsh:CLBe31
0030: 63 57 6c 65 36 44 6f 3a . 30 3a 30 3a 3a 2f 3a 2f | cWle6Do:0:0::/:/
0040: 62 69 6e 2f 63 73 68 0a . 64 61 65 6d 6f 6e 3a 78 | bin/csh*daemon:x
0050: 78 78 78 78 78 78 78 78 . 78 78 78 78 3a 31 3a 31 | xxxxxxxxxxxx:1:1
0060: 3a 3a 2f 3a 0a 62 69 6e . 3a 78 78 78 78 78 78 78 | ::/:*bin:xxxxxxx
0070: 78 78 78 78 78 78 3a 32 . 3a 32 3a 3a 2f 62 69 6e | xxxxxx:2:2::/bin
0080: 3a 0a 73 79 73 3a 78 78 . 78 78 78 78 78 78 78 78 | :*sys:xxxxxxxxxx
0090: 78 78 78 3a 33 3a 33 3a . 3a 2f 62 69 6e 3a 0a 61 | xxx:3:3::/bin:*a
00a0: 64 6d 3a 78 78 78 78 78 . 78 78 78 78 78 78 78 78 | dm:xxxxxxxxxxxxx
00b0: 3a 34 3a 34 3a 3a 2f 75 . 73 72 2f 61 64 6d 3a 0a | :4:4::/usr/adm:*
00c0: 75 75 63 70 3a 3a 35 3a . 35 3a 3a 2f 75 73 72 2f | uucp::5:5::/usr/
00d0: 73 70 6f 6f 6c 2f 75 75 . 63 70 70 75 62 6c 69 63 | spool/uucppublic
00e0: 3a 2f 75 73 72 2f 6c 69 . 62 2f 75 75 63 70 2f 75 | :/usr/lib/uucp/u
00f0: 75 73 68 65 6c 6c 0a 63 . 68 65 63 6b 3a 78 78 78 | ushell*check:xxx
0100: 78 78 78 78 78 78 78 78 . 78 78 3a 36 3a 36 3a 3a | xxxxxxxxxx:6:6::
0110: 2f 3a 0a 6c 70 3a 78 78 . 78 78 78 78 78 78 78 78 | /:*lp:xxxxxxxxxx
0120: 78 78 78 3a 37 3a 37 3a . 6c 70 3a 2f 75 73 72 2f | xxx:7:7:lp:/usr/
0130: 73 70 6f 6f 6c 2f 6c 70 . 3a 0a 75 73 72 36 38 3a | spool/lp:*usr68:
0140: 3a 31 30 3a 30 3a 3a 2f . 75 73 72 2f 67 75 65 73 | :10:0::/usr/gues
0150: 74 3a 2f 62 69 6e 2f 63 . 73 68 0a 77 68 6f 3a 3a | t:/bin/csh*who::
0160: 32 32 3a 30 3a 77 68 6f . 20 63 6f 6d 6d 61 6e 64 | 22:0:who command
0170: 3a 2f 62 69 6e 3a 2f 62 . 69 6e 2f 77 68 6f 0a 67 | :/bin:/bin/who*g
0180: 75 65 73 74 3a 3a 31 30 . 30 3a 31 30 30 3a 67 75 | uest::100:100:gu
0190: 65 73 74 20 61 63 63 6f . 75 6e 74 3a 2f 75 73 72 | est account:/usr
01a0: 2f 67 75 65 73 74 3a 2f . 62 69 6e 2f 63 73 68 0a | /guest:/bin/csh*
01b0: 6d 61 63 3a 3a 31 30 30 . 3a 31 30 30 3a 4d 61 63 | mac::100:100:Mac
01c0: 69 6e 74 6f 73 68 3a 2f . 75 73 72 2f 6d 61 63 3a | intosh:/usr/mac:
01d0: 2f 62 69 6e 2f 63 73 68 . 0a 00 00 00 00 00 00 00 | /bin/csh*
01e0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01f0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |


So now we need to find inodes that point to the proper entry for /etc and /bin

sector 132 is /etc's dir entry ( in hex 0x84)
sector 118 is /bin's dir entry (or part of it) (in hex 0x76 )
sector 125 is /dev (in hex 0x7D )

We need to find inodes that match the above. - offset 13-15 are the pointer to the 1st block in a file pointed to by the inode. These are the patterns to use if you've dumped the disk to a text file using lisafsh-tool:

"00 00 84 00 |"
"00 00 76 00 |"
"00 00 7d 00 |"

But, we're shit out of luck as these patterns cannot be found. :-( so the inodes to these guys have also been deleted! D'Oh!

We need to create new inodes, then link the directory entries back and adjust the superblock...

Before we do, let's poke around some more... here's the root dir... There's something funny about it...
Well, not funny, but rather, standard to all directories everywhere in Unix...

Sec 13:(0x000d)



+0 +1 +2 +3 +4 +5 . +6 +7 +8 +9 +a +b
tags: 00 00 00 00 00 00 . 00 00 00 00 00 00 |volid| ?? |fileid|absnext|next|previous

+0 +1 +2 +3 +4 +5 +6 +7 . +8 +9 +a +b +c +d +e +f
0000: 00 02 2e 00 00 00 00 00 . 00 00 00 00 00 00 00 00 | ".
0010: 00 02 2e 2e 00 00 00 00 . 00 00 00 00 00 00 00 00 | "..
0020: 00 1b 69 6e 73 74 61 6c . 6c 00 00 00 00 00 00 00 | ;install
0030: 00 27 69 6e 73 74 61 6c . 6c 2e 32 00 00 00 00 00 | 'install.2
0040: 00 29 69 6e 73 74 61 6c . 6c 5f 69 74 00 00 00 00 | )install_it
0050: 00 00 62 69 6e 00 00 00 . 00 00 00 00 00 00 00 00 | bin
0060: 00 00 64 65 76 00 00 00 . 00 00 00 00 00 00 00 00 | dev
0070: 00 00 65 74 63 00 00 00 . 00 00 00 00 00 00 00 00 | etc
0080: 00 09 74 00 00 00 00 00 . 00 00 00 00 00 00 00 00 | )t
0090: 00 0a 75 73 72 00 00 00 . 00 00 00 00 00 00 00 00 | *usr

What's funny? The . and .. entries point to inode 0002... Hmmm, that is an idea... Why? Because those are inode numbers!

So we lost /dev /bin and /etc.

But since the deleted directories must also contain a ".." and more importantly "." directory entry, we can figure out which inode number they should be, and then we can check if those are empty or if something else clobbered them...

So /etc is at sector 132:



Sec 132:(0x0084)

+0 +1 +2 +3 +4 +5 . +6 +7 +8 +9 +a +b
tags: 00 00 00 00 00 00 . 00 00 00 00 00 00 |volid| ?? |fileid|absnext|next|previous

+0 +1 +2 +3 +4 +5 +6 +7 . +8 +9 +a +b +c +d +e +f
0000: 00 08 2e 00 00 00 00 00 . 00 00 00 00 00 00 00 00 | (.
0010: 00 02 2e 2e 00 00 00 00 . 00 00 00 00 00 00 00 00 | "..
0020: 00 00 66 73 63 6b 31 62 . 00 00 00 00 00 00 00 00 | fsck1b
0030: 00 1c 67 72 6f 75 70 00 . 00 00 00 00 00 00 00 00 | <group
0040: 00 1d 69 6e 69 74 00 00 . 00 00 00 00 00 00 00 00 | =init
0050: 00 2a 69 6e 69 74 74 61 . 62 00 00 00 00 00 00 00 | *inittab
0060: 00 1f 6d 6b 66 73 31 62 . 00 00 00 00 00 00 00 00 | mkfs1b
0070: 00 20 70 61 73 73 77 64 . 00 00 00 00 00 00 00 00 | passwd
0080: 00 23 69 6f 63 74 6c 2e . 73 79 73 63 6f 6e 00 00 | #ioctl.syscon
0090: 00 26 6d 6e 74 74 61 62 . 00 00 00 00 00 00 00 00 | &mnttab

.. points to inode 0002 - which from the / directory entry we already know is the root directory's inode.
. points to 0008. Yeay! We have an inode number for the deleted /etc directory.

If we look a bit more we notice the other stuff in this directory hasn't been deleted! Phew! That's helpful because we'd have a hard time identifying random binaries without knowing what they are!

So rm -rf / wasn't done. Or if it was, it didn't recursively remove everything - maybe a well timed ^C? But I'd expect if someone did rm
-rf, the -rf part would start at the bottom of the tree, and not at the
directory level... Maybe it's a bug that got triggered somewhere that deleted these dirs, or maybe rm -rf is implemented differently.

Ok, we now know that /etc lives on sector 132 (0x84) and points to inode 0008. Let's repeat with the other two dirs:

/bin which lives at sector 118 (0x76) has .. pointing to 0002 - good, that's what it should be, and . is pointing to inode # 0006.

Sec 118:(0x0076)



+0 +1 +2 +3 +4 +5 . +6 +7 +8 +9 +a +b
tags: 00 00 00 00 00 00 . 00 00 00 00 00 00 |volid| ?? |fileid|absnext|next|previous

+0 +1 +2 +3 +4 +5 +6 +7 . +8 +9 +a +b +c +d +e +f
0000: 00 06 2e 00 00 00 00 00 . 00 00 00 00 00 00 00 00 | &.
0010: 00 02 2e 2e 00 00 00 00 . 00 00 00 00 00 00 00 00 | "..
0020: 00 0c 63 61 74 00 00 00 . 00 00 00 00 00 00 00 00 | ,cat
0030: 00 0d 63 68 67 72 70 00 . 00 00 00 00 00 00 00 00 | -chgrp
0040: 00 0e 63 68 6d 6f 64 00 . 00 00 00 00 00 00 00 00 | .chmod
0050: 00 0f 63 68 6f 77 6e 00 . 00 00 00 00 00 00 00 00 | /chown
0060: 00 10 63 70 00 00 00 00 . 00 00 00 00 00 00 00 00 | 0cp
0070: 00 11 65 63 68 6f 00 00 . 00 00 00 00 00 00 00 00 | 1echo
0080: 00 12 6c 73 00 00 00 00 . 00 00 00 00 00 00 00 00 | 2ls
0090: 00 13 6d 6b 64 69 72 00 . 00 00 00 00 00 00 00 00 | 3mkdir
00a0: 00 14 6d 6b 6e 6f 64 00 . 00 00 00 00 00 00 00 00 | 4mknod
00b0: 00 15 6d 6f 75 6e 74 00 . 00 00 00 00 00 00 00 00 | 5mount
00c0: 00 16 73 68 00 00 00 00 . 00 00 00 00 00 00 00 00 | 6sh
00d0: 00 17 73 75 00 00 00 00 . 00 00 00 00 00 00 00 00 | 7su
00e0: 00 18 73 79 6e 63 00 00 . 00 00 00 00 00 00 00 00 | 8sync
00f0: 00 19 74 61 72 00 00 00 . 00 00 00 00 00 00 00 00 | 9tar
0100: 00 1a 75 6d 6f 75 6e 74 . 00 00 00 00 00 00 00 00 | :umount
0110: 00 10 6c 6e 00 00 00 00 . 00 00 00 00 00 00 00 00 | 0ln

/dev lives at sector 125 (0x007d), .. again is 0002 . is 0007 so we know what the inodes should be.
I don't see an entry for /null... maybe this isn't /dev? But tty0, console syscon systty look like /dev entries to me. (We may have trouble if the rest of /dev is damaged...)

Sec 125:(0x007d)



+0 +1 +2 +3 +4 +5 . +6 +7 +8 +9 +a +b
tags: 00 00 00 00 00 00 . 00 00 00 00 00 00 |volid| ?? |fileid|absnext|next|previous

+0 +1 +2 +3 +4 +5 +6 +7 . +8 +9 +a +b +c +d +e +f
0000: 00 07 2e 00 00 00 00 00 . 00 00 00 00 00 00 00 00 | '.
0010: 00 02 2e 2e 00 00 00 00 . 00 00 00 00 00 00 00 00 | "..
0020: 00 22 63 6f 6e 73 6f 6c . 65 00 00 00 00 00 00 00 | "console
0030: 00 24 73 79 73 63 6f 6e . 00 00 00 00 00 00 00 00 | $syscon
0040: 00 24 73 79 73 74 74 79 . 00 00 00 00 00 00 00 00 | $systty
0050: 00 25 70 30 61 00 00 00 . 00 00 00 00 00 00 00 00 | %p0a
0060: 00 04 70 34 61 00 00 00 . 00 00 00 00 00 00 00 00 | $p4a
0070: 00 28 63 34 61 00 00 00 . 00 00 00 00 00 00 00 00 | (c4a
0080: 00 2b 70 61 00 00 00 00 . 00 00 00 00 00 00 00 00 | +pa
0090: 00 2e 6f 6f 6f 6f 6f 6f . 00 00 00 00 00 00 00 00 | .oooooo
00a0: 00 2f 74 74 79 30 00 00 . 00 00 00 00 00 00 00 00 | /tty0
00b0: 00 30 65 6a 65 63 74 00 . 00 00 00 00 00 00 00 00 | 0eject

So as long as those inodes weren't used by something else, let's assume that they weren't, we should be able to fix this.

To summarize:

/etc lives on sector 132 (0x84) and points to inode 0008
/bin which lives at sector 118 (0x76) points to inode 0006
/dev lives at sector 125 (0x007d), points to inode 0007

The inodes for these should all live in sector #2. Let's go there now:



Sec 2:(0x0002)

+0 +1 +2 +3 +4 +5 . +6 +7 +8 +9 +a +b
tags: 00 00 00 00 00 00 . 00 00 00 00 00 00 |volid| ?? |fileid|absnext|next|previous

+0 +1 +2 +3 +4 +5 +6 +7 . +8 +9 +a +b +c +d +e +f
0000: 80 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0010: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0020: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0030: 00 00 00 00 1e 59 6d 57 . 1e 59 6d 57 1e 59 6d 57 | >YmW>YmW>YmW

So this is inode #2 and it points to sector 13 (00 0d) which is the root directory entry. Above, therefore is inode #1, so that's why we had the off-by-one for /etc/passwd.

0040: 41 ff 00 07 00 00 00 00 . 00 00 00 f0[00 00 0d]00 | A  ' p -
0050: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0060: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0070: 00 00 00 00 21 5a 46 3c . 21 5a 46 78 21 5a 46 78 | !ZF<!ZFx!ZFx

inode 3

0080: 41 ff 00 02 00 64 00 64 . 00 00 01 60 00 00 22 00 | A  " d d !` "
0090: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
00a0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
00b0: 00 00 00 00 21 5a 42 53 . 1e 59 6d 7b 1e 59 6d 7b | !ZBS>Ym{>Ym{

inode 4

00c0: 89 ed 00 01 00 64 00 64 . 00 00 3c 1b 00 00 29 00 | )m ! d d <; )
00d0: 00 30 00 00 37 00 00 3e . 00 00 45 00 00 4c 00 00 | 0 7 > E L
00e0: 53 00 00 5a 00 00 61 00 . 00 68 00 00 6f 00 00 00 | S Z a h o
00f0: 00 00 00 00 1e 6f 81 97 . 20 2d 57 07 20 2d 57 09 | >o!7 -W' -W)

inode 5

0100: 81 ed 00 01 00 64 00 64 . 00 00 00 c4 00 01 09 00 | !m ! d d D !)
0110: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0120: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0130: 00 00 00 00 21 5a 42 ff . 20 2d 57 0e 20 2d 57 0e | !ZB  -W. -W.

inode 6: /bin

0140: 00 00 00 00 00 64 00 64 . 00 00 00 00 00 00 00 00 | d d
0150: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0160: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0170: 00 00 00 00 1e 6f 81 e9 . 21 5a 46 5c 21 5a 46 5c | >o!i!ZF\!ZF\

inode 7: /dev

0180: 00 00 00 00 00 64 00 64 . 00 00 00 00 00 00 00 00 | d d
0190: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01a0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01b0: 00 00 00 00 1e 6f 81 e9 . 21 5a 46 63 21 5a 46 63 | >o!i!ZFc!ZFc

inode 8: /etc

01c0: 00 00 00 00 00 64 00 64 . 00 00 00 00 00 00 00 00 | d d
01d0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01e0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01f0: 00 00 00 00 1e 6f 81 ea . 21 5a 46 67 21 5a 46 67 | >o!j!ZFg!ZFg

So sure enough inodes 6,7,8 are zeroed out in both the permissions and the blocks they point to. So we have to manually fix them. I'd imagine uid:gid of 0x64 means something like "deleted" as well.

Let's copy the inode for /usr since that's a directory.

 From sector 13, we have /usr's dir-entry:

0090:[00 0a]75 73 72 00 00 00 . 00 00 00 00 00 00 00 00 | *usr

So /usr's inode #0x000a (10), that's on sector #3 since the last inode on sector 2 is inode 8:

Sec 3:(0x0003)



+0 +1 +2 +3 +4 +5 . +6 +7 +8 +9 +a +b
tags: 00 00 00 00 00 00 . 00 00 00 00 00 00 |volid| ?? |fileid|absnext|next|previous

+0 +1 +2 +3 +4 +5 +6 +7 . +8 +9 +a +b +c +d +e +f

inode 9:
0000: 41 ff 00 02 00 00 00 00 . 00 00 00 20 00 00 8b 00 | A  " +
0010: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0020: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0030: 00 00 00 00 21 5a 42 52 . 1b 39 09 5f 1b 39 09 5f | !ZBR;9)_;9)_

inode 10: this should point to /usr.

0040: 41 ff 00 03 00 00 00 00 . 00 00 00 30[00 00 92]00 | A  # 0 2
0050: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0060: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0070: 00 00 00 00 21 5a 42 52 . 1b 39 09 61 1b 39 09 62 | !ZBR;9)a;9)b

inode 11: (this turns out to be /usr/bin)

0080: 41 ff 00 02 00 00 00 00 . 00 00 00 40 00 00 99 00 | A  " @ 9
0090: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
00a0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
00b0: 00 00 00 00 21 5a 42 52 . 1b 61 65 29 1b 61 65 29 | !ZBR;ae);ae)
...

Sector 0x92 contains:



Sec 146:(0x0092)

+0 +1 +2 +3 +4 +5 . +6 +7 +8 +9 +a +b
tags: 00 00 00 00 00 00 . 00 00 00 00 00 00 |volid| ?? |fileid|absnext|next|previous

+0 +1 +2 +3 +4 +5 +6 +7 . +8 +9 +a +b +c +d +e +f
0000: 00 0a 2e 00 00 00 00 00 . 00 00 00 00 00 00 00 00 | *.
0010: 00 02 2e 2e 00 00 00 00 . 00 00 00 00 00 00 00 00 | "..
0020: 00 0b 62 69 6e 00 00 00 . 00 00 00 00 00 00 00 00 | +bin
0030: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0040: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |

Ok, so I guess that's reasonable for an install disk to have just /usr/bin, and indeed, inode 11 is what points to /usr/bin...



Sec 153:(0x0099)

+0 +1 +2 +3 +4 +5 . +6 +7 +8 +9 +a +b
tags: 00 00 00 00 00 00 . 00 00 00 00 00 00 |volid| ?? |fileid|absnext|next|previous

+0 +1 +2 +3 +4 +5 +6 +7 . +8 +9 +a +b +c +d +e +f
0000: 00 0b 2e 00 00 00 00 00 . 00 00 00 00 00 00 00 00 | +.
0010: 00 0a 2e 2e 00 00 00 00 . 00 00 00 00 00 00 00 00 | *..
0020: 00 21 65 6a 65 63 74 00 . 00 00 00 00 00 00 00 00 | !eject
0030: 00 03 6c 73 37 00 00 00 . 00 00 00 00 00 00 00 00 | #ls7

and indeed this is /usr/bin... ok, ok, we're getting sidelined now, although it's good to verify everything. So back to the task at hand. We're copying the inode for /usr and modifying it so we can use it for our deleted directories...

Here it is again, the inode for /usr:

0040: 41 ff 00 03 00 00 00 00 . 00 00 00 30[00 00 92]00 | A  # 0 2
0050: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0060: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0070: 00 00 00 00 21 5a 42 52 . 1b 39 09 61 1b 39 09 62 | !ZBR;9)a;9)b

Let's leave all the fields alone for right now. The only one we care about is the pointer to the first block, we'll edit the others too, but let's look here a bit more closely.

Luckily since the directories removed only took up a single block (I think) we should be fine with replacing the data there. We'll have to also fix the sizes, but we'll get to that later. Worse, if this was the result of rm -rf, restoring these deleted inodes might work, *BUT* they've been added to the free list which will hurt us if anything further is written to the disk. But we'll deal with that later. No, really, we will.

So these guys (our deleted inodes) are all in sector 2. We'll copy the values from inode 10 (/usr) so we get the permissions right and all that. We still need to correct the sizes which will bite us in the ass if we don't. (Ignore the fact that the "text" after the | doesn't necessarily match, I'm not editing that ascii representation in the following block hex representations)

Weird, but /usr has 0003 for the number of links... This might mean something I don't know... I'd expect just 1, but maybe it means something else than I imagine... if you know, tell me... anyway root has 7 here... :-( that might mean something important, or it might not. Let's stick to 3.... if it's wrong, let's hope that it doesn't mess us up... anyway, if we can get UniPlus+ installed on a single Lisa, we can use that Lisa to do an fsck on the hand-fixed root floppy and then fix up any items we got wrong...

41ff is the perms/type on /usr which is probably too permissible,, but I'll ingore it for now.. (this is 40777 octal which is world writable, on a real unix system you don't want to give everyone write perms to /bin /dev and /etc... perhaps 40755 would be better... so 0x41ED is better... which means that /usr is screwed up, but let's not worry about it for now.)

Here's our legend again, so we don't have to scroll up:

/etc lives on sector 132 (0x84) and points to inode 0008
/bin which lives at sector 118 (0x76) points to inode 0006
/dev lives at sector 125 (0x007d), points to inode 0007

So I've also edited the permissions and the 1st data block in these. Again, these dirs are only one block long as far as I can tell, so one block is what's needed... I've also copied the 3 dates in the last line from /usr (maybe they're illegal values in the deleted ones that mean something like "hi, I'm a deleted inode" so we don't trust them, but we trust the ones from /usr.)

inode 6: /bin

0140: 41 ed 00 03 00 64 00 64 . 00 00 00 00 00 00 76 00 | d d
0150: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0160: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0170: 00 00 00 00 21 5a 42 52 . 1b 39 09 61 1b 39 09 62 | !ZBR;9)a;9)b

inode 7: /dev

0180: 41 ed 00 03 00 64 00 64 . 00 00 00 00 00 00 7d 00 | d d
0190: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01a0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01b0: 00 00 00 00 21 5a 42 52 . 1b 39 09 61 1b 39 09 62 | !ZBR;9)a;9)b

inode 8: /etc

01c0: 41 ed 00 03 00 64 00 64 . 00 00 00 00 00 00 84 00 | d d
01d0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01e0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01f0: 00 00 00 00 21 5a 42 52 . 1b 39 09 61 1b 39 09 62 | !ZBR;9)a;9)b

So now we have to figure out what the sizes mean... Back to inode 10 for /usr...

perms nlnk uid gid size

0040: [41ff][0003][0000][0000] .[00 00 00 30][00 00 92]00 | A  # 0 2
0050: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0060: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0070: 00 00 00 00 21 5a 42 52 . 1b 39 09 61 1b 39 09 62 | !ZBR;9)a;9)b

So 0x0000030 is 48... is that bytes? let's see the directory entry for /usr:



Sec 146:(0x0092)

+0 +1 +2 +3 +4 +5 . +6 +7 +8 +9 +a +b
tags: 00 00 00 00 00 00 . 00 00 00 00 00 00 |volid| ?? |fileid|absnext|next|previous

+0 +1 +2 +3 +4 +5 +6 +7 . +8 +9 +a +b +c +d +e +f
0000: 00 0a 2e 00 00 00 00 00 . 00 00 00 00 00 00 00 00 | *.
0010: 00 02 2e 2e 00 00 00 00 . 00 00 00 00 00 00 00 00 | "..
0020: 00 0b 62 69 6e 00 00 00 . 00 00 00 00 00 00 00 00 | +bin
0030: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0040: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |

Well, it turns out it is indeed in bytes (it's all zeroes after offset 0x2f)... ok, great, so lets' look at those missing dirs again...

(well, do it yourself, I'm tired of copying and pasting...) :-)

Our updated legend:
/etc lives on sector 132 (0x84) and points to inode 0008 - this is 0xb0 bytes long
/bin which lives at sector 118 (0x76) points to inode 0006 - this is 0x120 bytes long
/dev lives at sector 125 (0x007d), points to inode 0007 - this is 0xc0 bytes long...

So let's edit those inodes to fix their sizes, and also fix ownership to root:root

again, these are the fields we care about from /usr: perms nlnk uid gid size
0040: [41ff][0003][0000][0000] .[00 00 00 30][00 00 92]00 | A # 0 2 <- /usr

inode 6: /bin

0140: 41 ed 00 03 00 00 00 00 . 00 00 01 20 00 00 76 00 | d d
0150: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0160: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
0170: 00 00 00 00 21 5a 42 52 . 1b 39 09 61 1b 39 09 62 | !ZBR;9)a;9)b

inode 7: /dev

0180: 41 ed 00 03 00 00 00 00 . 00 00 00 c0 00 00 7d 00 | d d
0190: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01a0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01b0: 00 00 00 00 21 5a 42 52 . 1b 39 09 61 1b 39 09 62 | !ZBR;9)a;9)b

inode 8: /etc

01c0: 41 ed 00 03 00 00 00 00 . 00 00 00 b0 00 00 84 00 | d d
01d0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01e0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01f0: 00 00 00 00 21 5a 42 52 . 1b 39 09 61 1b 39 09 62 | !ZBR;9)a;9)b

Ok, so next, we need to fix up the entries in the root directory so that they also point to these new inodes, if we don't the installer won't be able to find anything and it won't work...

Here's our legend again:

/etc lives on sector 132 (0x84) and points to inode 0008 - this is 0xb0 bytes long
/bin which lives at sector 118 (0x76) points to inode 0006 - this is 0x120 bytes long
/dev lives at sector 125 (0x007d), points to inode 0007 - this is 0xc0 bytes long...

And here's the root directory sector:



Sec 13:(0x000d)

+0 +1 +2 +3 +4 +5 . +6 +7 +8 +9 +a +b
tags: 00 00 00 00 00 00 . 00 00 00 00 00 00 |volid| ?? |fileid|absnext|next|previous

+0 +1 +2 +3 +4 +5 +6 +7 . +8 +9 +a +b +c +d +e +f
0000: 00 02 2e 00 00 00 00 00 . 00 00 00 00 00 00 00 00 | ".
0010: 00 02 2e 2e 00 00 00 00 . 00 00 00 00 00 00 00 00 | "..
0020: 00 1b 69 6e 73 74 61 6c . 6c 00 00 00 00 00 00 00 | ;install
0030: 00 27 69 6e 73 74 61 6c . 6c 2e 32 00 00 00 00 00 | 'install.2
0040: 00 29 69 6e 73 74 61 6c . 6c 5f 69 74 00 00 00 00 | )install_it
here are the edits:
0050:[00 06]62 69 6e 00 00 00 . 00 00 00 00 00 00 00 00 | bin
0060:[00 07]64 65 76 00 00 00 . 00 00 00 00 00 00 00 00 | dev
0070:[00 08]65 74 63 00 00 00 . 00 00 00 00 00 00 00 00 | etc


Ok thats' good for right now...

Of course there's still the matter of the superblock to fix as it contains the free inodes list... if we don't fix it and the installer tries to create a temporary file, it'll erase our directories!!! But we'll fix it right now. :-)

We need to look for 0006 0007 0008 to undelete them. There's also a counter somewhere that says how many of them there are (nfree), but since I don't know the size of NICFREE and NICINOD, Well, assuming that they're the same as in the tar floppies we've extracted, looking in /usr/include and /usr/include/sys, we see that they are:

param.h:#define NICINOD 100 /* number of superblock inodes */ param.h:#define NICFREE 50 /* number of superblock free blocks */ these are in "longs" (daddr_t is typedef'ed as long) - so I suspect 4 bytes... so, 50*4=200 +8 (offset to first s_free entry) = 208 or 0xd0 is the end...

See the man page for fs(4) in the PDF's... p281 of the UniPlus+ User manual section 2-6.pdf for the meanings of these...



Sec 1:(0x0001)

isize=number if blocks of inodes starting at sector 2 fsize=number of blocks in volume (0x320 = 800 blocks, at 512 bytes each = 400k good)
nfree=number of free addresses in s_free ninode - number of free inodes
s_inode[NICINOD] =

isize fsize nfree free block list starts at 8

0000:[0008][00000320][00 0a] . 00 00 02 49 00 00 01 c1 | ( # * "I !A
0010: 00 00 01 c8 00 00 01 ba . 00 00 00 3e 00 00 01 17 | !H !: > !7
0020: 00 00 01 10 00 00 01 25 . 00 00 01 1e 00 00 01 2c | !0 !% !> !,
0030: 00 00 02 e0 00 00 02 d9 . 00 00 02 d2 00 00 02 cb | "` "Y "R "K
0040: 00 00 02 c4 00 00 02 bd . 00 00 02 b6 00 00 02 af | "D "= "6 "/
0050: 00 00 02 a8 00 00 02 a1 . 00 00 02 9a 00 00 02 93 | "( "! ": "3
0060: 00 00 02 8c 00 00 02 85 . 00 00 02 7e 00 00 02 77 | ", "% "~ "w
0070: 00 00 02 70 00 00 02 69 . 00 00 02 62 00 00 02 5b | "p "i "b "[
0080: 00 00 02 54 00 00 02 4d . 00 00 02 46 00 00 02 3f | "T "M "F "?
0090: 00 00 02 38 00 00 02 31 . 00 00 02 2a 00 00 02 23 | "8 "1 "* "#
00a0: 00 00 02 1c 00 00 02 15 . 00 00 02 0e 00 00 02 07 | "< "5 ". "'
00b0: 00 00 02 00 00 00 01 f9 . 00 00 01 f2 00 00 01 eb | " !y !r !k
00c0: 00 00 01 e4 00 00 01 dd . 00 00 02 65 00 00 02 5e | !d !] "e "^

So here's part of the list of free inodes! need to remove the 6,7,8: And this 0003 refers to our 3 inodes that we've undeleted - and it's followed by 00's...

So that implies that we should zero out bytes d0-d7 of the superblock to complete the undelete... I think...

00d0: [0003][0006][0007][0008]. 00 00 00 00 00 00 00 00 | # & ' ( 00e0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 | ... more stuff here (but irrelevant to this task)...

01d0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01e0: 00 00 00 00 00 00 00 00 . 00 00 00 00 00 00 00 00 |
01f0: 00 00 00 00 00 00 00 00 .[fd 18 7e 20][00000001] | }8~ !
the magic Fs1b=1

And that should do it - I hope...

So turning all of these edits into lisafsh-tool commands (be sure to copy the lines with just the numbers, they indicate the sector number to execute the commands on.)

Our Superblock changes:

1
editsector 0xd0 00 00 00 00 00 00 00 00

The root directory changes:
13
editsector 0x50 00 06
editsector 0x60 00 07
editsector 0x70 00 07

And the inode edits:

2
editsector 0x140 41 ed 00 03 00 00 00 00 00 00 01 20 00 00 76 00 editsector 0x150 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 editsector 0x160 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 editsector 0x170 00 00 00 00 21 5a 42 52 1b 39 09 61 1b 39 09 62 editsector 0x180 41 ed 00 03 00 00 00 00 00 00 00 c0 00 00 7d 00 editsector 0x190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 editsector 0x1a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 editsector 0x1b0 00 00 00 00 21 5a 42 52 1b 39 09 61 1b 39 09 62 editsector 0x1c0 41 ed 00 03 00 00 00 00 00 00 00 b0 00 00 84 00 editsector 0x1d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 editsector 0x1e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 editsector 0x1f0 00 00 00 00 21 5a 42 52 1b 39 09 61 1b 39 09 62

Let's hope this does the trick... Please let me know if you've tried it and it worked or not... Everyone else, pls keep your fingers crossed :-)

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "LisaList" group. To post to this group, send email to lisalist_at_email.domain.hidden To unsubscribe from this group, send email to lisalist-unsubscribe_at_email.domain.hidden For more options, visit this group at http://groups.google.com/group/lisalist?hl=en
-~----------~----~----~----~------~----~------~--~---
Received on 2008-03-25 14:13:45

This archive was generated by hypermail 2.4.0 : 2020-01-13 12:15:21 EST