xref: /aosp_15_r20/external/google-breakpad/src/client/mac/crash_generation/ConfigFile.mm (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1// Copyright 2011 Google LLC
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 LLC 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// Utility class that can persist a SimpleStringDictionary to disk.
30
31#import "client/mac/crash_generation/ConfigFile.h"
32
33#import <Foundation/Foundation.h>
34#include <stdio.h>
35#include <sys/time.h>
36
37#import "client/apple/Framework/BreakpadDefines.h"
38#import "common/mac/GTMDefines.h"
39
40
41namespace google_breakpad {
42
43//=============================================================================
44BOOL EnsureDirectoryPathExists(NSString* dirPath) {
45  NSFileManager* mgr = [NSFileManager defaultManager];
46
47  NSDictionary* attrs =
48    [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedLong:0750]
49                                forKey:NSFilePosixPermissions];
50
51  return [mgr createDirectoryAtPath:dirPath
52        withIntermediateDirectories:YES
53                         attributes:attrs
54                              error:nil];
55}
56
57//=============================================================================
58BOOL ConfigFile::WriteData(const void* data, size_t length) {
59  size_t result = write(config_file_, data, length);
60
61  return result == length;
62}
63
64//=============================================================================
65BOOL ConfigFile::AppendConfigData(const char* key,
66                                  const void* data, size_t length) {
67  assert(config_file_ != -1);
68
69  if (!key) {
70    return NO;
71  }
72
73  if (!data) {
74    return NO;
75  }
76
77  // Write the key, \n, length of data (ascii integer), \n, data
78  char buffer[16];
79  char nl = '\n';
80  BOOL result = WriteData(key, strlen(key));
81
82  snprintf(buffer, sizeof(buffer) - 1, "\n%lu\n", length);
83  result &= WriteData(buffer, strlen(buffer));
84  result &= WriteData(data, length);
85  result &= WriteData(&nl, 1);
86  return result;
87}
88
89//=============================================================================
90BOOL ConfigFile::AppendConfigString(const char* key,
91                                    const char* value) {
92  return AppendConfigData(key, value, strlen(value));
93}
94
95//=============================================================================
96BOOL ConfigFile::AppendCrashTimeParameters(const char* processStartTimeString) {
97  // Set process uptime parameter
98  struct timeval tv;
99  gettimeofday(&tv, NULL);
100
101  char processUptimeString[32], processCrashtimeString[32];
102  // Set up time if we've received the start time.
103  if (processStartTimeString) {
104    time_t processStartTime = strtol(processStartTimeString, NULL, 10);
105    time_t processUptime = tv.tv_sec - processStartTime;
106    // Store the uptime in milliseconds.
107    snprintf(processUptimeString, sizeof(processUptimeString), "%llu",
108             static_cast<unsigned long long int>(processUptime) * 1000);
109    if (!AppendConfigString(BREAKPAD_PROCESS_UP_TIME, processUptimeString))
110      return false;
111  }
112
113  snprintf(processCrashtimeString, sizeof(processCrashtimeString), "%llu",
114           static_cast<unsigned long long int>(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