Home | History | Annotate | Download | only in crash_generation
      1 // Copyright (c) 2011, Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 //
     30 // Utility class that can persist a SimpleStringDictionary to disk.
     31 
     32 #import "client/mac/crash_generation/ConfigFile.h"
     33 
     34 #import <Foundation/Foundation.h>
     35 #include <stdio.h>
     36 #include <sys/time.h>
     37 
     38 #import "client/apple/Framework/BreakpadDefines.h"
     39 #import "common/mac/GTMDefines.h"
     40 
     41 
     42 namespace google_breakpad {
     43 
     44 //=============================================================================
     45 BOOL EnsureDirectoryPathExists(NSString *dirPath) {
     46   NSFileManager *mgr = [NSFileManager defaultManager];
     47 
     48   NSDictionary *attrs =
     49     [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedLong:0750]
     50                                 forKey:NSFilePosixPermissions];
     51 
     52   return [mgr createDirectoryAtPath:dirPath
     53         withIntermediateDirectories:YES
     54                          attributes:attrs
     55                               error:nil];
     56 }
     57 
     58 //=============================================================================
     59 BOOL ConfigFile::WriteData(const void *data, size_t length) {
     60   size_t result = write(config_file_, data, length);
     61 
     62   return result == length;
     63 }
     64 
     65 //=============================================================================
     66 BOOL ConfigFile::AppendConfigData(const char *key,
     67                                   const void *data, size_t length) {
     68   assert(config_file_ != -1);
     69 
     70   if (!key) {
     71     return NO;
     72   }
     73 
     74   if (!data) {
     75     return NO;
     76   }
     77 
     78   // Write the key, \n, length of data (ascii integer), \n, data
     79   char buffer[16];
     80   char nl = '\n';
     81   BOOL result = WriteData(key, strlen(key));
     82 
     83   snprintf(buffer, sizeof(buffer) - 1, "\n%lu\n", length);
     84   result &= WriteData(buffer, strlen(buffer));
     85   result &= WriteData(data, length);
     86   result &= WriteData(&nl, 1);
     87   return result;
     88 }
     89 
     90 //=============================================================================
     91 BOOL ConfigFile::AppendConfigString(const char *key,
     92                                     const char *value) {
     93   return AppendConfigData(key, value, strlen(value));
     94 }
     95 
     96 //=============================================================================
     97 BOOL ConfigFile::AppendCrashTimeParameters(const char *processStartTimeString) {
     98   // Set process uptime parameter
     99   struct timeval tv;
    100   gettimeofday(&tv, NULL);
    101 
    102   char processUptimeString[32], processCrashtimeString[32];
    103   // Set up time if we've received the start time.
    104   if (processStartTimeString) {
    105     time_t processStartTime = strtol(processStartTimeString, NULL, 10);
    106     time_t processUptime = tv.tv_sec - processStartTime;
    107     // Store the uptime in milliseconds.
    108     sprintf(processUptimeString, "%llu",
    109         static_cast<unsigned long long int>(processUptime) * 1000);
    110     if (!AppendConfigString(BREAKPAD_PROCESS_UP_TIME, processUptimeString))
    111       return false;
    112   }
    113 
    114   sprintf(processCrashtimeString, "%zd", tv.tv_sec);
    115   return AppendConfigString(BREAKPAD_PROCESS_CRASH_TIME,
    116                             processCrashtimeString);
    117 }
    118 
    119 //=============================================================================
    120 void ConfigFile::WriteFile(const char* directory,
    121                            const SimpleStringDictionary *configurationParameters,
    122                            const char *dump_dir,
    123                            const char *minidump_id) {
    124 
    125   assert(config_file_ == -1);
    126 
    127   // Open and write out configuration file preamble
    128   if (directory) {
    129     snprintf(config_file_path_, sizeof(config_file_path_), "%s/Config-XXXXXX",
    130              directory);
    131   } else {
    132     strlcpy(config_file_path_, "/tmp/Config-XXXXXX",
    133             sizeof(config_file_path_));
    134   }
    135   config_file_ = mkstemp(config_file_path_);
    136 
    137   if (config_file_ == -1) {
    138     return;
    139   }
    140 
    141   has_created_file_ = true;
    142 
    143   // Add the minidump dir
    144   AppendConfigString(kReporterMinidumpDirectoryKey, dump_dir);
    145   AppendConfigString(kReporterMinidumpIDKey, minidump_id);
    146 
    147   // Write out the configuration parameters
    148   BOOL result = YES;
    149   const SimpleStringDictionary &dictionary = *configurationParameters;
    150 
    151   const SimpleStringDictionary::Entry *entry = NULL;
    152   SimpleStringDictionary::Iterator iter(dictionary);
    153 
    154   while ((entry = iter.Next())) {
    155     result = AppendConfigString(entry->key, entry->value);
    156 
    157     if (!result)
    158       break;
    159   }
    160   AppendCrashTimeParameters(
    161       configurationParameters->GetValueForKey(BREAKPAD_PROCESS_START_TIME));
    162 
    163   close(config_file_);
    164   config_file_ = -1;
    165 }
    166 
    167 } // namespace google_breakpad
    168