Throw clear out-of-space and bad-name exceptions

This commit is contained in:
Elliot Nunn 2018-10-23 17:51:37 +08:00
parent 48e04be236
commit cd433459d0
3 changed files with 37 additions and 14 deletions

View File

@ -35,5 +35,4 @@ def chunkify(b, blksize):
def pstring(orig):
macroman = orig.encode('mac_roman')
return bytes([len(macroman)]) + macroman
return bytes([len(orig)]) + orig

View File

@ -15,9 +15,6 @@ class AbstractFolder(collections.MutableMapping):
key.encode('mac_roman')
if not (1 <= len(key) <= 31):
raise ValueError('%r: Filename range 1-31 chars' % key)
lower = key.lower()
self._prefdict[lower] = key
self._maindict[lower] = value

View File

@ -78,12 +78,36 @@ def _get_every_extent(nblocks, firstrecord, cnid, xoflow, fork):
return extlist
def _encode_name(name, is_vol_name=False):
longest = 27 if is_vol_name else 31
try:
encoded = name.encode('mac_roman')
except UnicodeEncodeError:
raise BadNameError(name)
except AttributeError:
pass
if not 1 <= len(encoded) <= longest or b':' in encoded:
raise BadNameError(name)
return encoded
class _TempWrapper:
"""Volume uses this to store metadata while serialising"""
def __init__(self, of):
self.of = of
class OutOfSpaceError(Exception):
pass
class BadNameError(Exception):
pass
class Folder(directory.AbstractFolder):
def __init__(self):
super().__init__()
@ -226,6 +250,8 @@ class Volume(directory.AbstractFolder):
if size < 400 * 1024 or size % 512:
raise ValueError('size must be a multiple of 512b and >= 800K')
drVN = _encode_name(self.name, is_vol_name=True)
# overall layout:
# 1. two boot blocks (offset=0)
# 2. one volume control block (offset=2)
@ -252,12 +278,17 @@ class Volume(directory.AbstractFolder):
drNmAlBlks = (size - (5+bitmap_blk_cnt)*512) // drAlBlkSiz
blkaccum = []
def accumulate(x):
blkaccum.extend(x)
if len(blkaccum) > drNmAlBlks:
raise OutOfSpaceError
# <<< put the empty extents overflow file in here >>>
extoflowfile = btree.make_btree([], bthKeyLen=7, blksize=drAlBlkSiz)
# also need to do some cleverness to ensure that this gets picked up...
drXTFlSize = len(extoflowfile)
drXTExtRec_Start = len(blkaccum)
blkaccum.extend(bitmanip.chunkify(extoflowfile, drAlBlkSiz))
accumulate(bitmanip.chunkify(extoflowfile, drAlBlkSiz))
drXTExtRec_Cnt = len(blkaccum) - drXTExtRec_Start
# write all the files in the volume
@ -300,11 +331,11 @@ class Volume(directory.AbstractFolder):
wrap.dfrk = wrap.rfrk = (0, 0)
if obj.data:
pre = len(blkaccum)
blkaccum.extend(bitmanip.chunkify(obj.data, drAlBlkSiz))
accumulate(bitmanip.chunkify(obj.data, drAlBlkSiz))
wrap.dfrk = (pre, len(blkaccum)-pre)
if obj.rsrc:
pre = len(blkaccum)
blkaccum.extend(bitmanip.chunkify(obj.rsrc, drAlBlkSiz))
accumulate(bitmanip.chunkify(obj.rsrc, drAlBlkSiz))
wrap.rfrk = (pre, len(blkaccum)-pre)
self._prefdict = root_dict_backup
@ -318,7 +349,7 @@ class Volume(directory.AbstractFolder):
if wrap.cnid == 1: continue
obj = wrap.of
pstrname = bitmanip.pstring(path[-1])
pstrname = bitmanip.pstring(_encode_name(path[-1]))
mainrec_key = struct.pack('>L', path2wrap[path[:-1]].cnid) + pstrname
@ -379,7 +410,7 @@ class Volume(directory.AbstractFolder):
# also need to do some cleverness to ensure that this gets picked up...
drCTFlSize = len(catalogfile)
drCTExtRec_Start = len(blkaccum)
blkaccum.extend(bitmanip.chunkify(catalogfile, drAlBlkSiz))
accumulate(bitmanip.chunkify(catalogfile, drAlBlkSiz))
drCTExtRec_Cnt = len(blkaccum) - drCTExtRec_Start
if len(blkaccum) > drNmAlBlks:
@ -400,15 +431,11 @@ class Volume(directory.AbstractFolder):
drWrCnt = 0 # ????volume write count
drVCSize = drVBMCSize = drCtlCSize = 0
drAtrb = 1<<8 # volume attributes (hwlock, swlock, CLEANUNMOUNT, badblocks)
drVN = self.name.encode('mac_roman')
drVolBkUp = 0 # date and time of last backup
drVSeqNum = 0 # volume backup sequence number
drFndrInfo = bytes(32) # information used by the Finder
drCrDate, drLsMod, drVolBkUp = self.crdate, self.mddate, self.bkdate
if not (1 <= len(drVN) <= 27):
raise ValueError('Volume name range 1-27 chars')
vib = struct.pack('>2sLLHHHHHLLHLH28pLHLLLHLL32sHHHLHHxxxxxxxxLHHxxxxxxxx',
drSigWord, drCrDate, drLsMod, drAtrb, drNmFls,
drVBMSt, drAllocPtr, drNmAlBlks, drAlBlkSiz, drClpSiz, drAlBlSt,