]> git.ipfire.org Git - people/stevee/pakfire.git/blob - python/pakfire/packages/tar.py
Cleanup database and add indexes.
[people/stevee/pakfire.git] / python / pakfire / packages / tar.py
1 #!/usr/bin/python
2 ###############################################################################
3 # #
4 # Pakfire - The IPFire package management system #
5 # Copyright (C) 2012 Pakfire development team #
6 # #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
11 # #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
16 # #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 # #
20 ###############################################################################
21
22 import os
23 import tarfile
24
25 import logging
26 log = logging.getLogger("pakfire")
27
28 import pakfire.lzma as lzma
29 import pakfire.util as util
30 from pakfire.constants import *
31 from pakfire.i18n import _
32
33 class InnerTarFile(tarfile.TarFile):
34 def __init__(self, *args, **kwargs):
35 # Force the PAX format.
36 kwargs["format"] = tarfile.PAX_FORMAT
37
38 tarfile.TarFile.__init__(self, *args, **kwargs)
39
40 def add(self, name, arcname=None, recursive=None, exclude=None, filter=None):
41 """
42 Emulate the add function with capability support.
43 """
44 tarinfo = self.gettarinfo(name, arcname)
45
46 if tarinfo.isreg():
47 attrs = []
48
49 # Save capabilities.
50 caps = util.get_capabilities(name)
51 if caps:
52 log.debug("Saving capabilities for %s: %s" % (name, caps))
53 tarinfo.pax_headers["PAKFIRE.capabilities"] = caps
54
55 # Append the tar header and data to the archive.
56 f = tarfile.bltn_open(name, "rb")
57 self.addfile(tarinfo, f)
58 f.close()
59
60 elif tarinfo.isdir():
61 self.addfile(tarinfo)
62 if recursive:
63 for f in os.listdir(name):
64 self.add(os.path.join(name, f), os.path.join(arcname, f),
65 recursive, exclude, filter)
66
67 else:
68 self.addfile(tarinfo)
69
70 # Return the tar information about the file
71 return tarinfo
72
73 def extract(self, member, path=""):
74 target = os.path.join(path, member.name)
75
76 # Remove symlink targets, because tarfile cannot replace them.
77 if member.issym():
78 try:
79 os.unlink(target)
80 except OSError:
81 pass
82
83 # Extract file the normal way...
84 try:
85 tarfile.TarFile.extract(self, member, path)
86 except OSError, e:
87 log.warning(_("Could not extract file: /%(src)s - %(dst)s") \
88 % { "src" : member.name, "dst" : e, })
89
90 if path:
91 target = os.path.join(path, member.name)
92 else:
93 target = "/%s" % member.name
94
95 # ...and then apply the capabilities.
96 caps = member.pax_headers.get("PAKFIRE.capabilities", None)
97 if caps:
98 log.debug("Restoring capabilities for /%s: %s" % (member.name, caps))
99 util.set_capabilities(target, caps)
100
101
102 class InnerTarFileXz(InnerTarFile):
103 @classmethod
104 def open(cls, name=None, mode="r", fileobj=None, **kwargs):
105 fileobj = lzma.LZMAFile(name, mode, fileobj=fileobj)
106
107 try:
108 t = cls.taropen(name, mode, fileobj, **kwargs)
109 except lzma.LZMAError:
110 fileobj.close()
111 raise tarfile.ReadError("not an lzma file")
112
113 t._extfileobj = False
114 return t