OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/python | |
2 | |
3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | |
4 # Use of this source code is governed by a BSD-style license that can be | |
5 # found in the LICENSE file. | |
6 | |
7 """ | |
8 Script to generate a zip file of delta-generator and it's dependencies. | |
9 """ | |
10 import logging.handlers | |
11 import optparse | |
12 import os | |
13 import re | |
14 import shutil | |
15 import subprocess | |
16 import sys | |
17 import tempfile | |
18 | |
19 # GLOBALS | |
20 | |
21 logging_format = '%(asctime)s - %(filename)s - %(levelname)-8s: %(message)s' | |
22 date_format = '%Y/%m/%d %H:%M:%S' | |
23 logging.basicConfig(level=logging.INFO, format=logging_format, | |
24 datefmt=date_format) | |
25 | |
26 def CreateTempDir(): | |
27 """Creates a tempdir and returns the name of the tempdir.""" | |
28 temp_dir = tempfile.mkdtemp(suffix='au', prefix='tmp') | |
29 logging.info('Using tempdir = %s', temp_dir) | |
30 return temp_dir | |
31 | |
32 | |
33 def _SplitAndStrip(data): | |
34 """Prunes the ldd output, and return a list of needed library names | |
35 Example of data: | |
36 linux-vdso.so.1 => (0x00007ffffc96a000) | |
37 libbz2.so.1 => /lib/libbz2.so.1 (0x00007f3ff8782000) | |
38 libc.so.6 => /lib/libc.so.6 (0x00007f3ff83ff000) | |
39 /lib64/ld-linux-x86-64.so.2 (0x00007f3ff89b3000) | |
40 Args: | |
41 data: list of libraries from ldd output | |
42 Returns: | |
43 list of libararies that we should copy | |
44 | |
45 """ | |
46 return_list = [] | |
47 for line in data.split('\n'): | |
48 line = re.sub('.*not a dynamic executable.*', '', line) | |
49 line = re.sub('.* =>\s+', '', line) | |
50 line = re.sub('\(0x.*\)\s?', '', line) | |
51 line = line.strip() | |
52 if not len(line): | |
53 continue | |
54 logging.debug('MATCHED line = %s', line) | |
55 return_list.append(line) | |
56 | |
57 return return_list | |
58 | |
59 | |
60 def DepsToCopy(ldd_files, black_list): | |
61 """Returns a list of deps for a given dynamic executables list. | |
62 Args: | |
63 ldd_files: List of dynamic files that needs to have the deps evaluated | |
64 black_list: List of files that we should ignore | |
65 Returns: | |
66 library_list: List of files that are dependencies | |
67 """ | |
68 for file_name in ldd_files: | |
69 logging.info('Running ldd on %s', file_name) | |
70 cmd = ['/usr/bin/ldd', file_name] | |
71 stdout_data = '' | |
72 stderr_data = '' | |
73 | |
74 try: | |
75 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, | |
76 stderr=subprocess.PIPE) | |
77 (stdout_data, stderr_data) = proc.communicate(input=None) | |
78 except subprocess.CalledProcessError, e: | |
79 logging.error('Command %s failed', cmd) | |
80 logging.error('error code %s', e.returncode) | |
81 logging.error('ouput %s', e.output) | |
82 raise | |
83 | |
84 library_list = [] | |
85 if not stdout_data: | |
86 return library_list | |
87 | |
88 logging.debug('ldd for %s = stdout = %s stderr =%s', file_name, | |
89 stdout_data, stderr_data) | |
90 | |
91 library_list = _SplitAndStrip(stdout_data) | |
92 | |
93 return _ExcludeBlacklist(library_list, black_list) | |
94 | |
95 | |
96 def CopyRequiredFiles(dest_files_root): | |
97 """Generates a list of files that are required for au-generator zip file | |
98 Args: | |
99 dest_files_root: location of the directory where we should copy the files | |
100 """ | |
101 if not dest_files_root: | |
102 logging.error('Invalid option passed for dest_files_root') | |
103 sys.exit(1) | |
104 # Files that need to go through ldd | |
105 ldd_files = ['/usr/bin/delta_generator', '/usr/bin/bsdiff', | |
106 '/usr/bin/bspatch', '/usr/bin/cgpt'] | |
107 # statically linked files and scripts etc., | |
108 static_files = ['~/trunk/src/scripts/common.sh', | |
109 '~/trunk/src/scripts/cros_generate_update_payload', | |
110 '~/trunk/src/scripts/chromeos-common.sh'] | |
111 # We need directories to be copied recursively to a destination within tempdir | |
112 recurse_dirs = {'~/trunk/src/scripts/lib/shflags': 'lib/shflags'} | |
113 | |
114 black_list = [ | |
115 'linux-vdso.so', | |
116 'libgcc_s.so', | |
117 'libgthread-2.0.so', | |
118 'libpthread.so', | |
119 'librt.so', | |
120 'libstdc', | |
121 'libgcc_s.so', | |
122 'libc.so', | |
123 'ld-linux-x86-64', | |
124 'libm.so', | |
125 'libdl.so', | |
126 'libresolv.so', | |
127 ] | |
128 | |
129 all_files = ldd_files + static_files | |
130 all_files = map(os.path.expanduser, all_files) | |
131 | |
132 for file_name in all_files: | |
133 if not os.path.isfile(file_name): | |
134 logging.error('file = %s does not exist', file_name) | |
135 sys.exit(1) | |
136 | |
137 logging.debug('Given files that need to be copied = %s' .join(all_files)) | |
scottz-goog
2010/11/11 20:55:18
% ' '.join(all_files)
| |
138 all_files += DepsToCopy(ldd_files=ldd_files,black_list=black_list) | |
139 for file_name in all_files: | |
140 logging.info('Copying file %s to %s', file_name, dest_files_root) | |
141 shutil.copy2(file_name, dest_files_root) | |
142 | |
143 for source_dir, target_dir in recurse_dirs.iteritems(): | |
144 logging.info('Processing directory %s', source_dir) | |
145 full_path = os.path.expanduser(source_dir) | |
146 if not os.path.isdir(full_path): | |
147 logging.error("Directory given for %s expanded to %s doens't exist.", | |
148 source_dir, full_path) | |
149 sys.exit(1) | |
150 dest = os.path.join(dest_files_root, target_dir) | |
151 logging.info('Copying directory %s to %s.', full_path, target_dir) | |
152 shutil.copytree(full_path, dest) | |
153 | |
154 def CleanUp(temp_dir): | |
155 """Cleans up the tempdir | |
156 Args: | |
157 temp_dir = name of the directory to cleanup | |
158 """ | |
159 if os.path.exists(temp_dir): | |
160 shutil.rmtree(temp_dir, ignore_errors=True) | |
161 logging.info('Removed tempdir = %s', temp_dir) | |
162 | |
163 def GenerateZipFile(base_name, root_dir): | |
164 """Returns true if able to generate zip file | |
165 Args: | |
166 base_name: name of the zip file | |
167 root_dir: location of the directory that we should zip | |
168 Returns: | |
169 True if successfully generates the zip file otherwise False | |
170 """ | |
171 logging.info('Generating zip file %s with contents from %s', base_name, | |
172 root_dir) | |
173 current_dir = os.getcwd() | |
174 os.chdir(root_dir) | |
175 try: | |
176 subprocess.Popen(['zip', '-r', '-9', base_name, '.'], | |
177 stdout=subprocess.PIPE).communicate()[0] | |
scottz-goog
2010/11/11 20:55:18
align stdout with ['z..
| |
178 except OSError, e: | |
179 logging.error('Execution failed:%s', e.strerror) | |
180 return False | |
181 finally: | |
182 os.chdir(current_dir) | |
183 | |
184 return True | |
185 | |
186 | |
187 def _ExcludeBlacklist(library_list, black_list=[]): | |
188 """Deletes the set of files from black_list from the library_list | |
189 Args: | |
190 library_list: List of the library names to filter through black_list | |
191 black_list: List of the black listed names to filter | |
192 Returns: | |
193 Filtered library_list | |
194 """ | |
195 return_list = [] | |
196 pattern = re.compile(r'|'.join(black_list)) | |
197 | |
198 logging.debug('PATTERN: %s=', pattern) | |
199 | |
200 for library in library_list: | |
201 if pattern.search(library): | |
202 logging.debug('BLACK-LISTED = %s=', library) | |
203 continue | |
204 return_list.append(library) | |
205 | |
206 logging.debug('Returning return_list=%s=', return_list) | |
207 | |
208 return return_list | |
209 | |
210 | |
211 def CopyZipToFinalDestination(output_dir, zip_file_name): | |
212 """Copies the generated zip file to a final destination | |
213 Args: | |
214 output_dir: Directory where the file should be copied to | |
215 zip_file_name: name of the zip file that should be copied | |
216 Returns: | |
217 True on Success False on Failure | |
218 """ | |
219 if not os.path.isfile(zip_file_name): | |
220 logging.error("Zip file %s doesn't exist. Returning False", zip_file_name) | |
221 return False | |
222 | |
223 if not os.path.isdir(output_dir): | |
224 logging.debug('Creating %s', output_dir) | |
225 os.makedirs(output_dir) | |
226 logging.info('Copying %s to %s', zip_file_name, output_dir) | |
227 shutil.copy2(zip_file_name, output_dir) | |
228 return True | |
229 | |
230 | |
231 def main(): | |
232 """Main function to start the script""" | |
233 parser = optparse.OptionParser() | |
234 | |
235 parser.add_option( '-d', '--debug', dest='debug', action='store_true', | |
236 default=False, help='Verbose Default: False',) | |
237 parser.add_option('-o', '--output-dir', dest='output_dir', | |
238 default='/tmp/au-generator', | |
239 help='Specify the output location for copying the zipfile') | |
240 parser.add_option('-z', '--zip-name', dest='zip_name', | |
241 default='au-generator.zip', help='Name of the zip file') | |
242 parser.add_option('-k', '--keep-temp', dest='keep_temp', default=False, | |
243 action='store_true', help='Keep the temp files...',) | |
244 | |
245 (options, args) = parser.parse_args() | |
246 if options.debug: | |
247 logging.setLevel(logging.DEBUG) | |
248 | |
249 logging.debug('Options are %s ', options) | |
250 | |
251 temp_dir = CreateTempDir() | |
252 dest_files_root = os.path.join(temp_dir, 'au-generator') | |
253 os.makedirs(dest_files_root) | |
254 CopyRequiredFiles(dest_files_root=dest_files_root) | |
255 zip_file_name = os.path.join(temp_dir, options.zip_name) | |
256 GenerateZipFile(zip_file_name, dest_files_root) | |
257 CopyZipToFinalDestination(options.output_dir, zip_file_name) | |
258 | |
259 if not options.keep_temp: | |
260 CleanUp(temp_dir) | |
261 | |
262 if __name__ == '__main__': | |
263 main() | |
OLD | NEW |