| ... | @@ -57,6 +57,54 @@ static clock_serv_t cclock; | ... | @@ -57,6 +57,54 @@ static clock_serv_t cclock; |
| 57 | #include <errno.h> | 57 | #include <errno.h> |
| 58 | #include <time.h> | 58 | #include <time.h> |
| 59 | | 59 | |
| | 60 | // Ported from std/mem.zig. |
| | 61 | // Coordinate struct fields with memSplit function |
| | 62 | struct SplitIterator { |
| | 63 | size_t index; |
| | 64 | Slice<uint8_t> buffer; |
| | 65 | Slice<uint8_t> split_bytes; |
| | 66 | }; |
| | 67 | |
| | 68 | // Ported from std/mem.zig. |
| | 69 | static bool SplitIterator_isSplitByte(SplitIterator *self, uint8_t byte) { |
| | 70 | for (size_t i = 0; i < self->split_bytes.len; i += 1) { |
| | 71 | if (byte == self->split_bytes.ptr[i]) { |
| | 72 | return true; |
| | 73 | } |
| | 74 | } |
| | 75 | return false; |
| | 76 | } |
| | 77 | |
| | 78 | // Ported from std/mem.zig. |
| | 79 | static Optional<Slice<uint8_t>> SplitIterator_next(SplitIterator *self) { |
| | 80 | // move to beginning of token |
| | 81 | while (self->index < self->buffer.len && |
| | 82 | SplitIterator_isSplitByte(self, self->buffer.ptr[self->index])) |
| | 83 | { |
| | 84 | self->index += 1; |
| | 85 | } |
| | 86 | size_t start = self->index; |
| | 87 | if (start == self->buffer.len) { |
| | 88 | return {}; |
| | 89 | } |
| | 90 | |
| | 91 | // move to end of token |
| | 92 | while (self->index < self->buffer.len && |
| | 93 | !SplitIterator_isSplitByte(self, self->buffer.ptr[self->index])) |
| | 94 | { |
| | 95 | self->index += 1; |
| | 96 | } |
| | 97 | size_t end = self->index; |
| | 98 | |
| | 99 | return Optional<Slice<uint8_t>>::some(self->buffer.slice(start, end)); |
| | 100 | } |
| | 101 | |
| | 102 | // Ported from std/mem.zig |
| | 103 | static SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes) { |
| | 104 | return SplitIterator{0, buffer, split_bytes}; |
| | 105 | } |
| | 106 | |
| | 107 | |
| 60 | #if defined(ZIG_OS_POSIX) | 108 | #if defined(ZIG_OS_POSIX) |
| 61 | static void populate_termination(Termination *term, int status) { | 109 | static void populate_termination(Termination *term, int status) { |
| 62 | if (WIFEXITED(status)) { | 110 | if (WIFEXITED(status)) { |
| ... | @@ -266,15 +314,31 @@ int os_path_real(Buf *rel_path, Buf *out_abs_path) { | ... | @@ -266,15 +314,31 @@ int os_path_real(Buf *rel_path, Buf *out_abs_path) { |
| 266 | #endif | 314 | #endif |
| 267 | } | 315 | } |
| 268 | | 316 | |
| 269 | bool os_path_is_absolute(Buf *path) { | | |
| 270 | #if defined(ZIG_OS_WINDOWS) | 317 | #if defined(ZIG_OS_WINDOWS) |
| 271 | if (buf_starts_with_str(path, "/") || buf_starts_with_str(path, "\\")) | 318 | // Ported from std/os/path.zig |
| | 319 | static bool isAbsoluteWindows(Slice<uint8_t> path) { |
| | 320 | if (path.ptr[0] == '/') |
| 272 | return true; | 321 | return true; |
| 273 | | 322 | |
| 274 | if (buf_len(path) >= 3 && buf_ptr(path)[1] == ':') | 323 | if (path.ptr[0] == '\\') { |
| 275 | return true; | 324 | return true; |
| 276 | | 325 | } |
| | 326 | if (path.len < 3) { |
| | 327 | return false; |
| | 328 | } |
| | 329 | if (path.ptr[1] == ':') { |
| | 330 | if (path.ptr[2] == '/') |
| | 331 | return true; |
| | 332 | if (path.ptr[2] == '\\') |
| | 333 | return true; |
| | 334 | } |
| 277 | return false; | 335 | return false; |
| | 336 | } |
| | 337 | #endif |
| | 338 | |
| | 339 | bool os_path_is_absolute(Buf *path) { |
| | 340 | #if defined(ZIG_OS_WINDOWS) |
| | 341 | return isAbsoluteWindows(buf_to_slice(path)); |
| 278 | #elif defined(ZIG_OS_POSIX) | 342 | #elif defined(ZIG_OS_POSIX) |
| 279 | return buf_ptr(path)[0] == '/'; | 343 | return buf_ptr(path)[0] == '/'; |
| 280 | #else | 344 | #else |
| ... | @@ -282,14 +346,423 @@ bool os_path_is_absolute(Buf *path) { | ... | @@ -282,14 +346,423 @@ bool os_path_is_absolute(Buf *path) { |
| 282 | #endif | 346 | #endif |
| 283 | } | 347 | } |
| 284 | | 348 | |
| 285 | void os_path_resolve(Buf *ref_path, Buf *target_path, Buf *out_abs_path) { | 349 | #if defined(ZIG_OS_WINDOWS) |
| 286 | if (os_path_is_absolute(target_path)) { | 350 | |
| 287 | buf_init_from_buf(out_abs_path, target_path); | 351 | enum WindowsPathKind { |
| 288 | return; | 352 | WindowsPathKindNone, |
| | 353 | WindowsPathKindDrive, |
| | 354 | WindowsPathKindNetworkShare, |
| | 355 | }; |
| | 356 | |
| | 357 | struct WindowsPath { |
| | 358 | Slice<uint8_t> disk_designator; |
| | 359 | WindowsPathKind kind; |
| | 360 | bool is_abs; |
| | 361 | }; |
| | 362 | |
| | 363 | |
| | 364 | // Ported from std/os/path.zig |
| | 365 | static WindowsPath windowsParsePath(Slice<uint8_t> path) { |
| | 366 | if (path.len >= 2 && path.ptr[1] == ':') { |
| | 367 | return WindowsPath{ |
| | 368 | path.slice(0, 2), |
| | 369 | WindowsPathKindDrive, |
| | 370 | isAbsoluteWindows(path), |
| | 371 | }; |
| | 372 | } |
| | 373 | if (path.len >= 1 && (path.ptr[0] == '/' || path.ptr[0] == '\\') && |
| | 374 | (path.len == 1 || (path.ptr[1] != '/' && path.ptr[1] != '\\'))) |
| | 375 | { |
| | 376 | return WindowsPath{ |
| | 377 | path.slice(0, 0), |
| | 378 | WindowsPathKindNone, |
| | 379 | true, |
| | 380 | }; |
| | 381 | } |
| | 382 | WindowsPath relative_path = { |
| | 383 | str(""), |
| | 384 | WindowsPathKindNone, |
| | 385 | false, |
| | 386 | }; |
| | 387 | if (path.len < strlen("//a/b")) { |
| | 388 | return relative_path; |
| 289 | } | 389 | } |
| 290 | | 390 | |
| 291 | os_path_join(ref_path, target_path, out_abs_path); | 391 | { |
| 292 | return; | 392 | if (memStartsWith(path, str("//"))) { |
| | 393 | if (path.ptr[2] == '/') { |
| | 394 | return relative_path; |
| | 395 | } |
| | 396 | |
| | 397 | SplitIterator it = memSplit(path, str("/")); |
| | 398 | { |
| | 399 | Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it); |
| | 400 | if (!opt_component.is_some) return relative_path; |
| | 401 | } |
| | 402 | { |
| | 403 | Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it); |
| | 404 | if (!opt_component.is_some) return relative_path; |
| | 405 | } |
| | 406 | return WindowsPath{ |
| | 407 | path.slice(0, it.index), |
| | 408 | WindowsPathKindNetworkShare, |
| | 409 | isAbsoluteWindows(path), |
| | 410 | }; |
| | 411 | } |
| | 412 | } |
| | 413 | { |
| | 414 | if (memStartsWith(path, str("\\\\"))) { |
| | 415 | if (path.ptr[2] == '\\') { |
| | 416 | return relative_path; |
| | 417 | } |
| | 418 | |
| | 419 | SplitIterator it = memSplit(path, str("\\")); |
| | 420 | { |
| | 421 | Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it); |
| | 422 | if (!opt_component.is_some) return relative_path; |
| | 423 | } |
| | 424 | { |
| | 425 | Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it); |
| | 426 | if (!opt_component.is_some) return relative_path; |
| | 427 | } |
| | 428 | return WindowsPath{ |
| | 429 | path.slice(0, it.index), |
| | 430 | WindowsPathKindNetworkShare, |
| | 431 | isAbsoluteWindows(path), |
| | 432 | }; |
| | 433 | } |
| | 434 | } |
| | 435 | return relative_path; |
| | 436 | } |
| | 437 | |
| | 438 | // Ported from std/os/path.zig |
| | 439 | static uint8_t asciiUpper(uint8_t byte) { |
| | 440 | if (byte >= 'a' && byte <= 'z') { |
| | 441 | return 'A' + (byte - 'a'); |
| | 442 | } |
| | 443 | return byte; |
| | 444 | } |
| | 445 | |
| | 446 | // Ported from std/os/path.zig |
| | 447 | static bool asciiEqlIgnoreCase(Slice<uint8_t> s1, Slice<uint8_t> s2) { |
| | 448 | if (s1.len != s2.len) |
| | 449 | return false; |
| | 450 | for (size_t i = 0; i < s1.len; i += 1) { |
| | 451 | if (asciiUpper(s1.ptr[i]) != asciiUpper(s2.ptr[i])) |
| | 452 | return false; |
| | 453 | } |
| | 454 | return true; |
| | 455 | } |
| | 456 | |
| | 457 | // Ported from std/os/path.zig |
| | 458 | static bool compareDiskDesignators(WindowsPathKind kind, Slice<uint8_t> p1, Slice<uint8_t> p2) { |
| | 459 | switch (kind) { |
| | 460 | case WindowsPathKindNone: |
| | 461 | assert(p1.len == 0); |
| | 462 | assert(p2.len == 0); |
| | 463 | return true; |
| | 464 | case WindowsPathKindDrive: |
| | 465 | return asciiUpper(p1.ptr[0]) == asciiUpper(p2.ptr[0]); |
| | 466 | case WindowsPathKindNetworkShare: |
| | 467 | uint8_t sep1 = p1.ptr[0]; |
| | 468 | uint8_t sep2 = p2.ptr[0]; |
| | 469 | |
| | 470 | SplitIterator it1 = memSplit(p1, {&sep1, 1}); |
| | 471 | SplitIterator it2 = memSplit(p2, {&sep2, 1}); |
| | 472 | |
| | 473 | // TODO ASCII is wrong, we actually need full unicode support to compare paths. |
| | 474 | return asciiEqlIgnoreCase(SplitIterator_next(&it1).value, SplitIterator_next(&it2).value) && |
| | 475 | asciiEqlIgnoreCase(SplitIterator_next(&it1).value, SplitIterator_next(&it2).value); |
| | 476 | } |
| | 477 | zig_unreachable(); |
| | 478 | } |
| | 479 | |
| | 480 | // Ported from std/os/path.zig |
| | 481 | static Buf os_path_resolve_windows(Buf **paths_ptr, size_t paths_len) { |
| | 482 | if (paths_len == 0) { |
| | 483 | Buf cwd = BUF_INIT; |
| | 484 | int err; |
| | 485 | if ((err = os_get_cwd(&cwd))) { |
| | 486 | zig_panic("get cwd failed"); |
| | 487 | } |
| | 488 | return cwd; |
| | 489 | } |
| | 490 | |
| | 491 | // determine which disk designator we will result with, if any |
| | 492 | char result_drive_buf[2] = {'_', ':'}; |
| | 493 | Slice<uint8_t> result_disk_designator = str(""); |
| | 494 | WindowsPathKind have_drive_kind = WindowsPathKindNone; |
| | 495 | bool have_abs_path = false; |
| | 496 | size_t first_index = 0; |
| | 497 | size_t max_size = 0; |
| | 498 | for (size_t i = 0; i < paths_len; i += 1) { |
| | 499 | Slice<uint8_t> p = buf_to_slice(paths_ptr[i]); |
| | 500 | WindowsPath parsed = windowsParsePath(p); |
| | 501 | if (parsed.is_abs) { |
| | 502 | have_abs_path = true; |
| | 503 | first_index = i; |
| | 504 | max_size = result_disk_designator.len; |
| | 505 | } |
| | 506 | switch (parsed.kind) { |
| | 507 | case WindowsPathKindDrive: |
| | 508 | result_drive_buf[0] = asciiUpper(parsed.disk_designator.ptr[0]); |
| | 509 | result_disk_designator = str(result_drive_buf); |
| | 510 | have_drive_kind = WindowsPathKindDrive; |
| | 511 | break; |
| | 512 | case WindowsPathKindNetworkShare: |
| | 513 | result_disk_designator = parsed.disk_designator; |
| | 514 | have_drive_kind = WindowsPathKindNetworkShare; |
| | 515 | break; |
| | 516 | case WindowsPathKindNone: |
| | 517 | break; |
| | 518 | } |
| | 519 | max_size += p.len + 1; |
| | 520 | } |
| | 521 | |
| | 522 | // if we will result with a disk designator, loop again to determine |
| | 523 | // which is the last time the disk designator is absolutely specified, if any |
| | 524 | // and count up the max bytes for paths related to this disk designator |
| | 525 | if (have_drive_kind != WindowsPathKindNone) { |
| | 526 | have_abs_path = false; |
| | 527 | first_index = 0; |
| | 528 | max_size = result_disk_designator.len; |
| | 529 | bool correct_disk_designator = false; |
| | 530 | |
| | 531 | for (size_t i = 0; i < paths_len; i += 1) { |
| | 532 | Slice<uint8_t> p = buf_to_slice(paths_ptr[i]); |
| | 533 | WindowsPath parsed = windowsParsePath(p); |
| | 534 | if (parsed.kind != WindowsPathKindNone) { |
| | 535 | if (parsed.kind == have_drive_kind) { |
| | 536 | correct_disk_designator = compareDiskDesignators(have_drive_kind, result_disk_designator, parsed.disk_designator); |
| | 537 | } else { |
| | 538 | continue; |
| | 539 | } |
| | 540 | } |
| | 541 | if (!correct_disk_designator) { |
| | 542 | continue; |
| | 543 | } |
| | 544 | if (parsed.is_abs) { |
| | 545 | first_index = i; |
| | 546 | max_size = result_disk_designator.len; |
| | 547 | have_abs_path = true; |
| | 548 | } |
| | 549 | max_size += p.len + 1; |
| | 550 | } |
| | 551 | } |
| | 552 | |
| | 553 | // Allocate result and fill in the disk designator, calling getCwd if we have to. |
| | 554 | Slice<uint8_t> result; |
| | 555 | size_t result_index = 0; |
| | 556 | |
| | 557 | if (have_abs_path) { |
| | 558 | switch (have_drive_kind) { |
| | 559 | case WindowsPathKindDrive: { |
| | 560 | result = Slice<uint8_t>::alloc(max_size); |
| | 561 | |
| | 562 | memCopy(result, result_disk_designator); |
| | 563 | result_index += result_disk_designator.len; |
| | 564 | break; |
| | 565 | } |
| | 566 | case WindowsPathKindNetworkShare: { |
| | 567 | result = Slice<uint8_t>::alloc(max_size); |
| | 568 | SplitIterator it = memSplit(buf_to_slice(paths_ptr[first_index]), str("/\\")); |
| | 569 | Slice<uint8_t> server_name = SplitIterator_next(&it).value; |
| | 570 | Slice<uint8_t> other_name = SplitIterator_next(&it).value; |
| | 571 | |
| | 572 | result.ptr[result_index] = '\\'; |
| | 573 | result_index += 1; |
| | 574 | result.ptr[result_index] = '\\'; |
| | 575 | result_index += 1; |
| | 576 | memCopy(result.sliceFrom(result_index), server_name); |
| | 577 | result_index += server_name.len; |
| | 578 | result.ptr[result_index] = '\\'; |
| | 579 | result_index += 1; |
| | 580 | memCopy(result.sliceFrom(result_index), other_name); |
| | 581 | result_index += other_name.len; |
| | 582 | |
| | 583 | result_disk_designator = result.slice(0, result_index); |
| | 584 | break; |
| | 585 | } |
| | 586 | case WindowsPathKindNone: { |
| | 587 | Buf cwd = BUF_INIT; |
| | 588 | int err; |
| | 589 | if ((err = os_get_cwd(&cwd))) { |
| | 590 | zig_panic("get cwd failed"); |
| | 591 | } |
| | 592 | WindowsPath parsed_cwd = windowsParsePath(buf_to_slice(&cwd)); |
| | 593 | result = Slice<uint8_t>::alloc(max_size + parsed_cwd.disk_designator.len + 1); |
| | 594 | memCopy(result, parsed_cwd.disk_designator); |
| | 595 | result_index += parsed_cwd.disk_designator.len; |
| | 596 | result_disk_designator = result.slice(0, parsed_cwd.disk_designator.len); |
| | 597 | if (parsed_cwd.kind == WindowsPathKindDrive) { |
| | 598 | result.ptr[0] = asciiUpper(result.ptr[0]); |
| | 599 | } |
| | 600 | have_drive_kind = parsed_cwd.kind; |
| | 601 | break; |
| | 602 | } |
| | 603 | } |
| | 604 | } else { |
| | 605 | // TODO call get cwd for the result_disk_designator instead of the global one |
| | 606 | Buf cwd = BUF_INIT; |
| | 607 | int err; |
| | 608 | if ((err = os_get_cwd(&cwd))) { |
| | 609 | zig_panic("get cwd failed"); |
| | 610 | } |
| | 611 | result = Slice<uint8_t>::alloc(max_size + buf_len(&cwd) + 1); |
| | 612 | |
| | 613 | memCopy(result, buf_to_slice(&cwd)); |
| | 614 | result_index += buf_len(&cwd); |
| | 615 | WindowsPath parsed_cwd = windowsParsePath(result.slice(0, result_index)); |
| | 616 | result_disk_designator = parsed_cwd.disk_designator; |
| | 617 | if (parsed_cwd.kind == WindowsPathKindDrive) { |
| | 618 | result.ptr[0] = asciiUpper(result.ptr[0]); |
| | 619 | } |
| | 620 | have_drive_kind = parsed_cwd.kind; |
| | 621 | } |
| | 622 | |
| | 623 | // Now we know the disk designator to use, if any, and what kind it is. And our result |
| | 624 | // is big enough to append all the paths to. |
| | 625 | bool correct_disk_designator = true; |
| | 626 | for (size_t i = 0; i < paths_len; i += 1) { |
| | 627 | Slice<uint8_t> p = buf_to_slice(paths_ptr[i]); |
| | 628 | WindowsPath parsed = windowsParsePath(p); |
| | 629 | |
| | 630 | if (parsed.kind != WindowsPathKindNone) { |
| | 631 | if (parsed.kind == have_drive_kind) { |
| | 632 | correct_disk_designator = compareDiskDesignators(have_drive_kind, result_disk_designator, parsed.disk_designator); |
| | 633 | } else { |
| | 634 | continue; |
| | 635 | } |
| | 636 | } |
| | 637 | if (!correct_disk_designator) { |
| | 638 | continue; |
| | 639 | } |
| | 640 | SplitIterator it = memSplit(p.sliceFrom(parsed.disk_designator.len), str("/\\")); |
| | 641 | while (true) { |
| | 642 | Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it); |
| | 643 | if (!opt_component.is_some) break; |
| | 644 | Slice<uint8_t> component = opt_component.value; |
| | 645 | if (memEql(component, str("."))) { |
| | 646 | continue; |
| | 647 | } else if (memEql(component, str(".."))) { |
| | 648 | while (true) { |
| | 649 | if (result_index == 0 || result_index == result_disk_designator.len) |
| | 650 | break; |
| | 651 | result_index -= 1; |
| | 652 | if (result.ptr[result_index] == '\\' || result.ptr[result_index] == '/') |
| | 653 | break; |
| | 654 | } |
| | 655 | } else { |
| | 656 | result.ptr[result_index] = '\\'; |
| | 657 | result_index += 1; |
| | 658 | memCopy(result.sliceFrom(result_index), component); |
| | 659 | result_index += component.len; |
| | 660 | } |
| | 661 | } |
| | 662 | } |
| | 663 | |
| | 664 | if (result_index == result_disk_designator.len) { |
| | 665 | result.ptr[result_index] = '\\'; |
| | 666 | result_index += 1; |
| | 667 | } |
| | 668 | |
| | 669 | Buf return_value = BUF_INIT; |
| | 670 | buf_init_from_mem(&return_value, (char *)result.ptr, result_index); |
| | 671 | return return_value; |
| | 672 | } |
| | 673 | #endif |
| | 674 | |
| | 675 | #if defined(ZIG_OS_POSIX) |
| | 676 | // Ported from std/os/path.zig |
| | 677 | static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) { |
| | 678 | if (paths_len == 0) { |
| | 679 | Buf cwd = BUF_INIT; |
| | 680 | int err; |
| | 681 | if ((err = os_get_cwd(&cwd))) { |
| | 682 | zig_panic("get cwd failed"); |
| | 683 | } |
| | 684 | return cwd; |
| | 685 | } |
| | 686 | |
| | 687 | size_t first_index = 0; |
| | 688 | bool have_abs = false; |
| | 689 | size_t max_size = 0; |
| | 690 | for (size_t i = 0; i < paths_len; i += 1) { |
| | 691 | Buf *p = paths_ptr[i]; |
| | 692 | if (os_path_is_absolute(p)) { |
| | 693 | first_index = i; |
| | 694 | have_abs = true; |
| | 695 | max_size = 0; |
| | 696 | } |
| | 697 | max_size += buf_len(p) + 1; |
| | 698 | } |
| | 699 | |
| | 700 | uint8_t *result_ptr; |
| | 701 | size_t result_len; |
| | 702 | size_t result_index = 0; |
| | 703 | |
| | 704 | if (have_abs) { |
| | 705 | result_len = max_size; |
| | 706 | result_ptr = allocate_nonzero<uint8_t>(result_len); |
| | 707 | } else { |
| | 708 | Buf cwd = BUF_INIT; |
| | 709 | int err; |
| | 710 | if ((err = os_get_cwd(&cwd))) { |
| | 711 | zig_panic("get cwd failed"); |
| | 712 | } |
| | 713 | result_len = max_size + buf_len(&cwd) + 1; |
| | 714 | result_ptr = allocate_nonzero<uint8_t>(result_len); |
| | 715 | memcpy(result_ptr, buf_ptr(&cwd), buf_len(&cwd)); |
| | 716 | result_index += buf_len(&cwd); |
| | 717 | } |
| | 718 | |
| | 719 | for (size_t i = first_index; i < paths_len; i += 1) { |
| | 720 | Buf *p = paths_ptr[i]; |
| | 721 | SplitIterator it = memSplit(buf_to_slice(p), str("/")); |
| | 722 | while (true) { |
| | 723 | Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it); |
| | 724 | if (!opt_component.is_some) break; |
| | 725 | Slice<uint8_t> component = opt_component.value; |
| | 726 | |
| | 727 | if (memEql<uint8_t>(component, str("."))) { |
| | 728 | continue; |
| | 729 | } else if (memEql<uint8_t>(component, str(".."))) { |
| | 730 | while (true) { |
| | 731 | if (result_index == 0) |
| | 732 | break; |
| | 733 | result_index -= 1; |
| | 734 | if (result_ptr[result_index] == '/') |
| | 735 | break; |
| | 736 | } |
| | 737 | } else { |
| | 738 | result_ptr[result_index] = '/'; |
| | 739 | result_index += 1; |
| | 740 | memcpy(result_ptr + result_index, component.ptr, component.len); |
| | 741 | result_index += component.len; |
| | 742 | } |
| | 743 | } |
| | 744 | } |
| | 745 | |
| | 746 | if (result_index == 0) { |
| | 747 | result_ptr[0] = '/'; |
| | 748 | result_index += 1; |
| | 749 | } |
| | 750 | |
| | 751 | Buf return_value = BUF_INIT; |
| | 752 | buf_init_from_mem(&return_value, (char *)result_ptr, result_index); |
| | 753 | return return_value; |
| | 754 | } |
| | 755 | #endif |
| | 756 | |
| | 757 | // Ported from std/os/path.zig |
| | 758 | Buf os_path_resolve(Buf **paths_ptr, size_t paths_len) { |
| | 759 | #if defined(ZIG_OS_WINDOWS) |
| | 760 | return os_path_resolve_windows(paths_ptr, paths_len); |
| | 761 | #elif defined(ZIG_OS_POSIX) |
| | 762 | return os_path_resolve_posix(paths_ptr, paths_len); |
| | 763 | #else |
| | 764 | #error "missing os_path_resolve implementation" |
| | 765 | #endif |
| 293 | } | 766 | } |
| 294 | | 767 | |
| 295 | int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) { | 768 | int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) { |
| ... | @@ -558,7 +1031,7 @@ int os_exec_process(const char *exe, ZigList<const char *> &args, | ... | @@ -558,7 +1031,7 @@ int os_exec_process(const char *exe, ZigList<const char *> &args, |
| 558 | void os_write_file(Buf *full_path, Buf *contents) { | 1031 | void os_write_file(Buf *full_path, Buf *contents) { |
| 559 | FILE *f = fopen(buf_ptr(full_path), "wb"); | 1032 | FILE *f = fopen(buf_ptr(full_path), "wb"); |
| 560 | if (!f) { | 1033 | if (!f) { |
| 561 | zig_panic("open failed"); | 1034 | zig_panic("os_write_file failed for %s", buf_ptr(full_path)); |
| 562 | } | 1035 | } |
| 563 | size_t amt_written = fwrite(buf_ptr(contents), 1, buf_len(contents), f); | 1036 | size_t amt_written = fwrite(buf_ptr(contents), 1, buf_len(contents), f); |
| 564 | if (amt_written != (size_t)buf_len(contents)) | 1037 | if (amt_written != (size_t)buf_len(contents)) |
| ... | @@ -645,21 +1118,19 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) { | ... | @@ -645,21 +1118,19 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) { |
| 645 | | 1118 | |
| 646 | int os_get_cwd(Buf *out_cwd) { | 1119 | int os_get_cwd(Buf *out_cwd) { |
| 647 | #if defined(ZIG_OS_WINDOWS) | 1120 | #if defined(ZIG_OS_WINDOWS) |
| 648 | buf_resize(out_cwd, 4096); | 1121 | char buf[4096]; |
| 649 | if (GetCurrentDirectory(buf_len(out_cwd), buf_ptr(out_cwd)) == 0) { | 1122 | if (GetCurrentDirectory(4096, buf) == 0) { |
| 650 | zig_panic("GetCurrentDirectory failed"); | 1123 | zig_panic("GetCurrentDirectory failed"); |
| 651 | } | 1124 | } |
| | 1125 | buf_init_from_str(out_cwd, buf); |
| 652 | return 0; | 1126 | return 0; |
| 653 | #elif defined(ZIG_OS_POSIX) | 1127 | #elif defined(ZIG_OS_POSIX) |
| 654 | int err = ERANGE; | 1128 | char buf[PATH_MAX]; |
| 655 | buf_resize(out_cwd, 512); | 1129 | char *res = getcwd(buf, PATH_MAX); |
| 656 | while (err == ERANGE) { | 1130 | if (res == nullptr) { |
| 657 | buf_resize(out_cwd, buf_len(out_cwd) * 2); | 1131 | zig_panic("unable to get cwd: %s", strerror(errno)); |
| 658 | err = getcwd(buf_ptr(out_cwd), buf_len(out_cwd)) ? 0 : errno; | | |
| 659 | } | 1132 | } |
| 660 | if (err) | 1133 | buf_init_from_str(out_cwd, res); |
| 661 | zig_panic("unable to get cwd: %s", strerror(err)); | | |
| 662 | | | |
| 663 | return 0; | 1134 | return 0; |
| 664 | #else | 1135 | #else |
| 665 | #error "missing os_get_cwd implementation" | 1136 | #error "missing os_get_cwd implementation" |
| ... | @@ -898,21 +1369,20 @@ double os_get_time(void) { | ... | @@ -898,21 +1369,20 @@ double os_get_time(void) { |
| 898 | } | 1369 | } |
| 899 | | 1370 | |
| 900 | int os_make_path(Buf *path) { | 1371 | int os_make_path(Buf *path) { |
| 901 | Buf *resolved_path = buf_alloc(); | 1372 | Buf resolved_path = os_path_resolve(&path, 1); |
| 902 | os_path_resolve(buf_create_from_str("."), path, resolved_path); | | |
| 903 | | 1373 | |
| 904 | size_t end_index = buf_len(resolved_path); | 1374 | size_t end_index = buf_len(&resolved_path); |
| 905 | int err; | 1375 | int err; |
| 906 | while (true) { | 1376 | while (true) { |
| 907 | if ((err = os_make_dir(buf_slice(resolved_path, 0, end_index)))) { | 1377 | if ((err = os_make_dir(buf_slice(&resolved_path, 0, end_index)))) { |
| 908 | if (err == ErrorPathAlreadyExists) { | 1378 | if (err == ErrorPathAlreadyExists) { |
| 909 | if (end_index == buf_len(resolved_path)) | 1379 | if (end_index == buf_len(&resolved_path)) |
| 910 | return 0; | 1380 | return 0; |
| 911 | } else if (err == ErrorFileNotFound) { | 1381 | } else if (err == ErrorFileNotFound) { |
| 912 | // march end_index backward until next path component | 1382 | // march end_index backward until next path component |
| 913 | while (true) { | 1383 | while (true) { |
| 914 | end_index -= 1; | 1384 | end_index -= 1; |
| 915 | if (os_is_sep(buf_ptr(resolved_path)[end_index])) | 1385 | if (os_is_sep(buf_ptr(&resolved_path)[end_index])) |
| 916 | break; | 1386 | break; |
| 917 | } | 1387 | } |
| 918 | continue; | 1388 | continue; |
| ... | @@ -920,12 +1390,12 @@ int os_make_path(Buf *path) { | ... | @@ -920,12 +1390,12 @@ int os_make_path(Buf *path) { |
| 920 | return err; | 1390 | return err; |
| 921 | } | 1391 | } |
| 922 | } | 1392 | } |
| 923 | if (end_index == buf_len(resolved_path)) | 1393 | if (end_index == buf_len(&resolved_path)) |
| 924 | return 0; | 1394 | return 0; |
| 925 | // march end_index forward until next path component | 1395 | // march end_index forward until next path component |
| 926 | while (true) { | 1396 | while (true) { |
| 927 | end_index += 1; | 1397 | end_index += 1; |
| 928 | if (end_index == buf_len(resolved_path) || os_is_sep(buf_ptr(resolved_path)[end_index])) | 1398 | if (end_index == buf_len(&resolved_path) || os_is_sep(buf_ptr(&resolved_path)[end_index])) |
| 929 | break; | 1399 | break; |
| 930 | } | 1400 | } |
| 931 | } | 1401 | } |