From owner-freebsd-fs@FreeBSD.ORG Mon Dec 22 16:02:12 2003 Return-Path: Delivered-To: freebsd-fs@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 7834416A4CE for ; Mon, 22 Dec 2003 16:02:12 -0800 (PST) Received: from dastardly.newsbastards.org.72.27.172.IN-addr.ARPA.NOSPAM.dyndns.dk (does-d9b90acd.pool.mediaWays.net [217.185.10.205]) by mx1.FreeBSD.org (Postfix) with ESMTP id 34E6143D41 for ; Mon, 22 Dec 2003 16:01:14 -0800 (PST) (envelope-from bounce@NOSPAM.dyndns.dk) Received: from NOSPAM.spam.NOSPAM.spam.NOSPAM.dyndns.dk (NOSPAM.spam.NOSPAM.spam.NOSPAM.dyndns.dk [2002:d9b9:acd:0:200:c0ff:fefc:19aa]) (8.11.6/8.11.6-SPAMMERS-DeLiGHt) with ESMTP id hBN00iX30408 verified NO) for ; Tue, 23 Dec 2003 01:00:47 +0100 (CET) (envelope-from bounce@NOSPAM.dyndns.dk) Received: (from beer@localhost)hBN00bB03593; Tue, 23 Dec 2003 01:00:37 +0100 (CET) (envelope-from bounce@NOSPAM.dyndns.dk) Date: Tue, 23 Dec 2003 01:00:37 +0100 (CET) Message-Id: <200312230000.hBN00bB03593@NOSPAM.spam.NOSPAM.spam.NOSPAM.dyndns.dk> X-Authentication-Warning: NOSPAM.spam.NOSPAM.spam.NOSPAM.dyndns.dk: beer set sender to bounce@NOSPAM.dyndns.dk using -f To: Freebsd Filesystemmers From: Barry Bouwsma Subject: Questions related to file ``undeletion'' X-BeenThere: freebsd-fs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Filesystems List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Dec 2003 00:02:12 -0000 [Drop my (IPv6-only) address from replies; I catch the archives] Salve, I decided one day, purely for entertainment value, to see if I could undelete a file I had mistakenly `rm'ed before fully waking up, in order to to convince me to fall asleep much further from any keyboards. To my great glee, I had success using little more than shell commands and tools. However, there were a few things I had questions about, or don't quite comprehend. FreeBSD-4 in use here, UFS1, sans softdep. First, my introduction to `fsdb'. I think I read in the archives that it should work on mounted filesystems, but I couldn't get any changes I made to work. Also, it mentions giving the `-u -o reload' mount command, which does not seem to be a mount option. (This was also mentioned in the archives.) Finding the inode number was easy, though I can't remember exactly how I did it, and if `cat'ing the directory file itself was it, or what I did to verify the inode number. Finding the inode itself was something I wasn't able to figure out. Probably I need to study more headers, or else there's a tool out there I don't know about to do it for me. Now, `ffsinfo' reported the addresses of the various direct blocks, and the indirect block, as 0, rather than that of the blocks which held the data. Since I didn't find the inode proper to inspect its contents, I have to ask, when a file is unlinked, are these values in the inode cleared, or is this an artifact of `ffsinfo' when presented with an unallocaed inode? As a note, when I found the indirect block, its contents were intact, pointing to all the rest of the file. However, when I've deleted very large files, it's taken a while for the command to complete (without softupdates). Is there an explanation somewhere of exactly what is done on the disk when an unlink is done, other than the source, out there? Are the indirect blocks being cleared then, meaning I should not expect success finding a file larger than some number times the block size? I was lucky that my file fell in one cylinder group, and another file being written at the time I deleted the wrong file was going elsewhere. Also, in retrospect, I was lucky that my file was the only free space in that cylinder group, which I had filled with other data after writing the file. But that aside, My attempts to use `fsdb' to `ln' or to increase the link count did not succeed. Probably because I didn't panic the machine promptly. Using `fsdb' later on a test file led me to think there's some activity done at `umount' to clear the inodes; else I'm seeing artifacts of a mounted filesystem. Anyway, `fsdb' always printed that my inode I had `ln'ed was now of size 0, and the db/ib fields were all zeroed. This probably is to be expected in the particular case of filesystem activity I did, whatever that may be. So anyway, I had no idea where on the disk the contents of my inode would be found, so I somewhat exhaustively searched the list of free blocks as printed by `dumpfs'. This didn't work as hoped. The block numbers are relative to the cylinder group offset. `dumpfs' led me to believe that its value of `tell' could be used for this. That was close, but no cigar, as it turned out in my case to be offset by 4 fragments / 2 blocks below the actual free block number, when plugging the values into `dd'. Specific numbers: cg 3: magic 90255 tell 6d5020000 time Tue Dec 16 12:29:50 2003 cgx 3 ncyl 4664 niblk 512 ndblk 298496 nbfree 2244 ndir 1 nifree 511 nffree 0 rotor 192382 irotor 1 frotor 192376 frsum 0 sum of frsum: 0 iused: 0 free: 192502-192503, 192506-192507, 192510-192511, 192514-192515, 192518-192519, 192522-192523, 192526-192527, 192530-192531, 192534-192535, 192538-192539, 192542-192543, 192546-192547, [snip] When I plug 0x6d5020000 and 192502 and my fragment size here of 32768 into `dd', I don't get the first free block. I need to use 192498. Is there a constant formula I should be using with `dd', based on `tell' for the cylinder group, and the listed `free' block number? Will the difference always be 4 less than my fragment size, 2 less than the block size, or some multiple of something, like superblock size? Or should I use a different formula to convert cg / free into a `dd' offset? Anyway, lucky for me, once I found the start of my file, all the remaining free blocks comprised it, plus the indirect block after the first 12 direct data blocks. So I could write a shell script to write the first data blocks, then pull each pointer out of the indirect block and append the contents. Those block numbers needed no massaging, unlike the ones given by `dumpfs' above. (Or I could have skipped over the indirect block and just written all the rest, for the brute force solution.) There was my file, padded with NULs to be trimmed, then added as needed to fill the data structure. Yay. I haven't read the entire archives, and only grepped specific terms to try to find info useful for recovering a deleted file, so I've certainly overlooked something, like, say, I'm looking to find a ``Welcome to the Wonderful World of Unix File Deletion'' tutorial to enhance my knowledge. This way I'll understand that under favourable conditions, I should be able to find my direct blocks and indirect block, and when it's futile. For the benefit of anyone who wants to try their hand at undeleting a file, like me. thanks, barry bouwsma