xref: /haiku/src/kits/package/CommitTransactionResult.cpp (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
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 
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 
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 
49 BTransactionIssue::BTransactionIssue(const BTransactionIssue& other)
50 {
51 	*this = other;
52 }
53 
54 
55 BTransactionIssue::~BTransactionIssue()
56 {
57 }
58 
59 
60 BTransactionIssue::BType
61 BTransactionIssue::Type() const
62 {
63 	return fType;
64 }
65 
66 
67 const BString&
68 BTransactionIssue::PackageName() const
69 {
70 	return fPackageName;
71 }
72 
73 
74 const BString&
75 BTransactionIssue::Path1() const
76 {
77 	return fPath1;
78 }
79 
80 
81 const BString&
82 BTransactionIssue::Path2() const
83 {
84 	return fPath2;
85 }
86 
87 
88 status_t
89 BTransactionIssue::SystemError() const
90 {
91 	return fSystemError;
92 }
93 
94 
95 int
96 BTransactionIssue::ExitCode() const
97 {
98 	return fExitCode;
99 }
100 
101 
102 BString
103 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 	}
166 
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;
173 }
174 
175 
176 status_t
177 BTransactionIssue::AddToMessage(BMessage& message) const
178 {
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;
188 	}
189 
190 	return B_OK;
191 }
192 
193 
194 status_t
195 BTransactionIssue::ExtractFromMessage(const BMessage& message)
196 {
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;
208 	}
209 
210 	fType = (BType)type;
211 	fSystemError = (status_t)systemError;
212 	fExitCode = (int)exitCode;
213 
214 	return B_OK;
215 }
216 
217 
218 BTransactionIssue&
219 BTransactionIssue::operator=(const BTransactionIssue& other)
220 {
221 	fType = other.fType;
222 	fPackageName = other.fPackageName;
223 	fPath1 = other.fPath1;
224 	fPath2 = other.fPath2;
225  	fSystemError = other.fSystemError;
226 	fExitCode = other.fExitCode;
227 
228 	return *this;
229 }
230 
231 
232 // #pragma mark - BCommitTransactionResult
233 
234 
235 BCommitTransactionResult::BCommitTransactionResult()
236 	:
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)
246 {
247 }
248 
249 
250 BCommitTransactionResult::BCommitTransactionResult(BTransactionError error)
251 	:
252 	fError(error),
253 	fSystemError(B_ERROR),
254 	fErrorPackage(),
255 	fPath1(),
256 	fPath2(),
257 	fString1(),
258 	fString2(),
259 	fOldStateDirectory(),
260 	fIssues(10, true)
261 {
262 }
263 
264 
265 BCommitTransactionResult::BCommitTransactionResult(
266 	const BCommitTransactionResult& other)
267 	:
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)
277 {
278 	*this = other;
279 }
280 
281 
282 BCommitTransactionResult::~BCommitTransactionResult()
283 {
284 }
285 
286 
287 void
288 BCommitTransactionResult::Unset()
289 {
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();
299 }
300 
301 
302 int32
303 BCommitTransactionResult::CountIssues() const
304 {
305 	return fIssues.CountItems();
306 }
307 
308 
309 const BTransactionIssue*
310 BCommitTransactionResult::IssueAt(int32 index) const
311 {
312 	if (index < 0 || index >= CountIssues())
313 		return NULL;
314 	return fIssues.ItemAt(index);
315 }
316 
317 
318 bool
319 BCommitTransactionResult::AddIssue(const BTransactionIssue& issue)
320 {
321 	BTransactionIssue* newIssue = new(std::nothrow) BTransactionIssue(issue);
322 	if (newIssue == NULL || !fIssues.AddItem(newIssue)) {
323 		delete newIssue;
324 		return false;
325 	}
326 	return true;
327 }
328 
329 
330 BTransactionError
331 BCommitTransactionResult::Error() const
332 {
333 	return fError > 0 ? (BTransactionError)fError : B_TRANSACTION_OK;
334 }
335 
336 
337 void
338 BCommitTransactionResult::SetError(BTransactionError error)
339 {
340 	fError = error;
341 }
342 
343 
344 status_t
345 BCommitTransactionResult::SystemError() const
346 {
347 	return fSystemError;
348 }
349 
350 
351 void
352 BCommitTransactionResult::SetSystemError(status_t error)
353 {
354 	fSystemError = error;
355 }
356 
357 
358 const BString&
359 BCommitTransactionResult::ErrorPackage() const
360 {
361 	return fErrorPackage;
362 }
363 
364 
365 void
366 BCommitTransactionResult::SetErrorPackage(const BString& packageName)
367 {
368 	fErrorPackage = packageName;
369 }
370 
371 
372 BString
373 BCommitTransactionResult::FullErrorMessage() const
374 {
375 	if (fError == 0)
376 		return "no error";
377 
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%";
415 				}
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%";
424 				}
425 			}
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;
486 	}
487 
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;
496 }
497 
498 
499 const BString&
500 BCommitTransactionResult::Path1() const
501 {
502 	return fPath1;
503 }
504 
505 
506 void
507 BCommitTransactionResult::SetPath1(const BString& path)
508 {
509 	fPath1 = path;
510 }
511 
512 
513 const BString&
514 BCommitTransactionResult::Path2() const
515 {
516 	return fPath2;
517 }
518 
519 
520 void
521 BCommitTransactionResult::SetPath2(const BString& path)
522 {
523 	fPath2 = path;
524 }
525 
526 
527 const BString&
528 BCommitTransactionResult::String1() const
529 {
530 	return fString1;
531 }
532 
533 
534 void
535 BCommitTransactionResult::SetString1(const BString& string)
536 {
537 	fString1 = string;
538 }
539 
540 
541 const BString&
542 BCommitTransactionResult::String2() const
543 {
544 	return fString2;
545 }
546 
547 
548 void
549 BCommitTransactionResult::SetString2(const BString& string)
550 {
551 	fString2 = string;
552 }
553 
554 
555 const BString&
556 BCommitTransactionResult::OldStateDirectory() const
557 {
558 	return fOldStateDirectory;
559 }
560 
561 
562 void
563 BCommitTransactionResult::SetOldStateDirectory(const BString& directory)
564 {
565 	fOldStateDirectory = directory;
566 }
567 
568 
569 status_t
570 BCommitTransactionResult::AddToMessage(BMessage& message) const
571 {
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;
584 	}
585 
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;
593 		}
594 	}
595 
596 	return B_OK;
597 }
598 
599 
600 status_t
601 BCommitTransactionResult::ExtractFromMessage(const BMessage& message)
602 {
603 	Unset();
604 
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;
618 	}
619 
620 	fError = (BTransactionError)resultError;
621 	fSystemError = (status_t)systemError;
622 
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;
630 
631 		if (!AddIssue(issue))
632 			return B_NO_MEMORY;
633 	}
634 
635 	return B_OK;
636 }
637 
638 
639 BCommitTransactionResult&
640 BCommitTransactionResult::operator=(const BCommitTransactionResult& other)
641 {
642 	Unset();
643 
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;
652 
653 	for (int32 i = 0; const BTransactionIssue* issue = other.fIssues.ItemAt(i);
654 			i++) {
655 		AddIssue(*issue);
656 	}
657 
658 	return *this;
659 }
660 
661 
662 } // namespace BPackageKit
663