diff --git a/directory.py b/directory.py index 43a7350..e3ec380 100644 --- a/directory.py +++ b/directory.py @@ -1,14 +1,66 @@ -class AbstractFolder(dict): - def paths(self): +import collections + + +_CASE = list(range(256)) # cheating, fix this! + + + +def _to_lower(orig): + return bytes(_CASE[x] for x in orig) + + +class AbstractFolder(collections.MutableMapping): + def __init__(self, from_dict=()): + self._prefdict = {} # lowercase to preferred + self._maindict = {} # lowercase to contents + self.update(from_dict) + + def __setitem__(self, key, value): + try: + key = key.encode('mac_roman') + except AttributeError: + pass + + if len(key) > 31: + raise ValueError('Max filename length = 31') + + lower = _to_lower(key) + self._prefdict[lower] = key + self._maindict[lower] = value + + def __getitem__(self, key): + try: + key = key.encode('mac_roman') + except AttributeError: + pass + + lower = _to_lower(key) + return self._maindict[lower] + + def __delitem__(self, key): + try: + value = value.encode('mac_roman') + except AttributeError: + pass + + lower = _to_lower(key) + del self._maindict[lower] + del self._prefdict[lower] + + def __iter__(self): + return iter(self._prefdict.values()) + + def __len__(self): + return len(self._maindict) + + def iter_paths(self): for name, child in self.items(): + print(name, child) yield ((name,), child) try: - childs_children = child.paths() + childs_children = child.iter_paths() except AttributeError: pass else: for each_path, each_child in childs_children: yield (name,) + each_path, each_child - - def __str__(self): - return 'Folder valence=%d' % len(self) diff --git a/main.py b/main.py index 7c34bd0..1eed199 100644 --- a/main.py +++ b/main.py @@ -101,27 +101,27 @@ class Volume(_directory.AbstractFolder): super().__init__() 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 = 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 - self.drFndrInfo = bytes(32) # information used by the Finder + self.crdate = 0 # date and time of volume creation + self.lsmod = 0 # date and time of last modification + self.name = b'Untitled' def read(self, from_volume): self._dirtree = {} self.bootblocks = from_volume[:1024] - drSigWord, self.drCrDate, self.drLsMod, self.drAtrb, drNmFls, \ + drSigWord, drCrDate, drLsMod, drAtrb, drNmFls, \ drVBMSt, drAllocPtr, drNmAlBlks, drAlBlkSiz, drClpSiz, drAlBlSt, \ - drNxtCNID, drFreeBks, self.drVN, self.drVolBkUp, self.drVSeqNum, \ + drNxtCNID, drFreeBks, drVN, drVolBkUp, drVSeqNum, \ drWrCnt, drXTClpSiz, drCTClpSiz, drNmRtDirs, drFilCnt, drDirCnt, \ - self.drFndrInfo, drVCSize, drVBMCSize, drCtlCSize, \ + drFndrInfo, drVCSize, drVBMCSize, drCtlCSize, \ drXTFlSize, drXTExtRec, \ drCTFlSize, drCTExtRec, \ = struct.unpack_from('>2sLLHHHHHLLHLH28pLHLLLHLL32sHHHL12sL12s', from_volume, 1024) + self.crdate = drCrDate + self.lsmod = drLsMod + self.name = drVN + block2offset = lambda block: 512*drAlBlSt + drAlBlkSiz*block extent2bytes = lambda firstblk, blkcnt: from_volume[block2offset(firstblk):block2offset(firstblk+blkcnt)] extrec2bytes = lambda extrec: b''.join(extent2bytes(a, b) for (a, b) in _btree.unpack_extent_record(extrec)) @@ -248,16 +248,16 @@ class Volume(_directory.AbstractFolder): # write all the files in the volume topwrap = _TempWrapper(self) - topwrap.path = (self.drVN,) + topwrap.path = (self.name,) topwrap.cnid = 2 godwrap = _TempWrapper(None) godwrap.cnid = 1 - path2wrap = {(): godwrap, (self.drVN,): topwrap} + path2wrap = {(): godwrap, (self.name,): topwrap} drNxtCNID = 16 - for path, obj in self.paths(): - path = (self.drVN,) + path + for path, obj in self.iter_paths(): + path = (self.name,) + path wrap = _TempWrapper(obj) path2wrap[path] = wrap wrap.path = path @@ -363,13 +363,20 @@ class Volume(_directory.AbstractFolder): drFreeBks = drNmAlBlks - len(blkaccum) drWrCnt = 0 # ????volume write count drVCSize = drVBMCSize = drCtlCSize = 0 + drAtrb = 1<<8 # volume attributes (hwlock, swlock, CLEANUNMOUNT, badblocks) + drVN = self.name + drVolBkUp = 0 # date and time of last backup + drVSeqNum = 0 # volume backup sequence number + drFndrInfo = bytes(32) # information used by the Finder + drCrDate = self.crdate + drLsMod = self.lsmod vib = struct.pack('>2sLLHHHHHLLHLH28pLHLLLHLL32sHHHLHHxxxxxxxxLHHxxxxxxxx', - drSigWord, self.drCrDate, self.drLsMod, self.drAtrb, drNmFls, + drSigWord, drCrDate, drLsMod, drAtrb, drNmFls, drVBMSt, drAllocPtr, drNmAlBlks, drAlBlkSiz, drClpSiz, drAlBlSt, - drNxtCNID, drFreeBks, self.drVN, self.drVolBkUp, self.drVSeqNum, + drNxtCNID, drFreeBks, drVN, drVolBkUp, drVSeqNum, drWrCnt, drXTClpSiz, drCTClpSiz, drNmRtDirs, drFilCnt, drDirCnt, - self.drFndrInfo, drVCSize, drVBMCSize, drCtlCSize, + drFndrInfo, drVCSize, drVBMCSize, drCtlCSize, drXTFlSize, drXTExtRec_Start, drXTExtRec_Cnt, drCTFlSize, drCTExtRec_Start, drCTExtRec_Cnt, ) diff --git a/main_test.py b/main_test.py index da4f1b5..38b85ce 100644 --- a/main_test.py +++ b/main_test.py @@ -19,7 +19,7 @@ def test_roundtrip(): def test_macos_mount(): h = Volume() - h.drVN = b'ElmoTest' + h.name = b'ElmoTest' hf = File() hf.data = b'12345' * 10 for i in reversed(range(100)):