OLD | NEW |
---|---|
1 // Copyright 2015 The Crashpad Authors. All rights reserved. | 1 // Copyright 2015 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
87 if (mkdir(path.value().c_str(), 0755) == 0) { | 87 if (mkdir(path.value().c_str(), 0755) == 0) { |
88 return true; | 88 return true; |
89 } | 89 } |
90 if (errno != EEXIST) { | 90 if (errno != EEXIST) { |
91 PLOG(ERROR) << "mkdir " << path.value(); | 91 PLOG(ERROR) << "mkdir " << path.value(); |
92 return false; | 92 return false; |
93 } | 93 } |
94 return EnsureDirectoryExists(path); | 94 return EnsureDirectoryExists(path); |
95 } | 95 } |
96 | 96 |
97 // Creates a long database xattr name from the short constant name. These names | |
98 // have changed, and new_name determines whether the returned xattr name will be | |
99 // the old name or its new equivalent. | |
100 std::string XattrNameInternal(const base::StringPiece& name, bool new_name) { | |
Mark Mentovai
2015/10/29 20:45:24
This file is the only one with a code change.
| |
101 return base::StringPrintf(new_name ? "org.chromium.crashpad.database.%s" | |
102 : "com.googlecode.crashpad.%s", | |
103 name.data()); | |
104 } | |
105 | |
97 //! \brief A CrashReportDatabase that uses HFS+ extended attributes to store | 106 //! \brief A CrashReportDatabase that uses HFS+ extended attributes to store |
98 //! report metadata. | 107 //! report metadata. |
99 //! | 108 //! |
100 //! The database maintains three directories of reports: `"new"` to hold crash | 109 //! The database maintains three directories of reports: `"new"` to hold crash |
101 //! reports that are in the process of being written, `"completed"` to hold | 110 //! reports that are in the process of being written, `"completed"` to hold |
102 //! reports that have been written and are awaiting upload, and `"uploaded"` to | 111 //! reports that have been written and are awaiting upload, and `"uploaded"` to |
103 //! hold reports successfully uploaded to a collection server. If the user has | 112 //! hold reports successfully uploaded to a collection server. If the user has |
104 //! opted out of report collection, reports will still be written and moved | 113 //! opted out of report collection, reports will still be written and moved |
105 //! to the completed directory, but they just will not be uploaded. | 114 //! to the completed directory, but they just will not be uploaded. |
106 //! | 115 //! |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
166 static base::ScopedFD ObtainReportLock(const base::FilePath& path); | 175 static base::ScopedFD ObtainReportLock(const base::FilePath& path); |
167 | 176 |
168 //! \brief Reads all the database xattrs from a file into a Report. The file | 177 //! \brief Reads all the database xattrs from a file into a Report. The file |
169 //! must be locked with ObtainReportLock. | 178 //! must be locked with ObtainReportLock. |
170 //! | 179 //! |
171 //! \param[in] path The path of the report. | 180 //! \param[in] path The path of the report. |
172 //! \param[out] report The object into which data will be read. | 181 //! \param[out] report The object into which data will be read. |
173 //! | 182 //! |
174 //! \return `true` if all the metadata was read successfully, `false` | 183 //! \return `true` if all the metadata was read successfully, `false` |
175 //! otherwise. | 184 //! otherwise. |
176 static bool ReadReportMetadataLocked(const base::FilePath& path, | 185 bool ReadReportMetadataLocked(const base::FilePath& path, Report* report); |
177 Report* report); | |
178 | 186 |
179 //! \brief Reads the metadata from all the reports in a database subdirectory. | 187 //! \brief Reads the metadata from all the reports in a database subdirectory. |
180 //! Invalid reports are skipped. | 188 //! Invalid reports are skipped. |
181 //! | 189 //! |
182 //! \param[in] path The database subdirectory path. | 190 //! \param[in] path The database subdirectory path. |
183 //! \param[out] reports An empty vector of reports, which will be filled. | 191 //! \param[out] reports An empty vector of reports, which will be filled. |
184 //! | 192 //! |
185 //! \return The operation status code. | 193 //! \return The operation status code. |
186 static OperationStatus ReportsInDirectory(const base::FilePath& path, | 194 OperationStatus ReportsInDirectory(const base::FilePath& path, |
187 std::vector<Report>* reports); | 195 std::vector<Report>* reports); |
188 | 196 |
189 //! \brief Creates a database xattr name from the short constant name. | 197 //! \brief Creates a database xattr name from the short constant name. |
190 //! | 198 //! |
191 //! \param[in] name The short name of the extended attribute. | 199 //! \param[in] name The short name of the extended attribute. |
192 //! | 200 //! |
193 //! \return The long name of the extended attribute. | 201 //! \return The long name of the extended attribute. |
194 static std::string XattrName(const base::StringPiece& name); | 202 std::string XattrName(const base::StringPiece& name); |
195 | 203 |
196 base::FilePath base_dir_; | 204 base::FilePath base_dir_; |
197 Settings settings_; | 205 Settings settings_; |
206 bool xattr_new_names_; | |
198 InitializationStateDcheck initialized_; | 207 InitializationStateDcheck initialized_; |
199 | 208 |
200 DISALLOW_COPY_AND_ASSIGN(CrashReportDatabaseMac); | 209 DISALLOW_COPY_AND_ASSIGN(CrashReportDatabaseMac); |
201 }; | 210 }; |
202 | 211 |
203 CrashReportDatabaseMac::CrashReportDatabaseMac(const base::FilePath& path) | 212 CrashReportDatabaseMac::CrashReportDatabaseMac(const base::FilePath& path) |
204 : CrashReportDatabase(), | 213 : CrashReportDatabase(), |
205 base_dir_(path), | 214 base_dir_(path), |
206 settings_(base_dir_.Append(kSettings)), | 215 settings_(base_dir_.Append(kSettings)), |
216 xattr_new_names_(false), | |
207 initialized_() { | 217 initialized_() { |
208 } | 218 } |
209 | 219 |
210 CrashReportDatabaseMac::~CrashReportDatabaseMac() {} | 220 CrashReportDatabaseMac::~CrashReportDatabaseMac() {} |
211 | 221 |
212 bool CrashReportDatabaseMac::Initialize(bool may_create) { | 222 bool CrashReportDatabaseMac::Initialize(bool may_create) { |
213 INITIALIZATION_STATE_SET_INITIALIZING(initialized_); | 223 INITIALIZATION_STATE_SET_INITIALIZING(initialized_); |
214 | 224 |
215 // Check if the database already exists. | 225 // Check if the database already exists. |
216 if (may_create) { | 226 if (may_create) { |
217 if (!CreateOrEnsureDirectoryExists(base_dir_)) { | 227 if (!CreateOrEnsureDirectoryExists(base_dir_)) { |
218 return false; | 228 return false; |
219 } | 229 } |
220 } else if (!EnsureDirectoryExists(base_dir_)) { | 230 } else if (!EnsureDirectoryExists(base_dir_)) { |
221 return false; | 231 return false; |
222 } | 232 } |
223 | 233 |
224 // Create the three processing directories for the database. | 234 // Create the three processing directories for the database. |
225 for (size_t i = 0; i < arraysize(kReportDirectories); ++i) { | 235 for (size_t i = 0; i < arraysize(kReportDirectories); ++i) { |
226 if (!CreateOrEnsureDirectoryExists(base_dir_.Append(kReportDirectories[i]))) | 236 if (!CreateOrEnsureDirectoryExists(base_dir_.Append(kReportDirectories[i]))) |
227 return false; | 237 return false; |
228 } | 238 } |
229 | 239 |
230 if (!settings_.Initialize()) | 240 if (!settings_.Initialize()) |
231 return false; | 241 return false; |
232 | 242 |
233 // Write an xattr as the last step, to ensure the filesystem has support for | 243 // Do an xattr operation as the last step, to ensure the filesystem has |
234 // them. This attribute will never be read. | 244 // support for them. This xattr also serves as a marker for whether the |
235 if (!WriteXattrBool(base_dir_, XattrName(kXattrDatabaseInitialized), true)) | 245 // database uses old or new xattr names. |
236 return false; | 246 bool value; |
247 if (ReadXattrBool(base_dir_, | |
248 XattrNameInternal(kXattrDatabaseInitialized, true), | |
249 &value) == XattrStatus::kOK && | |
250 value) { | |
251 xattr_new_names_ = true; | |
252 } else if (ReadXattrBool(base_dir_, | |
253 XattrNameInternal(kXattrDatabaseInitialized, false), | |
254 &value) == XattrStatus::kOK && | |
255 value) { | |
256 xattr_new_names_ = false; | |
257 } else { | |
258 xattr_new_names_ = true; | |
259 if (!WriteXattrBool(base_dir_, XattrName(kXattrDatabaseInitialized), true)) | |
260 return false; | |
261 } | |
237 | 262 |
238 INITIALIZATION_STATE_SET_VALID(initialized_); | 263 INITIALIZATION_STATE_SET_VALID(initialized_); |
239 return true; | 264 return true; |
240 } | 265 } |
241 | 266 |
242 Settings* CrashReportDatabaseMac::GetSettings() { | 267 Settings* CrashReportDatabaseMac::GetSettings() { |
243 INITIALIZATION_STATE_DCHECK_VALID(initialized_); | 268 INITIALIZATION_STATE_DCHECK_VALID(initialized_); |
244 return &settings_; | 269 return &settings_; |
245 } | 270 } |
246 | 271 |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
533 | 558 |
534 // static | 559 // static |
535 base::ScopedFD CrashReportDatabaseMac::ObtainReportLock( | 560 base::ScopedFD CrashReportDatabaseMac::ObtainReportLock( |
536 const base::FilePath& path) { | 561 const base::FilePath& path) { |
537 int fd = HANDLE_EINTR(open(path.value().c_str(), | 562 int fd = HANDLE_EINTR(open(path.value().c_str(), |
538 O_RDONLY | O_EXLOCK | O_NONBLOCK)); | 563 O_RDONLY | O_EXLOCK | O_NONBLOCK)); |
539 PLOG_IF(ERROR, fd < 0) << "open lock " << path.value(); | 564 PLOG_IF(ERROR, fd < 0) << "open lock " << path.value(); |
540 return base::ScopedFD(fd); | 565 return base::ScopedFD(fd); |
541 } | 566 } |
542 | 567 |
543 // static | |
544 bool CrashReportDatabaseMac::ReadReportMetadataLocked( | 568 bool CrashReportDatabaseMac::ReadReportMetadataLocked( |
545 const base::FilePath& path, Report* report) { | 569 const base::FilePath& path, Report* report) { |
546 std::string uuid_string; | 570 std::string uuid_string; |
547 if (ReadXattr(path, XattrName(kXattrUUID), | 571 if (ReadXattr(path, XattrName(kXattrUUID), |
548 &uuid_string) != XattrStatus::kOK || | 572 &uuid_string) != XattrStatus::kOK || |
549 !report->uuid.InitializeFromString(uuid_string)) { | 573 !report->uuid.InitializeFromString(uuid_string)) { |
550 return false; | 574 return false; |
551 } | 575 } |
552 | 576 |
553 if (ReadXattrTimeT(path, XattrName(kXattrCreationTime), | 577 if (ReadXattrTimeT(path, XattrName(kXattrCreationTime), |
(...skipping 22 matching lines...) Expand all Loading... | |
576 | 600 |
577 report->upload_attempts = 0; | 601 report->upload_attempts = 0; |
578 if (ReadXattrInt(path, XattrName(kXattrUploadAttemptCount), | 602 if (ReadXattrInt(path, XattrName(kXattrUploadAttemptCount), |
579 &report->upload_attempts) == XattrStatus::kOtherError) { | 603 &report->upload_attempts) == XattrStatus::kOtherError) { |
580 return false; | 604 return false; |
581 } | 605 } |
582 | 606 |
583 return true; | 607 return true; |
584 } | 608 } |
585 | 609 |
586 // static | |
587 CrashReportDatabase::OperationStatus CrashReportDatabaseMac::ReportsInDirectory( | 610 CrashReportDatabase::OperationStatus CrashReportDatabaseMac::ReportsInDirectory( |
588 const base::FilePath& path, | 611 const base::FilePath& path, |
589 std::vector<CrashReportDatabase::Report>* reports) { | 612 std::vector<CrashReportDatabase::Report>* reports) { |
590 base::mac::ScopedNSAutoreleasePool pool; | 613 base::mac::ScopedNSAutoreleasePool pool; |
591 | 614 |
592 DCHECK(reports->empty()); | 615 DCHECK(reports->empty()); |
593 | 616 |
594 NSError* error = nil; | 617 NSError* error = nil; |
595 NSArray* paths = [[NSFileManager defaultManager] | 618 NSArray* paths = [[NSFileManager defaultManager] |
596 contentsOfDirectoryAtPath:base::SysUTF8ToNSString(path.value()) | 619 contentsOfDirectoryAtPath:base::SysUTF8ToNSString(path.value()) |
(...skipping 16 matching lines...) Expand all Loading... | |
613 LOG(WARNING) << "Failed to read report metadata for " | 636 LOG(WARNING) << "Failed to read report metadata for " |
614 << report.file_path.value(); | 637 << report.file_path.value(); |
615 continue; | 638 continue; |
616 } | 639 } |
617 reports->push_back(report); | 640 reports->push_back(report); |
618 } | 641 } |
619 | 642 |
620 return kNoError; | 643 return kNoError; |
621 } | 644 } |
622 | 645 |
623 // static | |
624 std::string CrashReportDatabaseMac::XattrName(const base::StringPiece& name) { | 646 std::string CrashReportDatabaseMac::XattrName(const base::StringPiece& name) { |
625 return base::StringPrintf("com.googlecode.crashpad.%s", name.data()); | 647 return XattrNameInternal(name, xattr_new_names_); |
626 } | 648 } |
627 | 649 |
628 scoped_ptr<CrashReportDatabase> InitializeInternal(const base::FilePath& path, | 650 scoped_ptr<CrashReportDatabase> InitializeInternal(const base::FilePath& path, |
629 bool may_create) { | 651 bool may_create) { |
630 scoped_ptr<CrashReportDatabaseMac> database_mac( | 652 scoped_ptr<CrashReportDatabaseMac> database_mac( |
631 new CrashReportDatabaseMac(path)); | 653 new CrashReportDatabaseMac(path)); |
632 if (!database_mac->Initialize(may_create)) | 654 if (!database_mac->Initialize(may_create)) |
633 database_mac.reset(); | 655 database_mac.reset(); |
634 | 656 |
635 return scoped_ptr<CrashReportDatabase>(database_mac.release()); | 657 return scoped_ptr<CrashReportDatabase>(database_mac.release()); |
636 } | 658 } |
637 | 659 |
638 } // namespace | 660 } // namespace |
639 | 661 |
640 // static | 662 // static |
641 scoped_ptr<CrashReportDatabase> CrashReportDatabase::Initialize( | 663 scoped_ptr<CrashReportDatabase> CrashReportDatabase::Initialize( |
642 const base::FilePath& path) { | 664 const base::FilePath& path) { |
643 return InitializeInternal(path, true); | 665 return InitializeInternal(path, true); |
644 } | 666 } |
645 | 667 |
646 // static | 668 // static |
647 scoped_ptr<CrashReportDatabase> CrashReportDatabase::InitializeWithoutCreating( | 669 scoped_ptr<CrashReportDatabase> CrashReportDatabase::InitializeWithoutCreating( |
648 const base::FilePath& path) { | 670 const base::FilePath& path) { |
649 return InitializeInternal(path, false); | 671 return InitializeInternal(path, false); |
650 } | 672 } |
651 | 673 |
652 } // namespace crashpad | 674 } // namespace crashpad |
OLD | NEW |