blob: cac7437096a961517001bd948aa5791e77f4c940 [file] [log] [blame]
mbligh67b5ece2006-04-23 02:53:12 +00001import os,os.path,shutil,urllib,sys,signal,commands
apwbc2867d2006-04-06 18:21:16 +00002from error import *
mblighcdf02a42006-04-23 02:22:49 +00003import re
mblighf4c35322006-03-13 01:01:10 +00004
5def grep(pattern, file):
6# This is mainly to fix the return code inversion from grep
mbligha975fb62006-04-22 19:56:25 +00007 return not system('grep "' + pattern + '" "' + file + '"')
mblighf4c35322006-03-13 01:01:10 +00008
9
10def difflist(list1, list2):
11# returns items in list 2 that are not in list 1
12 diff = [];
13 for x in list2:
14 if x not in list1:
15 diff.append(x)
16 return diff
17
mblighf4c35322006-03-13 01:01:10 +000018def cat_file_to_cmd(file, command):
mbligh712cd142006-04-22 18:57:50 +000019 if not os.path.isfile(file):
20 raise NameError, 'invalid file %s to cat to command %s' % file, command
mblighf4c35322006-03-13 01:01:10 +000021 if file.endswith('.bz2'):
mbligha975fb62006-04-22 19:56:25 +000022 system('bzcat ' + file + ' | ' + command)
mbligh3d914912006-04-22 17:37:19 +000023 elif (file.endswith('.gz') or file.endswith('.tgz')):
mbligha975fb62006-04-22 19:56:25 +000024 system('zcat ' + file + ' | ' + command)
mblighf4c35322006-03-13 01:01:10 +000025 else:
mbligha975fb62006-04-22 19:56:25 +000026 system('cat ' + file + ' | ' + command)
mblighf4c35322006-03-13 01:01:10 +000027
mbligh712cd142006-04-22 18:57:50 +000028
29# Extract a tarball to a specified directory name instead of whatever
30# the top level of a tarball is - useful for versioned directory names, etc
31def extract_tarball_to_dir(tarball, dir):
32 if os.path.exists(dir):
33 raise NameError, 'target %s already exists' % dir
34 pwd = os.getcwd()
35 os.chdir(os.path.dirname(os.path.abspath(dir)))
36 newdir = extract_tarball(tarball)
37 os.rename(newdir, dir)
38 os.chdir(pwd)
39
40
41# Returns the first found newly created directory by the tarball extraction
42def extract_tarball(tarball):
43 oldlist = os.listdir('.')
44 cat_file_to_cmd(tarball, 'tar xf -')
45 newlist = os.listdir('.')
46 newfiles = difflist(oldlist, newlist) # what is new dir ?
47 new_dir = None
48 for newfile in newfiles:
49 if (os.path.isdir(newfile)):
50 return newfile
51 raise NameError, "extracting tarball produced no dir"
52
mblighcdf02a42006-04-23 02:22:49 +000053
mblighea30c8a2006-04-22 22:24:25 +000054def is_url(path):
55 if (path.startswith('http://')) or (path.startswith('ftp://')):
56 # should cope with other url types here, but we don't handle them yet
57 return 1
58 return 0
59
mblighcdf02a42006-04-23 02:22:49 +000060
mblighf4c35322006-03-13 01:01:10 +000061def get_file(src, dest):
mbligh31186612006-04-22 21:55:56 +000062 if (src == dest): # no-op here allows clean overrides in tests
63 return
mblighf4c35322006-03-13 01:01:10 +000064 # get a file, either from url or local
mblighea30c8a2006-04-22 22:24:25 +000065 if (is_url(src)):
mblighf4c35322006-03-13 01:01:10 +000066 print 'PWD: ' + os.getcwd()
67 print 'Fetching \n\t', src, '\n\t->', dest
68 try:
69 urllib.urlretrieve(src, dest)
70 except IOError:
71 sys.stderr.write("Unable to retrieve %s (to %s)\n" % (src, dest))
72 sys.exit(1)
73 return dest
mblighf4c35322006-03-13 01:01:10 +000074 shutil.copyfile(src, dest)
75 return dest
76
mblighea30c8a2006-04-22 22:24:25 +000077
mbligh82641862006-04-23 06:21:36 +000078def unmap_url(srcdir, src, destdir = '.'):
mblighea30c8a2006-04-22 22:24:25 +000079 if is_url(src):
80 dest = destdir + '/' + os.path.basename(src)
81 get_file(src, dest)
82 return dest
mbligh82641862006-04-23 06:21:36 +000083 else:
84 return srcdir + '/' + src
mblighea30c8a2006-04-22 22:24:25 +000085
86
mblighf4c35322006-03-13 01:01:10 +000087def basename(path):
88 i = path.rfind('/');
89 return path[i+1:]
90
91
92def force_copy(src, dest):
93 if os.path.isfile(dest):
94 os.remove(dest)
95 return shutil.copyfile(src, dest)
96
97
mblighcdf02a42006-04-23 02:22:49 +000098def file_contains_pattern(file, pattern):
99 if not os.path.isfile(file):
100 raise NameError, 'file %s does not exist' % file
101 return not system('egrep -q ' + pattern + ' ' + file, ignorestatus = 1)
102
103
104def list_grep(list, pattern):
105 compiled = re.compile(pattern)
106 for line in list:
107 match = compiled.search(line)
108 if (match):
109 return 1
110 return 0
111
112
mblighf49d5cf2006-04-23 02:24:42 +0000113def get_vmlinux():
114 # Ahem. This is crap. Pray harder. Bad Martin.
mbligh67b5ece2006-04-23 02:53:12 +0000115 vmlinux = '/boot/vmlinux'
116 if not os.path.isfile(vmlinux):
117 raise NameError, 'Cannot find vmlinux'
118 return vmlinux
mblighf49d5cf2006-04-23 02:24:42 +0000119
120
121def get_systemmap():
122 # Ahem. This is crap. Pray harder. Bad Martin.
mbligh67b5ece2006-04-23 02:53:12 +0000123 map = '/boot/System.map'
124 if not os.path.isfile(map):
125 raise NameError, 'Cannot find System.map'
126 return map
127
128
129def get_modules_dir():
130 kernel_version = system_output('uname -r')
131 return '/lib/modules/%s/kernel' % kernel_version
mblighf49d5cf2006-04-23 02:24:42 +0000132
133
mblighcdf02a42006-04-23 02:22:49 +0000134def get_arch():
mblighf4c35322006-03-13 01:01:10 +0000135# Work out which CPU architecture we're running on
mblighcdf02a42006-04-23 02:22:49 +0000136 f = open('/proc/cpuinfo', 'r')
137 cpuinfo = f.readlines()
138 f.close()
139 if list_grep(cpuinfo, '^cpu.*(RS64|POWER3|Broadband Engine)'):
140 return 'power'
141 elif list_grep(cpuinfo, '^cpu.*POWER4'):
142 return 'power4'
143 elif list_grep(cpuinfo, '^cpu.*POWER5'):
144 return 'power5'
145 elif list_grep(cpuinfo, '^cpu.*POWER6'):
146 return 'power6'
147 elif list_grep(cpuinfo, '^cpu.*PPC970'):
148 return 'power970'
149 elif list_grep(cpuinfo, 'Opteron'):
150 return 'x86_64'
151 elif list_grep(cpuinfo, 'GenuineIntel') and list_grep(cpuinfo, '48 bits virtual'):
mblighf4c35322006-03-13 01:01:10 +0000152 return 'x86_64'
153 else:
154 return 'i386'
155
156
mblighcdf02a42006-04-23 02:22:49 +0000157def get_target_arch():
158 arch = get_arch()
159 if arch.startswith('power'):
160 return 'ppc64'
161 else:
162 return arch
163
164
mblighf4c35322006-03-13 01:01:10 +0000165def kernelexpand(kernel):
166 # if not (kernel.startswith('http://') or kernel.startswith('ftp://') or os.path.isfile(kernel)):
167 if kernel.find('/'):
168 w, r = os.popen2('./kernelexpand ' + kernel)
169
170 kernel = r.readline().strip()
171 r.close()
172 w.close()
173 return kernel
174
175
176def count_cpus():
177 f = file('/proc/cpuinfo', 'r')
178 cpus = 0
179 for line in f.readlines():
180 if line.startswith('processor'):
181 cpus += 1
182 return cpus
183
184
apwbc2867d2006-04-06 18:21:16 +0000185# We have our own definition of system here, as the stock os.system doesn't
mbligh3d914912006-04-22 17:37:19 +0000186# correctly handle sigpipe
187# (ie things like "yes | head" will hang because yes doesn't get the SIGPIPE).
mbligha975fb62006-04-22 19:56:25 +0000188#
189# Also the stock os.system didn't raise errors based on exit status, this
190# version does unless you explicitly specify ignorestatus=1
191def system(cmd, ignorestatus = 0):
mblighf4c35322006-03-13 01:01:10 +0000192 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
193 try:
apwbc2867d2006-04-06 18:21:16 +0000194 status = os.system(cmd)
mblighf4c35322006-03-13 01:01:10 +0000195 finally:
196 signal.signal(signal.SIGPIPE, signal.SIG_IGN)
mbligha975fb62006-04-22 19:56:25 +0000197
mbligh67b5ece2006-04-23 02:53:12 +0000198 if ((status != 0) and not ignorestatus):
apwbc2867d2006-04-06 18:21:16 +0000199 raise CmdError(cmd, status)
mbligha975fb62006-04-22 19:56:25 +0000200 return status
mbligh3d914912006-04-22 17:37:19 +0000201
202
mbligh67b5ece2006-04-23 02:53:12 +0000203def system_output(command, ignorestatus = 0):
204 (result, data) = commands.getstatusoutput(command)
205 if ((result != 0) and not ignorestatus):
206 raise CmdError, 'command failed: ' + command
207 return data
208
209
mblighf4c35322006-03-13 01:01:10 +0000210def where_art_thy_filehandles():
211 os.system("ls -l /proc/%d/fd >> /dev/tty" % os.getpid())
212
213
214def print_to_tty(string):
215 os.system("echo " + string + " >> /dev/tty")
216
217
218class fd_stack:
219 # Note that we need to redirect both the sys.stdout type descriptor
220 # (which print, etc use) and the low level OS numbered descriptor
221 # which os.system() etc use.
222
223 def __init__(self, fd, filehandle):
224 self.fd = fd # eg 1
225 self.filehandle = filehandle # eg sys.stdout
226 self.stack = [(fd, filehandle)]
227
228
229 def redirect(self, filename):
230 fdcopy = os.dup(self.fd)
231 self.stack.append( (fdcopy, self.filehandle) )
232 # self.filehandle = file(filename, 'w')
233 if (os.path.isfile(filename)):
234 newfd = os.open(filename, os.O_WRONLY)
235 else:
236 newfd = os.open(filename, os.O_WRONLY | os.O_CREAT)
237 os.dup2(newfd, self.fd)
238 os.close(newfd)
239 self.filehandle = os.fdopen(self.fd, 'w')
240
241
242 def tee_redirect(self, filename):
243 print_to_tty("tee_redirect to " + filename)
244 where_art_thy_filehandles()
245 fdcopy = os.dup(self.fd)
246 self.stack.append( (fdcopy, self.filehandle) )
247 r, w = os.pipe()
248 pid = os.fork()
249 if pid: # parent
250 os.close(r)
251 os.dup2(w, self.fd)
252 os.close(w)
253 else: # child
254 os.close(w)
255 os.dup2(r, 0)
256 os.dup2(2, 1)
257 os.execlp('tee', 'tee', filename)
258 self.filehandle = os.fdopen(self.fd, 'w')
259 where_art_thy_filehandles()
260 print_to_tty("done tee_redirect to " + filename)
261
262
263 def restore(self):
mblighcf315332006-04-02 19:58:30 +0000264 # print_to_tty("ENTERING RESTORE %d" % self.fd)
mblighf4c35322006-03-13 01:01:10 +0000265 # where_art_thy_filehandles()
266 (old_fd, old_filehandle) = self.stack.pop()
267 # print_to_tty("old_fd %d" % old_fd)
268 # print_to_tty("self.fd %d" % self.fd)
269 self.filehandle.close() # seems to close old_fd as well.
270 # where_art_thy_filehandles()
271 os.dup2(old_fd, self.fd)
272 # print_to_tty("CLOSING FD %d" % old_fd)
273 os.close(old_fd)
274 # where_art_thy_filehandles()
275 self.filehandle = old_filehandle
276 # where_art_thy_filehandles()
277 # print_to_tty("EXIT RESTORE %d" % self.fd)