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