Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2007, Google Inc. | |
Mark Mentovai
2011/10/10 13:36:14
2011
| |
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 #include <stdio.h> | |
35 #include <sys/time.h> | |
36 | |
37 #import "client/mac/Framework/Breakpad.h" | |
38 #import "common/mac/SimpleStringDictionary.h" | |
39 #import "GTMDefines.h" | |
40 | |
41 #import <Foundation/Foundation.h> | |
Mark Mentovai
2011/10/10 13:36:14
This is a system header and belongs up with the <s
| |
42 | |
43 #if VERBOSE | |
44 bool gDebugLog = true; | |
45 #else | |
46 bool gDebugLog = false; | |
47 #endif | |
48 | |
49 namespace google_breakpad { | |
50 | |
51 //============================================================================= | |
52 BOOL EnsureDirectoryPathExists(NSString *dirPath) { | |
53 NSFileManager *mgr = [NSFileManager defaultManager]; | |
54 | |
55 // If we got a relative path, prepend the current directory | |
56 if (![dirPath isAbsolutePath]) | |
57 dirPath = [[mgr currentDirectoryPath] stringByAppendingPathComponent:dirPath ]; | |
Mark Mentovai
2011/10/10 13:36:14
80 characters.
| |
58 | |
59 NSString *path = dirPath; | |
60 | |
61 // Ensure that no file exists within the path which would block creation | |
62 while (1) { | |
63 BOOL isDir; | |
64 if ([mgr fileExistsAtPath:path isDirectory:&isDir]) { | |
65 if (isDir) | |
66 break; | |
67 | |
68 return NO; | |
69 } | |
70 | |
71 path = [path stringByDeletingLastPathComponent]; | |
72 } | |
73 | |
74 // Path now contains the first valid directory (or is empty) | |
75 if (![path length]) | |
76 return NO; | |
77 | |
78 NSString *common = | |
79 [dirPath commonPrefixWithString:path options:NSLiteralSearch]; | |
80 | |
81 // If everything is good | |
82 if ([common isEqualToString:dirPath]) | |
83 return YES; | |
84 | |
85 // Break up the difference into components | |
86 NSString *diff = [dirPath substringFromIndex:[common length] + 1]; | |
87 NSArray *components = [diff pathComponents]; | |
88 NSUInteger count = [components count]; | |
89 | |
90 // Rebuild the path one component at a time | |
91 NSDictionary *attrs = | |
92 [NSDictionary dictionaryWithObject:[NSNumber numberWithUnsignedLong:0750] | |
93 forKey:NSFilePosixPermissions]; | |
94 path = common; | |
95 for (NSUInteger i = 0; i < count; ++i) { | |
96 path = [path stringByAppendingPathComponent:[components objectAtIndex:i]]; | |
97 | |
98 if (![mgr createDirectoryAtPath:path attributes:attrs]) | |
99 return NO; | |
100 } | |
101 | |
102 return YES; | |
103 } | |
104 | |
105 //============================================================================= | |
106 BOOL ConfigFile::WriteData(const void *data, size_t length) { | |
107 size_t result = write(config_file_, data, length); | |
108 | |
109 return result == length; | |
110 } | |
111 | |
112 //============================================================================= | |
113 BOOL ConfigFile::AppendConfigData(const char *key, | |
114 const void *data, size_t length) { | |
115 assert(config_file_ != -1); | |
116 | |
117 if (!key) { | |
118 DEBUGLOG(stderr, "Breakpad: Missing Key\n"); | |
119 return NO; | |
120 } | |
121 | |
122 if (!data) { | |
123 DEBUGLOG(stderr, "Breakpad: Missing data for key: %s\n", key ? key : | |
124 "<Unknown Key>"); | |
125 return NO; | |
126 } | |
127 | |
128 // Write the key, \n, length of data (ascii integer), \n, data | |
129 char buffer[16]; | |
130 char nl = '\n'; | |
131 BOOL result = WriteData(key, strlen(key)); | |
132 | |
133 snprintf(buffer, sizeof(buffer) - 1, "\n%lu\n", length); | |
134 result &= WriteData(buffer, strlen(buffer)); | |
135 result &= WriteData(data, length); | |
136 result &= WriteData(&nl, 1); | |
137 return result; | |
138 } | |
139 | |
140 //============================================================================= | |
141 BOOL ConfigFile::AppendConfigString(const char *key, | |
142 const char *value) { | |
143 return AppendConfigData(key, value, strlen(value)); | |
144 } | |
145 | |
146 //============================================================================= | |
147 BOOL ConfigFile::AppendCrashTimeParameters(const char *processStartTimeString) { | |
148 // Set process uptime parameter | |
149 struct timeval tv; | |
150 gettimeofday(&tv, NULL); | |
151 | |
152 char processUptimeString[32], processCrashtimeString[32]; | |
153 // Set up time if we've received the start time. | |
154 if (processStartTimeString) { | |
155 time_t processStartTime = strtol(processStartTimeString, NULL, 10); | |
156 time_t processUptime = tv.tv_sec - processStartTime; | |
157 sprintf(processUptimeString, "%zd", processUptime); | |
158 if (!AppendConfigString(BREAKPAD_PROCESS_UP_TIME, processUptimeString)) | |
159 return false; | |
160 } | |
161 | |
162 sprintf(processCrashtimeString, "%zd", tv.tv_sec); | |
163 return AppendConfigString(BREAKPAD_PROCESS_CRASH_TIME, | |
164 processCrashtimeString); | |
165 } | |
166 | |
167 //============================================================================= | |
168 void ConfigFile::WriteFile(const char* directory, | |
169 const SimpleStringDictionary *configurationParameters , | |
170 const char *dump_dir, | |
171 const char *minidump_id) { | |
172 | |
173 assert(config_file_ == -1); | |
174 | |
175 // Open and write out configuration file preamble | |
176 if (directory) { | |
177 snprintf(config_file_path_, sizeof(config_file_path_), "%s/Config-XXXXXX", | |
178 directory); | |
179 } else { | |
180 strlcpy(config_file_path_, "/tmp/Config-XXXXXX", | |
181 sizeof(config_file_path_)); | |
182 } | |
183 config_file_ = mkstemp(config_file_path_); | |
184 | |
185 if (config_file_ == -1) { | |
186 DEBUGLOG(stderr, | |
187 "mkstemp(config_file_path_) == -1 (%s)\n", | |
188 strerror(errno)); | |
189 return; | |
190 } | |
191 else { | |
192 DEBUGLOG(stderr, "Writing config file to (%s)\n", config_file_path_); | |
193 } | |
194 | |
195 has_created_file_ = true; | |
196 | |
197 // Add the minidump dir | |
198 AppendConfigString(kReporterMinidumpDirectoryKey, dump_dir); | |
199 AppendConfigString(kReporterMinidumpIDKey, minidump_id); | |
200 | |
201 // Write out the configuration parameters | |
202 BOOL result = YES; | |
203 const SimpleStringDictionary &dictionary = *configurationParameters; | |
204 | |
205 const KeyValueEntry *entry = NULL; | |
206 SimpleStringDictionaryIterator iter(dictionary); | |
207 | |
208 while ((entry = iter.Next())) { | |
209 DEBUGLOG(stderr, | |
210 "config: (%s) -> (%s)\n", | |
211 entry->GetKey(), | |
212 entry->GetValue()); | |
213 result = AppendConfigString(entry->GetKey(), entry->GetValue()); | |
214 | |
215 if (!result) | |
216 break; | |
217 } | |
218 AppendCrashTimeParameters( | |
219 configurationParameters->GetValueForKey(BREAKPAD_PROCESS_START_TIME)); | |
220 | |
221 close(config_file_); | |
222 config_file_ = -1; | |
223 } | |
224 | |
225 } // namespace google_breakpad | |
226 | |
Mark Mentovai
2011/10/10 13:36:14
Unnecessary blank line at EOF.
| |
OLD | NEW |