CAB files

Thomas Heller theller at python.net
Fri Aug 8 16:29:10 CEST 2008


Virgil Stokes schrieb:
> I would appreciate python code for creating *.cab files.
> 
> --V. Stokes

Here is some code that I have still laying around.  It has never been
used in production and I do not know what you can do with the cab files
it creates, but I have been able to create a cab and open it with winzip.

Thomas

<cab.py>
from ctypes import *
import sys, os, tempfile, glob

BOOL = c_int
ULONG = c_ulong
UINT = c_uint
USHORT = c_ushort

class ERF(Structure):
    _fields_ = [("erfOper", c_int),
                ("erfType", c_int),
                ("fError", BOOL)]

CB_MAX_CHUNK =           32768
CB_MAX_DISK =        0x7ffffff
CB_MAX_FILENAME =           256
CB_MAX_CABINET_NAME =       256
CB_MAX_CAB_PATH =           256
CB_MAX_DISK_NAME =          256

class CCAB(Structure):
    _fields_ = [
        ("cb", ULONG),                  # size available for cabinet on this media
        ("cbFolderThresh", ULONG),      # Thresshold for forcing a new Folder
        ("cbReserveCFHeader", UINT),   # Space to reserve in CFHEADER
        ("cbReserveCFFolder", UINT),   # Space to reserve in CFFOLDER
        ("cbReserveCFData", UINT),     # Space to reserve in CFDATA
        ("iCab", c_int),                # sequential numbers for cabinets
        ("iDisk", c_int),               # Disk number
        ("fFailOnIncompressible", c_int), # TRUE => Fail if a block is incompressible
        ("setID", USHORT),               # Cabinet set ID
        ("szDisk", c_char * CB_MAX_DISK_NAME),    # current disk name
        ("szCab", c_char * CB_MAX_CABINET_NAME),  # current cabinet name
        ("szCabPath", c_char * CB_MAX_CAB_PATH),  # path for creating cabinet
        ]

cab = cdll.cabinet

class HFCI(object):
    _handle = 0
    _as_parameter_ = property(lambda self: self._handle)

    def __init__(self, fnm, verbose=1):
        self.verbose = verbose
        self.erf = ERF()
        ccab = self.ccab = CCAB()
        ccab.cb = 100000000
        ccab.cbFolderThresh = 100000
        ccab.szCab = os.path.basename(fnm)
        dirname = os.path.dirname(fnm)
        if not dirname:
            dirname = "."
        ccab.szCabPath = dirname + "\\"
        self._init_callbacks()
        self._handle = cab.FCICreate(byref(self.erf),
                                     self.pfn_filedest,
                                     cdll.msvcrt.malloc,
                                     cdll.msvcrt.free,
                                     cdll.msvcrt._open,
                                     cdll.msvcrt._read,
                                     cdll.msvcrt._write,
                                     cdll.msvcrt._close,
                                     cdll.msvcrt._lseek,
                                     cdll.msvcrt._unlink,
                                     self.pfn_gettempfnm,
                                     byref(ccab),
                                     None)

    def _init_callbacks(self):
        self.pfn_gettempfnm = CFUNCTYPE(c_int, c_void_p, c_int, c_void_p)(self._gettempfnm)
        self.pfn_filedest = CFUNCTYPE(c_int)(self._filedest)
        self.pfn_status = CFUNCTYPE(c_int, c_int, c_uint, c_uint, c_void_p)(self._status)
        self.pfn_getnextcab = CFUNCTYPE(c_int)(self._getnextcab)
        self.pfn_getopeninfo = CFUNCTYPE(c_int, c_char_p)(self._getopeninfo)

    def _getopeninfo(self, fnm):
        if self.verbose:
            print "File", fnm
        return cdll.msvcrt._open(fnm, os.O_BINARY | os.O_RDONLY)

    def _status(self, typeStatus, cb1, cb2, pv):
        return 0

    def _filedest(self):
        return 0

    def _getnextcab(self):
        return 0

    def _gettempfnm(self, pszTempName, cbTempName, pv):
        # same as tempfile.mktemp(), but this is deprecated
        fh, fnm = tempfile.mkstemp()
        os.close(fh)
        os.remove(fnm)
        cdll.msvcrt.strcpy(pszTempName, fnm)
        return 1

    def AddFile(self, src, dst=None, compressed=0):
        if dst is None:
            dst = os.path.basename(src)
        cab.FCIAddFile(self,
                       src,
                       dst,
                       0, # fExecute
                       self.pfn_getnextcab,
                       self.pfn_status,
                       self.pfn_getopeninfo,
                       compressed)

    def Close(self):
        if self._handle != 0:
            cab.FCIFlushCabinet(self,
                                0, # fGetNextCab
                                self.pfn_getnextcab,
                                self.pfn_status)
            cab.FCIDestroy(self)
            self._handle = 0

if __name__ == "__main__":
    import os, glob

    hfci = HFCI("my-first.cab", verbose=1)

    files = glob.glob(r".\cab\*.*")

    for fnm in files:
        hfci.AddFile(fnm)

    hfci.Close()
<eof>



More information about the Python-list mailing list