1 # Copyright (C) 2003-2007 John Goerzen
2 # <jgoerzen@complete.org>
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 class ExecProblem(Exception):
26 def mainexec(program
, args
= [], child_stdout
= None,
27 child_stdin
= None, child_stderr
= None, wait
= 1, closefds
= []):
28 """Runs the program as a sub-process, passing to it args if specified.
29 The sub-process has its file descriptors adjusted as per the arguments.
31 If wait is 1, wait until the child exits, then return the result code from
34 If wait is 0, return the PID immediately."""
36 def setfds(source
, dest
):
38 if hasattr(source
, 'fileno'):
39 source
= source
.fileno()
45 print "Running: ", program
, args
46 setfds(child_stdin
, 0)
47 setfds(child_stdout
, 1)
48 setfds(child_stderr
, 2)
51 os
.execvp(program
, (program
,) + tuple(args
))
55 return os
.waitpid(pid
, 0)[1]
59 def safeexec(program
, args
= [], child_stdout
= None,
60 child_stdin
= None, child_stderr
= None,
62 """Calls mainexec() with the appropriate arguments, and raises
63 an exception if the program died with a signal or returned an
64 error code other than expected. This function will always wait."""
65 result
= mainexec(program
, args
, child_stdout
, child_stdin
, child_stderr
)
66 return checkresult(result
, expected
)
68 def getstdoutsafeexec(program
, args
, expected
= 0):
70 pid
= mainexec(program
, args
, child_stdout
= pipes
[1], wait
= 0)
72 fd
= os
.fdopen(pipes
[0], 'r')
73 retval
= fd
.readlines()
74 checkpid(pid
, expected
)
78 def silentsafeexec(program
, args
, expected
= 0):
79 """Silently runs the specified program."""
81 result
= mainexec(program
, args
, null
, null
, null
)
82 return checkresult(result
, expected
)
84 def checkresult(result
, expected
):
86 if os
.WIFSIGNALED(result
):
87 info
.append("got signal %d" % os
.WTERMSIG(result
))
88 if os
.WIFEXITED(result
):
89 info
.append("exited with code %d" % os
.WEXITSTATUS(result
))
91 if not os
.WIFEXITED(result
):
92 raise ExecProblem
, info
93 if os
.WEXITSTATUS(result
) != expected
:
94 raise ExecProblem
, info
+ " (expected exit code %d)" % expected
97 def checkpid(pid
, expected
):
98 return checkresult(os
.waitpid(pid
, 0)[1], expected
)
103 nulldev
= open("/dev/null", "w+")
106 def chdircmd(newdir
, func
, *args
, **kwargs
):
110 return apply(func
, args
, kwargs
)
114 def maketree(path
, addpath
= None, ignore
= [], res
= None):
115 thisdir
= os
.listdir(path
)
119 res
= [re
.compile(x
) for x
in ignore
]
123 if retest
.search(item
):
128 dirname
= os
.path
.join(path
, item
)
129 if os
.path
.isdir(dirname
) and not os
.path
.islink(dirname
):
131 retval
.append(os
.path
.join(addpath
, item
) + '/')
133 retval
.append(item
+ '/')
135 newaddpath
= os
.path
.join(addpath
, item
)
138 others
.extend(maketree(dirname
, newaddpath
, res
= res
))
141 retval
.append(os
.path
.join(addpath
, item
))
144 return sorttree(retval
+ others
)
146 def sorttree(srctree
, filesfirst
= False):
148 dirs
= [x
for x
in srctree
if x
.endswith('/')]
149 files
= [x
for x
in srctree
if not x
.endswith('/')]
158 def copyfrom(srcdir
, destdir
):
162 # verbargs.append('-v')
163 readerpid
= chdircmd(srcdir
, mainexec
, "tar", ["-cSpf", "-", "."],
164 child_stdout
= pipes
[1], wait
= 0,
165 closefds
= [pipes
[0]])
166 writerpid
= chdircmd(destdir
, mainexec
, "tar", ["-xSpf", "-"] + verbargs
,
167 child_stdin
= pipes
[0], wait
= 0, closefds
= [pipes
[1]])
170 checkpid(readerpid
, 0)
171 checkpid(writerpid
, 0)