blob: 667aac5eafd1bcbf0d8d8cf2a2135848347c1f2a [file] [log] [blame]
import os,os.path,shutil,urllib,sys,signal
from error import *
def grep(pattern, file):
# This is mainly to fix the return code inversion from grep
return not system('grep "' + pattern + '" "' + file + '"')
def difflist(list1, list2):
# returns items in list 2 that are not in list 1
diff = [];
for x in list2:
if x not in list1:
diff.append(x)
return diff
def cat_file_to_cmd(file, command):
if not os.path.isfile(file):
raise NameError, 'invalid file %s to cat to command %s' % file, command
if file.endswith('.bz2'):
system('bzcat ' + file + ' | ' + command)
elif (file.endswith('.gz') or file.endswith('.tgz')):
system('zcat ' + file + ' | ' + command)
else:
system('cat ' + file + ' | ' + command)
# Extract a tarball to a specified directory name instead of whatever
# the top level of a tarball is - useful for versioned directory names, etc
def extract_tarball_to_dir(tarball, dir):
if os.path.exists(dir):
raise NameError, 'target %s already exists' % dir
pwd = os.getcwd()
os.chdir(os.path.dirname(os.path.abspath(dir)))
newdir = extract_tarball(tarball)
os.rename(newdir, dir)
os.chdir(pwd)
# Returns the first found newly created directory by the tarball extraction
def extract_tarball(tarball):
oldlist = os.listdir('.')
cat_file_to_cmd(tarball, 'tar xf -')
newlist = os.listdir('.')
newfiles = difflist(oldlist, newlist) # what is new dir ?
new_dir = None
for newfile in newfiles:
if (os.path.isdir(newfile)):
return newfile
raise NameError, "extracting tarball produced no dir"
def is_url(path):
if (path.startswith('http://')) or (path.startswith('ftp://')):
# should cope with other url types here, but we don't handle them yet
return 1
return 0
def get_file(src, dest):
if (src == dest): # no-op here allows clean overrides in tests
return
# get a file, either from url or local
if (is_url(src)):
print 'PWD: ' + os.getcwd()
print 'Fetching \n\t', src, '\n\t->', dest
try:
urllib.urlretrieve(src, dest)
except IOError:
sys.stderr.write("Unable to retrieve %s (to %s)\n" % (src, dest))
sys.exit(1)
return dest
shutil.copyfile(src, dest)
return dest
def unmap_potential_url(src, destdir = '.'):
if is_url(src):
dest = destdir + '/' + os.path.basename(src)
get_file(src, dest)
return dest
return src
def basename(path):
i = path.rfind('/');
return path[i+1:]
def force_copy(src, dest):
if os.path.isfile(dest):
os.remove(dest)
return shutil.copyfile(src, dest)
def get_target_arch():
# Work out which CPU architecture we're running on
if not system("egrep '^cpu.*(RS64|POWER(3|4|5)|PPC970|Broadband Engine)' /proc/cpuinfo"):
return 'ppc64'
elif not system("grep -q 'Opteron' /proc/cpuinfo"):
# THIS IS WRONG, needs Intel too
return 'x86_64'
else:
return 'i386'
def kernelexpand(kernel):
# if not (kernel.startswith('http://') or kernel.startswith('ftp://') or os.path.isfile(kernel)):
if kernel.find('/'):
w, r = os.popen2('./kernelexpand ' + kernel)
kernel = r.readline().strip()
r.close()
w.close()
return kernel
def count_cpus():
f = file('/proc/cpuinfo', 'r')
cpus = 0
for line in f.readlines():
if line.startswith('processor'):
cpus += 1
return cpus
# We have our own definition of system here, as the stock os.system doesn't
# correctly handle sigpipe
# (ie things like "yes | head" will hang because yes doesn't get the SIGPIPE).
#
# Also the stock os.system didn't raise errors based on exit status, this
# version does unless you explicitly specify ignorestatus=1
def system(cmd, ignorestatus = 0):
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
try:
status = os.system(cmd)
finally:
signal.signal(signal.SIGPIPE, signal.SIG_IGN)
if ((status != 0) and (ignorestatus != 0)):
raise CmdError(cmd, status)
return status
def where_art_thy_filehandles():
os.system("ls -l /proc/%d/fd >> /dev/tty" % os.getpid())
def print_to_tty(string):
os.system("echo " + string + " >> /dev/tty")
class fd_stack:
# Note that we need to redirect both the sys.stdout type descriptor
# (which print, etc use) and the low level OS numbered descriptor
# which os.system() etc use.
def __init__(self, fd, filehandle):
self.fd = fd # eg 1
self.filehandle = filehandle # eg sys.stdout
self.stack = [(fd, filehandle)]
def redirect(self, filename):
fdcopy = os.dup(self.fd)
self.stack.append( (fdcopy, self.filehandle) )
# self.filehandle = file(filename, 'w')
if (os.path.isfile(filename)):
newfd = os.open(filename, os.O_WRONLY)
else:
newfd = os.open(filename, os.O_WRONLY | os.O_CREAT)
os.dup2(newfd, self.fd)
os.close(newfd)
self.filehandle = os.fdopen(self.fd, 'w')
def tee_redirect(self, filename):
print_to_tty("tee_redirect to " + filename)
where_art_thy_filehandles()
fdcopy = os.dup(self.fd)
self.stack.append( (fdcopy, self.filehandle) )
r, w = os.pipe()
pid = os.fork()
if pid: # parent
os.close(r)
os.dup2(w, self.fd)
os.close(w)
else: # child
os.close(w)
os.dup2(r, 0)
os.dup2(2, 1)
os.execlp('tee', 'tee', filename)
self.filehandle = os.fdopen(self.fd, 'w')
where_art_thy_filehandles()
print_to_tty("done tee_redirect to " + filename)
def restore(self):
# print_to_tty("ENTERING RESTORE %d" % self.fd)
# where_art_thy_filehandles()
(old_fd, old_filehandle) = self.stack.pop()
# print_to_tty("old_fd %d" % old_fd)
# print_to_tty("self.fd %d" % self.fd)
self.filehandle.close() # seems to close old_fd as well.
# where_art_thy_filehandles()
os.dup2(old_fd, self.fd)
# print_to_tty("CLOSING FD %d" % old_fd)
os.close(old_fd)
# where_art_thy_filehandles()
self.filehandle = old_filehandle
# where_art_thy_filehandles()
# print_to_tty("EXIT RESTORE %d" % self.fd)