jivanpal / drat

Utility for performing data recovery and analysis of APFS partitions/containers.
GNU General Public License v3.0
163 stars 21 forks source link

Recover file metadata (Icon file cannot be recovered) #34

Open akira-okumura opened 2 years ago

akira-okumura commented 2 years ago

The special Icon\r files on macOS cannot be recovered maybe due to its special file name. It ends with \r.

Can I recover this file by drat?

$ sudo ./drat recover --container /dev/disk2s2 --volume 1 --path /movie/Megane.dvdmedia/Icon --output /Volumes/TOSHIBA_8TB/movie/Megane.dvdmedia/ 
Creating file `/Volumes/TOSHIBA_8TB/movie/Megane.dvdmedia/_com.dratapp.recover_Icon` ... OK.
Opening `/dev/disk2s2` in read-only mode ... OK.
Determining block size ... 4096 bytes.

Finding most recent container superblock:
- Reading block 0x0 ... validating ... OK.
- Loading checkpoint descriptor area ... OK.
- Searching checkpoint descriptor area ... found most recent container superblock at index 159, its XID is 0x4921b.
Finding container's omap tree:
- Container's omap has Physical OID 0x624395.
- Reading block 0x624395 ... validating ... OK.
- Container's omap tree has Physical OID 0x624484.
- Reading block 0x624484 ... validating ...OK.

Finding volume 1's superblock:
- Volume 1 has Virtual OID 0x402 ... maps to block 0x624353 with XID 0x4921b.
- Reading block 0x624353 ... validating ... OK.
- Volume name: G-DRIVE
Finding volume's omap tree:
- Volume's omap has Physical OID 0x5d6493.
- Reading block 0x5d6493 ... validating ... OK.
- Volume's omap tree has Physical OID 0x5d7962.
- Reading block 0x5d7962 ... validating ... OK.

Finding volume's filesystem tree:
- Filesystem tree has Virtual OID 0x404 ... maps to block 0x5df33f.
- Reading block 0x5df33f ... validating ... OK.

Navigating to path `/movie/Megane.dvdmedia/Icon` ... END: No dentry found for path `/movie/Megane.dvdmedia/Icon`.

This recover command results in an empty file.

$ ls -l /Volumes/TOSHIBA_8TB/movie/Megane.dvdmedia/_com.dratapp.recover_Icon
-rw-------  1 oxon  staff  0 Feb 24 23:37 /Volumes/TOSHIBA_8TB/movie/Megane.dvdmedia/_com.dratapp.recover_Icon
$ sudo ./drat list --container /dev/disk2s2 --volume 1 --path /movie/Megane.dvdmedia/       
Opening `/dev/disk2s2` in read-only mode ... OK.
Determining block size ... 4096 bytes.

Finding most recent container superblock:
- Reading block 0x0 ... validating ... OK.
- Loading checkpoint descriptor area ... OK.
- Searching checkpoint descriptor area ... found most recent container superblock at index 159, its XID is 0x4921b.
Finding container's omap tree:
- Container's omap has Physical OID 0x624395.
- Reading block 0x624395 ... validating ... OK.
- Container's omap tree has Physical OID 0x624484.
- Reading block 0x624484 ... validating ...OK.

Finding volume 1's superblock:
- Volume 1 has Virtual OID 0x402 ... maps to block 0x624353 with XID 0x4921b.
- Reading block 0x624353 ... validating ... OK.
- Volume name: G-DRIVE
Finding volume's omap tree:
- Volume's omap has Physical OID 0x5d6493.
- Reading block 0x5d6493 ... validating ... OK.
- Volume's omap tree has Physical OID 0x5d7962.
- Reading block 0x5d7962 ... validating ... OK.

Finding volume's filesystem tree:
- Filesystem tree has Virtual OID 0x404 ... maps to block 0x5df33f.
- Reading block 0x5df33f ... validating ... OK.

Navigating to path `/movie/Megane.dvdmedia/` ... its FSOID is 0x18f3.
Finding records for FSOID 0x18f3 ... OK.
Filesystem object has 6 records, as follows:
- INODE
- XATTR || name = com.apple.FinderInfo
- XATTR || name = com.apple.lastuseddate#PS
- DIR REC || RegFile || target ID =   0x18f4 || name = .DS_Store
- DIR REC || RegFile || target ID =   0x18f5 || name = Icon
- DIR REC || Dirctry || target ID =   0x18f7 || name = VIDEO_TS
jivanpal commented 2 years ago

You will need to input the filepath containing the CR/\r character in a way that your shell can understand. In Bash, this can be done with $'\r', e.g. /movie/Megane.dvdmedia/Icon$'\r' or $'/movie/Megane.dvdmedia/Icon\r'

akira-okumura commented 2 years ago

Thank you very much again. I was able to pass \r to the command, but recover fails getting the file size. Any idea? The same problem also happens for at least two other Icon files.

$ sudo ./drat recover --container /dev/disk2s2 --volume 1 --path /movie/Megane.dvdmedia/Icon$'\r' --output /Volumes/TOSHIBA_8TB/movie/Megane.dvdmedia/
` ... OK.file `/Volumes/TOSHIBA_8TB/movie/Megane.dvdmedia/_com.dratapp.recover_Icon
Opening `/dev/disk2s2` in read-only mode ... OK.
Determining block size ... 4096 bytes.

Finding most recent container superblock:
- Reading block 0x0 ... validating ... OK.
- Loading checkpoint descriptor area ... OK.
- Searching checkpoint descriptor area ... found most recent container superblock at index 159, its XID is 0x4921b.
Finding container's omap tree:
- Container's omap has Physical OID 0x624395.
- Reading block 0x624395 ... validating ... OK.
- Container's omap tree has Physical OID 0x624484.
- Reading block 0x624484 ... validating ...OK.

Finding volume 1's superblock:
- Volume 1 has Virtual OID 0x402 ... maps to block 0x624353 with XID 0x4921b.
- Reading block 0x624353 ... validating ... OK.
- Volume name: G-DRIVE
Finding volume's omap tree:
- Volume's omap has Physical OID 0x5d6493.
- Reading block 0x5d6493 ... validating ... OK.
- Volume's omap tree has Physical OID 0x5d7962.
- Reading block 0x5d7962 ... validating ... OK.

Finding volume's filesystem tree:
- Filesystem tree has Virtual OID 0x404 ... maps to block 0x5df33f.
- Reading block 0x5df33f ... validating ... OK.

` ... its FSOID is 0x18f5./Megane.dvdmedia/Icon
Finding records for FSOID 0x18f5 ... OK.
Filesystem object has 3 records, as follows:
- INODE
- XATTR || name = com.apple.FinderInfo
- XATTR || name = com.apple.ResourceFork

ERROR: get_file_size: No file size found.
jivanpal commented 2 years ago

Looks like an empty file that doesn't even specify that the file size is zero. There are not even any file extents listed at the end there, only the inode and a couple xattrs. We currently assume that the file size is stated in the inode or xfields, and that it should be non-zero. Moreover, recover only recovers file data, not metadata like xattrs. I'll take this is a feature request to improve file recovery by still recovering empty files and file metadata.

akira-okumura commented 2 years ago

Extended attributes are quite important for some Apple style file management. In Photos the original file name, for example, is not stored in SQL data base but in an extended attribute. It would be great if they could be recovered in a future version.

$ sudo ./drat list --container /dev/disk2s2 --volume 1 --path /Nagoya\ 2021-.photoslibrary/originals/9/9A02683E-F7D5-4B79-8BB1-F159C80812F2.jpeg                                       
Opening `/dev/disk2s2` in read-only mode ... OK.
Determining block size ... 4096 bytes.

Finding most recent container superblock:
- Reading block 0x0 ... validating ... OK.
- Loading checkpoint descriptor area ... OK.
- Searching checkpoint descriptor area ... found most recent container superblock at index 159, its XID is 0x4921b.
Finding container's omap tree:
- Container's omap has Physical OID 0x624395.
- Reading block 0x624395 ... validating ... OK.
- Container's omap tree has Physical OID 0x624484.
- Reading block 0x624484 ... validating ...OK.

Finding volume 1's superblock:
- Volume 1 has Virtual OID 0x402 ... maps to block 0x624353 with XID 0x4921b.
- Reading block 0x624353 ... validating ... OK.
- Volume name: G-DRIVE
Finding volume's omap tree:
- Volume's omap has Physical OID 0x5d6493.
- Reading block 0x5d6493 ... validating ... OK.
- Volume's omap tree has Physical OID 0x5d7962.
- Reading block 0x5d7962 ... validating ... OK.

Finding volume's filesystem tree:
- Filesystem tree has Virtual OID 0x404 ... maps to block 0x5df33f.
- Reading block 0x5df33f ... validating ... OK.

Navigating to path `/Nagoya 2021-.photoslibrary/originals/9/9A02683E-F7D5-4B79-8BB1-F159C80812F2.jpeg` ... its FSOID is 0x67cfdf.
Finding records for FSOID 0x67cfdf ... OK.
Filesystem object has 23 records, as follows:
- INODE
- XATTR || name = com.apple.assetsd.UUID
- XATTR || name = com.apple.assetsd.addedDate
- XATTR || name = com.apple.assetsd.assetType
- XATTR || name = com.apple.assetsd.avalanche.type
- XATTR || name = com.apple.assetsd.creatorBundleID
- XATTR || name = com.apple.assetsd.customCreationDate
- XATTR || name = com.apple.assetsd.dbRebuildUuid
- XATTR || name = com.apple.assetsd.deferredProcessing
- XATTR || name = com.apple.assetsd.favorite
- XATTR || name = com.apple.assetsd.grouping.state
- XATTR || name = com.apple.assetsd.hidden
- XATTR || name = com.apple.assetsd.importedBy
- XATTR || name = com.apple.assetsd.importedByDisplayName
- XATTR || name = com.apple.assetsd.originalFilename
- XATTR || name = com.apple.assetsd.publicGlobalUUID
- XATTR || name = com.apple.assetsd.timeZoneName
- XATTR || name = com.apple.assetsd.timeZoneOffset
- XATTR || name = com.apple.assetsd.trashed
- XATTR || name = com.apple.assetsd.videoComplementVisibility
- XATTR || name = com.apple.quarantine
- DSTREAM ID  || file ID = 0x67cfdf || ref. count = 1
- FILE EXTENT || file ID = 0x67cfdf || log. addr. =          0 || length = 12214272 B =   0xba6000 B =  2982 blocks =   0xba6 blocks || phys. block = 0x3e9cacb4
akira-okumura commented 2 years ago

I found that even the commercial software Disk Drill didn't support recovering Icon files or any other extended attributes of normal files at all.

I am just curios to ask you. How difficult is it to recover them on APFS?

jivanpal commented 2 years ago

These things are not particularly difficult, they are just likely not features that have been demanded much. Also, depending on the state of the filesystem, recovering metadata may be impossible whilst recovering file data may be relatively simple. This is beacuse a file's xattrs etc. are stored separately from the file's inode, as records alongside it in the filesystem root tree. Thus, if that tree is corrupt, the xattrs may be undiscoverable, corrupt, or unable to be matched with the corresponding file; whilst the file inode itself will still be identifiable and this the file data can be found along with the corresponding file name if the inode is fully intact.