Fixed to work with ABIv1.
[AROS.git] / tools / package / pkg
blob366d936e8c27f62628e4290e61c8e40353fa1b86
1 #!/usr/bin/env python
2 # -*- coding: iso-8859-1 -*-
4 import os, sys, struct
5 from stat import ST_SIZE
7 PKG_PREFIX = 'PKG'
8 PKG_VERSION = 1
10 PKG_HEADER_FORMAT = '3cB'
12 PKG_FILE_PATHLENGTH_FORMAT = '!I'
13 PKG_FILE_DATALENGTH_FORMAT = '!I'
15 def readHeader( file ):
16 'readHeader( file ) -> version'
18 header = struct.unpack(
19 PKG_HEADER_FORMAT,
20 file.read( struct.calcsize( PKG_HEADER_FORMAT ) )
22 version = header[3]
24 size = struct.unpack(
25 PKG_FILE_DATALENGTH_FORMAT,
26 file.read( struct.calcsize( PKG_FILE_DATALENGTH_FORMAT ) )
29 return version
32 def writeHeader( file, version ):
33 'writeHeader( file, version ) -> None'
35 file.write(
36 struct.pack(
37 PKG_HEADER_FORMAT,
38 PKG_PREFIX[0], PKG_PREFIX[1], PKG_PREFIX[2], PKG_VERSION
42 file.write(
43 struct.pack(
44 PKG_FILE_DATALENGTH_FORMAT,
50 def readFile( file ):
51 'readFile( file ) -> (path, data)'
53 pathLength = struct.unpack(
54 PKG_FILE_PATHLENGTH_FORMAT,
55 file.read( struct.calcsize( PKG_FILE_PATHLENGTH_FORMAT ) )
58 path = file.read( pathLength[0] )
59 file.read(1)
61 dataLength = struct.unpack(
62 PKG_FILE_DATALENGTH_FORMAT,
63 file.read( struct.calcsize( PKG_FILE_DATALENGTH_FORMAT ) )
66 data = file.read( dataLength[0] )
68 return (path, data)
71 def writeFile( file, path, data ):
72 'writeFile( file, path, data ) -> None'
74 file.write( struct.pack( "!I" + str( ( len( path ) + 4 ) & ~3 ) + "sI", -1 + ( ( len( path ) + 4 ) & ~3 ), path, len( data ) ) )
75 file.write( data )
78 def listFiles( path='.' ):
79 'listFiles( path ) -> []'
81 files = []
82 for name in os.listdir( path ):
83 name = os.path.join( path, name )
85 if os.path.isdir( name ):
86 files.extend( listFiles( name ) )
87 else:
88 files.append( os.path.normpath( name ) )
90 return files
93 def unpack( source, destination ):
94 'unpack( source, destination ) -> None'
96 if not os.path.exists( destination ):
97 os.makedirs( destination )
99 inputSize = os.path.getsize( source )
100 input = open( source, 'rb' )
102 oldwd = os.getcwd()
103 os.chdir( destination )
105 version = readHeader( input )
107 while input.tell() < inputSize:
108 (path, data) = readFile( input )
110 print %s (%d bytes)' % (path, len( data ))
112 directory = os.path.dirname( path )
113 if directory != '' and not os.path.exists( directory ):
114 os.makedirs( directory )
116 output = open( path, 'wb' )
117 output.write( data )
118 output.close()
120 os.chdir( oldwd )
123 def pack( destination, files ):
124 'pack( source, destination ) -> None'
126 output = open( destination, 'wb' )
128 oldwd = os.getcwd()
129 if os.path.isdir( files[0] ):
130 os.chdir( files[0] )
131 files = files[1:]
133 if len(files) == 0:
134 files = listFiles()
136 writeHeader( output, PKG_VERSION )
138 for path in files:
139 print %s (%d bytes)' % (path, os.path.getsize( path ))
141 input = open( path, 'rb' )
142 writeFile( output, path, input.read() )
143 input.close()
145 os.chdir( oldwd )
147 output.seek( struct.calcsize( PKG_HEADER_FORMAT ) )
148 st = os.fstat( output.fileno() )
150 output.write(
151 struct.pack(
152 PKG_FILE_DATALENGTH_FORMAT,
153 st[ST_SIZE]
158 output.close()
161 if __name__ == '__main__':
162 mode = sys.argv[1]
164 if mode == 'c':
165 destination = sys.argv[2]
166 files = sys.argv[3:]
167 pack( destination, files )
168 elif mode == 'x':
169 source = sys.argv[2]
170 destination = sys.argv[3]
171 unpack( source, destination )
172 else:
173 print 'Invalid mode.'