Bug Summary

File:/boot/home/haiku/haiku/src/apps/packageinstaller/PackageItem.cpp
Location:line 339, column 4
Description:Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'

Annotated Source Code

1/*
2 * Copyright 2007-2009, Haiku, Inc.
3 * Distributed under the terms of the MIT license.
4 *
5 * Author:
6 * Ɓukasz 'Sil2100' Zemczak <sil2100@vexillium.org>
7 */
8
9
10#include "PackageItem.h"
11
12#include <string.h>
13
14#include <Alert.h>
15#include <ByteOrder.h>
16#include <Catalog.h>
17#include <Directory.h>
18#include <fs_info.h>
19#include <Locale.h>
20#include <NodeInfo.h>
21#include <OS.h>
22#include <SymLink.h>
23#include <Volume.h>
24
25#include "zlib.h"
26
27
28#undef B_TRANSLATION_CONTEXT"PackageItem"
29#define B_TRANSLATION_CONTEXT"PackageItem" "PackageItem"
30
31enum {
32 P_CHUNK_SIZE = 256
33};
34
35static const uint32 kDefaultMode = 0777;
36static const uint8 padding[7] = { 0, 0, 0, 0, 0, 0, 0 };
37
38enum {
39 P_DATA = 0,
40 P_ATTRIBUTE
41};
42
43extern const char **environ;
44
45
46status_t
47inflate_data(uint8 *in, uint32 inSize, uint8 *out, uint32 outSize)
48{
49 parser_debug("inflate_data() called - input_size: %ld, output_size: %ld\n",
50 inSize, outSize);
51 z_stream stream;
52 stream.zalloc = Z_NULL0;
53 stream.zfree = Z_NULL0;
54 stream.opaque = Z_NULL0;
55 stream.avail_in = inSize;
56 stream.next_in = in;
57 status_t ret;
58
59 ret = inflateInit(&stream)inflateInit_((&stream), "1.2.7", (int)sizeof(z_stream));
60 if (ret != Z_OK0) {
61 parser_debug("inflatInit failed\n");
62 return B_ERROR(-1);
63 }
64
65 stream.avail_out = outSize;
66 stream.next_out = out;
67
68 ret = inflate(&stream, Z_NO_FLUSH0);
69 if (ret != Z_STREAM_END1) {
70 // Uncompressed file size in package info corrupted
71 parser_debug("Left: %d\n", stream.avail_out);
72 return B_ERROR(-1);
73 }
74
75 inflateEnd(&stream);
76 return B_OK((int)0);
77}
78
79
80static inline int
81inflate_file_to_file(BFile *in, uint64 in_size, BFile *out, uint64 out_size)
82{
83 z_stream stream;
84 stream.zalloc = Z_NULL0;
85 stream.zfree = Z_NULL0;
86 stream.opaque = Z_NULL0;
87 stream.avail_in = 0;
88 stream.next_in = Z_NULL0;
89 status_t ret;
90
91 uint8 buffer_out[P_CHUNK_SIZE], buffer_in[P_CHUNK_SIZE];
92 uint64 bytes_read = 0, read = P_CHUNK_SIZE, write = 0;
93
94 ret = inflateInit(&stream)inflateInit_((&stream), "1.2.7", (int)sizeof(z_stream));
95 if (ret != Z_OK0) {
96 parser_debug("inflate_file_to_file: inflateInit failed\n");
97 return B_ERROR(-1);
98 }
99
100 do {
101 bytes_read += P_CHUNK_SIZE;
102 if (bytes_read > in_size) {
103 read = in_size - (bytes_read - P_CHUNK_SIZE);
104 bytes_read = in_size;
105 }
106
107 stream.avail_in = in->Read(buffer_in, read);
108 if (stream.avail_in != read) {
109 parser_debug("inflate_file_to_file: read failed\n");
110 (void)inflateEnd(&stream);
111 return B_ERROR(-1);
112 }
113 stream.next_in = buffer_in;
114
115 do {
116 stream.avail_out = P_CHUNK_SIZE;
117 stream.next_out = buffer_out;
118
119 ret = inflate(&stream, Z_NO_FLUSH0);
120 if (ret != Z_OK0 && ret != Z_STREAM_END1 && ret != Z_BUF_ERROR(-5)) {
121 parser_debug("inflate_file_to_file: inflate failed\n");
122 (void)inflateEnd(&stream);
123 return B_ERROR(-1);
124 }
125
126 write = P_CHUNK_SIZE - stream.avail_out;
127 if (static_cast<uint64>(out->Write(buffer_out, write)) != write) {
128 parser_debug("inflate_file_to_file: write failed\n");
129 (void)inflateEnd(&stream);
130 return B_ERROR(-1);
131 }
132 }
133 while (stream.avail_out == 0);
134 }
135 while (bytes_read != in_size);
136
137 (void)inflateEnd(&stream);
138
139 return B_OK((int)0);
140}
141
142
143// #pragma mark - PackageItem
144
145
146PackageItem::PackageItem(BFile *parent, const BString &path, uint8 type,
147 uint32 ctime, uint32 mtime, uint64 offset, uint64 size)
148{
149 SetTo(parent, path, type, ctime, mtime, offset, size);
150}
151
152
153PackageItem::~PackageItem()
154{
155}
156
157
158void
159PackageItem::SetTo(BFile *parent, const BString &path, uint8 type, uint32 ctime,
160 uint32 mtime, uint64 offset, uint64 size)
161{
162 fPackage = parent;
163 fPath = path;
164
165 fOffset = offset;
166 fSize = size;
167 fPathType = type;
168 fCreationTime = ctime;
169 fModificationTime = mtime;
170}
171
172
173status_t
174PackageItem::InitPath(const char *path, BPath *destination)
175{
176 status_t ret = B_OK((int)0);
177
178 if (fPathType == P_INSTALL_PATH) {
179 if (!path) {
180 parser_debug("InitPath path is NULL\n");
181 return B_ERROR(-1);
182 }
183 ret = destination->SetTo(path, fPath.String());
184 }
185 else if (fPathType == P_SYSTEM_PATH)
186 ret = destination->SetTo(fPath.String());
187 else {
188 if (!path) {
189 parser_debug("InitPath path is NULL\n");
190 return B_ERROR(-1);
191 }
192
193 BVolume volume(dev_for_path(path));
194 ret = volume.InitCheck();
195 if (ret != B_OK((int)0))
196 return ret;
197
198 BDirectory temp;
199 ret = volume.GetRootDirectory(&temp);
200 if (ret != B_OK((int)0))
201 return ret;
202
203 BPath mountPoint(&temp, NULL__null);
204 ret = destination->SetTo(mountPoint.Path(), fPath.String());
205 }
206
207 return ret;
208}
209
210
211status_t
212PackageItem::HandleAttributes(BPath *destination, BNode *node,
213 const char *header)
214{
215 status_t ret = B_OK((int)0);
216
217 BVolume volume(dev_for_path(destination->Path()));
218 if (volume.KnowsAttr()) {
9
Taking true branch
219 parser_debug("We have an offset\n");
220 if (!fPackage)
10
Taking false branch
221 return B_ERROR(-1);
222
223 ret = fPackage->InitCheck();
224 if (ret != B_OK((int)0))
11
Assuming 'ret' is equal to 0
12
Taking false branch
225 return ret;
226
227 // We need to parse the data section now
228 fPackage->Seek(fOffset, SEEK_SET0);
229 uint8 buffer[7];
230 if (fPackage->Read(buffer, 7) != 7 || memcmp(buffer, header, 5))
13
Taking false branch
231 return B_ERROR(-1);
232 parser_debug("Header validated!\n");
233
234 char *attrName = 0;
235 uint32 nameSize = 0;
236 uint8 *attrData = new uint8[P_CHUNK_SIZE];
14
Memory is allocated
237 uint64 dataSize = P_CHUNK_SIZE;
238 uint8 *temp = new uint8[P_CHUNK_SIZE];
239 uint64 tempSize = P_CHUNK_SIZE;
240
241 uint64 attrCSize = 0, attrOSize = 0;
242 uint32 attrType = 0; // type_code type
243 bool attrStarted = false, done = false;
244
245 while (fPackage->Read(buffer, 7) == 7) {
15
Loop condition is true. Entering loop body
18
Loop condition is true. Entering loop body
246 if (!memcmp(buffer, "FBeA", 5))
16
Taking false branch
19
Taking false branch
247 continue;
248
249 ret = ParseAttribute(buffer, node, &attrName, &nameSize, &attrType,
20
Calling 'PackageItem::ParseAttribute'
250 &attrData, &dataSize, &temp, &tempSize, &attrCSize, &attrOSize,
251 &attrStarted, &done);
252 if (ret != B_OK((int)0) || done) {
17
Taking false branch
253 if (ret != B_OK((int)0)) {
254 parser_debug("_ParseAttribute failed for %s\n",
255 destination->Path());
256 }
257 break;
258 }
259 }
260
261 delete[] attrData;
262 delete[] temp;
263 }
264
265 return ret;
266}
267
268
269status_t
270PackageItem::ParseAttribute(uint8 *buffer, BNode *node, char **attrName,
271 uint32 *nameSize, uint32 *attrType, uint8 **attrData, uint64 *dataSize,
272 uint8 **temp, uint64 *tempSize, uint64 *attrCSize, uint64 *attrOSize,
273 bool *attrStarted, bool *done)
274{
275 status_t ret = B_OK((int)0);
276 uint32 length;
277
278 if (!memcmp(buffer, "BeAI", 5)) {
21
Taking false branch
279 parser_debug(" Attribute started.\n");
280 if (*attrName)
281 *attrName[0] = 0;
282 *attrCSize = 0;
283 *attrOSize = 0;
284
285 *attrStarted = true;
286 } else if (!memcmp(buffer, "BeAN", 5)) {
22
Taking false branch
287 if (!*attrStarted) {
288 ret = B_ERROR(-1);
289 return ret;
290 }
291
292 parser_debug(" BeAN.\n");
293 fPackage->Read(&length, 4);
294 swap_data(B_UINT32_TYPE, &length, sizeof(uint32),
295 B_SWAP_BENDIAN_TO_HOST);
296
297 if (*nameSize < (length + 1)) {
298 delete[] *attrName;
299 *nameSize = length + 1;
300 *attrName = new char[*nameSize];
301 }
302 fPackage->Read(*attrName, length);
303 (*attrName)[length] = 0;
304
305 parser_debug(" (%ld) = %s\n", length, *attrName);
306 } else if (!memcmp(buffer, "BeAT", 5)) {
23
Taking false branch
307 if (!*attrStarted) {
308 ret = B_ERROR(-1);
309 return ret;
310 }
311
312 parser_debug(" BeAT.\n");
313 fPackage->Read(attrType, 4);
314 swap_data(B_UINT32_TYPE, attrType, sizeof(*attrType),
315 B_SWAP_BENDIAN_TO_HOST);
316 } else if (!memcmp(buffer, "BeAD", 5)) {
24
Taking true branch
317 if (!*attrStarted) {
25
Taking false branch
318 ret = B_ERROR(-1);
319 return ret;
320 }
321
322 parser_debug(" BeAD.\n");
323 fPackage->Read(attrCSize, 8);
324 swap_data(B_UINT64_TYPE, attrCSize, sizeof(*attrCSize),
325 B_SWAP_BENDIAN_TO_HOST);
326
327 fPackage->Read(attrOSize, 8);
328 swap_data(B_UINT64_TYPE, attrOSize, sizeof(*attrOSize),
329 B_SWAP_BENDIAN_TO_HOST);
330
331 fPackage->Seek(4, SEEK_CUR1); // TODO: Check what this means
332
333 if (*tempSize < *attrCSize) {
26
Taking false branch
334 delete[] *temp;
335 *tempSize = *attrCSize;
336 *temp = new uint8[*tempSize];
337 }
338 if (*dataSize < *attrOSize) {
27
Taking true branch
339 delete *attrData;
28
Memory allocated by 'new[]' should be deallocated by 'delete[]', not 'delete'
340 *dataSize = *attrOSize;
341 *attrData = new uint8[*dataSize];
342 }
343
344 if (fPackage->Read(*temp, *attrCSize)
345 != static_cast<ssize_t>(*attrCSize)) {
346 ret = B_ERROR(-1);
347 return ret;
348 }
349
350 parser_debug(" Data read successfuly. Inflating!\n");
351 ret = inflate_data(*temp, *tempSize, *attrData, *dataSize);
352 if (ret != B_OK((int)0))
353 return ret;
354 } else if (!memcmp(buffer, padding, 7)) {
355 if (!*attrStarted) {
356 *done = true;
357 return ret;
358 }
359
360 parser_debug(" Padding.\n");
361 ssize_t wrote = node->WriteAttr(*attrName, *attrType, 0, *attrData,
362 *attrOSize);
363 if (wrote != static_cast<ssize_t>(*attrOSize)) {
364 parser_debug("Failed to write attribute %s %s\n", *attrName, strerror(wrote));
365 return B_ERROR(-1);
366 }
367
368 *attrStarted = false;
369 if (*attrName)
370 *attrName[0] = 0;
371 *attrCSize = 0;
372 *attrOSize = 0;
373
374 parser_debug(" > Attribute added.\n");
375 } else {
376 parser_debug(" Unknown attribute\n");
377 ret = B_ERROR(-1);
378 }
379
380 return ret;
381}
382
383
384status_t
385PackageItem::SkipAttribute(uint8 *buffer, bool *attrStarted, bool *done)
386{
387 status_t ret = B_OK((int)0);
388 uint32 length;
389
390 if (!memcmp(buffer, "BeAI", 5)) {
391 parser_debug(" Attribute started.\n");
392 *attrStarted = true;
393 } else if (!memcmp(buffer, "BeAN", 5)) {
394 if (!*attrStarted) {
395 ret = B_ERROR(-1);
396 return ret;
397 }
398
399 parser_debug(" BeAN.\n");
400 fPackage->Read(&length, 4);
401 swap_data(B_UINT32_TYPE, &length, sizeof(uint32),
402 B_SWAP_BENDIAN_TO_HOST);
403
404 fPackage->Seek(length, SEEK_CUR1);
405 } else if (!memcmp(buffer, "BeAT", 5)) {
406 if (!*attrStarted) {
407 ret = B_ERROR(-1);
408 return ret;
409 }
410
411 parser_debug(" BeAT.\n");
412 fPackage->Seek(4, SEEK_CUR1);
413 } else if (!memcmp(buffer, "BeAD", 5)) {
414 if (!*attrStarted) {
415 ret = B_ERROR(-1);
416 return ret;
417 }
418
419 parser_debug(" BeAD.\n");
420 uint64 length64;
421 fPackage->Read(&length64, 8);
422 swap_data(B_UINT64_TYPE, &length64, sizeof(length64),
423 B_SWAP_BENDIAN_TO_HOST);
424
425 fPackage->Seek(12 + length64, SEEK_CUR1);
426
427 parser_debug(" Data skipped successfuly.\n");
428 } else if (!memcmp(buffer, padding, 7)) {
429 if (!*attrStarted) {
430 *done = true;
431 return ret;
432 }
433
434 parser_debug(" Padding.\n");
435 *attrStarted = false;
436 parser_debug(" > Attribute skipped.\n");
437 } else {
438 parser_debug(" Unknown attribute\n");
439 ret = B_ERROR(-1);
440 }
441
442 return ret;
443}
444
445
446status_t
447PackageItem::ParseData(uint8 *buffer, BFile *file, uint64 originalSize,
448 bool *done)
449{
450 status_t ret = B_OK((int)0);
451
452 if (!memcmp(buffer, "FiMF", 5)) {
453 parser_debug(" Found file data.\n");
454 uint64 compressed, original;
455 fPackage->Read(&compressed, 8);
456 swap_data(B_UINT64_TYPE, &compressed, sizeof(uint64),
457 B_SWAP_BENDIAN_TO_HOST);
458
459 fPackage->Read(&original, 8);
460 swap_data(B_UINT64_TYPE, &original, sizeof(uint64),
461 B_SWAP_BENDIAN_TO_HOST);
462 parser_debug(" Still good... (%llu : %llu)\n", original,
463 originalSize);
464
465 if (original != originalSize) {
466 parser_debug(" File size mismatch\n");
467 return B_ERROR(-1); // File size mismatch
468 }
469 parser_debug(" Still good...\n");
470
471 if (fPackage->Read(buffer, 4) != 4) {
472 parser_debug(" Read(buffer, 4) failed\n");
473 return B_ERROR(-1);
474 }
475 parser_debug(" Still good...\n");
476
477 ret = inflate_file_to_file(fPackage, compressed, file, original);
478 if (ret != B_OK((int)0)) {
479 parser_debug(" inflate_file_to_file failed\n");
480 return ret;
481 }
482 parser_debug(" File data inflation complete!\n");
483 }
484 else if (!memcmp(buffer, padding, 7)) {
485 *done = true;
486 return ret;
487 }
488 else {
489 parser_debug("_ParseData unknown tag\n");
490 ret = B_ERROR(-1);
491 }
492
493 return ret;
494}
495
496
497// #pragma mark - PackageScript
498
499
500PackageScript::PackageScript(BFile *parent, uint64 offset, uint64 size,
501 uint64 originalSize)
502 :
503 PackageItem(parent, NULL__null, 0, 0, 0, offset, size),
504 fOriginalSize(originalSize),
505 fThreadId(-1)
506{
507}
508
509
510status_t
511PackageScript::DoInstall(const char *path, ItemState *state)
512{
513 status_t ret = B_OK((int)0);
514 parser_debug("Script: DoInstall() called!\n");
515
516 if (fOffset) {
517 parser_debug("We have an offset\n");
518 if (!fPackage)
519 return B_ERROR(-1);
520
521 ret = fPackage->InitCheck();
522 if (ret != B_OK((int)0))
523 return ret;
524
525 // We need to parse the data section now
526 fPackage->Seek(fOffset, SEEK_SET0);
527 uint8 buffer[7];
528 bool attrStarted = false, done = false;
529
530 uint8 section = P_ATTRIBUTE;
531
532 while (fPackage->Read(buffer, 7) == 7) {
533 if (!memcmp(buffer, "FBeA", 5)) {
534 parser_debug("-> Attribute\n");
535 section = P_ATTRIBUTE;
536 continue;
537 } else if (!memcmp(buffer, "FiDa", 5)) {
538 parser_debug("-> File data\n");
539 section = P_DATA;
540 continue;
541 }
542
543 switch (section) {
544 case P_ATTRIBUTE:
545 ret = SkipAttribute(buffer, &attrStarted, &done);
546 break;
547
548 case P_DATA:
549 ret = _ParseScript(buffer, fOriginalSize, &done);
550 break;
551
552 default:
553 return B_ERROR(-1);
554 }
555
556 if (ret != B_OK((int)0) || done)
557 break;
558 }
559 }
560
561 parser_debug("Ret: %ld %s\n", ret, strerror(ret));
562 return ret;
563}
564
565
566const uint32
567PackageScript::ItemKind()
568{
569 return P_KIND_SCRIPT;
570}
571
572
573status_t
574PackageScript::_ParseScript(uint8 *buffer, uint64 originalSize, bool *done)
575{
576 status_t ret = B_OK((int)0);
577
578 if (!memcmp(buffer, "FiMF", 5)) {
579 parser_debug(" Found file (script) data.\n");
580 uint64 compressed, original;
581 fPackage->Read(&compressed, 8);
582 swap_data(B_UINT64_TYPE, &compressed, sizeof(uint64),
583 B_SWAP_BENDIAN_TO_HOST);
584
585 fPackage->Read(&original, 8);
586 swap_data(B_UINT64_TYPE, &original, sizeof(uint64),
587 B_SWAP_BENDIAN_TO_HOST);
588 parser_debug(" Still good... (%llu : %llu)\n", original,
589 originalSize);
590
591 if (original != originalSize) {
592 parser_debug(" File size mismatch\n");
593 return B_ERROR(-1); // File size mismatch
594 }
595 parser_debug(" Still good...\n");
596
597 if (fPackage->Read(buffer, 4) != 4) {
598 parser_debug(" Read(buffer, 4) failed\n");
599 return B_ERROR(-1);
600 }
601 parser_debug(" Still good...\n");
602
603 uint8 *temp = new uint8[compressed];
604 if (fPackage->Read(temp, compressed) != (int64)compressed) {
605 parser_debug(" Read(temp, compressed) failed\n");
606 delete[] temp;
607 return B_ERROR(-1);
608 }
609
610 uint8 *script = new uint8[original];
611 ret = inflate_data(temp, compressed, script, original);
612 if (ret != B_OK((int)0)) {
613 parser_debug(" inflate_data failed\n");
614 delete[] temp;
615 delete[] script;
616 return ret;
617 }
618
619 ret = _RunScript(script, originalSize);
620 delete[] script;
621 delete[] temp;
622 parser_debug(" Script data inflation complete!\n");
623 } else if (!memcmp(buffer, padding, 7)) {
624 *done = true;
625 return ret;
626 } else {
627 parser_debug("_ParseData unknown tag\n");
628 ret = B_ERROR(-1);
629 }
630
631 return ret;
632}
633
634
635status_t
636PackageScript::_RunScript(uint8 *script, uint32 len)
637{
638 // This function written by Peter Folk <pfolk@uni.uiuc.edu>
639 // and published in the BeDevTalk FAQ, modified for use in the
640 // PackageInstaller
641 // http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209
642
643 // Save current FDs
644 int old_in = dup(0);
645 int old_out = dup(1);
646 int old_err = dup(2);
647
648 int filedes[2];
649
650 /* Create new pipe FDs as stdin, stdout, stderr */
651 pipe(filedes); dup2(filedes[0], 0); close(filedes[0]);
652 int in = filedes[1]; // Write to in, appears on cmd's stdin
653 pipe(filedes); dup2(filedes[1], 1); close(filedes[1]);
654 pipe(filedes); dup2(filedes[1], 2); close(filedes[1]);
655
656 const char **argv = new const char * [3];
657 argv[0] = strdup("/bin/sh");
658 argv[1] = strdup("-s");
659 argv[2] = NULL__null;
660
661 // "load" command.
662 fThreadId = load_image(2, argv, environ);
663
664 int i;
665 for (i = 0; i < 2; i++)
666 delete argv[i];
667 delete [] argv;
668
669 if (fThreadId < B_OK((int)0))
670 return fThreadId;
671
672 // thread id is now suspended.
673 setpgid(fThreadId, fThreadId);
674
675 // Restore old FDs
676 close(0); dup(old_in); close(old_in);
677 close(1); dup(old_out); close(old_out);
678 close(2); dup(old_err); close(old_err);
679
680 set_thread_priority(fThreadId, B_LOW_PRIORITY5);
681 resume_thread(fThreadId);
682
683 // Write the script
684 if (write(in, script, len) != (int32)len || write(in, "\nexit\n", 6) != 6) {
685 parser_debug("Writing script failed\n");
686 kill_thread(fThreadId);
687 return B_ERROR(-1);
688 }
689
690 return B_OK((int)0);
691}
692
693
694// #pragma mark - PackageDirectory
695
696
697PackageDirectory::PackageDirectory(BFile *parent, const BString &path,
698 uint8 type, uint32 ctime, uint32 mtime, uint64 offset, uint64 size)
699 :
700 PackageItem(parent, path, type, ctime, mtime, offset, size)
701{
702}
703
704
705status_t
706PackageDirectory::DoInstall(const char *path, ItemState *state)
707{
708 BPath &destination = state->destination;
709 status_t ret;
710 parser_debug("Directory: %s DoInstall() called!\n", fPath.String());
711
712 ret = InitPath(path, &destination);
713 parser_debug("Ret: %ld %s\n", ret, strerror(ret));
714 if (ret != B_OK((int)0))
715 return ret;
716
717 // Since Haiku is single-user right now, we give the newly
718 // created directory default permissions
719 ret = create_directory(destination.Path(), kDefaultMode);
720 parser_debug("Create dir ret: %ld %s\n", ret, strerror(ret));
721 if (ret != B_OK((int)0))
722 return ret;
723 BDirectory dir(destination.Path());
724 parser_debug("Directory created!\n");
725
726 if (fCreationTime)
727 dir.SetCreationTime(static_cast<time_t>(fCreationTime));
728
729 if (fModificationTime)
730 dir.SetModificationTime(static_cast<time_t>(fModificationTime));
731
732 // Since directories can only have attributes in the offset section,
733 // we can check here whether it is necessary to continue
734 if (fOffset)
735 ret = HandleAttributes(&destination, &dir, "FoDa");
736
737 parser_debug("Ret: %ld %s\n", ret, strerror(ret));
738 return ret;
739}
740
741
742const uint32
743PackageDirectory::ItemKind()
744{
745 return P_KIND_DIRECTORY;
746}
747
748
749// #pragma mark - PackageFile
750
751
752PackageFile::PackageFile(BFile *parent, const BString &path, uint8 type,
753 uint32 ctime, uint32 mtime, uint64 offset, uint64 size,
754 uint64 originalSize, uint32 platform, const BString &mime,
755 const BString &signature, uint32 mode)
756 :
757 PackageItem(parent, path, type, ctime, mtime, offset, size),
758 fOriginalSize(originalSize),
759 fPlatform(platform),
760 fMode(mode),
761 fMimeType(mime),
762 fSignature(signature)
763{
764}
765
766
767status_t
768PackageFile::DoInstall(const char *path, ItemState *state)
769{
770 if (state == NULL__null)
771 return B_ERROR(-1);
772
773 BPath &destination = state->destination;
774 status_t ret = B_OK((int)0);
775 parser_debug("File: %s DoInstall() called!\n", fPath.String());
776
777 BFile file;
778 if (state->status == B_NO_INIT((-2147483647 - 1) + 13) || destination.InitCheck() != B_OK((int)0)) {
779 ret = InitPath(path, &destination);
780 if (ret != B_OK((int)0))
781 return ret;
782
783 ret = file.SetTo(destination.Path(),
784 B_WRITE_ONLY0x0001 | B_CREATE_FILE0x0200 | B_FAIL_IF_EXISTS0x0100);
785 if (ret == B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3)) {
786 BPath directory;
787 destination.GetParent(&directory);
788 if (create_directory(directory.Path(), kDefaultMode) != B_OK((int)0))
789 return B_ERROR(-1);
790
791 ret = file.SetTo(destination.Path(), B_WRITE_ONLY0x0001 | B_CREATE_FILE0x0200);
792 } else if (ret == B_FILE_EXISTS(((-2147483647 - 1) + 0x6000) + 2))
793 state->status = B_FILE_EXISTS(((-2147483647 - 1) + 0x6000) + 2);
794
795 if (ret != B_OK((int)0))
796 return ret;
797 }
798
799 if (state->status == B_FILE_EXISTS(((-2147483647 - 1) + 0x6000) + 2)) {
800 switch (state->policy) {
801 case P_EXISTS_OVERWRITE:
802 ret = file.SetTo(destination.Path(),
803 B_WRITE_ONLY0x0001 | B_ERASE_FILE0x0400);
804 break;
805
806 case P_EXISTS_NONE:
807 case P_EXISTS_ASK:
808 ret = B_FILE_EXISTS(((-2147483647 - 1) + 0x6000) + 2);
809 break;
810
811 case P_EXISTS_SKIP:
812 return B_OK((int)0);
813 }
814 }
815
816 if (ret != B_OK((int)0))
817 return ret;
818
819 parser_debug(" File created!\n");
820
821 // Set the file permissions, creation and modification times
822 ret = file.SetPermissions(static_cast<mode_t>(fMode));
823 if (fCreationTime && ret == B_OK((int)0))
824 ret = file.SetCreationTime(static_cast<time_t>(fCreationTime));
825 if (fModificationTime && ret == B_OK((int)0))
826 ret = file.SetModificationTime(static_cast<time_t>(fModificationTime));
827
828 if (ret != B_OK((int)0))
829 return ret;
830
831 // Set the mimetype and application signature if present
832 BNodeInfo info(&file);
833 if (fMimeType.Length() > 0) {
834 ret = info.SetType(fMimeType.String());
835 if (ret != B_OK((int)0))
836 return ret;
837 }
838 if (fSignature.Length() > 0) {
839 ret = info.SetPreferredApp(fSignature.String());
840 if (ret != B_OK((int)0))
841 return ret;
842 }
843
844 if (fOffset) {
845 parser_debug("We have an offset\n");
846 if (!fPackage)
847 return B_ERROR(-1);
848
849 ret = fPackage->InitCheck();
850 if (ret != B_OK((int)0))
851 return ret;
852
853 // We need to parse the data section now
854 fPackage->Seek(fOffset, SEEK_SET0);
855 uint8 buffer[7];
856
857 char *attrName = 0;
858 uint32 nameSize = 0;
859 uint8 *attrData = new uint8[P_CHUNK_SIZE];
860 uint64 dataSize = P_CHUNK_SIZE;
861 uint8 *temp = new uint8[P_CHUNK_SIZE];
862 uint64 tempSize = P_CHUNK_SIZE;
863
864 uint64 attrCSize = 0, attrOSize = 0;
865 uint32 attrType = 0; // type_code type
866 bool attrStarted = false, done = false;
867
868 uint8 section = P_ATTRIBUTE;
869
870 while (fPackage->Read(buffer, 7) == 7) {
871 if (!memcmp(buffer, "FBeA", 5)) {
872 parser_debug("-> Attribute\n");
873 section = P_ATTRIBUTE;
874 continue;
875 } else if (!memcmp(buffer, "FiDa", 5)) {
876 parser_debug("-> File data\n");
877 section = P_DATA;
878 continue;
879 }
880
881 switch (section) {
882 case P_ATTRIBUTE:
883 ret = ParseAttribute(buffer, &file, &attrName, &nameSize,
884 &attrType, &attrData, &dataSize, &temp, &tempSize,
885 &attrCSize, &attrOSize, &attrStarted, &done);
886 break;
887
888 case P_DATA:
889 ret = ParseData(buffer, &file, fOriginalSize, &done);
890 break;
891
892 default:
893 return B_ERROR(-1);
894 }
895
896 if (ret != B_OK((int)0) || done)
897 break;
898 }
899
900 delete[] attrData;
901 delete[] temp;
902 }
903
904 return ret;
905}
906
907
908const uint32
909PackageFile::ItemKind()
910{
911 return P_KIND_FILE;
912}
913
914
915// #pragma mark -
916
917
918PackageLink::PackageLink(BFile *parent, const BString &path,
919 const BString &link, uint8 type, uint32 ctime, uint32 mtime,
920 uint32 mode, uint64 offset, uint64 size)
921 :
922 PackageItem(parent, path, type, ctime, mtime, offset, size),
923 fMode(mode),
924 fLink(link)
925{
926}
927
928
929status_t
930PackageLink::DoInstall(const char *path, ItemState *state)
931{
932 if (state == NULL__null)
1
Taking false branch
933 return B_ERROR(-1);
934
935 status_t ret = B_OK((int)0);
936 BSymLink symlink;
937 parser_debug("Symlink: %s DoInstall() called!\n", fPath.String());
938
939 BPath &destination = state->destination;
940 BDirectory *dir = &state->parent;
941
942 if (state->status == B_NO_INIT((-2147483647 - 1) + 13) || destination.InitCheck() != B_OK((int)0)
2
Taking false branch
943 || dir->InitCheck() != B_OK((int)0)) {
944 // Not yet initialized
945 ret = InitPath(path, &destination);
946 if (ret != B_OK((int)0))
947 return ret;
948
949 BString linkName(destination.Leaf());
950 parser_debug("%s:%s:%s\n", fPath.String(), destination.Path(),
951 linkName.String());
952
953 BPath dirPath;
954 ret = destination.GetParent(&dirPath);
955 ret = dir->SetTo(dirPath.Path());
956
957 if (ret == B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3)) {
958 ret = create_directory(dirPath.Path(), kDefaultMode);
959 if (ret != B_OK((int)0)) {
960 parser_debug("create_directory()) failed\n");
961 return B_ERROR(-1);
962 }
963 }
964 if (ret != B_OK((int)0)) {
965 parser_debug("destination InitCheck failed %s for %s\n",
966 strerror(ret), dirPath.Path());
967 return ret;
968 }
969
970 ret = dir->CreateSymLink(destination.Path(), fLink.String(), &symlink);
971 if (ret == B_FILE_EXISTS(((-2147483647 - 1) + 0x6000) + 2)) {
972 // We need to check if the existing symlink is pointing at the same path
973 // as our new one - if not, let's prompt the user
974 symlink.SetTo(destination.Path());
975 BPath oldLink;
976
977 ret = symlink.MakeLinkedPath(dir, &oldLink);
978 chdir(dirPath.Path());
979
980 if (ret == B_BAD_VALUE((-2147483647 - 1) + 5) || oldLink != fLink.String())
981 state->status = ret = B_FILE_EXISTS(((-2147483647 - 1) + 0x6000) + 2);
982 else
983 ret = B_OK((int)0);
984 }
985 }
986
987 if (state->status == B_FILE_EXISTS(((-2147483647 - 1) + 0x6000) + 2)) {
3
Taking false branch
988 switch (state->policy) {
989 case P_EXISTS_OVERWRITE:
990 {
991 BEntry entry;
992 ret = entry.SetTo(destination.Path());
993 if (ret != B_OK((int)0))
994 return ret;
995
996 entry.Remove();
997 ret = dir->CreateSymLink(destination.Path(), fLink.String(),
998 &symlink);
999 break;
1000 }
1001
1002 case P_EXISTS_NONE:
1003 case P_EXISTS_ASK:
1004 ret = B_FILE_EXISTS(((-2147483647 - 1) + 0x6000) + 2);
1005 break;
1006
1007 case P_EXISTS_SKIP:
1008 return B_OK((int)0);
1009 }
1010 }
1011
1012 if (ret != B_OK((int)0)) {
4
Taking false branch
1013 parser_debug("CreateSymLink failed\n");
1014 return ret;
1015 }
1016
1017 parser_debug(" Symlink created!\n");
1018
1019 ret = symlink.SetPermissions(static_cast<mode_t>(fMode));
1020
1021 if (fCreationTime && ret == B_OK((int)0))
1022 ret = symlink.SetCreationTime(static_cast<time_t>(fCreationTime));
1023
1024 if (fModificationTime && ret == B_OK((int)0)) {
1025 ret = symlink.SetModificationTime(static_cast<time_t>(
1026 fModificationTime));
1027 }
1028
1029 if (ret != B_OK((int)0)) {
5
Assuming 'ret' is equal to 0
6
Taking false branch
1030 parser_debug("Failed to set symlink attributes\n");
1031 return ret;
1032 }
1033
1034 if (fOffset) {
7
Taking true branch
1035 // Symlinks also seem to have attributes - so parse them
1036 ret = HandleAttributes(&destination, &symlink, "LnDa");
8
Calling 'PackageItem::HandleAttributes'
1037 }
1038
1039 return ret;
1040}
1041
1042
1043const uint32
1044PackageLink::ItemKind()
1045{
1046 return P_KIND_SYM_LINK;
1047}
1048