[Pkg-python-debian-commits] r63 trunk: first checkin of arfile.py, work in progress

zack at bononia.it zack at bononia.it
Sat Jul 14 06:56:21 UTC 2007


------------------------------------------------------------
revno: 63
committer: zack at bononia.it
branch nick: pkg-python-debian.debfile
timestamp: Sat 2007-07-14 08:56:21 +0200
message:
  first checkin of arfile.py, work in progress
added:
  debian_bundle/arfile.py
-------------- next part --------------
=== added file 'debian_bundle/arfile.py'
--- a/debian_bundle/arfile.py	1970-01-01 00:00:00 +0000
+++ b/debian_bundle/arfile.py	2007-07-14 06:56:21 +0000
@@ -0,0 +1,168 @@
+#!/usr/bin/python
+
+GLOBAL_HEADER = "!<arch>\n"
+GLOBAL_HEADER_LENGTH = 8
+
+FILE_HEADER_LENGTH = 60
+FILE_MAGIC = "`\n"
+
+class ArFile(object):
+# XXX trying to mimick the interface of TarFile in the standard library
+
+    def __init__(self, fname, mode="r"):
+# FIXME i membri possono avere anche lo stesso nome! meglio una lista di Member 
+        self.__members = {}   # dict: member name -> File object
+        self.__members_list = None
+        self.__fname = fname
+		
+        if mode == "r":
+            self.__index_archive()
+        pass    # TODO
+
+    def __index_archive(self):
+        fp = open(self.__fname, "rb")
+
+        if fp.read(GLOBAL_HEADER_LENGTH) != GLOBAL_HEADER:
+            raise IOError
+
+        while True:
+            newmember = Member.from_file(fp, self.__fname)
+            if not newmember:
+                break
+            self.__members.update( {newmember.getname() : newmember} )
+            fp.seek(newmember.getsize(), 1) # skip to next header
+
+        self.__updateMembersList() # XXX serve a qualcosa? 
+        fp.close()
+
+
+
+    def getmember(self, name):
+        return self.__members[name]
+
+    def __updateMembersList(self):
+        if self.__members_list is None:
+            self.__members_list = self.__members.values()
+            self.__members_list.sort(lambda f1, f2: cmp(f1.seqno, f2.seqno))
+
+    def getmembers(self):
+        self.__updateMembersList()
+        return self.__members_list
+
+    def getnames(self):
+        self.__updateMembersList()
+        return map(lambda f: f.name, self.__members_list)
+
+    def next():
+        pass    # TODO
+
+    def extractall():
+        pass    # TODO
+
+    def extract(self, member, path):
+        pass    # TODO
+
+    def extractfile(self, member):
+        pass    # TODO
+
+class Member(object):
+    # XXX trying to mimick the interface of TarInfo in the standard library
+
+    def __init__(self):
+        self.__seqno = None     # sequential number in the archive
+        self.__name = None      # member name (i.e. filename) in the archive
+        self.__mtime = None 
+        self.__owner = None 
+        self.__group = None 
+        self.__mode  = None 
+        self.__size  = None     # member size in bytes
+        self.__fname = None     # file name associated with this member
+        self.__fp    = None     # XXX serve globale?
+        self.__offset = None    # start-of-data offset
+        pass    # TODO
+
+    def _from_file(fp, fname):
+        """fp is an open File object positioned to a valid file header or global header.
+        Returns a new Member on success"""
+
+        buf = fp.read(FILE_HEADER_LENGTH)
+
+        if not buf:
+            return False
+
+# XXX testare
+        # fp is an ar archive start
+#		if buf[0:GLOBAL_HEADER_LENGTH] == GLOBAL_HEADER:
+#			buf = buf[GLOBAL_HEADER_LENGTH:] + fp.read(GLOBAL_HEADER_LENGTH)
+
+        # sanity checks
+        if len(buf) < FILE_HEADER_LENGTH:
+            raise IOError
+
+        if buf[58:60] != FILE_MAGIC:
+            raise IOError
+
+# http://en.wikipedia.org/wiki/Ar_(Unix)	
+#from   to 	Name 	   				 	Format
+#0    	15 	File name 					ASCII
+#16 	27 	File modification date 		Decimal
+#28 	33 	Owner ID 					Decimal
+#34 	39 	Group ID 					Decimal
+#40 	47 	File mode 					Octal
+#48 	57 	File size in bytes 			Decimal
+#58 	59 	File magic 					\140\012
+
+        f = Member()
+        f.__name = buf[0:16].split("/")[0]
+        f.__mtime = int(buf[16:28])
+        f.__owner = int(buf[28:34])
+        f.__group = int(buf[34:40])
+        f.__mode  = buf[40:48]  # XXX e' un ottale
+        f.__size  = int(buf[48:58])
+# XXX seqno a cosa serve? se e' solo per ordinarli si puo' usare l'offset
+
+        f.__fname = fname
+        f.__offset = fp.tell() # start-of-data
+
+        return f
+
+    from_file = staticmethod(_from_file) # o class method?
+
+    def getseqno(self): return self.__seqno
+    seqno = property(getseqno)
+
+    def getname(self): return self.__name
+    name = property(getname)
+
+    def getmtime(self): return self.__mtime
+    mtime = property(getmtime)
+
+    def getowner(self): return self.__owner
+    owner = property(getowner)
+
+    def getgroup(self): return self.__group
+    group = property(getgroup)
+
+    def getmode(self): return self.__mode
+    mode = property(getmode)
+
+    def getsize(self): return self.__size
+    size = property(getsize)
+
+
+    # ALTRE PROP da aggiungere: mtime, mode, ...
+
+    def tobuf():
+        pass    # TODO
+
+#    FINQUI
+
+if __name__ == '__main__':
+# test
+# ar r test.ar <file1> <file2> .. <fileN>
+	t = ArFile("test.ar")
+	print t.getmembers()
+	print t.getnames()
+
+
+# vim:et:ts=4



More information about the pkg-python-debian-commits mailing list