Sunday, May 03, 2020

Misappropriation

These are unauthorized and unofficial ramblings. I didn't take notes when I heard this, so you’re getting my recollections at a later date; all errors are mine.

About misappropriation of funds in general

… not necessarily this case in particular:
We often won’t know how long misappropriation went on.
Sometimes an initial report will mention “at least five years,” because it's fairly easy to get bank records going back five years. Farther back, they’re harder to get.
We often won’t know how much money was taken without an arduous investigation.
Perpetrators do not usually keep separate ledger columns, so they don’t know. They don’t want to know, really. It takes time to analyze financial records, and if the misappropriation went on for over five years, records may also be incomplete.
Whether stolen assets can be returned depends on how much the perpetrator has in the way of recoverable assets.
Many organizations have insurance policies to protect them from losses of this kind. Insurers often require a police report to be filed in order to process a claim.
Police report? Aren’t these civil matters?
IANAL but I understand that there can be both criminal and civil actions. Any criminal charge would be filed by the District Attorney. It is the DA’s decision whether to file charges and prosecute. When guilt is admitted, I understand that the DA would usually proceed to file charges. This decision is influenced by many factors, including political factors.
What about a civil case?
Any civil case would typically be initiated by the insurer. This decision may be based on a judgment of whether recoverable assets would likely exceed the costs of litigation. If a defendant owns a house in the San Francisco Bay Area, then equity in the house would typically be the largest single asset and might be recoverable in a civil action.

If recoverable assets do not exceed the estimated litigation expense, a civil action would likely not be initiated.

Why the perpetrator did it is something that is usually not knowable.
Perpetrators, like all of us, tell themselves stories to justify themselves. These stories evolve over time. They tell the stories to themselves for so long that they actually believe them, even though their version of events may contain elements that simply did not happen that way. So after some time, even they don’t know why they started; consequently, they cannot tell us.

In the Trinity case, whose funds were taken?

Some denominations have legal ownership of all a church’s assets; this is true at Trinity. All assets “owned” by Trinity Menlo Park are, as a legal matter, held in trust for the Diocese of California. The Diocese is the legal owner of bank accounts, real estate, and everything else that Trinity “owns.”

When funds were taken from Trinity, then, they were as a legal matter actually taken from the Diocese. The injured party in this case is thus the Diocese; it is not “us.” That is why the Diocese must be involved.

What has Matthew said?

The Diocese’s “Title IV” process prohibits Matthew from communicating to us; we are requested not to reach out to him by any means (including social media). I recently thought to consult local news media. An April 19th article in the Mercury News includes these excerpts:

“This is a very painful time for me, and particularly for my family,” Dutton-Gillett said in a statement to this news organization. “I have a deep love for the Trinity community, and they for me, and I know that this is painful for them, as well. I regret that deeply.”

“The essence of the Christian faith is repentance and reconciliation with reparation,” Dutton-Gillett said in the statement. “It is my profound hope that we will find a way to continue our journey together in a way that embodies Christ’s forgiveness and healing, finding our way back to a place of mutual trust.”

Jail Ministry

I’ll confess here to one of my many blind spots. Until a recent meeting of Trinity’s jail ministry team, the question of jail time had not occurred to me. Or if it did, I guess I suppressed the thought because I like Matthew and worry about his future and his family.

In that jail team meeting, a team member commented that as we try to serve jail inmates, some of whom may be there unjustly, it made no sense that a white male with connections is still at large even though he has admitted guilt; there is no doubt that he stole some $125,000. This was of course a criminal act (or a sequence of criminal acts).

This team member is withdrawing from the jail team for a time, and possibly also from Trinity.

The above comments shocked me, not because I disagreed, but because, as I mentioned above, the question of criminal prosecution had somehow not occurred to me at all. It put me in mind of the Roman Catholic Church’s scandal exposed by the Boston Globe’s Spotlight team—at least as depicted in the eponymous film. What stood out for me from it was the comment from so many parishioners that they didn’t want to get the Father in trouble.

I remember feeling shocked to hear parents say that, and this instance is hardly as egregious, but I can now completely sympathize with the feelings of fondness and respect for a teacher/counselor figure.

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 testdisk—i.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!

Saturday, March 21, 2020

Data recovery: Seagate SRD0SD1

This external backup drive is at least seven years old. Some days ago, it just wouldn't power itself on. Could I fix it?

My first hope, soon dashed, was that it might the power supply. It would have been perhaps the easiest fix. But I determined that 12 volts were being supplied, and that the voltage didn't drop when the supply was plugged securely into the drive.

Next came some web searches. "Research" would not really be a fair way to characterize this, but maybe it would pass for research these days :-). I found "Danny"’s totally excellent teardown video, which enabled me to get the drive out of the enclosure.

I have a desktopside computer with SATA drives. I connected the Seagate 3TB drive in place of one of the existing drives, and tried, as superuser, "mount /dev/sdb /foo/sdb"

No joy. More web searching and after "apt-get install hfsprogs" I got this at the end of dmesg:

[67539.205183] hfsplus: unable to find HFS+ superblock
[67547.971602] hfs: can't find a HFS filesystem on dev sdb1
Well, let's have a look at the drive
collin@p64:~$ sudo fdisk -l /dev/sdb

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

Device     Boot Start       End   Sectors   Size Id Type
/dev/sdb1  *     2048 732565503 732563456 349.3G af HFS / HFS+

collin@p64:~$ 
So that's totally bogus; this is a 3TB drive! Then I remembered some work I did with netbsd around 2001; *BSD systems apparently use “labels” rather than the partition table. So the ptn table is just so much random bits 8^(

I decided to troll around a little, and found this. Don't ask me how I came up with 2048 blocks (with a totally unwarranted 4K blocksize) but here's what struck me:

collin@p64:~$ sudo dd status=none if=/dev/sdb bs=4k skip=2048 count=1 | hexdump -C
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400  48 2b 00 04 80 00 21 00  48 46 53 4a 00 00 15 d7  |H+....!.HFSJ....|
00000410  d9 35 08 4d da 54 1b 92  00 00 00 00 d9 35 6a bd  |.5.M.T.......5j.|
00000420  00 30 c1 f8 00 0b 41 4c  00 00 20 00 15 d5 04 00  |.0....AL.. .....|
00000430  0a f1 a3 84 0a ef 00 00  00 01 00 00 00 01 00 00  |................|
00000440  00 3c 44 75 00 1e 9a f1  00 00 00 00 00 00 00 01  |.<Du............|
00000450  00 00 00 02 00 10 2d b8  00 00 00 00 00 00 00 00  |......-.........|
00000460  00 00 00 00 00 00 00 00  7d c5 0b 14 d5 a8 92 17  |........}.......|
00000470  00 00 00 00 02 ba c0 00  02 ba c0 00 00 00 15 d6  |................|
00000480  00 00 00 01 00 00 15 d6  00 00 00 00 00 00 00 00  |................|
00000490  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000004c0  00 00 00 00 01 00 00 00  01 00 00 00 00 00 08 00  |................|
000004d0  00 00 85 d8 00 00 08 00  00 00 00 00 00 00 00 00  |................|
000004e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000510  00 00 00 00 69 a0 00 00  15 20 00 00 00 03 4d 00  |....i.... ....M.|
00000520  00 07 d0 d8 00 03 4d 00  00 00 00 00 00 00 00 00  |......M.........|
00000530  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000560  00 00 00 00 a9 00 00 00  15 20 00 00 00 05 48 00  |......... ....H.|
00000570  00 00 8d d8 00 05 48 00  00 00 00 00 00 00 00 00  |......H.........|
00000580  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00001000
collin@p64:~$ 
Okay, now that’s more like it. "H+" and "HFSJ" appear there. Searching around the web, I came upon the "Volume Header" section in Apple Technical Note TN1150, which begins:
Each HFS Plus volume contains a volume header 1024 bytes from the start of the volume. The volume header -- analogous to the master directory block (MDB) for HFS -- contains information about the volume as a whole, including the location of other key structures in the volume. The implementation is responsible for ensuring that this structure is updated before the volume is unmounted.

A copy of the volume header, the alternate volume header, is stored starting 1024 bytes before the end of the volume. The implementation should only update this copy when the length or location of one of the special files changes. The alternate volume header is intended for use solely by disk repair utilities.

Okay, so note how that "H+" begins at 0x400 (i.e., 1024) bytes from the start of this block? the vol begins 2048 blocks in, with a 4K block size, and this block is 1024 bytes in from there. What else?

Somewhere on the web I read the instructions to get testdisk, as in sudo apt-get install testdisk. I said sudo testdisk /dev/sdb and after some flailing I got this:

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

Disk /dev/sdb - 3000 GB / 2794 GiB - CHS 364801 255 63
     Partition               Start        End    Size in sectors
>P HFS                        16384 5860524031 5860507648
Okay, so if a sector is 512 bytes, then testdisk agrees with me that the vol starts 8MB in (MB=1024*1024 bytes). Let's see if we can find the backup/alternate vol header by subtracting 1 from that 5860524031 number:
collin@p64:~$ sudo dd status=none if=/dev/sdb bs=512 skip=5860524030 count=1 | 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............|
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  |................|
*
00000200
collin@p64:~$ 
Okay, now that's good to know. One other piece of info here. I saw on https://superuser.com/questions/657655/problems-with-mounting-hfs-drives that there is a program gdisk, somewhat like fdisk, can give somewhat more detail on the partition types. And that there are (at least) two partition types of interest:
While the answer provided by mcy should work if the partition is actually an HFS+ partition, starting with OSX Yosemite the default partition type for a Mac is "Core Storage", which is used to handle logical volumes. This means that what you actually want to mount is a logical volume (using HFS+ filesytem) inside the "Core Storage" partition.

To see if your partition is of type "Apple Core Storage" you can use gdisk: AF05 is the code for "Apple Core Storage", while af00 is the code for "Apple HFS/HFS+".

What is this gdisk of which you speak? type gdisk said "not found" so I said:
collin@p64:~$ sudo apt-get install gdisk
Reading package lists... Done
Building dependency tree       
Reading state information... Done
gdisk is already the newest version.
gdisk set to manually installed.
The following packages were automatically installed and are no longer required:
  python-cffi python-colorama python-cryptography python-distlib
  python-ndg-httpsclient python-openssl python-ply python-pyasn1
  python-pycparser python-requests python-urllib3 python-wheel
Use 'apt-get autoremove' to remove them.
0 upgraded, 0 newly installed, 0 to remove and 455 not upgraded.
collin@p64:~$ type gdisk
bash: type: gdisk: not found
collin@p64:~$ 
Hurmpf. Was it...? Yes it was. Here:
collin@p64:~$ sudo /sbin/gdisk -l /dev/sdb
GPT fdisk (gdisk) version 0.8.10
...
***************************************************************
Found invalid GPT and valid MBR; converting MBR to GPT format
in memory. 
***************************************************************

Disk /dev/sdb: 5860533168 sectors, 2.7 TiB
Logical sector size: 512 bytes
Disk identifier (GUID): C599270C-2980-42BA-996C-7BF534EE6702
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 5860533134
Partitions will be aligned on 2048-sector boundaries
Total free space is 5127969645 sectors (2.4 TiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048       732565503   349.3 GiB   AF00  Apple HFS/HFS+
collin@p64:~$ 
Well, it still seems silly about the 349.3GBytes, but it says the partition code is the HFSplus one, not the core storage one. That's good news at least.

But not good enough I think. Note that even gdisk thinks we ought to be starting at sector 2048 and that the partition is only about 350gb in size. I noted "offset" and "sizelimit" options in https://superuser.com/questions/961401/mounting-hfs-partition-on-arch-linux/1088110, but mount(8) tells me that those are losetup options only:

       The mount command automatically creates a loop device  from  a  regular
       file  if  a filesystem type is not specified or the filesystem is known
       for libblkid, for example:

              mount /tmp/disk.img /mnt

              mount -t ext3 /tmp/disk.img /mnt

       This type of mount knows about three options, namely loop,  offset  and
       sizelimit,  that  are really options to losetup(8).  (These options can
       be used in addition to those specific to the filesystem type.)
I don't want to hack the partition table, as I might totally b0rk it; another idea involves getting an adapter, sata↔USB, and just try mounting it on a mac. It would have to be one with a power supply. Maybe something from newegg.com

Thursday, December 26, 2019

Some things I'm thankful for (particularly at work)

Some weeks ago at Trinity Menlo Park, Pastor Aaron reminded us that life is short, and we don’t have many days to bless those around us. Inspired by that remark, I emailed the below to a few (i.e., quite a few) of my co-workers.
2019-12-04 2:12pm Pacific
Colleagues,

I was reflecting the other day on things I’m grateful for. Family and friends, of course; a measure of health; vehicles and home appliances that work well enough. Not least is the opportunity to work together with so many intelligent, hard-working folks (yes I mean you).

And as I reflect on the ONTAP development experience at NetApp, it strikes me how much better that experience is today as compared to what it has been. Reviewboard is just one of the major improvements that came in over the past 15 years or so.

In the “old days,” you could check something into ontap/main, only to get a nasty-gram from the build daemon. Then you’d find out that the build daemon had been failing for several hours because somebody broke it and no one fixed it!

Auto-heal isn’t perfect, but it’s pretty close, which we can tell by how surprised everybody is when it can’t back out a bad checkin.

I also remember a day when Isabelle submitted something and the build-ng daemon whined at her. She backed her change out and the daemon kept failing! It took several days to figure out that missing dependencies had hidden the real culprit, which had been submitted some weeks before :-(

Bedrock and DOT/dev aren’t perfect either, but again we’re surprised at sporadic failures...

I think of Anchorsteam, which shipped at least a full year late. We added Scrimshaw after Fullsail, because customers were waiting so long for another release—but Scrimshaw was late, too! Back then, managers really had no idea how close we were to being ready. Or they wouldn’t say :-(

Although the six-month release cadence hasn’t been a panacea, it has brought some reality into the management ranks.

And do you remember how much stuff we shipped without testing? Scrimshaw.3 had no snapmirror testing whatsoever! A former VP demanded that we test patches more thoroughly—and also ship them more rapidly—that didn’t work too well.

I am so thankful that today we have CITs and auto-heal, daily code coverage reports, CTL, and other tools to enhance ONTAP’s quality.

All these things took a lot of work from a lot of folks. Reviewboard, bedrock, bammbamm, CITs, auto-heal on both build and CIT, and so much more. You know who you are.

Thank you thank you thank you for how you’ve improved life for developers, and thereby for all the folks that rely on our products every day.

Monday, December 23, 2019

What did Jesus mean when he said “salvation”?

Recently the story of Jesus’s encounter with Zacchaeus appeared on pray-as-you-go at this link for November 19th; “coincidentally,” Menlo Church’s November 24th sermon covered the same passage. The lovely Carol showed me a page from her devotional guide that also focused on this passage, and encouraged its readers to write a few paragraphs about salvation: what does that mean to me? Following are a few thoughts.
9Jesus said to him, “Today salvation has come to this house, because this man, too, is a son of Abraham. 10For the Son of Man came to seek and to save the lost.”
Luke 19:9–10, NIV (2013)
Perhaps you know the story: Zacchaeus, a rich and corrupt tax collector in first-century Israel, encounters Jesus in Jericho; Jesus goes to Zack’s house for a meal, Zack repents, and Jesus says that salvation had come to the house. The full text is here.

Reflecting on this story, and particularly what Jesus says about salvation, it struck me that my understanding of the passage is quite different from the way I understood it 20–30 years ago. Back then, as a young evangelical, I would have had a very narrow idea of “salvation”: I thought it meant the shift from a dim eternal destiny to a bright one. Before salvation, Zacchaeus was headed for hell; once saved, he was headed for heaven.

The way this happened, I would have said, was that some time during the visit, Zack came to “believe in Jesus” (in a John 3:16 sort of way), and at that point, became a child of God, as John 1:12 promises. Being thus adopted by God, he was now destined for heaven. And I would have said that his proclamation (“Here and now I give half of my possessions to the poor…”) was evidence of Zack’s belief and perhaps of an incipient transformation wrought by God.

That belief somehow caused God to change his mind about Zack; God’s view used to be that Zack was deserving of hell, but after Zack came to believe, God saw him as forgiven: in the words of the hymn, “clothed in His righteousness alone / faultless to stand before the throne.”

OK, that explanation wasn’t as clear and crisp as I’d have liked, though, because as Romans 3 teaches, nobody ever looks for God. Ephesians 2:8 says we’re saved by grace through faith, but even faith is a gift from God; we can’t generate that faith by ourselves.

Suppose that Zacchaeus had said nothing about providing for the poor, or about making restitution to those he cheated? It would not have made any difference to me back then; my view, based on verses like John 1:12 and John 3:16 and John 5:24, was that basically “all you need is to believe.”

Although there was some muddiness in my understanding, that’s how I thought about the “salvation” thing.

Thirty years later…

How is my thinking different today? For one thing, my understanding of “salvation” is broader and with a different focus. As I understand it, in first-century Israel, Eternity-in-Hell-after-you-die was not the thing people would feel most in need of being saved from. They would be thinking of how to be saved from oppression, poverty, fear or shame. Or from being a pariah in the community.

Which Zacchaeus was. I wonder how his short stature affected his experience growing up. Was he ridiculed or bullied? Is that why he he decided to collaborate with the Roman oppressors to exploit his own people? And to cheat them besides?

So he became a tax collector, then chief. He got money, and maybe some sort of revenge against his persecutors, but his wealth didn’t gain him respect within the community. I see him as caught in a viscious cycle partly of his own making. And I think that when Zacchaeus saw Jesus, he didn’t see the kind of hate and judgment that he saw on the faces of those around him. Somehow, during the party, he was enabled to see a way out of that viscious cycle—he saw a better way to be. This is the kind of thing that can happen when Jesus encounters us: we find ourselves suddenly able to take a step we had not previously imagined.

As Paul wrote in Titus 3: “For we ourselves were once foolish, disobedient, led astray, slaves to various passions and pleasures, spending our days in malice and envy, hated by others and hating one another. But when the goodness and mercy of God our savior appeared, he saved us, not on the basis of our good deeds, but according to his mercy…”

God, in the person of Jesus, made it possible for Zacchaeus to escape the slavery of those various passions and pleasures—or at least, to begin the journey. How could Zacchaeus keep on the journey? How can any of us do so? The author of Hebrews exhorts us to pay attention so as not to drift away.

1We must pay more careful attention, therefore, to what we have heard, so that we do not drift away. 2For if the message spoken by angels was binding, and every violation and disobedience received its just punishment, 3how shall we escape if we ignore such a great salvation?
from Hebrews 2
She writes that Jesus is “the source of eternal salvation to all who obey him” (5:9). She exhorts us to be diligent in pursuing our hope, that we may not be sluggish, but “imitators of those who through faith and patience inherit the promises” (6:12).

What does this look like? Suppose I fall into the ocean at night. I can’t touch bottom. Suddenly I hear a life preserver splash in the water but I can’t see it. A voice tells me to swim ahead. It tells me to turn right; I pay careful attention and do what I’m told. Eventually I grab it. In this story, I have a big problem: I’m helpless in the water. Do I want to be saved? Well, yes—but I’m way more concerned about drowning than about eternal destiny. I had to pay attention; I couldn’t ignore such a salvation. I had to obey.

But I might also be worried about eternal destiny; it’s the kind of thing we tend to postpone thinking about until the last possible moment. And a first-century Israelite might very well be thinking about sin and forgiveness. The book of Leviticus has the most instances of “forgiven” of any in the English Bible. John baptized people “for the remission of sins.”

So I think people would be concerned about both. Actually, as I was thinking and writing about this, I remembered that first-century Greek has a lot fewer words than modern American English. The word translated “saved” can be (and sometimes is) translated “healed.” And in Matthew’s gospel, we read that the angel told Joseph to call the baby Jesus, “because he will save his people from their sins” (1:21).

I now think of salvation as being much broader: as saving the whole person from every kind of hurt: ostracism, drowning, cancer, PTSD, guilt and shame, loneliness, depression, famine, sword. Ultimately, from death: as the Apostle Paul writes, we are destined not for wrath but for obtaining salvation through our Lord Jesus Christ, who died for us so that whether we are awake or asleep (a euphemism for dying), we may live together with him. I think that’s in 1 Thessalonians… yes it is: link here (NASB)

Tuesday, December 10, 2019

Wednesday with Poppy

being a shortened version of this post from July

with Carol in July

with me, June campout in Big Sur
17 July 2019

I do and I don’t want to forget this day. The past several months, Poppy has been clingy, maybe feeling uncomfortable because of her kidney disease. Last week I was wishing she could pee normally. But as they say, “Be careful what you wish for,” because yesterday she let loose with a puddle on the hardwood floor.

Before walking her, I surveyed the back yard. There on the path was a normal-looking #2. I never thought I’d be so happy to see one of these; her elimination had been out of whack since the vet put her on a low-protein diet. I found her lead and a pet refuse bag, and invited her out. She bounded over with almost her former intensity, and exploded out the gate once I opened it. She soon ran out of gas, but we walked fully 20 minutes.

Carol would be out most of the day; I worked from home so Poppy wouldn’t be alone. The past few days I prepared her meals from leftovers. Poppy was refusing the weird stuff from the vet, and didn’t even want her old kibble. On this morning I put a little water and rice on the stove, and some salmon, under her close supervision. After it simmered a few minutes, I stirred in a fiber capsule, let it cool for a bit, and walked it to her crate. “Sit!” I commanded. She promptly obeyed. Placing her bowl on the floor, I said, “OK,” and she fell to.

In a couple of minutes she found me and gave me her “More?” look. I scooped a handful of her formerly-favorite kibble into her bowl. She ate most of that, and then stopped. “Well,” I thought, “She must be feeling better.”

A while later, it was time to go to the bank. “Want to go for a ride?” I called.

She jumped off the couch and looked at me expectantly. I gathered my things and she followed me to the garage. The van is too high for her to get into by herself, so I lifted her onto my seat. She jumped to the passenger side. I lowered her window, belted myself in, and off we went. About half-way through town, she began looking toward my window. “Want to come over?” I asked.

At the next traffic signal, I scooted back a few inches, and she took a tentative step. I lifted her onto my lap, and as the light turned green, she put her paws onto the door. A few blocks later, she wanted to go back; I gave her a one-handed boost to the passenger seat.

I left both front windows open a few inches. “I’ll be back in a flash,” I told her, and went into the bank.

I returned to find her in the driver’s seat. “Excuse me,” I said as I opened the door. She returned to the passenger seat and we went for her last ride back to the house. I gave her a half-tablet of the antiemetic, to help her feel more comfortable in her final hours.

I fed her for the last time. Well, almost the last: she came to me in the kitchen with her “Carrot?” look. I handed her one, which she cheerfully chomped. (She did that Monday, too, but immediately vomited the whole thing. This time everything stayed down.)

Carol came home to take Poppy to the vet. I just wanted to be somewhere else, so I gathered a few things and went to the office. Poppy followed me outside. Maybe she suspected something was up, because when I leave I always say, “Be a good girl”; this time I knelt down and stroked her fur. “I’m sorry, Poppy,” I said. “I’m so sorry.” I’m sure she could tell I was really broken up about something.

At work it was “Employee Appreciation Week” and there was an ice cream social. But I didn’t want ice cream and didn’t feel social, so I skipped it. I did something vaguely productive and went home. As I entered the house there was no jingle of Poppy’s tags on her collar, no little footsteps.

Monday, September 09, 2019

LG 34UM58-P Revisited: a Puzzle

I wrote earlier about this LG ultrawide monitor: 2560x1080 pixels, about 34" diagonal. Although it's great having all the pixels, the screen didn't look all that good on my Linux machine.
I created the image file you see at left. The squares in the upper-left corner have the red pixel turned on at x=0, 5, 10, 15, etc., and at y=0, 5, 10, 15, etc. I wanted to have just one of the color-dots on in each pixel, and I thought a black background would show up better what was going on.

I ran the display(1) program (from ImageMagick) and pulled out my camera. The picture below shows the sad story.

As you can see, the horizontal lines look more or less like lines, but the vertical lines are a mess. Before I examined the screen carefully, I had assumed the card didn't have enough horizontal pixels; maybe it had just 1920 per line, and it was dithering or something to decide what signal to send. But then I thought we ought to get a clean vertical line at some point.

So this is a puzzle. When I hooked this monitor up to the lovely Carol's macbook, the display looked great, not muddy at all. I wondered if it was the cable; I bought a new one with better specs. Maybe it looks a little better, but the photo was shot while using the new cable. Maybe I should be using the card's DVI outputs rather than the mini-HDMI output? I have no idea.