1 /*
2 * Copyright 2013-2014, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Ingo Weinhold <ingo_weinhold@gmx.de>
7 */
8
9
10 #include <package/CommitTransactionResult.h>
11
12 #include <Message.h>
13
14 //#include <package/DaemonDefs.h>
15
16
17 namespace BPackageKit {
18
19
20 // #pragma mark - BTransactionIssue
21
22
BTransactionIssue()23 BTransactionIssue::BTransactionIssue()
24 :
25 fType(B_WRITABLE_FILE_TYPE_MISMATCH),
26 fPackageName(),
27 fPath1(),
28 fPath2(),
29 fSystemError(B_OK),
30 fExitCode(0)
31 {
32 }
33
34
BTransactionIssue(BType type,const BString & packageName,const BString & path1,const BString & path2,status_t systemError,int exitCode)35 BTransactionIssue::BTransactionIssue(BType type, const BString& packageName,
36 const BString& path1, const BString& path2, status_t systemError,
37 int exitCode)
38 :
39 fType(type),
40 fPackageName(packageName),
41 fPath1(path1),
42 fPath2(path2),
43 fSystemError(systemError),
44 fExitCode(exitCode)
45 {
46 }
47
48
BTransactionIssue(const BTransactionIssue & other)49 BTransactionIssue::BTransactionIssue(const BTransactionIssue& other)
50 {
51 *this = other;
52 }
53
54
~BTransactionIssue()55 BTransactionIssue::~BTransactionIssue()
56 {
57 }
58
59
60 BTransactionIssue::BType
Type() const61 BTransactionIssue::Type() const
62 {
63 return fType;
64 }
65
66
67 const BString&
PackageName() const68 BTransactionIssue::PackageName() const
69 {
70 return fPackageName;
71 }
72
73
74 const BString&
Path1() const75 BTransactionIssue::Path1() const
76 {
77 return fPath1;
78 }
79
80
81 const BString&
Path2() const82 BTransactionIssue::Path2() const
83 {
84 return fPath2;
85 }
86
87
88 status_t
SystemError() const89 BTransactionIssue::SystemError() const
90 {
91 return fSystemError;
92 }
93
94
95 int
ExitCode() const96 BTransactionIssue::ExitCode() const
97 {
98 return fExitCode;
99 }
100
101
102 BString
ToString() const103 BTransactionIssue::ToString() const
104 {
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;
165 case B_PRE_UNINSTALL_SCRIPT_NOT_FOUND:
166 messageTemplate = "Failed to find pre-uninstall script "
167 " \"%path1%\": %error%.";
168 break;
169 case B_STARTING_PRE_UNINSTALL_SCRIPT_FAILED:
170 messageTemplate = "Failed to run pre-uninstall script "
171 " \"%path1%\": %error%.";
172 break;
173 case B_PRE_UNINSTALL_SCRIPT_FAILED:
174 messageTemplate = "The pre-uninstall script "
175 " \"%path1%\" failed with exit code %exitCode%.";
176 break;
177 }
178
179 BString message(messageTemplate);
180 message.ReplaceAll("%path1%", fPath1)
181 .ReplaceAll("%path2%", fPath2)
182 .ReplaceAll("%error%", strerror(fSystemError))
183 .ReplaceAll("%exitCode%", BString() << fExitCode);
184 return message;
185 }
186
187
188 status_t
AddToMessage(BMessage & message) const189 BTransactionIssue::AddToMessage(BMessage& message) const
190 {
191 status_t error;
192 if ((error = message.AddInt32("type", (int32)fType)) != B_OK
193 || (error = message.AddString("package", fPackageName)) != B_OK
194 || (error = message.AddString("path1", fPath1)) != B_OK
195 || (error = message.AddString("path2", fPath2)) != B_OK
196 || (error = message.AddInt32("system error", (int32)fSystemError))
197 != B_OK
198 || (error = message.AddInt32("exit code", (int32)fExitCode)) != B_OK) {
199 return error;
200 }
201
202 return B_OK;
203 }
204
205
206 status_t
ExtractFromMessage(const BMessage & message)207 BTransactionIssue::ExtractFromMessage(const BMessage& message)
208 {
209 status_t error;
210 int32 type;
211 int32 systemError;
212 int32 exitCode;
213 if ((error = message.FindInt32("type", &type)) != B_OK
214 || (error = message.FindString("package", &fPackageName)) != B_OK
215 || (error = message.FindString("path1", &fPath1)) != B_OK
216 || (error = message.FindString("path2", &fPath2)) != B_OK
217 || (error = message.FindInt32("system error", &systemError)) != B_OK
218 || (error = message.FindInt32("exit code", &exitCode)) != B_OK) {
219 return error;
220 }
221
222 fType = (BType)type;
223 fSystemError = (status_t)systemError;
224 fExitCode = (int)exitCode;
225
226 return B_OK;
227 }
228
229
230 BTransactionIssue&
operator =(const BTransactionIssue & other)231 BTransactionIssue::operator=(const BTransactionIssue& other)
232 {
233 fType = other.fType;
234 fPackageName = other.fPackageName;
235 fPath1 = other.fPath1;
236 fPath2 = other.fPath2;
237 fSystemError = other.fSystemError;
238 fExitCode = other.fExitCode;
239
240 return *this;
241 }
242
243
244 // #pragma mark - BCommitTransactionResult
245
246
BCommitTransactionResult()247 BCommitTransactionResult::BCommitTransactionResult()
248 :
249 fError(B_TRANSACTION_INTERNAL_ERROR),
250 fSystemError(B_ERROR),
251 fErrorPackage(),
252 fPath1(),
253 fPath2(),
254 fString1(),
255 fString2(),
256 fOldStateDirectory(),
257 fIssues(10, true)
258 {
259 }
260
261
BCommitTransactionResult(BTransactionError error)262 BCommitTransactionResult::BCommitTransactionResult(BTransactionError error)
263 :
264 fError(error),
265 fSystemError(B_ERROR),
266 fErrorPackage(),
267 fPath1(),
268 fPath2(),
269 fString1(),
270 fString2(),
271 fOldStateDirectory(),
272 fIssues(10, true)
273 {
274 }
275
276
BCommitTransactionResult(const BCommitTransactionResult & other)277 BCommitTransactionResult::BCommitTransactionResult(
278 const BCommitTransactionResult& other)
279 :
280 fError(B_TRANSACTION_INTERNAL_ERROR),
281 fSystemError(B_ERROR),
282 fErrorPackage(),
283 fPath1(),
284 fPath2(),
285 fString1(),
286 fString2(),
287 fOldStateDirectory(),
288 fIssues(10, true)
289 {
290 *this = other;
291 }
292
293
~BCommitTransactionResult()294 BCommitTransactionResult::~BCommitTransactionResult()
295 {
296 }
297
298
299 void
Unset()300 BCommitTransactionResult::Unset()
301 {
302 fError = B_TRANSACTION_INTERNAL_ERROR;
303 fSystemError = B_ERROR;
304 fErrorPackage.Truncate(0);
305 fPath1.Truncate(0);
306 fPath2.Truncate(0);
307 fString1.Truncate(0);
308 fString2.Truncate(0);
309 fOldStateDirectory.Truncate(0);
310 fIssues.MakeEmpty();
311 }
312
313
314 int32
CountIssues() const315 BCommitTransactionResult::CountIssues() const
316 {
317 return fIssues.CountItems();
318 }
319
320
321 const BTransactionIssue*
IssueAt(int32 index) const322 BCommitTransactionResult::IssueAt(int32 index) const
323 {
324 if (index < 0 || index >= CountIssues())
325 return NULL;
326 return fIssues.ItemAt(index);
327 }
328
329
330 bool
AddIssue(const BTransactionIssue & issue)331 BCommitTransactionResult::AddIssue(const BTransactionIssue& issue)
332 {
333 BTransactionIssue* newIssue = new(std::nothrow) BTransactionIssue(issue);
334 if (newIssue == NULL || !fIssues.AddItem(newIssue)) {
335 delete newIssue;
336 return false;
337 }
338 return true;
339 }
340
341
342 BTransactionError
Error() const343 BCommitTransactionResult::Error() const
344 {
345 return fError > 0 ? (BTransactionError)fError : B_TRANSACTION_OK;
346 }
347
348
349 void
SetError(BTransactionError error)350 BCommitTransactionResult::SetError(BTransactionError error)
351 {
352 fError = error;
353 }
354
355
356 status_t
SystemError() const357 BCommitTransactionResult::SystemError() const
358 {
359 return fSystemError;
360 }
361
362
363 void
SetSystemError(status_t error)364 BCommitTransactionResult::SetSystemError(status_t error)
365 {
366 fSystemError = error;
367 }
368
369
370 const BString&
ErrorPackage() const371 BCommitTransactionResult::ErrorPackage() const
372 {
373 return fErrorPackage;
374 }
375
376
377 void
SetErrorPackage(const BString & packageName)378 BCommitTransactionResult::SetErrorPackage(const BString& packageName)
379 {
380 fErrorPackage = packageName;
381 }
382
383
384 BString
FullErrorMessage() const385 BCommitTransactionResult::FullErrorMessage() const
386 {
387 if (fError == 0)
388 return "no error";
389
390 const char* messageTemplate = "";
391 switch ((BTransactionError)fError) {
392 case B_TRANSACTION_OK:
393 messageTemplate = "Everything went fine.";
394 break;
395 case B_TRANSACTION_NO_MEMORY:
396 messageTemplate = "Out of memory.";
397 break;
398 case B_TRANSACTION_INTERNAL_ERROR:
399 messageTemplate = "An internal error occurred. Specifics can be"
400 " found in the syslog.";
401 break;
402 case B_TRANSACTION_INSTALLATION_LOCATION_BUSY:
403 messageTemplate = "Another package operation is already in"
404 " progress.";
405 break;
406 case B_TRANSACTION_CHANGE_COUNT_MISMATCH:
407 messageTemplate = "The transaction is out of date.";
408 break;
409 case B_TRANSACTION_BAD_REQUEST:
410 messageTemplate = "The requested transaction is invalid.";
411 break;
412 case B_TRANSACTION_NO_SUCH_PACKAGE:
413 messageTemplate = "No such package \"%package%\".";
414 break;
415 case B_TRANSACTION_PACKAGE_ALREADY_EXISTS:
416 messageTemplate = "The to be activated package \"%package%\" does"
417 " already exist.";
418 break;
419 case B_TRANSACTION_FAILED_TO_GET_ENTRY_PATH:
420 if (fPath1.IsEmpty()) {
421 if (fErrorPackage.IsEmpty()) {
422 messageTemplate = "A file path could not be determined:"
423 "%error%";
424 } else {
425 messageTemplate = "While processing package \"%package%\""
426 " a file path could not be determined: %error%";
427 }
428 } else {
429 if (fErrorPackage.IsEmpty()) {
430 messageTemplate = "The file path for \"%path1%\" could not"
431 " be determined: %error%";
432 } else {
433 messageTemplate = "While processing package \"%package%\""
434 " the file path for \"%path1%\" could not be"
435 " determined: %error%";
436 }
437 }
438 break;
439 case B_TRANSACTION_FAILED_TO_OPEN_DIRECTORY:
440 messageTemplate = "Failed to open directory \"%path1%\": %error%";
441 break;
442 case B_TRANSACTION_FAILED_TO_CREATE_DIRECTORY:
443 messageTemplate = "Failed to create directory \"%path1%\": %error%";
444 break;
445 case B_TRANSACTION_FAILED_TO_REMOVE_DIRECTORY:
446 messageTemplate = "Failed to remove directory \"%path1%\": %error%";
447 break;
448 case B_TRANSACTION_FAILED_TO_MOVE_DIRECTORY:
449 messageTemplate = "Failed to move directory \"%path1%\" to"
450 " \"%path2%\": %error%";
451 break;
452 case B_TRANSACTION_FAILED_TO_WRITE_ACTIVATION_FILE:
453 messageTemplate = "Failed to write new package activation file"
454 " \"%path1%\": %error%";
455 break;
456 case B_TRANSACTION_FAILED_TO_READ_PACKAGE_FILE:
457 messageTemplate = "Failed to read package file \"%path1%\":"
458 " %error%";
459 break;
460 case B_TRANSACTION_FAILED_TO_EXTRACT_PACKAGE_FILE:
461 messageTemplate = "Failed to extract \"%path1%\" from package"
462 " \"%package%\": %error%";
463 break;
464 case B_TRANSACTION_FAILED_TO_OPEN_FILE:
465 messageTemplate = "Failed to open file \"%path1%\": %error%";
466 break;
467 case B_TRANSACTION_FAILED_TO_MOVE_FILE:
468 messageTemplate = "Failed to move file \"%path1%\" to \"%path2%\":"
469 " %error%";
470 break;
471 case B_TRANSACTION_FAILED_TO_COPY_FILE:
472 messageTemplate = "Failed to copy file \"%path1%\" to \"%path2%\":"
473 " %error%";
474 break;
475 case B_TRANSACTION_FAILED_TO_WRITE_FILE_ATTRIBUTE:
476 messageTemplate = "Failed to write attribute \"%string1%\" of file"
477 " \"%path1%\": %error%";
478 break;
479 case B_TRANSACTION_FAILED_TO_ACCESS_ENTRY:
480 messageTemplate = "Failed to access entry \"%path1%\": %error%";
481 break;
482 case B_TRANSACTION_FAILED_TO_ADD_GROUP:
483 messageTemplate = "Failed to add user group \"%string1%\" required"
484 " by package \"%package%\".";
485 break;
486 case B_TRANSACTION_FAILED_TO_ADD_USER:
487 messageTemplate = "Failed to add user \"%string1%\" required"
488 " by package \"%package%\".";
489 break;
490 case B_TRANSACTION_FAILED_TO_ADD_USER_TO_GROUP:
491 messageTemplate = "Failed to add user \"%string1%\" to group"
492 " \"%string2%\" as required by package \"%package%\".";
493 break;
494 case B_TRANSACTION_FAILED_TO_CHANGE_PACKAGE_ACTIVATION:
495 messageTemplate = "Failed to change the package activation in"
496 " packagefs: %error%";
497 break;
498 }
499
500 BString message(messageTemplate);
501 message.ReplaceAll("%package%", fErrorPackage)
502 .ReplaceAll("%path1%", fPath1)
503 .ReplaceAll("%path2%", fPath2)
504 .ReplaceAll("%string1%", fString1)
505 .ReplaceAll("%string2%", fString2)
506 .ReplaceAll("%error%", strerror(fSystemError));
507 return message;
508 }
509
510
511 const BString&
Path1() const512 BCommitTransactionResult::Path1() const
513 {
514 return fPath1;
515 }
516
517
518 void
SetPath1(const BString & path)519 BCommitTransactionResult::SetPath1(const BString& path)
520 {
521 fPath1 = path;
522 }
523
524
525 const BString&
Path2() const526 BCommitTransactionResult::Path2() const
527 {
528 return fPath2;
529 }
530
531
532 void
SetPath2(const BString & path)533 BCommitTransactionResult::SetPath2(const BString& path)
534 {
535 fPath2 = path;
536 }
537
538
539 const BString&
String1() const540 BCommitTransactionResult::String1() const
541 {
542 return fString1;
543 }
544
545
546 void
SetString1(const BString & string)547 BCommitTransactionResult::SetString1(const BString& string)
548 {
549 fString1 = string;
550 }
551
552
553 const BString&
String2() const554 BCommitTransactionResult::String2() const
555 {
556 return fString2;
557 }
558
559
560 void
SetString2(const BString & string)561 BCommitTransactionResult::SetString2(const BString& string)
562 {
563 fString2 = string;
564 }
565
566
567 const BString&
OldStateDirectory() const568 BCommitTransactionResult::OldStateDirectory() const
569 {
570 return fOldStateDirectory;
571 }
572
573
574 void
SetOldStateDirectory(const BString & directory)575 BCommitTransactionResult::SetOldStateDirectory(const BString& directory)
576 {
577 fOldStateDirectory = directory;
578 }
579
580
581 status_t
AddToMessage(BMessage & message) const582 BCommitTransactionResult::AddToMessage(BMessage& message) const
583 {
584 status_t error;
585 if ((error = message.AddInt32("error", (int32)fError)) != B_OK
586 || (error = message.AddInt32("system error", (int32)fSystemError))
587 != B_OK
588 || (error = message.AddString("error package", fErrorPackage)) != B_OK
589 || (error = message.AddString("path1", fPath1)) != B_OK
590 || (error = message.AddString("path2", fPath2)) != B_OK
591 || (error = message.AddString("string1", fString1)) != B_OK
592 || (error = message.AddString("string2", fString2)) != B_OK
593 || (error = message.AddString("old state", fOldStateDirectory))
594 != B_OK) {
595 return error;
596 }
597
598 int32 count = fIssues.CountItems();
599 for (int32 i = 0; i < count; i++) {
600 const BTransactionIssue* issue = fIssues.ItemAt(i);
601 BMessage issueMessage;
602 if ((error = issue->AddToMessage(issueMessage)) != B_OK
603 || (error = message.AddMessage("issues", &issueMessage)) != B_OK) {
604 return error;
605 }
606 }
607
608 return B_OK;
609 }
610
611
612 status_t
ExtractFromMessage(const BMessage & message)613 BCommitTransactionResult::ExtractFromMessage(const BMessage& message)
614 {
615 Unset();
616
617 int32 resultError;
618 int32 systemError;
619 status_t error;
620 if ((error = message.FindInt32("error", &resultError)) != B_OK
621 || (error = message.FindInt32("system error", &systemError)) != B_OK
622 || (error = message.FindString("error package", &fErrorPackage)) != B_OK
623 || (error = message.FindString("path1", &fPath1)) != B_OK
624 || (error = message.FindString("path2", &fPath2)) != B_OK
625 || (error = message.FindString("string1", &fString1)) != B_OK
626 || (error = message.FindString("string2", &fString2)) != B_OK
627 || (error = message.FindString("old state", &fOldStateDirectory))
628 != B_OK) {
629 return error;
630 }
631
632 fError = (BTransactionError)resultError;
633 fSystemError = (status_t)systemError;
634
635 BMessage issueMessage;
636 for (int32 i = 0; message.FindMessage("issues", i, &issueMessage) == B_OK;
637 i++) {
638 BTransactionIssue issue;
639 error = issue.ExtractFromMessage(issueMessage);
640 if (error != B_OK)
641 return error;
642
643 if (!AddIssue(issue))
644 return B_NO_MEMORY;
645 }
646
647 return B_OK;
648 }
649
650
651 BCommitTransactionResult&
operator =(const BCommitTransactionResult & other)652 BCommitTransactionResult::operator=(const BCommitTransactionResult& other)
653 {
654 Unset();
655
656 fError = other.fError;
657 fSystemError = other.fSystemError;
658 fErrorPackage = other.fErrorPackage;
659 fPath1 = other.fPath1;
660 fPath2 = other.fPath2;
661 fString1 = other.fString1;
662 fString2 = other.fString2;
663 fOldStateDirectory = other.fOldStateDirectory;
664
665 for (int32 i = 0; const BTransactionIssue* issue = other.fIssues.ItemAt(i);
666 i++) {
667 AddIssue(*issue);
668 }
669
670 return *this;
671 }
672
673
674 } // namespace BPackageKit
675