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 42namespace google_breakpad { 43 44//============================================================================= 45BOOL 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//============================================================================= 59BOOL 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//============================================================================= 66BOOL 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//============================================================================= 91BOOL ConfigFile::AppendConfigString(const char *key, 92 const char *value) { 93 return AppendConfigData(key, value, strlen(value)); 94} 95 96//============================================================================= 97BOOL 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//============================================================================= 120void 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