mirror of
https://github.com/elliotnunn/machfs.git
synced 2024-06-16 18:29:29 +00:00
after getting mounting, before ripping out index nodes
This commit is contained in:
parent
95e6097268
commit
e4e2a68cd0
116
thing.py
116
thing.py
|
@ -25,7 +25,6 @@ def _dump_btree_recs(buf, start):
|
||||||
bthDepth, bthRoot, bthNRecs, bthFNode, bthLNode, bthNodeSize, bthKeyLen, bthNNodes, bthFree = \
|
bthDepth, bthRoot, bthNRecs, bthFNode, bthLNode, bthNodeSize, bthKeyLen, bthNNodes, bthFree = \
|
||||||
struct.unpack_from('>HLLLLHHLL', header_rec)
|
struct.unpack_from('>HLLLLHHLL', header_rec)
|
||||||
# print('btree', bthDepth, bthRoot, bthNRecs, bthFNode, bthLNode, bthNodeSize, bthKeyLen, bthNNodes, bthFree)
|
# print('btree', bthDepth, bthRoot, bthNRecs, bthFNode, bthLNode, bthNodeSize, bthKeyLen, bthNNodes, bthFree)
|
||||||
print('btree', bthKeyLen)
|
|
||||||
|
|
||||||
# And iterate through the linked list of leaf nodes
|
# And iterate through the linked list of leaf nodes
|
||||||
this_leaf = bthFNode
|
this_leaf = bthFNode
|
||||||
|
@ -39,6 +38,7 @@ def _dump_btree_recs(buf, start):
|
||||||
this_leaf = ndFLink
|
this_leaf = ndFLink
|
||||||
|
|
||||||
def _pack_leaf_record(key, value): # works correctly
|
def _pack_leaf_record(key, value): # works correctly
|
||||||
|
if len(value) & 1: value += b'\x00'
|
||||||
b = bytes([len(key)+1, 0, *key])
|
b = bytes([len(key)+1, 0, *key])
|
||||||
if len(b) & 1: b += bytes(1)
|
if len(b) & 1: b += bytes(1)
|
||||||
b += value
|
b += value
|
||||||
|
@ -115,14 +115,16 @@ def _mkbtree(records, bthKeyLen):
|
||||||
curnode = [keyval]
|
curnode = [keyval]
|
||||||
biglist[-1].append(curnode)
|
biglist[-1].append(curnode)
|
||||||
|
|
||||||
|
if biglist == [[[]]]: biglist = []
|
||||||
|
|
||||||
biglist.reverse() # index nodes then leaf nodes
|
biglist.reverse() # index nodes then leaf nodes
|
||||||
|
|
||||||
# cool, now biglist is of course brilliant
|
# cool, now biglist is of course brilliant
|
||||||
for i, level in enumerate(biglist, 1):
|
# for i, level in enumerate(biglist, 1):
|
||||||
print('LEVEL', i)
|
# print('LEVEL', i)
|
||||||
for node in level:
|
# for node in level:
|
||||||
print('(%d)' % len(node), *(rec[0] for rec in node))
|
# print('(%d)' % len(node), *(rec[0] for rec in node))
|
||||||
print()
|
# print()
|
||||||
|
|
||||||
# Make space for a header node at element 0
|
# Make space for a header node at element 0
|
||||||
hnode = _Node()
|
hnode = _Node()
|
||||||
|
@ -167,7 +169,7 @@ def _mkbtree(records, bthKeyLen):
|
||||||
bits_covered = 2048
|
bits_covered = 2048
|
||||||
mapnodes = []
|
mapnodes = []
|
||||||
while bits_covered < len(nodelist):
|
while bits_covered < len(nodelist):
|
||||||
print('making map node!')
|
# print('making map node!')
|
||||||
bits_covered += 3952 # bits in a max-sized record
|
bits_covered += 3952 # bits in a max-sized record
|
||||||
mapnode = _Node()
|
mapnode = _Node()
|
||||||
nodelist.append(mapnode)
|
nodelist.append(mapnode)
|
||||||
|
@ -191,6 +193,7 @@ def _mkbtree(records, bthKeyLen):
|
||||||
# print(n.__dict__)
|
# print(n.__dict__)
|
||||||
|
|
||||||
bthFree = len(nodelist) // 4 # maybe limber this up in the future
|
bthFree = len(nodelist) // 4 # maybe limber this up in the future
|
||||||
|
bthFree = 11 if bthKeyLen == 7 else 10 ## fix this later??
|
||||||
|
|
||||||
# populate the bitmap (1 = used)
|
# populate the bitmap (1 = used)
|
||||||
hnode.records[2] = _bits(2048, len(nodelist))
|
hnode.records[2] = _bits(2048, len(nodelist))
|
||||||
|
@ -200,7 +203,7 @@ def _mkbtree(records, bthKeyLen):
|
||||||
|
|
||||||
# populate the header node:
|
# populate the header node:
|
||||||
bthDepth = len(biglist)
|
bthDepth = len(biglist)
|
||||||
bthRoot = 1 # root node is first-but-one
|
bthRoot = 1 if biglist else 0 # root node is first-but-one, or no node at all
|
||||||
# bthNRecs set above
|
# bthNRecs set above
|
||||||
# bthFNode/bthLNode also set above
|
# bthFNode/bthLNode also set above
|
||||||
bthNodeSize = 512
|
bthNodeSize = 512
|
||||||
|
@ -333,7 +336,7 @@ class Volume(_AbstractFolder):
|
||||||
self.bootblocks = bytes(1024) # optional; for booting HFS volumes
|
self.bootblocks = bytes(1024) # optional; for booting HFS volumes
|
||||||
self.drCrDate = 0 # date and time of volume creation
|
self.drCrDate = 0 # date and time of volume creation
|
||||||
self.drLsMod = 0 # date and time of last modification
|
self.drLsMod = 0 # date and time of last modification
|
||||||
self.drAtrb = 0 # volume attributes (hwlock, swlock, cleanunmount, badblocks)
|
self.drAtrb = 1<<8 # volume attributes (hwlock, swlock, CLEANUNMOUNT, badblocks)
|
||||||
self.drVN = b'Untitled' # volume name Pascal string
|
self.drVN = b'Untitled' # volume name Pascal string
|
||||||
self.drVolBkUp = 0 # date and time of last backup
|
self.drVolBkUp = 0 # date and time of last backup
|
||||||
self.drVSeqNum = 0 # volume backup sequence number
|
self.drVSeqNum = 0 # volume backup sequence number
|
||||||
|
@ -371,14 +374,14 @@ class Volume(_AbstractFolder):
|
||||||
val = rec[_pad_up(1+rec_len, 2):]
|
val = rec[_pad_up(1+rec_len, 2):]
|
||||||
|
|
||||||
ckrParID, namelen = struct.unpack_from('>LB', key)
|
ckrParID, namelen = struct.unpack_from('>LB', key)
|
||||||
ckrCName = key[6:6+namelen]
|
ckrCName = key[5:5+namelen]
|
||||||
|
|
||||||
datatype = (None, 'dir', 'file', 'dthread', 'fthread')[val[0]]
|
datatype = (None, 'dir', 'file', 'dthread', 'fthread')[val[0]]
|
||||||
datarec = val[2:]
|
datarec = val[2:]
|
||||||
|
|
||||||
print(datatype)
|
print(datatype + '\t' + repr(key))
|
||||||
print('\t', key)
|
|
||||||
print('\t', datarec)
|
print('\t', datarec)
|
||||||
|
print()
|
||||||
|
|
||||||
if datatype == 'dir':
|
if datatype == 'dir':
|
||||||
dirFlags, dirVal, dirDirID, dirCrDat, dirMdDat, dirBkDat, dirUsrInfo, dirFndrInfo \
|
dirFlags, dirVal, dirDirID, dirCrDat, dirMdDat, dirBkDat, dirUsrInfo, dirFndrInfo \
|
||||||
|
@ -503,7 +506,8 @@ class Volume(_AbstractFolder):
|
||||||
|
|
||||||
catalog = [] # (key, value) tuples
|
catalog = [] # (key, value) tuples
|
||||||
|
|
||||||
drFilCnt = drDirCnt = 0
|
drFilCnt = 0
|
||||||
|
drDirCnt = -1 # to exclude the root directory
|
||||||
|
|
||||||
for path, wrap in path2wrap.items():
|
for path, wrap in path2wrap.items():
|
||||||
if wrap.cnid == 1: continue
|
if wrap.cnid == 1: continue
|
||||||
|
@ -548,7 +552,7 @@ class Volume(_AbstractFolder):
|
||||||
dirCrDat, dirMdDat, dirBkDat = (0,0,0) if obj is self else (obj.crdat, obj.mddat, obj.bkdat)
|
dirCrDat, dirMdDat, dirBkDat = (0,0,0) if obj is self else (obj.crdat, obj.mddat, obj.bkdat)
|
||||||
dirUsrInfo = bytes(16)
|
dirUsrInfo = bytes(16)
|
||||||
dirFndrInfo = bytes(16)
|
dirFndrInfo = bytes(16)
|
||||||
mainrec_val = struct.pack('>BxHHLLLL16s16sxxxxxxxx',
|
mainrec_val = struct.pack('>BxHHLLLL16s16sxxxxxxxxxxxxxxxx',
|
||||||
cdrType, dirFlags, dirVal, dirDirID,
|
cdrType, dirFlags, dirVal, dirDirID,
|
||||||
dirCrDat, dirMdDat, dirBkDat,
|
dirCrDat, dirMdDat, dirBkDat,
|
||||||
dirUsrInfo, dirFndrInfo,
|
dirUsrInfo, dirFndrInfo,
|
||||||
|
@ -584,7 +588,7 @@ class Volume(_AbstractFolder):
|
||||||
drNmFls = sum(isinstance(x, File) for x in self.values())
|
drNmFls = sum(isinstance(x, File) for x in self.values())
|
||||||
drNmRtDirs = sum(not isinstance(x, File) for x in self.values())
|
drNmRtDirs = sum(not isinstance(x, File) for x in self.values())
|
||||||
drVBMSt = 3 # first block of volume bitmap
|
drVBMSt = 3 # first block of volume bitmap
|
||||||
drAllocPtr = len(blkaccum)
|
drAllocPtr = 0
|
||||||
drClpSiz = drXTClpSiz = drCTClpSiz = drAlBlkSiz
|
drClpSiz = drXTClpSiz = drCTClpSiz = drAlBlkSiz
|
||||||
drAlBlSt = 3 + bitmap_blk_cnt
|
drAlBlSt = 3 + bitmap_blk_cnt
|
||||||
drFreeBks = drNmAlBlks - len(blkaccum)
|
drFreeBks = drNmAlBlks - len(blkaccum)
|
||||||
|
@ -608,85 +612,3 @@ class Volume(_AbstractFolder):
|
||||||
finalchunks.append(vib)
|
finalchunks.append(vib)
|
||||||
finalchunks.append(bytes(512))
|
finalchunks.append(bytes(512))
|
||||||
return b''.join(finalchunks)
|
return b''.join(finalchunks)
|
||||||
|
|
||||||
|
|
||||||
import sys
|
|
||||||
if sys.argv[1:]:
|
|
||||||
infile = sys.argv[1]
|
|
||||||
else:
|
|
||||||
infile = 'SourceForEmulator.dmg'
|
|
||||||
import pprint
|
|
||||||
|
|
||||||
|
|
||||||
# Volume().read(open('SourceForEmulator.dmg', 'rb').read())
|
|
||||||
# exit()
|
|
||||||
|
|
||||||
|
|
||||||
# print(_mkbtree([]))
|
|
||||||
|
|
||||||
# h = Volume()
|
|
||||||
# h.read(open(infile,'rb').read())
|
|
||||||
|
|
||||||
|
|
||||||
# open('/tmp/aj', 'wb').write(h[b'Extensions'][b'AppleJack 2.1'].rsrc)
|
|
||||||
# pprint.pprint(h)
|
|
||||||
# for path, obj in h.paths():
|
|
||||||
# print(path, obj)
|
|
||||||
|
|
||||||
|
|
||||||
h = Volume()
|
|
||||||
f = File()
|
|
||||||
h[b'file'] = f
|
|
||||||
f.data = b'mydatafork\r'
|
|
||||||
wr = h.write(800*1024)
|
|
||||||
open(infile,'wb').write(wr)
|
|
||||||
|
|
||||||
h2 = Volume()
|
|
||||||
h2.read(wr)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
42
thing_test.py
Normal file
42
thing_test.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
from thing import *
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
|
def test_roundtrip():
|
||||||
|
h = Volume()
|
||||||
|
f = File()
|
||||||
|
h[b'single file'] = f
|
||||||
|
f.data = f.rsrc = b'1234' * 4096
|
||||||
|
|
||||||
|
copies = [h.write(800*1024)]
|
||||||
|
for i in range(2):
|
||||||
|
h2 = Volume()
|
||||||
|
h2.read(copies[-1])
|
||||||
|
copies.append(h2.write(800*1024))
|
||||||
|
|
||||||
|
assert copies[0] == copies[1]
|
||||||
|
assert copies[1] == copies[2]
|
||||||
|
|
||||||
|
def test_macos_mount():
|
||||||
|
h = Volume()
|
||||||
|
h.drVN = b'ElmoTest'
|
||||||
|
hf = File()
|
||||||
|
hf.data = b'1234' * 2000
|
||||||
|
h[b'testfile'] = hf
|
||||||
|
ser = h.write(800*1024)
|
||||||
|
open('/tmp/SMALL.dmg','wb').write(ser)
|
||||||
|
os.system('open /tmp/SMALL.dmg')
|
||||||
|
n = 10
|
||||||
|
while 1:
|
||||||
|
n += 1
|
||||||
|
assert n < 20
|
||||||
|
time.sleep(0.1)
|
||||||
|
try:
|
||||||
|
recovered = open('/Volumes/ElmoTest/testfile','rb').read()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
os.system('umount /Volumes/ElmoTest')
|
||||||
|
os.unlink('/tmp/SMALL.dmg')
|
||||||
|
assert recovered == hf.data
|
Loading…
Reference in New Issue
Block a user