Saturday, March 28, 2020

Data Recovery... part deux

Trying again, this time using a Tripp-Lite SATA↔usb adapter cable. I had no joy the first few times I plugged this into my Linux box, but then I ran
collin@p64:~$ udevadm monitor --udev
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing

UDEV  [531312.705378] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4 (usb)
UDEV  [531312.708846] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0 (usb)
UDEV  [531312.709620] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host7 (scsi)
UDEV  [531312.710318] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host7/scsi_host/host7 (scsi_host)
UDEV  [531313.701247] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host7/target7:0:0 (scsi)
UDEV  [531313.701815] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host7/target7:0:0/7:0:0:0 (scsi)
UDEV  [531313.702273] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0 (scsi_disk)
UDEV  [531313.703261] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host7/target7:0:0/7:0:0:0/scsi_device/7:0:0:0 (scsi_device)
UDEV  [531313.703584] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host7/target7:0:0/7:0:0:0/bsg/7:0:0:0 (bsg)
UDEV  [531313.703599] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host7/target7:0:0/7:0:0:0/scsi_generic/sg6 (scsi_generic)
UDEV  [531313.705480] add      /devices/virtual/bdi/8:96 (bdi)
UDEV  [531314.784064] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host7/target7:0:0/7:0:0:0/block/sdg (block)
UDEV  [531314.855365] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host7/target7:0:0/7:0:0:0/block/sdg/sdg1 (block)
Nice to see that. Next was:
collin@p64:~$ sudo fdisk -l /dev/sdg

Disk /dev/sdg: 2.7 TiB, 3000592982016 bytes, 5860533168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xcea3ed1a

Device     Boot Start       End   Sectors   Size Id Type
/dev/sdg1  *     2048 732565503 732563456 349.3G af HFS / HFS+
Right, so the partition table matches what I saw last time.

After realizing that MacOS thinks the disk only holds about 349GB, I realized that the partition table really is horked; it's not a mere incompatibility with the bsd label business, which I'm not even sure is still a thing. It's been like 20 years since I partitioned (or labeled) a *bsd disk so I'm likely behind the times.

I wrote a couple of articles for Linux Journal, apparently in 2005. This one received a comment around that time of, "why didn't you just use gpart?" or maybe gparted. Uh, because of total ignorance? As Sheri says, "Dad knows the hard way to do everything."

Let's see if I can do this the easy way. I said sudo gpart /dev/sdg and went to lunch. An hour later, all that was on my screen was Begin scan... so I guess not. So we can't do this the easy way; we're gonna do it the hard way. Sheri might be right, that is if I'm successful.

Referring to the part of Apple's Technical Note TN1150 showing the volume header format and examining the bytes... from my earlier attempt... OK, one step at a time. I figured out at that time that the partition started 2048 blocks in, where each block is 4096 bytes. The volume header is 1024 bytes in from there. So if the block size is 1024 bytes, we can look 8193 1KB blocks in, we should find the header there:

collin@p64:~$ sudo dd if=/dev/sdg bs=1024 skip=8193 count=1 status=none | hexdump -C
00000000  48 2b 00 04 80 00 21 00  48 46 53 4a 00 00 15 d7  |H+....!.HFSJ....|
00000010  d9 35 08 4d da 54 1b 92  00 00 00 00 d9 35 6a bd  |.5.M.T.......5j.|
00000020  00 30 c1 f8 00 0b 41 4c  00 00 20 00 15 d5 04 00  |.0....AL.. .....|
00000030  0a f1 a3 84 0a ef 00 00  00 01 00 00 00 01 00 00  |................|
00000040  00 3c 44 75 00 1e 9a f1  00 00 00 00 00 00 00 01  |.<Du............|
00000050  00 00 00 02 00 10 2d b8  00 00 00 00 00 00 00 00  |......-.........|
00000060  00 00 00 00 00 00 00 00  7d c5 0b 14 d5 a8 92 17  |........}.......|
00000070  00 00 00 00 02 ba c0 00  02 ba c0 00 00 00 15 d6  |................|
00000080  00 00 00 01 00 00 15 d6  00 00 00 00 00 00 00 00  |................|
00000090  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000000c0  00 00 00 00 01 00 00 00  01 00 00 00 00 00 08 00  |................|
000000d0  00 00 85 d8 00 00 08 00  00 00 00 00 00 00 00 00  |................|
000000e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000110  00 00 00 00 69 a0 00 00  15 20 00 00 00 03 4d 00  |....i.... ....M.|
00000120  00 07 d0 d8 00 03 4d 00  00 00 00 00 00 00 00 00  |......M.........|
00000130  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000160  00 00 00 00 a9 00 00 00  15 20 00 00 00 05 48 00  |......... ....H.|
00000170  00 00 8d d8 00 05 48 00  00 00 00 00 00 00 00 00  |......H.........|
00000180  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400
Let's interpret this.
  • signature is "H+"
  • version is 4
  • attributes: 0x80002100; no idea what that means
  • lastMountedVersion: "HFSJ"
  • journalInfoBlock: 0x15d7; no idea about that either
    (offset 0x10)
  • createDate: This and the following dates are in the format described here; I translate them into localtime using this one-liner:
    h2d() { python -c "import time; hs='0x$1$2$3$4'; print time.ctime(int(hs, base=0) - 2082844800)"; }
    whence
    collin@p64:~$ h2d d9 35 08 4d
            Sun Jun 23 03:43:25 2019
  • modifyDate
    collin@p64:~$ h2d  da 54 1b 92
            Sun Jan 26 20:46:10 2020
  • backupDate: all zeroes.
  • checkedDate
    collin@p64:~$ h2d d9 35 6a bd
            Sun Jun 23 10:43:25 2019

    (offset 0x20)
  • fileCount: 0x30c1f8 or 3195384. Three million files.
  • folderCount: 0xb414c or 737612. Average of what, 4 files per directory?
  • blockSize 0x2000, that is 8K
  • totalBlocks 0x15d50400, or 366281728.
Okay, I think that's all I care about. That last was very interesting; it says the partition ought to be 366281728 blocks (block = 8K; by 'K' I mean 1024). If we started at 1024 (8KB-sized) blocks from the start of the disk, and the end of the partition is 366281728 blocks later, that's, umm, 366282752 8K blocks. I mean that ...2752 number is the first 8K-block after the end of the partition.

So let me see, how many 1K blocks would that be? 2930262016 1K-blocks. If we want to look at the last-but-one, then this command ought to give me the trailing volume header:

collin@p64:~$ sudo dd if=/dev/sdg bs=1024 skip=2930262015 count=1 status=none | hexdump -C
00000000  48 2b 00 04 80 00 20 00  48 46 53 4a 00 00 15 d7  |H+.... .HFSJ....|
00000010  d9 35 08 4d da 54 0b 51  00 00 00 00 d9 35 6a bd  |.5.M.T.Q.....5j.|
00000020  00 2c 98 1f 00 0a 81 3b  00 00 20 00 15 d5 04 00  |.,.....;.. .....|
00000030  0b 00 70 9f 0a dd b9 b7  00 01 00 00 00 01 00 00  |..p.............|
00000040  00 37 5a 59 00 1d 85 1d  00 00 00 00 00 00 00 01  |.7ZY............|
… you get the idea …
Glad that worked. This also agrees with the 5860524030 number (of 512-byte blocks) used in the second dd command on my earlier post (i.e., it's half that). Whew!

OK, so let me save off the first 4K of the drive, just in case I totally hork this. Also let me make sure I understand what I think it says.

collin@p64:~$ sudo dd if=/dev/sdg of=sheri-backup-hdd-4K.data bs=4k count=1
1+0 records in
1+0 records out
4096 bytes (4.1 kB) copied, 0.236593 s, 17.3 kB/s
collin@p64:~$ hexdump -C sheri-backup-hdd-4K.data
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001b0  00 00 00 00 00 00 00 00  1a ed a3 ce 00 00 80 fe  |................|
000001c0  ff ff af fe ff ff 00 08  00 00 00 08 aa 2b 00 00  |.............+..|
000001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001000
A web search led me to https://wiki.osdev.org/Partition_Table, where I found that this disk has just one partition defined, starting at byte 0x1be. The numbers are all little-endian.
  • bootable yes
  • starting head 0xfe (what)
  • starting sector 0x3f (high bits are for starting cylinder)
  • starting cylinder 0x3ff
  • system ID 0xaf, which this page says is "MacOS X HFS." Cool.
  • ending head 0xfe
  • ending sector 0x3f
  • ending cylinder 0x3ff
  • relative sector to start of ptn: 0x800
  • total sectors in partition 0x2baa0800 = 732563456
Now that last number, 0x2baa0800 or 732563456, matches the number of "sectors" that fdisk thought this drive had. So fdisk(1) was almost right.

Meanwhile, that wiki.osdev.org page notes that since CHS fields are useless on almost all current drives; the CHS fields are set as above (an invalid setting). That was interesting but not, as they say, actionable. What am I supposed to do to fix this? Maybe testdisk? It currently says this:

TestDisk 6.14, Data Recovery Utility, July 2013
Christophe GRENIER 
http://www.cgsecurity.org

Disk /dev/sdg - 3000 GB / 2794 GiB - CHS 364801 255 63
     Partition               Start        End    Size in sectors
* HFS                      1   5  5 364800 190 62 5860507648











Structure: Ok.  Use Up/Down Arrow keys to select partition.
Use Left/Right Arrow keys to CHANGE partition characteristics:
*=Primary bootable  P=Primary  L=Logical  E=Extended  D=Deleted
Keys A: add partition, L: load backup, T: change type,
     Enter: to continue
HFS+ blocksize=8192, 3000 GB / 2794 GiB
So I hit <Enter>, and it gave me the option to "Write", so I said yes and exited. It says I have to reboot for the change to take effect. Well, how about if I just unplug the disk?

Well, it looks like I can't just unplug it and plug it back in again. I have to wait some time... maybe about 3 minutes? Then the system will recognize the disk and re-read the partition table, etc. Like this

collin@p64:~$ udevadm monitor --udev
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing

UDEV  [540827.342967] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4 (usb)
UDEV  [540827.377682] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0 (usb)
UDEV  [540827.378275] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host8 (scsi)
UDEV  [540827.378709] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host8/scsi_host/host8 (scsi_host)
UDEV  [540828.293126] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host8/target8:0:0 (scsi)
UDEV  [540828.293685] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host8/target8:0:0/8:0:0:0 (scsi)
UDEV  [540828.294498] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host8/target8:0:0/8:0:0:0/scsi_disk/8:0:0:0 (scsi_disk)
UDEV  [540828.295261] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host8/target8:0:0/8:0:0:0/scsi_device/8:0:0:0 (scsi_device)
UDEV  [540828.295499] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host8/target8:0:0/8:0:0:0/scsi_generic/sg6 (scsi_generic)
UDEV  [540828.295630] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host8/target8:0:0/8:0:0:0/bsg/8:0:0:0 (bsg)
UDEV  [540828.296220] add      /devices/virtual/bdi/8:96 (bdi)
UDEV  [540828.674004] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host8/target8:0:0/8:0:0:0/block/sdg (block)
UDEV  [540828.792427] add      /devices/pci0000:00/0000:00:1a.7/usb7/7-4/7-4:1.0/host8/target8:0:0/8:0:0:0/block/sdg/sdg1 (block)
UDEV  [540829.220135] add      /module/hfsplus (module)
UDEV  [540829.230641] add      /module/nls_utf8 (module)
Cool. Next:
collin@p64:~$ sudo fdisk -l /dev/sdg

Disk /dev/sdg: 2.7 TiB, 3000592982016 bytes, 5860533168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xcea3ed1a

Device     Boot Start        End    Sectors Size Id Type
/dev/sdg1  *    16384 4294983678 4294967295   2T af HFS / HFS+

collin@p64:~$ 
So let fortune favor the foolish
collin@p64:~$ sudo mount -o ro /dev/sdg1 /foo/sdb1
mount: wrong fs type, bad option, bad superblock on /dev/sdg1,
       missing codepage or helper program, or other error

       In some cases useful info is found in syslog - try
       dmesg | tail or so.
collin@p64:~$
Well. dmesg told me this near the end:
[540827.160035] usb 7-4: new high-speed USB device number 6 using ehci-pci
[540827.293356] usb 7-4: New USB device found, idVendor=1f75, idProduct=0611
[540827.293359] usb 7-4: New USB device strings: Mfr=4, Product=5, SerialNumber=6
[540827.293361] usb 7-4: SerialNumber: 20181129
[540827.293640] usb-storage 7-4:1.0: USB Mass Storage device detected
[540827.293953] scsi8 : usb-storage 7-4:1.0
[540828.292492] scsi scan: INQUIRY result too short (5), using 36
[540828.292499] scsi 8:0:0:0: Direct-Access     ST3000DM 001-9YN166            PQ: 0 ANSI: 0
[540828.292806] sd 8:0:0:0: Attached scsi generic sg6 type 0
[540828.293492] sd 8:0:0:0: [sdg] Very big device. Trying to use READ CAPACITY(16).
[540828.293868] sd 8:0:0:0: [sdg] 5860533168 512-byte logical blocks: (3.00 TB/2.72 TiB)
[540828.294986] sd 8:0:0:0: [sdg] Write Protect is off
[540828.294989] sd 8:0:0:0: [sdg] Mode Sense: 3b 00 00 00
[540828.295985] sd 8:0:0:0: [sdg] No Caching mode page found
[540828.295989] sd 8:0:0:0: [sdg] Assuming drive cache: write through
[540828.297608] sd 8:0:0:0: [sdg] Very big device. Trying to use READ CAPACITY(16).
[540828.538767]  sdg: sdg1
[540828.539863] sd 8:0:0:0: [sdg] Very big device. Trying to use READ CAPACITY(16).
[540828.542869] sd 8:0:0:0: [sdg] Attached SCSI disk
[540829.251371] hfsplus: invalid secondary volume header
[540829.251377] hfsplus: unable to find HFS+ superblock
[541163.757363] hfsplus: invalid secondary volume header
[541163.757366] hfsplus: unable to find HFS+ superblock
Well, that is of course disappointing. Let's see whether MacOS can read it.

YES!

So I plugged the drive into macbook, and it was mounted immediately. MacOS apparently is a bit more tolerant of the placement of the backup volume header table—or rather, the advertised partition size. Probably it read the "first" Volume Header and believed the size it found there. And the placement of the backup volume header was consistent with that. So MacOS is happily copying files over to a new drive.

What if macOS hadn't been able to read the drive? Well, just before trying, I noticed that the size of the partition reported by testdiski.e., 5860507648 sectors—didn't match the partition size I calculated, viz. 5860524032 512-byte blocks. So if MacOS had still balked, I would have taken the drive back to my Linux box and attempted to tweak the size in the partition table. Fortunately it didn't come to that. Whew!

No comments: