source: products/quintagroup.transmogrifier/trunk/quintagroup/transmogrifier/patches.py @ 1589

Last change on this file since 1589 was 1255, checked in by koval, 15 years ago

added patch for tarfile module

File size: 4.1 KB
Line 
1import os
2import time
3from tarfile import TarInfo, DIRTYPE
4from StringIO import StringIO
5
6# TarballExportContext don't write dirs in tarball and we need to fix this
7
8#security.declareProtected( ManagePortal, 'writeDataFile' )
9def writeDataFile( self, filename, text, content_type, subdir=None ):
10
11    """ See IExportContext.
12    """
13    mod_time = time.time()
14    if subdir is not None:
15        elements = subdir.split('/')
16        parents = filter(None, elements)
17        while parents:
18            dirname = os.path.join(*parents)
19            try:
20                self._archive.getmember(dirname+'/')
21            except KeyError:
22                info = TarInfo(dirname)
23                info.size = 0
24                info.mode = 509
25                info.mtime = mod_time
26                info.type = DIRTYPE
27                self._archive.addfile(info, StringIO())
28            parents = parents[:-1]
29
30        filename = '/'.join( ( subdir, filename ) )
31
32    stream = StringIO( text )
33    info = TarInfo( filename )
34    info.size = len( text )
35    info.mode = 436
36    info.mtime = mod_time
37    self._archive.addfile( info, stream )
38
39from Products.GenericSetup.context import TarballExportContext
40TarballExportContext.writeDataFile = writeDataFile
41
42from Products.GenericSetup.context import SKIPPED_FILES, SKIPPED_SUFFIXES
43
44def listDirectory(self, path, skip=SKIPPED_FILES,
45                    skip_suffixes=SKIPPED_SUFFIXES):
46
47    """ See IImportContext.
48    """
49    if path is None:  # root is special case:  no leading '/'
50        path = ''
51    elif path:
52        if not self.isDirectory(path):
53            return None
54
55        if not path.endswith('/'):
56            path = path + '/'
57
58    pfx_len = len(path)
59
60    names = []
61    for name in self._archive.getnames():
62        if name == path or not name.startswith(path):
63            continue
64        name = name[pfx_len:]
65        if name.count('/') > 1:
66            continue
67        if '/' in name and not name.endswith('/'):
68            continue
69        if name in skip:
70            continue
71        if [s for s in skip_suffixes if name.endswith(s)]:
72            continue
73        # directories have trailing '/' character and we need to remove it
74        name = name.rstrip('/')
75        names.append(name)
76
77    return names
78
79from Products.GenericSetup.context import TarballImportContext
80TarballImportContext.listDirectory = listDirectory
81
82# patch for this bug in tarfile module - http://bugs.python.org/issue1719898
83from tarfile import TarInfo, nts, GNUTYPE_SPARSE, normpath, DIRTYPE
84def frombuf(cls, buf):
85    """Construct a TarInfo object from a 512 byte string buffer.
86    """
87    tarinfo = cls()
88    tarinfo.name   = nts(buf[0:100])
89    tarinfo.mode   = int(buf[100:108], 8)
90    tarinfo.uid    = int(buf[108:116],8)
91    tarinfo.gid    = int(buf[116:124],8)
92
93    # There are two possible codings for the size field we
94    # have to discriminate, see comment in tobuf() below.
95    if buf[124] != chr(0200):
96        tarinfo.size = long(buf[124:136], 8)
97    else:
98        tarinfo.size = 0L
99        for i in range(11):
100            tarinfo.size <<= 8
101            tarinfo.size += ord(buf[125 + i])
102
103    tarinfo.mtime  = long(buf[136:148], 8)
104    tarinfo.chksum = int(buf[148:156], 8)
105    tarinfo.type   = buf[156:157]
106    tarinfo.linkname = nts(buf[157:257])
107    tarinfo.uname  = nts(buf[265:297])
108    tarinfo.gname  = nts(buf[297:329])
109    try:
110        tarinfo.devmajor = int(buf[329:337], 8)
111        tarinfo.devminor = int(buf[337:345], 8)
112    except ValueError:
113        tarinfo.devmajor = tarinfo.devmajor = 0
114    tarinfo.prefix = buf[345:500]
115
116    # The prefix field is used for filenames > 100 in
117    # the POSIX standard.
118    # name = prefix + '/' + name
119    if tarinfo.type != GNUTYPE_SPARSE:
120        tarinfo.name = normpath(os.path.join(nts(tarinfo.prefix), tarinfo.name))
121
122    # Some old tar programs represent a directory as a regular
123    # file with a trailing slash.
124    if tarinfo.isreg() and tarinfo.name.endswith("/"):
125        tarinfo.type = DIRTYPE
126
127    # Directory names should have a '/' at the end.
128    if tarinfo.isdir():
129        tarinfo.name += "/"
130    return tarinfo
131
132frombuf = classmethod(frombuf)
133TarInfo.frombuf = frombuf
Note: See TracBrowser for help on using the repository browser.