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 = \
|
||||
struct.unpack_from('>HLLLLHHLL', header_rec)
|
||||
# print('btree', bthDepth, bthRoot, bthNRecs, bthFNode, bthLNode, bthNodeSize, bthKeyLen, bthNNodes, bthFree)
|
||||
print('btree', bthKeyLen)
|
||||
|
||||
# And iterate through the linked list of leaf nodes
|
||||
this_leaf = bthFNode
|
||||
|
@ -39,6 +38,7 @@ def _dump_btree_recs(buf, start):
|
|||
this_leaf = ndFLink
|
||||
|
||||
def _pack_leaf_record(key, value): # works correctly
|
||||
if len(value) & 1: value += b'\x00'
|
||||
b = bytes([len(key)+1, 0, *key])
|
||||
if len(b) & 1: b += bytes(1)
|
||||
b += value
|
||||
|
@ -115,14 +115,16 @@ def _mkbtree(records, bthKeyLen):
|
|||
curnode = [keyval]
|
||||
biglist[-1].append(curnode)
|
||||
|
||||
if biglist == [[[]]]: biglist = []
|
||||
|
||||
biglist.reverse() # index nodes then leaf nodes
|
||||
|
||||
# cool, now biglist is of course brilliant
|
||||
for i, level in enumerate(biglist, 1):
|
||||
print('LEVEL', i)
|
||||
for node in level:
|
||||
print('(%d)' % len(node), *(rec[0] for rec in node))
|
||||
print()
|
||||
# for i, level in enumerate(biglist, 1):
|
||||
# print('LEVEL', i)
|
||||
# for node in level:
|
||||
# print('(%d)' % len(node), *(rec[0] for rec in node))
|
||||
# print()
|
||||
|
||||
# Make space for a header node at element 0
|
||||
hnode = _Node()
|
||||
|
@ -167,7 +169,7 @@ def _mkbtree(records, bthKeyLen):
|
|||
bits_covered = 2048
|
||||
mapnodes = []
|
||||
while bits_covered < len(nodelist):
|
||||
print('making map node!')
|
||||
# print('making map node!')
|
||||
bits_covered += 3952 # bits in a max-sized record
|
||||
mapnode = _Node()
|
||||
nodelist.append(mapnode)
|
||||
|
@ -191,6 +193,7 @@ def _mkbtree(records, bthKeyLen):
|
|||
# print(n.__dict__)
|
||||
|
||||
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)
|
||||
hnode.records[2] = _bits(2048, len(nodelist))
|
||||
|
@ -200,7 +203,7 @@ def _mkbtree(records, bthKeyLen):
|
|||
|
||||
# populate the header node:
|
||||
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
|
||||
# bthFNode/bthLNode also set above
|
||||
bthNodeSize = 512
|
||||
|
@ -333,7 +336,7 @@ class Volume(_AbstractFolder):
|
|||
self.bootblocks = bytes(1024) # optional; for booting HFS volumes
|
||||
self.drCrDate = 0 # date and time of volume creation
|
||||
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.drVolBkUp = 0 # date and time of last backup
|
||||
self.drVSeqNum = 0 # volume backup sequence number
|
||||
|
@ -371,14 +374,14 @@ class Volume(_AbstractFolder):
|
|||
val = rec[_pad_up(1+rec_len, 2):]
|
||||
|
||||
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]]
|
||||
datarec = val[2:]
|
||||
|
||||
print(datatype)
|
||||
print('\t', key)
|
||||
print(datatype + '\t' + repr(key))
|
||||
print('\t', datarec)
|
||||
print()
|
||||
|
||||
if datatype == 'dir':
|
||||
dirFlags, dirVal, dirDirID, dirCrDat, dirMdDat, dirBkDat, dirUsrInfo, dirFndrInfo \
|
||||
|
@ -503,7 +506,8 @@ class Volume(_AbstractFolder):
|
|||
|
||||
catalog = [] # (key, value) tuples
|
||||
|
||||
drFilCnt = drDirCnt = 0
|
||||
drFilCnt = 0
|
||||
drDirCnt = -1 # to exclude the root directory
|
||||
|
||||
for path, wrap in path2wrap.items():
|
||||
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)
|
||||
dirUsrInfo = bytes(16)
|
||||
dirFndrInfo = bytes(16)
|
||||
mainrec_val = struct.pack('>BxHHLLLL16s16sxxxxxxxx',
|
||||
mainrec_val = struct.pack('>BxHHLLLL16s16sxxxxxxxxxxxxxxxx',
|
||||
cdrType, dirFlags, dirVal, dirDirID,
|
||||
dirCrDat, dirMdDat, dirBkDat,
|
||||
dirUsrInfo, dirFndrInfo,
|
||||
|
@ -584,7 +588,7 @@ class Volume(_AbstractFolder):
|
|||
drNmFls = sum(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
|
||||
drAllocPtr = len(blkaccum)
|
||||
drAllocPtr = 0
|
||||
drClpSiz = drXTClpSiz = drCTClpSiz = drAlBlkSiz
|
||||
drAlBlSt = 3 + bitmap_blk_cnt
|
||||
drFreeBks = drNmAlBlks - len(blkaccum)
|
||||
|
@ -608,85 +612,3 @@ class Volume(_AbstractFolder):
|
|||
finalchunks.append(vib)
|
||||
finalchunks.append(bytes(512))
|
||||
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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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