Home | History | Annotate | Download | only in system
      1 # Copyright (c) 2011, Google Inc. All rights reserved.
      2 #
      3 # Redistribution and use in source and binary forms, with or without
      4 # modification, are permitted provided that the following conditions are
      5 # met:
      6 #
      7 #     * Redistributions of source code must retain the above copyright
      8 # notice, this list of conditions and the following disclaimer.
      9 #     * Redistributions in binary form must reproduce the above
     10 # copyright notice, this list of conditions and the following disclaimer
     11 # in the documentation and/or other materials provided with the
     12 # distribution.
     13 #     * Neither the name of Google Inc. nor the names of its
     14 # contributors may be used to endorse or promote products derived from
     15 # this software without specific prior written permission.
     16 #
     17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 
     29 import re
     30 
     31 
     32 class CrashLogs(object):
     33     def __init__(self, host):
     34         self._host = host
     35 
     36     def find_newest_log(self, process_name, pid=None, include_errors=False, newer_than=None):
     37         if self._host.platform.is_mac():
     38             return self._find_newest_log_darwin(process_name, pid, include_errors, newer_than)
     39         return None
     40 
     41     def _log_directory_darwin(self):
     42         log_directory = self._host.filesystem.expanduser("~")
     43         log_directory = self._host.filesystem.join(log_directory, "Library", "Logs")
     44         if self._host.filesystem.exists(self._host.filesystem.join(log_directory, "DiagnosticReports")):
     45             log_directory = self._host.filesystem.join(log_directory, "DiagnosticReports")
     46         else:
     47             log_directory = self._host.filesystem.join(log_directory, "CrashReporter")
     48         return log_directory
     49 
     50     def _find_newest_log_darwin(self, process_name, pid, include_errors, newer_than):
     51         def is_crash_log(fs, dirpath, basename):
     52             return basename.startswith(process_name + "_") and basename.endswith(".crash")
     53 
     54         log_directory = self._log_directory_darwin()
     55         logs = self._host.filesystem.files_under(log_directory, file_filter=is_crash_log)
     56         first_line_regex = re.compile(r'^Process:\s+(?P<process_name>.*) \[(?P<pid>\d+)\]$')
     57         errors = ''
     58         for path in reversed(sorted(logs)):
     59             try:
     60                 if not newer_than or self._host.filesystem.mtime(path) > newer_than:
     61                     f = self._host.filesystem.read_text_file(path)
     62                     match = first_line_regex.match(f[0:f.find('\n')])
     63                     if match and match.group('process_name') == process_name and (pid is None or int(match.group('pid')) == pid):
     64                         return errors + f
     65             except IOError, e:
     66                 if include_errors:
     67                     errors += "ERROR: Failed to read '%s': %s\n" % (path, str(e))
     68             except OSError, e:
     69                 if include_errors:
     70                     errors += "ERROR: Failed to read '%s': %s\n" % (path, str(e))
     71 
     72         if include_errors and errors:
     73             return errors
     74         return None
     75