vfs: check userland buffers before reading them.
[haiku.git] / src / kits / package / CommitTransactionResult.cpp
blob0429e5f93e88ef97b686f39107839aa3dcd73f53
1 /*
2 * Copyright 2013-2014, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Ingo Weinhold <ingo_weinhold@gmx.de>
7 */
10 #include <package/CommitTransactionResult.h>
12 #include <Message.h>
14 //#include <package/DaemonDefs.h>
17 namespace BPackageKit {
20 // #pragma mark - BTransactionIssue
23 BTransactionIssue::BTransactionIssue()
25 fType(B_WRITABLE_FILE_TYPE_MISMATCH),
26 fPackageName(),
27 fPath1(),
28 fPath2(),
29 fSystemError(B_OK),
30 fExitCode(0)
35 BTransactionIssue::BTransactionIssue(BType type, const BString& packageName,
36 const BString& path1, const BString& path2, status_t systemError,
37 int exitCode)
39 fType(type),
40 fPackageName(packageName),
41 fPath1(path1),
42 fPath2(path2),
43 fSystemError(systemError),
44 fExitCode(exitCode)
49 BTransactionIssue::BTransactionIssue(const BTransactionIssue& other)
51 *this = other;
55 BTransactionIssue::~BTransactionIssue()
60 BTransactionIssue::BType
61 BTransactionIssue::Type() const
63 return fType;
67 const BString&
68 BTransactionIssue::PackageName() const
70 return fPackageName;
74 const BString&
75 BTransactionIssue::Path1() const
77 return fPath1;
81 const BString&
82 BTransactionIssue::Path2() const
84 return fPath2;
88 status_t
89 BTransactionIssue::SystemError() const
91 return fSystemError;
95 int
96 BTransactionIssue::ExitCode() const
98 return fExitCode;
102 BString
103 BTransactionIssue::ToString() const
105 const char* messageTemplate = "";
106 switch (fType) {
107 case B_WRITABLE_FILE_TYPE_MISMATCH:
108 messageTemplate = "\"%path1%\" cannot be updated automatically,"
109 " since its type doesn't match the type of \"%path2%\" which it"
110 " is supposed to be updated with."
111 " Please perform the update manually if needed.";
112 break;
113 case B_WRITABLE_FILE_NO_PACKAGE_ATTRIBUTE:
114 messageTemplate = "\"%path1%\" cannot be updated automatically,"
115 " since it doesn't have a SYS:PACKAGE attribute."
116 " Please perform the update manually if needed.";
117 break;
118 case B_WRITABLE_FILE_OLD_ORIGINAL_FILE_MISSING:
119 messageTemplate = "\"%path1%\" cannot be updated automatically,"
120 " since \"%path2%\" which we need to compare it with is"
121 " missing."
122 " Please perform the update manually if needed.";
123 break;
124 case B_WRITABLE_FILE_OLD_ORIGINAL_FILE_TYPE_MISMATCH:
125 messageTemplate = "\"%path1%\" cannot be updated automatically,"
126 " since its type doesn't match the type of \"%path2%\" which we"
127 " need to compare it with."
128 " Please perform the update manually if needed.";
129 break;
130 case B_WRITABLE_FILE_COMPARISON_FAILED:
131 messageTemplate = "\"%path1%\" cannot be updated automatically,"
132 " since the comparison with \"%path2%\" failed: %error%."
133 " Please perform the update manually if needed.";
134 break;
135 case B_WRITABLE_FILE_NOT_EQUAL: // !keep old
136 messageTemplate = "\"%path1%\" cannot be updated automatically,"
137 " since it was changed manually from previous version"
138 " \"%path2%\"."
139 " Please perform the update manually if needed.";
140 break;
141 case B_WRITABLE_SYMLINK_COMPARISON_FAILED: // !keep old
142 messageTemplate = "Symbolic link \"%path1%\" cannot be updated"
143 " automatically, since the comparison with \"%path2%\" failed:"
144 " %error%."
145 " Please perform the update manually if needed.";
146 break;
147 case B_WRITABLE_SYMLINK_NOT_EQUAL: // !keep old
148 messageTemplate = "Symbolic link \"%path1%\" cannot be updated"
149 " automatically, since it was changed manually from previous"
150 " version \"%path2%\"."
151 " Please perform the update manually if needed.";
152 break;
153 case B_POST_INSTALL_SCRIPT_NOT_FOUND:
154 messageTemplate = "Failed to find post-installation script "
155 " \"%path1%\": %error%.";
156 break;
157 case B_STARTING_POST_INSTALL_SCRIPT_FAILED:
158 messageTemplate = "Failed to run post-installation script "
159 " \"%path1%\": %error%.";
160 break;
161 case B_POST_INSTALL_SCRIPT_FAILED:
162 messageTemplate = "The post-installation script "
163 " \"%path1%\" failed with exit code %exitCode%.";
164 break;
167 BString message(messageTemplate);
168 message.ReplaceAll("%path1%", fPath1)
169 .ReplaceAll("%path2%", fPath2)
170 .ReplaceAll("%error%", strerror(fSystemError))
171 .ReplaceAll("%exitCode%", BString() << fExitCode);
172 return message;
176 status_t
177 BTransactionIssue::AddToMessage(BMessage& message) const
179 status_t error;
180 if ((error = message.AddInt32("type", (int32)fType)) != B_OK
181 || (error = message.AddString("package", fPackageName)) != B_OK
182 || (error = message.AddString("path1", fPath1)) != B_OK
183 || (error = message.AddString("path2", fPath2)) != B_OK
184 || (error = message.AddInt32("system error", (int32)fSystemError))
185 != B_OK
186 || (error = message.AddInt32("exit code", (int32)fExitCode)) != B_OK) {
187 return error;
190 return B_OK;
194 status_t
195 BTransactionIssue::ExtractFromMessage(const BMessage& message)
197 status_t error;
198 int32 type;
199 int32 systemError;
200 int32 exitCode;
201 if ((error = message.FindInt32("type", &type)) != B_OK
202 || (error = message.FindString("package", &fPackageName)) != B_OK
203 || (error = message.FindString("path1", &fPath1)) != B_OK
204 || (error = message.FindString("path2", &fPath2)) != B_OK
205 || (error = message.FindInt32("system error", &systemError)) != B_OK
206 || (error = message.FindInt32("exit code", &exitCode)) != B_OK) {
207 return error;
210 fType = (BType)type;
211 fSystemError = (status_t)systemError;
212 fExitCode = (int)exitCode;
214 return B_OK;
218 BTransactionIssue&
219 BTransactionIssue::operator=(const BTransactionIssue& other)
221 fType = other.fType;
222 fPackageName = other.fPackageName;
223 fPath1 = other.fPath1;
224 fPath2 = other.fPath2;
225 fSystemError = other.fSystemError;
226 fExitCode = other.fExitCode;
228 return *this;
232 // #pragma mark - BCommitTransactionResult
235 BCommitTransactionResult::BCommitTransactionResult()
237 fError(B_TRANSACTION_INTERNAL_ERROR),
238 fSystemError(B_ERROR),
239 fErrorPackage(),
240 fPath1(),
241 fPath2(),
242 fString1(),
243 fString2(),
244 fOldStateDirectory(),
245 fIssues(10, true)
250 BCommitTransactionResult::BCommitTransactionResult(BTransactionError error)
252 fError(error),
253 fSystemError(B_ERROR),
254 fErrorPackage(),
255 fPath1(),
256 fPath2(),
257 fString1(),
258 fString2(),
259 fOldStateDirectory(),
260 fIssues(10, true)
265 BCommitTransactionResult::BCommitTransactionResult(
266 const BCommitTransactionResult& other)
268 fError(B_TRANSACTION_INTERNAL_ERROR),
269 fSystemError(B_ERROR),
270 fErrorPackage(),
271 fPath1(),
272 fPath2(),
273 fString1(),
274 fString2(),
275 fOldStateDirectory(),
276 fIssues(10, true)
278 *this = other;
282 BCommitTransactionResult::~BCommitTransactionResult()
287 void
288 BCommitTransactionResult::Unset()
290 fError = B_TRANSACTION_INTERNAL_ERROR;
291 fSystemError = B_ERROR;
292 fErrorPackage.Truncate(0);
293 fPath1.Truncate(0);
294 fPath2.Truncate(0);
295 fString1.Truncate(0);
296 fString2.Truncate(0);
297 fOldStateDirectory.Truncate(0);
298 fIssues.MakeEmpty();
302 int32
303 BCommitTransactionResult::CountIssues() const
305 return fIssues.CountItems();
309 const BTransactionIssue*
310 BCommitTransactionResult::IssueAt(int32 index) const
312 if (index < 0 || index >= CountIssues())
313 return NULL;
314 return fIssues.ItemAt(index);
318 bool
319 BCommitTransactionResult::AddIssue(const BTransactionIssue& issue)
321 BTransactionIssue* newIssue = new(std::nothrow) BTransactionIssue(issue);
322 if (newIssue == NULL || !fIssues.AddItem(newIssue)) {
323 delete newIssue;
324 return false;
326 return true;
330 BTransactionError
331 BCommitTransactionResult::Error() const
333 return fError > 0 ? (BTransactionError)fError : B_TRANSACTION_OK;
337 void
338 BCommitTransactionResult::SetError(BTransactionError error)
340 fError = error;
344 status_t
345 BCommitTransactionResult::SystemError() const
347 return fSystemError;
351 void
352 BCommitTransactionResult::SetSystemError(status_t error)
354 fSystemError = error;
358 const BString&
359 BCommitTransactionResult::ErrorPackage() const
361 return fErrorPackage;
365 void
366 BCommitTransactionResult::SetErrorPackage(const BString& packageName)
368 fErrorPackage = packageName;
372 BString
373 BCommitTransactionResult::FullErrorMessage() const
375 if (fError == 0)
376 return "no error";
378 const char* messageTemplate = "";
379 switch ((BTransactionError)fError) {
380 case B_TRANSACTION_OK:
381 messageTemplate = "Everything went fine.";
382 break;
383 case B_TRANSACTION_NO_MEMORY:
384 messageTemplate = "Out of memory.";
385 break;
386 case B_TRANSACTION_INTERNAL_ERROR:
387 messageTemplate = "An internal error occurred. Specifics can be"
388 " found in the syslog.";
389 break;
390 case B_TRANSACTION_INSTALLATION_LOCATION_BUSY:
391 messageTemplate = "Another package operation is already in"
392 " progress.";
393 break;
394 case B_TRANSACTION_CHANGE_COUNT_MISMATCH:
395 messageTemplate = "The transaction is out of date.";
396 break;
397 case B_TRANSACTION_BAD_REQUEST:
398 messageTemplate = "The requested transaction is invalid.";
399 break;
400 case B_TRANSACTION_NO_SUCH_PACKAGE:
401 messageTemplate = "No such package \"%package%\".";
402 break;
403 case B_TRANSACTION_PACKAGE_ALREADY_EXISTS:
404 messageTemplate = "The to be activated package \"%package%\" does"
405 " already exist.";
406 break;
407 case B_TRANSACTION_FAILED_TO_GET_ENTRY_PATH:
408 if (fPath1.IsEmpty()) {
409 if (fErrorPackage.IsEmpty()) {
410 messageTemplate = "A file path could not be determined:"
411 "%error%";
412 } else {
413 messageTemplate = "While processing package \"%package%\""
414 " a file path could not be determined: %error%";
416 } else {
417 if (fErrorPackage.IsEmpty()) {
418 messageTemplate = "The file path for \"%path1%\" could not"
419 " be determined: %error%";
420 } else {
421 messageTemplate = "While processing package \"%package%\""
422 " the file path for \"%path1%\" could not be"
423 " determined: %error%";
426 break;
427 case B_TRANSACTION_FAILED_TO_OPEN_DIRECTORY:
428 messageTemplate = "Failed to open directory \"%path1%\": %error%";
429 break;
430 case B_TRANSACTION_FAILED_TO_CREATE_DIRECTORY:
431 messageTemplate = "Failed to create directory \"%path1%\": %error%";
432 break;
433 case B_TRANSACTION_FAILED_TO_REMOVE_DIRECTORY:
434 messageTemplate = "Failed to remove directory \"%path1%\": %error%";
435 break;
436 case B_TRANSACTION_FAILED_TO_MOVE_DIRECTORY:
437 messageTemplate = "Failed to move directory \"%path1%\" to"
438 " \"%path2%\": %error%";
439 break;
440 case B_TRANSACTION_FAILED_TO_WRITE_ACTIVATION_FILE:
441 messageTemplate = "Failed to write new package activation file"
442 " \"%path1%\": %error%";
443 break;
444 case B_TRANSACTION_FAILED_TO_READ_PACKAGE_FILE:
445 messageTemplate = "Failed to read package file \"%path1%\":"
446 " %error%";
447 break;
448 case B_TRANSACTION_FAILED_TO_EXTRACT_PACKAGE_FILE:
449 messageTemplate = "Failed to extract \"%path1%\" from package"
450 " \"%package%\": %error%";
451 break;
452 case B_TRANSACTION_FAILED_TO_OPEN_FILE:
453 messageTemplate = "Failed to open file \"%path1%\": %error%";
454 break;
455 case B_TRANSACTION_FAILED_TO_MOVE_FILE:
456 messageTemplate = "Failed to move file \"%path1%\" to \"%path2%\":"
457 " %error%";
458 break;
459 case B_TRANSACTION_FAILED_TO_COPY_FILE:
460 messageTemplate = "Failed to copy file \"%path1%\" to \"%path2%\":"
461 " %error%";
462 break;
463 case B_TRANSACTION_FAILED_TO_WRITE_FILE_ATTRIBUTE:
464 messageTemplate = "Failed to write attribute \"%string1%\" of file"
465 " \"%path1%\": %error%";
466 break;
467 case B_TRANSACTION_FAILED_TO_ACCESS_ENTRY:
468 messageTemplate = "Failed to access entry \"%path1%\": %error%";
469 break;
470 case B_TRANSACTION_FAILED_TO_ADD_GROUP:
471 messageTemplate = "Failed to add user group \"%string1%\" required"
472 " by package \"%package%\".";
473 break;
474 case B_TRANSACTION_FAILED_TO_ADD_USER:
475 messageTemplate = "Failed to add user \"%string1%\" required"
476 " by package \"%package%\".";
477 break;
478 case B_TRANSACTION_FAILED_TO_ADD_USER_TO_GROUP:
479 messageTemplate = "Failed to add user \"%string1%\" to group"
480 " \"%string2%\" as required by package \"%package%\".";
481 break;
482 case B_TRANSACTION_FAILED_TO_CHANGE_PACKAGE_ACTIVATION:
483 messageTemplate = "Failed to change the package activation in"
484 " packagefs: %error%";
485 break;
488 BString message(messageTemplate);
489 message.ReplaceAll("%package%", fErrorPackage)
490 .ReplaceAll("%path1%", fPath1)
491 .ReplaceAll("%path2%", fPath2)
492 .ReplaceAll("%string1%", fString1)
493 .ReplaceAll("%string2%", fString2)
494 .ReplaceAll("%error%", strerror(fSystemError));
495 return message;
499 const BString&
500 BCommitTransactionResult::Path1() const
502 return fPath1;
506 void
507 BCommitTransactionResult::SetPath1(const BString& path)
509 fPath1 = path;
513 const BString&
514 BCommitTransactionResult::Path2() const
516 return fPath2;
520 void
521 BCommitTransactionResult::SetPath2(const BString& path)
523 fPath2 = path;
527 const BString&
528 BCommitTransactionResult::String1() const
530 return fString1;
534 void
535 BCommitTransactionResult::SetString1(const BString& string)
537 fString1 = string;
541 const BString&
542 BCommitTransactionResult::String2() const
544 return fString2;
548 void
549 BCommitTransactionResult::SetString2(const BString& string)
551 fString2 = string;
555 const BString&
556 BCommitTransactionResult::OldStateDirectory() const
558 return fOldStateDirectory;
562 void
563 BCommitTransactionResult::SetOldStateDirectory(const BString& directory)
565 fOldStateDirectory = directory;
569 status_t
570 BCommitTransactionResult::AddToMessage(BMessage& message) const
572 status_t error;
573 if ((error = message.AddInt32("error", (int32)fError)) != B_OK
574 || (error = message.AddInt32("system error", (int32)fSystemError))
575 != B_OK
576 || (error = message.AddString("error package", fErrorPackage)) != B_OK
577 || (error = message.AddString("path1", fPath1)) != B_OK
578 || (error = message.AddString("path2", fPath2)) != B_OK
579 || (error = message.AddString("string1", fString1)) != B_OK
580 || (error = message.AddString("string2", fString2)) != B_OK
581 || (error = message.AddString("old state", fOldStateDirectory))
582 != B_OK) {
583 return error;
586 int32 count = fIssues.CountItems();
587 for (int32 i = 0; i < count; i++) {
588 const BTransactionIssue* issue = fIssues.ItemAt(i);
589 BMessage issueMessage;
590 if ((error = issue->AddToMessage(issueMessage)) != B_OK
591 || (error = message.AddMessage("issues", &issueMessage)) != B_OK) {
592 return error;
596 return B_OK;
600 status_t
601 BCommitTransactionResult::ExtractFromMessage(const BMessage& message)
603 Unset();
605 int32 resultError;
606 int32 systemError;
607 status_t error;
608 if ((error = message.FindInt32("error", &resultError)) != B_OK
609 || (error = message.FindInt32("system error", &systemError)) != B_OK
610 || (error = message.FindString("error package", &fErrorPackage)) != B_OK
611 || (error = message.FindString("path1", &fPath1)) != B_OK
612 || (error = message.FindString("path2", &fPath2)) != B_OK
613 || (error = message.FindString("string1", &fString1)) != B_OK
614 || (error = message.FindString("string2", &fString2)) != B_OK
615 || (error = message.FindString("old state", &fOldStateDirectory))
616 != B_OK) {
617 return error;
620 fError = (BTransactionError)resultError;
621 fSystemError = (status_t)systemError;
623 BMessage issueMessage;
624 for (int32 i = 0; message.FindMessage("issues", i, &issueMessage) == B_OK;
625 i++) {
626 BTransactionIssue issue;
627 error = issue.ExtractFromMessage(issueMessage);
628 if (error != B_OK)
629 return error;
631 if (!AddIssue(issue))
632 return B_NO_MEMORY;
635 return B_OK;
639 BCommitTransactionResult&
640 BCommitTransactionResult::operator=(const BCommitTransactionResult& other)
642 Unset();
644 fError = other.fError;
645 fSystemError = other.fSystemError;
646 fErrorPackage = other.fErrorPackage;
647 fPath1 = other.fPath1;
648 fPath2 = other.fPath2;
649 fString1 = other.fString1;
650 fString2 = other.fString2;
651 fOldStateDirectory = other.fOldStateDirectory;
653 for (int32 i = 0; const BTransactionIssue* issue = other.fIssues.ItemAt(i);
654 i++) {
655 AddIssue(*issue);
658 return *this;
662 } // namespace BPackageKit