兩三年前買了兒童相機給小孩亂拍,坊間大部分的兒童相機都大同小異,有的著重相機畫素,有的著重拍攝的方便性,像是可自拍、觸控螢幕等。後來,我選了觸控螢幕款,畢竟方便第一,至於畫素、閃光燈等等的就放掉,並買了一張 32GB microSD ,讓小孩大小可隨便錄影。
最近出遊時,兒童相機在開機的狀態下,不小心摔到地上,接著無法拍照(儲存),也看不到所有已拍攝的資料。
當下在想,這種 microSD 跟 SSD 的,不像以前的 HDD 有轉盤在那邊轉,應該不至於壞軌,再細想一下,有可能像 OS 優化連續錄影/開多檔快速寫檔案,但這時撞到地上導致 OS 狀態異常,沒有把資料收尾而損毀,可能導致 micorSD 檔案系統 Header 就被破壞掉,而不是 microSD 受到什麼物理性的破壞。
接著,就來煩 AI 了 XD 我自己是先把損毀的 microSD 透過 macOS 內建的 Disk Utility 先備份一份 Image 檔案(備份過程也不是很正常的結束,但至少產生了一個 img 檔案),接著拿另一張同樣容量的 32GB microSD 來處理,避免一開始就對原始 microSD 卡操作。
最後,透過跟 AI 聊天的過程,他認為我的想法/直覺有機會解掉,於是乎就操作看看,出發點是想重建 microSD header,流程:
- 先把損毀的 microSD卡(A),透過 macOS 內建 Disk Utility 先備份一份 Image 檔案,產出 a_card.img
- 製作乾淨的 microSD卡(B),把額外一張 microSD 卡放入兒童相機格式化,確保資料檔案系統跟損毀的 microSD 卡一樣,在產出 clean_b_card.img
- 後續則是在 microSD卡(B) 操作,用 a_card.img 資料覆蓋 microSD卡(B),這時 microSD卡(B) 插入兒童相機一樣會顯示檔案損毀的狀態
- 最後則是拿 clean_b_card.img 部分資料去覆蓋 microSD卡(B) ,直到可以 OS 正常讀出資料
執行過程中,AI 其實會去猜檔案系統為何,然後摸索 Header 大小,像是建議一開始用 8MB 來猜,然後測試完看不到資料,又說可以試試 4MB (一樣看不到資料),又說要不要試試 2MB,這時我反而去問他應該要從 header size 小到大來測試,也讓 AI 想起可以用 macos 內建的 diskutil 指令查詢資料,此例是 microSD 插入後被系統安置在 /dev/disk10 ,相關指令如:
% diskutil info /dev/disk10 | grep -E "(Block|Cluster|Sector)"Device Block Size: 512 BytesAllocation Block Size: 512 Bytes
不然根據 AI 的建議,他的操作每一次都要重新製作一次 microSD卡(B) ,滿費時的,最終我就只測試三次,分別是 8MB, 4MB ,接著到 512KB 就搞定了(過程重建 3次資料),而我請 AI 由小到大的 header size 測試,他給予的指令流程:
# 1. 先一次性寫入 A 卡資料(只做這一次)diskutil unmountDisk /dev/disk10sudo dd if=a_card.img of=/dev/rdisk10 bs=1m# 2. 從最小範圍開始測試 - 只覆蓋 Boot Sector (512 bytes)sudo dd if=clean_b_card.img of=/dev/rdisk10 bs=512 count=1 conv=notruncdiskutil mountDisk /dev/disk10# 檢查是否有資料,如果沒有繼續下一步# 3. 如果 512 bytes 不夠,擴大到 40KB(到 FAT 表開始位置)diskutil unmountDisk /dev/disk10sudo dd if=clean_b_card.img of=/dev/rdisk10 bs=1k count=40 conv=notruncdiskutil mountDisk /dev/disk10# 檢查結果# 4. 如果還不夠,擴大到 100KBdiskutil unmountDisk /dev/disk10sudo dd if=clean_b_card.img of=/dev/rdisk10 bs=1k count=100 conv=notruncdiskutil mountDisk /dev/disk10# 檢查結果# 5. 繼續擴大到 500KBdiskutil unmountDisk /dev/disk10sudo dd if=clean_b_card.img of=/dev/rdisk10 bs=1k count=500 conv=notruncdiskutil mountDisk /dev/disk10# 檢查結果# 6. 最後到 1MBdiskutil unmountDisk /dev/disk10sudo dd if=clean_b_card.img of=/dev/rdisk10 bs=1k count=1024 conv=notruncdiskutil mountDisk /dev/disk10
我後來只做這些,就看得到資料:
% diskutil unmountDisk /dev/disk10% sudo dd if=a_card.img of=/dev/rdisk10 bs=1m9297+1 records in9297+1 records out9748611584 bytes transferred in 642.300766 secs (15177643 bytes/sec)% sudo dd if=clean_b_card.img of=/dev/rdisk10 bs=512 count=1 conv=notruncPassword:1+0 records in1+0 records out512 bytes transferred in 0.009456 secs (54146 bytes/sec)% diskutil mountDisk /dev/disk10Volume(s) mounted successfully
如此能看到資料後,也確定有些檔案相機的確沒正確寫入,顯示損毀,猜測應該是晚一點寫檔的機制(cache),導致有些檔案並未正確收尾。
最後在靠這些:
最後在靠這些:
% diskutil unmountDisk /dev/disk10Unmount of all volumes on disk10 was successful% sudo fsck_msdos -f -y /dev/disk10Password:** /dev/rdisk10** Phase 1 - Preparing FAT** Phase 2 - Checking Directories** Phase 3 - Checking for Orphan ClustersWarning: 175 files, 31120736 KiB free (972523 clusters)% brew install testdisk% sudo photorec /dev/disk10
過程:
PhotoRec 7.2, Data Recovery Utility, February 2024Christophe GRENIER <grenier@cgsecurity.org>https://www.cgsecurity.orgDisk /dev/disk10 - 31 GB / 29 GiB (RO)Partition Start End Size in sectorsP FAT32 0 62333951 62333952 [NO NAME]Destination /path/recup_dirPass 1 - Reading sector 6458368/62333952, 217 files foundElapsed time 0h02m02s - Estimated time to completion 0h17m35jpg: 101 recoveredtxt: 94 recoveredmov: 17 recoveredgz: 5 recovered
希望可以救多一點