1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
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 | |
31 | enum { |
32 | P_CHUNK_SIZE = 256 |
33 | }; |
34 | |
35 | static const uint32 kDefaultMode = 0777; |
36 | static const uint8 padding[7] = { 0, 0, 0, 0, 0, 0, 0 }; |
37 | |
38 | enum { |
39 | P_DATA = 0, |
40 | P_ATTRIBUTE |
41 | }; |
42 | |
43 | extern const char **environ; |
44 | |
45 | |
46 | status_t |
47 | inflate_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 | |
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 | |
80 | static inline int |
81 | inflate_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 | |
144 | |
145 | |
146 | PackageItem::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 | |
153 | PackageItem::~PackageItem() |
154 | { |
155 | } |
156 | |
157 | |
158 | void |
159 | PackageItem::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 | |
173 | status_t |
174 | PackageItem::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 | |
211 | status_t |
212 | PackageItem::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()) { |
| |
219 | parser_debug("We have an offset\n"); |
220 | if (!fPackage) |
| |
221 | return B_ERROR(-1); |
222 | |
223 | ret = fPackage->InitCheck(); |
224 | if (ret != B_OK((int)0)) |
| 11 | | Assuming 'ret' is equal to 0 | |
|
| |
225 | return ret; |
226 | |
227 | |
228 | fPackage->Seek(fOffset, SEEK_SET0); |
229 | uint8 buffer[7]; |
230 | if (fPackage->Read(buffer, 7) != 7 || memcmp(buffer, header, 5)) |
| |
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]; |
| |
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; |
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)) |
| |
| |
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) { |
| |
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 | |
269 | status_t |
270 | PackageItem::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)) { |
| |
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)) { |
| |
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)) { |
| |
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)) { |
| |
317 | if (!*attrStarted) { |
| |
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); |
332 | |
333 | if (*tempSize < *attrCSize) { |
| |
334 | delete[] *temp; |
335 | *tempSize = *attrCSize; |
336 | *temp = new uint8[*tempSize]; |
337 | } |
338 | if (*dataSize < *attrOSize) { |
| |
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 | |
384 | status_t |
385 | PackageItem::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 | |
446 | status_t |
447 | PackageItem::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); |
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 | |
498 | |
499 | |
500 | PackageScript::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 | |
510 | status_t |
511 | PackageScript::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 | |
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 | |
566 | const uint32 |
567 | PackageScript::ItemKind() |
568 | { |
569 | return P_KIND_SCRIPT; |
570 | } |
571 | |
572 | |
573 | status_t |
574 | PackageScript::_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); |
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 | |
635 | status_t |
636 | PackageScript::_RunScript(uint8 *script, uint32 len) |
637 | { |
638 | |
639 | |
640 | |
641 | |
642 | |
643 | |
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 | |
651 | pipe(filedes); dup2(filedes[0], 0); close(filedes[0]); |
652 | int in = filedes[1]; |
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 | |
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 | |
673 | setpgid(fThreadId, fThreadId); |
674 | |
675 | |
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 | |
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 | |
695 | |
696 | |
697 | PackageDirectory::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 | |
705 | status_t |
706 | PackageDirectory::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 | |
718 | |
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 | |
733 | |
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 | |
742 | const uint32 |
743 | PackageDirectory::ItemKind() |
744 | { |
745 | return P_KIND_DIRECTORY; |
746 | } |
747 | |
748 | |
749 | |
750 | |
751 | |
752 | PackageFile::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 | |
767 | status_t |
768 | PackageFile::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 | |
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 | |
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 | |
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; |
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 | |
908 | const uint32 |
909 | PackageFile::ItemKind() |
910 | { |
911 | return P_KIND_FILE; |
912 | } |
913 | |
914 | |
915 | |
916 | |
917 | |
918 | PackageLink::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 | |
929 | status_t |
930 | PackageLink::DoInstall(const char *path, ItemState *state) |
931 | { |
932 | if (state == NULL__null) |
| |
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) |
| |
943 | || dir->InitCheck() != B_OK((int)0)) { |
944 | |
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 | |
973 | |
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)) { |
| |
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)) { |
| |
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 | |
|
| |
1030 | parser_debug("Failed to set symlink attributes\n"); |
1031 | return ret; |
1032 | } |
1033 | |
1034 | if (fOffset) { |
| |
1035 | |
1036 | ret = HandleAttributes(&destination, &symlink, "LnDa"); |
| 8 | | Calling 'PackageItem::HandleAttributes' | |
|
1037 | } |
1038 | |
1039 | return ret; |
1040 | } |
1041 | |
1042 | |
1043 | const uint32 |
1044 | PackageLink::ItemKind() |
1045 | { |
1046 | return P_KIND_SYM_LINK; |
1047 | } |
1048 | |