Improve and fix the use of dpkg-query:
- Store in a dictionary all of the result of dpkg-query calls to prevent calling dpkg-query for the
same file twice, this speeds up the test a lot if there are many deleted libraries and they all
point to the same file (i.e. libc6 update)
- do not process dpkg-query until the process has finished properly
- send the STDERR output to the pipe for processing and to prevent showing errors in console
Javier Fernandez-Sanguino
12 years ago
61 | 61 | sys.stderr.write('usage: checkrestart [-vhpa]\n') |
62 | 62 | |
63 | 63 | def main(): |
64 | global lc_all_c_env | |
64 | global lc_all_c_env, file_query_check | |
65 | 65 | process = None |
66 | 66 | toRestart = {} |
67 | 67 | |
68 | 68 | lc_all_c_env = os.environ |
69 | 69 | lc_all_c_env['LC_ALL'] = 'C' |
70 | file_query_check = {} | |
70 | 71 | blacklistFiles = [] |
71 | 72 | blacklist = [] |
72 | 73 | |
149 | 150 | packages = {} |
150 | 151 | diverted = None |
151 | 152 | dpkgQuery = ["dpkg-query", "--search"] + programs.keys() |
152 | dpkgProc = subprocess.Popen(dpkgQuery, stdout=subprocess.PIPE, stderr=None, | |
153 | dpkgProc = subprocess.Popen(dpkgQuery, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, | |
153 | 154 | env = lc_all_c_env) |
155 | if verbose: | |
156 | print "Running:%s" % dpkgQuery | |
154 | 157 | for line in dpkgProc.stdout.readlines(): |
155 | 158 | if line.startswith('local diversion'): |
156 | 159 | continue |
185 | 188 | if package == 'util-linux': |
186 | 189 | continue |
187 | 190 | dpkgQuery = ["dpkg-query", "--listfiles", package.name] |
188 | dpkgProc = subprocess.Popen(dpkgQuery, stdout=subprocess.PIPE, stderr=None, | |
191 | dpkgProc = subprocess.Popen(dpkgQuery, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, | |
189 | 192 | env = lc_all_c_env) |
190 | 193 | for line in dpkgProc.stdout.readlines(): |
191 | 194 | path = line[:-1] |
267 | 270 | processes.values()) |
268 | 271 | return toRestart |
269 | 272 | |
273 | # Tells if a file is part of a package | |
274 | # Returns: | |
275 | # - False - file does not exist in the system or cannot be found when querying the package database | |
276 | # - True - file is found in an operating system package | |
277 | def ispackagedFile (f): | |
278 | file_in_package = False | |
279 | # First check if the file exists, do not call dpkg-query | |
280 | # if the file simply does not exist in the file system | |
281 | if os.path.exists(f): | |
282 | # If it exists, run dpkg-query | |
283 | dpkgQuery = ["dpkg-query", "--search", f] | |
284 | dpkgProc = subprocess.Popen(dpkgQuery, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, | |
285 | env = lc_all_c_env, close_fds=True) | |
286 | dpkgProc.wait() | |
287 | if verbose: | |
288 | print "Running:%s" % dpkgQuery | |
289 | for line in dpkgProc.stdout.readlines(): | |
290 | line = line.strip() | |
291 | if line.find('no path found matching pattern ' + f) > 0: | |
292 | file_in_package = False | |
293 | break | |
294 | if line.endswith(f): | |
295 | file_in_package = True | |
296 | break | |
297 | ||
298 | return file_in_package | |
299 | ||
270 | 300 | # Tells if a file has to be considered a deleted file |
271 | 301 | # Returns: |
272 | 302 | # - 0 (NO) for known locations of files which might be deleted |
273 | 303 | # - 1 (YES) for valid deleted files we are interested in |
274 | 304 | def isdeletedFile (f, blacklist = None): |
275 | 305 | |
276 | global lc_all_c_env | |
306 | global lc_all_c_env, file_query_check | |
277 | 307 | |
278 | 308 | if allFiles: |
279 | 309 | return 1 |
329 | 359 | return 0 |
330 | 360 | # Skip, if asked to, files that do not belong to any package |
331 | 361 | if onlyPackageFiles: |
332 | file_in_package = False | |
333 | 362 | # Remove some lsof information from the file to ensure that it is |
334 | 363 | # a proper filename |
335 | 364 | file_name = re.sub(r'\(.*\)','', f) |
336 | 365 | file_name = re.sub(r'\s+$','', file_name) |
337 | dpkgQuery = ["dpkg-query", "--search", file_name] | |
338 | dpkgProc = subprocess.Popen(dpkgQuery, stdout=subprocess.PIPE, stderr=None, | |
339 | env = lc_all_c_env) | |
340 | for line in dpkgProc.stdout.readlines(): | |
341 | if line.endswith(f): | |
342 | file_in_package = True | |
343 | break | |
344 | if not file_in_package: | |
345 | return 0 | |
366 | # First check: have we checked this file before? If we have not then make the check | |
367 | if not file_name in file_query_check: | |
368 | file_query_check[file_name] = ispackagedFile(file_name) | |
369 | # Once we have the result then check if the file belongs to a package | |
370 | if not file_query_check[file_name]: | |
371 | return 0 | |
346 | 372 | |
347 | 373 | # TODO: it should only care about library files (i.e. /lib, /usr/lib and the like) |
348 | 374 | # build that check with a regexp to exclude others |