磁盘文件系统坏了,是因为使用了HFS+ FOR WINDOWS 在macos和windows两边进行读写修改之类的,结果悲剧了,整个 HFS+的分区都变了成只读(read only),也无法使用“急救”来修复。
挂之前的现象的是写大文件会给截断,如8G的文件,copy过去,结果就变成了2G, 太坑了。。。
好在还能读,赶紧把最重要的图片放到另一个硬盘上。
放完之后,打开“照片”应用,提交原文件不可用,无法打开云云,于是尝试使用sqite3修复一下.
1. 先把照片应用都退出
ps aux | grep -i photo | awk '{print $1}' | xargs kill -9
2. 备份db
#先备份
cp -r /Volumes/evo/myphotos.photoslibrary/database /Volumes/evo/myphotos.photoslibrary/database.bak
3. 先修复ZGENERICASSET
#更新资源的路径
sqlite3 /Volumes/evo/myphotos.photoslibrary/database/Photos.sqlite "
update ZGENERICASSET set ZDIRECTORY=replace(ZDIRECTORY,\"/Volumes/st3t/pictures/\", \"/Volumes/nas2/pictures/\");"
4. 修复ZFILESYSTEMBOOKMARK, 这个主要内容是放在blob的字段里的ZBOOKMARKDATA, 这个比较麻烦,要先.dump出来用sed改一下,再导入db中。
#先导出来:
$ sqlite3 /Volumes/evo/myphotos.photoslibrary/database/Photos.sqlite ".dump" > bak.sql
#计算要原目录的16进制字节码串
$ echo -n "st3t" | xxd -p | tr [:lower:] [:upper:]
73743374
#检查一下不是导出的是大写的
grep 73743374 bak.sql | wc -l
#如上面的返回0, 表示sql是小写的, 那么不需要 tr [:lower:] [:upper:]
#计算目标目录的16进制字节码串
$ echo -n "nas2" | xxd -p | tr [:lower:] [:upper:]
6E617332
#替换
sed -i "s/73743374/6E617332/g" bak.sql
#恢复db
sqlite3 temp.sqlite ".read bak.sql"
#替换
mv temp.sqlite /Volumes/evo/myphotos.photoslibrary/database/Photos.sqlite
5. 删除临时文件, 不删除打开会报错。
rm Photos.sqlite-shm Photos.sqlite-wal Photos.sqlite.lock
6. 删除无用的volume 记录 。
sqlite3 /Volumes/evo/myphotos.photoslibrary/database/Photos.sqlite "delete from ZFILESYSTEMVOLUME"
PS: 要是文夹名字不会其它文件名重复,可以直接
sqlite3 /Volumes/evo/myphotos.photoslibrary/database/Photos.sqlite ".dump" | sed 's/nas2/nas3/g' | sed 's/6e617332/6e617333/g' > tmp.sql
7.因为放到了smb的共享目录,沙箱检查会过不了。需要补丁一下PLSandboxHelper processWithID:canReadSandboxForPath的调用户让它总是返回1.
/System/Library/Frameworks/Photos.framework/Versions/A/Photos
#PLFileUtilities processCanReadSandboxForPath
b -r processCanReadSandboxForPath
Photos`__80-[PHAssetResourceManager reconnectAssets:urlResolvingHandler:completionHandler:]_block_invoke:
___80__PHAssetResourceManager_reconnectAssets_urlResolvingHandler_completionHandler___block_invoke
...
_text:000000000018D9F6 4D 85 FF test r15, r15
__text:000000000018D9F9 74 33 jz short loc_18DA2E
__text:000000000018D9FB 48 8B 3D B6 76 13 00 mov rdi, cs:classRef_PLSandboxHelper ; void *
__text:000000000018DA02 48 8B B5 90 FD FF FF mov rsi, [rbp+processCanReadSandboxForPath] ; char *
__text:000000000018DA09 4C 89 FA mov rdx, r15
__text:000000000018DA0C FF 15 76 1E 0C 00 call cs:_objc_msgSend_ptr
__text:000000000018DA12 BB 05 00 00 00 mov ebx, 5
__text:000000000018DA17 84 C0 test al, al
__text:000000000018DA19 4C 8B 25 70 1E 0C 00 mov r12, cs:_objc_release_ptr
__text:000000000018DA20 74 0C jz short
#这里修改一下,变成90 90 , nop, nop
loc_18DA2E
__text:000000000018DA22 4C 8B B5 B8 FE FF FF mov r14, [rbp+anonymous_45]
__text:000000000018DA29 E9 AD 01 00 00 jmp loc_18DBDB
__text:000000000018DA2E ; ---------------------------------------------------------------------------
__text:000000000018DA2E
__text:000000000018DA2E loc_18DA2E: ; CODE XREF: ___80__PHAssetResourceManager_reconnectAssets_urlResolvingHandler_completionHandler___block_invoke+61B↑j
__text:000000000018DA2E ; ___80__PHAssetResourceManager_reconnectAssets_urlResolvingHandler_completionHandler___block_invoke+642↑j
__text:000000000018DA2E 44 88 AD CF FE FF FF mov byte ptr [rbp+anonymous_0+1], r13b
__text:000000000018DA35 44 88 AD CE FE FF FF mov byte ptr [rbp+anonymous_0], r13b
__text:000000000018DA3C 44 88 AD CD FE FF FF mov [rbp+anonymous_1], r13b
b sandbox_check
Breakpoint 6: where = AssetsLibraryServices`+[PLSandboxHelper processWithID:canReadSandboxForPath:], address = 0x00007fff4b283117
(lldb) b *0x7fff4b283112
Breakpoint 7: where = AssetsLibraryServices`+[PLSandboxHelper processCanReadSandboxForPath:] + 64, address = 0x00007fff4b283112
(lldb) register write rax 1
(lldb) breakpoint command add 7
Enter your debugger command(s). Type 'DONE' to end.
> register write rax 1
> c
> DONE
(lldb) c
* thread #90, queue = 'PHAssetResourceManager.reconnectAssets', stop reason = breakpoint 6.1
* frame #0: 0x00007fff714896c8 libsystem_sandbox.dylib`sandbox_check
frame #1: 0x00007fff4b28317a AssetsLibraryServices`+[PLSandboxHelper processWithID:canReadSandboxForPath:] + 99
frame #2: 0x00007fff4b283102 AssetsLibraryServices`+[PLSandboxHelper processCanReadSandboxForPath:] + 48
frame #3: 0x00007fff4226aa12 Photos`__80-[PHAssetResourceManager reconnectAssets:urlResolvingHandler:completionHandler:]_block_invoke + 1588
frame #4: 0x00007fff712246c4 libdispatch.dylib`_dispatch_call_block_and_release + 12
frame #5: 0x00007fff71225658 libdispatch.dylib`_dispatch_client_callout + 8
frame #6: 0x00007fff7122ac44 libdispatch.dylib`_dispatch_lane_serial_drain + 597
frame #7: 0x00007fff7122b5d6 libdispatch.dylib`_dispatch_lane_invoke + 363
frame #8: 0x00007fff71234c09 libdispatch.dylib`_dispatch_workloop_worker_thread + 596
frame #9: 0x00007fff7147fa3d libsystem_pthread.dylib`_pthread_wqthread + 290
frame #10: 0x00007fff7147eb77 libsystem_pthread.dylib`start_wqthread + 15
(lldb)