3477 createSymbolicLinkFrom:oldPath to:newPath |
3486 createSymbolicLinkFrom:oldPath to:newPath |
3478 "make a symbolic link for 'newPath' to the file 'oldPath'. |
3487 "make a symbolic link for 'newPath' to the file 'oldPath'. |
3479 The link will be a soft (symbolic) link. |
3488 The link will be a soft (symbolic) link. |
3480 Return true if successful, false if not." |
3489 Return true if successful, false if not." |
3481 |
3490 |
|
3491 |encodedOldPathName encodedNewPathName| |
|
3492 |
|
3493 encodedOldPathName := self encodePath:oldPath. |
|
3494 encodedNewPathName := self encodePath:newPath. |
3482 %{ |
3495 %{ |
3483 #ifdef S_IFLNK |
3496 #ifdef S_IFLNK |
3484 int ret; |
3497 int ret; |
3485 |
3498 |
3486 if (__isStringLike(oldPath) && __isStringLike(newPath)) { |
3499 if (__isStringLike(encodedOldPathName) && __isStringLike(encodedNewPathName)) { |
3487 __BEGIN_INTERRUPTABLE__ |
3500 __BEGIN_INTERRUPTABLE__ |
3488 do { |
3501 do { |
3489 ret = symlink((char *) __stringVal(oldPath), (char *) __stringVal(newPath)); |
3502 ret = symlink((char *) __stringVal(encodedOldPathName), (char *) __stringVal(encodedNewPathName)); |
3490 } while (ret < 0 && errno == EINTR); |
3503 } while (ret < 0 && errno == EINTR); |
3491 __END_INTERRUPTABLE__ |
3504 __END_INTERRUPTABLE__ |
3492 if (ret < 0) { |
3505 if (ret < 0) { |
3493 @global(LastErrorNumber) = __mkSmallInteger(errno); |
3506 @global(LastErrorNumber) = __mkSmallInteger(errno); |
3494 RETURN ( false ); |
3507 RETURN ( false ); |
3495 } |
3508 } |
3496 RETURN (true); |
3509 RETURN (true); |
3497 } |
3510 } |
3498 #endif |
3511 #endif |
3499 %}. |
3512 %}. |
3500 (oldPath isString not or:[newPath isString not]) ifTrue:[ |
3513 (encodedOldPathName isString not or:[encodedNewPathName isString not]) ifTrue:[ |
3501 "/ |
3514 "/ |
3502 "/ bad argument(s) given |
3515 "/ bad argument(s) given |
3503 "/ |
3516 "/ |
3504 ^ self primitiveFailed |
3517 ^ self primitiveFailed |
3505 ]. |
3518 ]. |
3506 |
3519 |
3507 "/ |
3520 "/ |
3508 "/ this Unix does not seem to support symbolic links |
3521 "/ this Unix does not seem to support symbolic links |
3509 "/ |
3522 "/ |
3516 |
3529 |
3517 open:path attributes:attributes mode:modeInteger |
3530 open:path attributes:attributes mode:modeInteger |
3518 "open a file, return an os specific fileHandle. |
3531 "open a file, return an os specific fileHandle. |
3519 openmode is a symbol defining the way to open |
3532 openmode is a symbol defining the way to open |
3520 valid modes are: |
3533 valid modes are: |
3521 #O_RDONLY |
3534 #O_RDONLY |
3522 #O_RDWR |
3535 #O_RDWR |
3523 #O_WRONLY |
3536 #O_WRONLY |
3524 #O_CREAT |
3537 #O_CREAT |
3525 #O_APPEND |
3538 #O_APPEND |
3526 #O_SYNC |
3539 #O_SYNC |
3527 #O_LARGEFILE |
3540 #O_LARGEFILE |
3528 |
3541 |
3529 This is a private entry, but maybe useful to open/create a file in a special mode, |
3542 This is a private entry, but maybe useful to open/create a file in a special mode, |
3530 which is proprietrary to the operatingSystem." |
3543 which is proprietrary to the operatingSystem." |
3531 |
3544 |
3532 |error fileDescriptor| |
3545 |error fileDescriptor encodedPathName| |
|
3546 |
|
3547 encodedPathName := self encodePath:path. |
3533 |
3548 |
3534 %{ |
3549 %{ |
3535 OBJ *ap; |
3550 OBJ *ap; |
3536 int nAttributes; |
3551 int nAttributes; |
3537 int fd; |
3552 int fd; |
3538 int mode, openFlags = 0; |
3553 int mode, openFlags = 0; |
3539 int n; |
3554 int n; |
3540 |
3555 |
3541 if (!__isStringLike(path)) { |
3556 if (!__isStringLike(encodedPathName)) { |
3542 error = @symbol(badArgument1); |
3557 error = @symbol(badArgument1); |
3543 goto err; |
3558 goto err; |
3544 } |
3559 } |
3545 if (!__isArrayLike(attributes)) { |
3560 if (!__isArrayLike(attributes)) { |
3546 error = @symbol(badArgument2); |
3561 error = @symbol(badArgument2); |
3547 goto err; |
3562 goto err; |
3548 } |
3563 } |
3549 if (modeInteger == nil) { |
3564 if (modeInteger == nil) { |
3550 mode = 0644; |
3565 mode = 0644; |
3551 } else if (__isSmallInteger(modeInteger)) { |
3566 } else if (__isSmallInteger(modeInteger)) { |
3552 mode = __intVal(modeInteger); |
3567 mode = __intVal(modeInteger); |
3553 } else { |
3568 } else { |
3554 error = @symbol(badArgument3); |
3569 error = @symbol(badArgument3); |
3555 goto err; |
3570 goto err; |
3556 } |
3571 } |
3557 |
3572 |
3558 nAttributes = __arraySize(attributes); |
3573 nAttributes = __arraySize(attributes); |
3559 for (n = 0, ap = __arrayVal(attributes); n < nAttributes; n++) { |
3574 for (n = 0, ap = __arrayVal(attributes); n < nAttributes; n++) { |
3560 OBJ attribute = ap[n]; |
3575 OBJ attribute = ap[n]; |
3561 |
3576 |
3562 if (attribute == @symbol(O_RDONLY)) { |
3577 if (attribute == @symbol(O_RDONLY)) { |
3563 openFlags |= O_RDONLY; |
3578 openFlags |= O_RDONLY; |
3564 } else if (attribute == @symbol(O_RDWR)) { |
3579 } else if (attribute == @symbol(O_RDWR)) { |
3565 openFlags |= O_RDWR; |
3580 openFlags |= O_RDWR; |
3566 } else if (attribute == @symbol(O_WRONLY)) { |
3581 } else if (attribute == @symbol(O_WRONLY)) { |
3567 openFlags |= O_WRONLY; |
3582 openFlags |= O_WRONLY; |
3568 } else if (attribute == @symbol(O_CREAT)) { |
3583 } else if (attribute == @symbol(O_CREAT)) { |
3569 openFlags |= O_CREAT; |
3584 openFlags |= O_CREAT; |
3570 } else if (attribute == @symbol(O_APPEND)) { |
3585 } else if (attribute == @symbol(O_APPEND)) { |
3571 openFlags |= O_APPEND; |
3586 openFlags |= O_APPEND; |
3572 } else if (attribute == @symbol(O_EXCL)) { |
3587 } else if (attribute == @symbol(O_EXCL)) { |
3573 openFlags |= O_EXCL; |
3588 openFlags |= O_EXCL; |
3574 } else if (attribute == @symbol(O_TRUNC)) { |
3589 } else if (attribute == @symbol(O_TRUNC)) { |
3575 openFlags |= O_TRUNC; |
3590 openFlags |= O_TRUNC; |
3576 } else if (attribute == @symbol(O_LARGEFILE)) { |
3591 } else if (attribute == @symbol(O_LARGEFILE)) { |
3577 #ifdef O_LARGEFILE |
3592 #ifdef O_LARGEFILE |
3578 openFlags |= O_LARGEFILE; |
3593 openFlags |= O_LARGEFILE; |
3579 #else |
3594 #else |
3580 error = @symbol(badArgument2); |
3595 error = @symbol(badArgument2); |
3581 goto err; |
3596 goto err; |
3582 #endif |
3597 #endif |
3583 } else if (attribute == @symbol(O_SYNC)) { |
3598 } else if (attribute == @symbol(O_SYNC)) { |
3584 #ifdef O_SYNC |
3599 #ifdef O_SYNC |
3585 openFlags |= O_SYNC; |
3600 openFlags |= O_SYNC; |
3586 #else |
3601 #else |
3587 error = @symbol(badArgument2); |
3602 error = @symbol(badArgument2); |
3588 goto err; |
3603 goto err; |
3589 #endif |
3604 #endif |
3590 } |
3605 } |
3591 } |
3606 } |
3592 |
3607 |
3593 #if defined(O_NONBLOCK) |
3608 #if defined(O_NONBLOCK) |
3594 openFlags |= O_NONBLOCK; |
3609 openFlags |= O_NONBLOCK; |
3595 #elif defined(O_NDELAY) |
3610 #elif defined(O_NDELAY) |
3596 openFlags |= O_NDELAY; |
3611 openFlags |= O_NDELAY; |
3597 #endif |
3612 #endif |
3598 |
3613 |
3599 again: |
3614 again: |
3600 fd = open((char *) __stringVal(path), openFlags, mode); |
3615 fd = open((char *) __stringVal(encodedPathName), openFlags, mode); |
3601 if (fd < 0) { |
3616 if (fd < 0) { |
3602 if (errno == EINTR) { |
3617 if (errno == EINTR) { |
3603 __HANDLE_INTERRUPTS__; |
3618 __HANDLE_INTERRUPTS__; |
3604 goto again; |
3619 goto again; |
3605 } else { |
3620 } else { |
3606 error = __mkSmallInteger(errno); |
3621 error = __mkSmallInteger(errno); |
3607 goto err; |
3622 goto err; |
3608 } |
3623 } |
3609 } |
3624 } |
3610 fileDescriptor = __mkSmallInteger(fd); |
3625 fileDescriptor = __mkSmallInteger(fd); |
3611 err:; |
3626 err:; |
3612 %}. |
3627 %}. |
3613 ^ fileDescriptor notNil ifTrue:[ |
3628 ^ fileDescriptor notNil ifTrue:[ |
3614 FileDescriptorHandle for:fileDescriptor. |
3629 FileDescriptorHandle for:fileDescriptor. |
3615 ] ifFalse:[ |
3630 ] ifFalse:[ |
3616 (self errorHolderForNumber:error) reportError |
3631 (self errorHolderForNumber:error) reportError |
3617 ]. |
3632 ]. |
3618 |
3633 |
3619 " |
3634 " |
3620 self open:'/etc/hosts' attributes:#(O_RDONLY) mode:nil |
3635 self open:'/etc/hosts' attributes:#(O_RDONLY) mode:nil |
3621 self open:'/tmp/xxzz' attributes:#(O_RDWR O_CREAT) mode:8r611 |
3636 self open:'/tmp/xxzz' attributes:#(O_RDWR O_CREAT) mode:8r611 |
3622 self open:'/etc/passwd' attributes:#(O_RDWR) mode:nil |
3637 self open:'/etc/passwd' attributes:#(O_RDWR) mode:nil |
3623 self open:'/no one knows this file' attributes:#(O_RDONLY) mode:nil |
3638 self open:'/no one knows this file' attributes:#(O_RDONLY) mode:nil |
3624 self open:'foo/bar/baz' attributes:#(O_RDWR O_CREAT) mode:nil |
3639 self open:'foo/bar/baz' attributes:#(O_RDWR O_CREAT) mode:nil |
3625 " |
3640 " |
3626 ! |
3641 ! |
3627 |
3642 |
3628 openFileForAppend:pathName |
3643 openFileForAppend:pathName |
3629 |
3644 |
3677 "remove the directory named 'fullPathName'. |
3692 "remove the directory named 'fullPathName'. |
3678 The directory must be empty and you must have appropriate access rights. |
3693 The directory must be empty and you must have appropriate access rights. |
3679 Return true if successful, false if directory is not empty or no permission. |
3694 Return true if successful, false if directory is not empty or no permission. |
3680 This is a lowLevel entry - use Filename protocol for compatibility." |
3695 This is a lowLevel entry - use Filename protocol for compatibility." |
3681 |
3696 |
|
3697 |encodedPathName| |
|
3698 |
|
3699 encodedPathName := self encodePath:fullPathName. |
3682 %{ |
3700 %{ |
3683 int ret; |
3701 int ret; |
3684 |
3702 |
3685 if (__isStringLike(fullPathName)) { |
3703 if (__isStringLike(encodedPathName)) { |
3686 __BEGIN_INTERRUPTABLE__ |
3704 __BEGIN_INTERRUPTABLE__ |
3687 do { |
3705 do { |
3688 ret = rmdir((char *) __stringVal(fullPathName)); |
3706 ret = rmdir((char *) __stringVal(encodedPathName)); |
3689 } while (ret < 0 && errno == EINTR); |
3707 } while (ret < 0 && errno == EINTR); |
3690 __END_INTERRUPTABLE__ |
3708 __END_INTERRUPTABLE__ |
3691 if (ret < 0) { |
3709 if (ret < 0) { |
3692 @global(LastErrorNumber) = __mkSmallInteger(errno); |
3710 @global(LastErrorNumber) = __mkSmallInteger(errno); |
3693 RETURN ( false ); |
3711 RETURN ( false ); |
3694 } |
3712 } |
3695 RETURN (true); |
3713 RETURN (true); |
3696 } |
3714 } |
3697 %}. |
3715 %}. |
3698 "/ |
3716 "/ |
3699 "/ either not a string argument, |
3717 "/ either not a string argument, |
3700 "/ or not supported by OS |
3718 "/ or not supported by OS |
3736 correct for the OS used - therefore, this should not be called |
3757 correct for the OS used - therefore, this should not be called |
3737 directly. Instead, use Filename protocol to rename; this cares for |
3758 directly. Instead, use Filename protocol to rename; this cares for |
3738 any invalid names. |
3759 any invalid names. |
3739 Returns true if successful, false if not" |
3760 Returns true if successful, false if not" |
3740 |
3761 |
|
3762 |encodedOldPathName encodedNewPathName| |
|
3763 |
|
3764 encodedOldPathName := self encodePath:oldPath. |
|
3765 encodedNewPathName := self encodePath:newPath. |
3741 %{ |
3766 %{ |
3742 int ret, eno; |
3767 int ret, eno; |
3743 |
3768 |
3744 if (__isStringLike(oldPath) && __isStringLike(newPath)) { |
3769 if (__isStringLike(encodedOldPathName) && __isStringLike(encodedNewPathName)) { |
3745 #if defined(HAS_RENAME) |
3770 #if defined(HAS_RENAME) |
3746 __BEGIN_INTERRUPTABLE__ |
3771 __BEGIN_INTERRUPTABLE__ |
3747 do { |
3772 do { |
3748 ret = rename((char *) __stringVal(oldPath), (char *) __stringVal(newPath)); |
3773 ret = rename((char *) __stringVal(encodedOldPathName), (char *) __stringVal(encodedNewPathName)); |
3749 } while (ret < 0 && errno == EINTR); |
3774 } while (ret < 0 && errno == EINTR); |
3750 __END_INTERRUPTABLE__ |
3775 __END_INTERRUPTABLE__ |
3751 #else |
3776 #else |
3752 ret = link((char *) __stringVal(oldPath), (char *) __stringVal(newPath)); |
3777 ret = link((char *) __stringVal(encodedOldPathName), (char *) __stringVal(encodedNewPathName)); |
3753 if (ret >= 0) { |
3778 if (ret >= 0) { |
3754 ret = unlink((char *) __stringVal(oldPath)); |
3779 ret = unlink((char *) __stringVal(encodedOldPathName)); |
3755 if (ret < 0) { |
3780 if (ret < 0) { |
3756 eno = errno; |
3781 eno = errno; |
3757 unlink((char *) __stringVal(newPath)); |
3782 unlink((char *) __stringVal(encodedNewPathName)); |
3758 errno = eno; |
3783 errno = eno; |
3759 } |
3784 } |
3760 } |
3785 } |
3761 #endif |
3786 #endif |
3762 if (ret < 0) { |
3787 if (ret < 0) { |
3763 @global(LastErrorNumber) = __mkSmallInteger(errno); |
3788 @global(LastErrorNumber) = __mkSmallInteger(errno); |
3764 RETURN ( false ); |
3789 RETURN ( false ); |
3765 } |
3790 } |
3766 RETURN (true); |
3791 RETURN (true); |
3767 } |
3792 } |
3768 %}. |
3793 %}. |
3769 ^ self primitiveFailed |
3794 ^ self primitiveFailed |
3770 |
3795 |
3771 " |
3796 " |
3776 truncateFile:aPathName to:newSize |
3801 truncateFile:aPathName to:newSize |
3777 "change a files size return true on success, false on failure. |
3802 "change a files size return true on success, false on failure. |
3778 This may not be supported on all architectures. |
3803 This may not be supported on all architectures. |
3779 |
3804 |
3780 This is a low-level entry - use Filename protocol." |
3805 This is a low-level entry - use Filename protocol." |
|
3806 |
|
3807 |encodedPathName| |
|
3808 |
|
3809 encodedPathName := self encodePath:aPathName. |
3781 |
3810 |
3782 %{ |
3811 %{ |
3783 #if defined(HAS_TRUNCATE) || defined(HAS_FTRUNCATE) |
3812 #if defined(HAS_TRUNCATE) || defined(HAS_FTRUNCATE) |
3784 int ret; |
3813 int ret; |
3785 off_t truncateSize; |
3814 off_t truncateSize; |
3786 |
3815 |
3787 if (!__isStringLike(aPathName)) |
3816 if (!__isStringLike(encodedPathName)) |
3788 goto getOutOfHere; |
3817 goto getOutOfHere; |
3789 |
3818 |
3790 if (__isSmallInteger(newSize)) { |
3819 if (__isSmallInteger(newSize)) { |
3791 truncateSize = __intVal(newSize); |
3820 truncateSize = __intVal(newSize); |
3792 if (truncateSize < 0) { |
3821 if (truncateSize < 0) { |
3793 goto getOutOfHere; |
3822 goto getOutOfHere; |
3794 } |
3823 } |
3795 } else { |
3824 } else { |
3796 truncateSize = __signedLongIntVal(newSize); |
3825 truncateSize = __signedLongIntVal(newSize); |
3797 if (truncateSize < 0) { |
3826 if (truncateSize < 0) { |
3798 goto getOutOfHere; |
3827 goto getOutOfHere; |
3799 } |
3828 } |
3800 if (truncateSize == 0) { |
3829 if (truncateSize == 0) { |
3801 if (sizeof(truncateSize) == 8) { |
3830 if (sizeof(truncateSize) == 8) { |
3802 if (__signedLong64IntVal(newSize, &truncateSize) == 0 || truncateSize < 0) { |
3831 if (__signedLong64IntVal(newSize, &truncateSize) == 0 || truncateSize < 0) { |
3803 goto getOutOfHere; |
3832 goto getOutOfHere; |
3804 } |
3833 } |
3805 } else { |
3834 } else { |
3806 goto getOutOfHere; |
3835 goto getOutOfHere; |
3807 } |
3836 } |
3808 } |
3837 } |
3809 } |
3838 } |
3810 |
3839 |
3811 #if defined(HAS_TRUNCATE) |
3840 #if defined(HAS_TRUNCATE) |
3812 __BEGIN_INTERRUPTABLE__ |
3841 __BEGIN_INTERRUPTABLE__ |
3813 do { |
3842 do { |
3814 ret = truncate((char *) __stringVal(aPathName), truncateSize); |
3843 ret = truncate((char *) __stringVal(encodedPathName), truncateSize); |
3815 } while (ret < 0 && errno == EINTR); |
3844 } while (ret < 0 && errno == EINTR); |
3816 __END_INTERRUPTABLE__ |
3845 __END_INTERRUPTABLE__ |
3817 #else |
3846 #else |
3818 # ifdef HAS_FTRUNCATE |
3847 # ifdef HAS_FTRUNCATE |
3819 { |
3848 { |
3820 int fd; |
3849 int fd; |
3821 |
3850 |
3822 do { |
3851 do { |
3823 fd = open((char *) __stringVal(aPathName), 2); |
3852 fd = open((char *) __stringVal(encodedPathName), 2); |
3824 } while (fd < 0 && errno == EINTR); |
3853 } while (fd < 0 && errno == EINTR); |
3825 if (fd < 0) { |
3854 if (fd < 0) { |
3826 @global(LastErrorNumber) = __mkSmallInteger(errno); |
3855 @global(LastErrorNumber) = __mkSmallInteger(errno); |
3827 RETURN ( false ); |
3856 RETURN ( false ); |
3828 } |
3857 } |
3829 |
3858 |
3830 ret = ftruncate(fd, truncateSize); |
3859 ret = ftruncate(fd, truncateSize); |
3831 close(fd); |
3860 close(fd); |
3832 } |
3861 } |
3833 # endif /* HAS_FTRUNCATE */ |
3862 # endif /* HAS_FTRUNCATE */ |
3834 #endif |
3863 #endif |
3835 if (ret < 0) { |
3864 if (ret < 0) { |
3836 @global(LastErrorNumber) = __mkSmallInteger(errno); |
3865 @global(LastErrorNumber) = __mkSmallInteger(errno); |
3837 RETURN ( false ); |
3866 RETURN ( false ); |
3838 } |
3867 } |
3839 RETURN (true); |
3868 RETURN (true); |
3840 getOutOfHere:; |
3869 getOutOfHere:; |
3841 #endif |
3870 #endif |
3842 %}. |
3871 %}. |
3920 Notice that the returned number is OS dependent - use the |
3949 Notice that the returned number is OS dependent - use the |
3921 modeMasks as returned by OperatingSystem>>accessMaskFor:" |
3950 modeMasks as returned by OperatingSystem>>accessMaskFor:" |
3922 |
3951 |
3923 " |
3952 " |
3924 this could have been implemented as: |
3953 this could have been implemented as: |
3925 (self infoOf:aPathName) at:#mode |
3954 (self infoOf:aPathName) at:#mode |
3926 but for huge directory searches the code below is faster |
3955 but for huge directory searches the code below is faster |
3927 " |
3956 " |
3928 |
3957 |
|
3958 |encodedPathName| |
|
3959 |
|
3960 encodedPathName := self encodePath:aPathName. |
3929 %{ |
3961 %{ |
3930 struct stat buf; |
3962 struct stat buf; |
3931 int ret; |
3963 int ret; |
3932 |
3964 |
3933 if (__isStringLike(aPathName)) { |
3965 if (__isStringLike(encodedPathName)) { |
3934 # ifdef TRACE_STAT_CALLS |
3966 # ifdef TRACE_STAT_CALLS |
3935 printf("stat on '%s' for accessMode\n", __stringVal(aPathName)); |
3967 printf("stat on '%s' for accessMode\n", __stringVal(encodedPathName)); |
3936 # endif |
3968 # endif |
3937 __BEGIN_INTERRUPTABLE__ |
3969 __BEGIN_INTERRUPTABLE__ |
3938 do { |
3970 do { |
3939 ret = stat((char *) __stringVal(aPathName), &buf); |
3971 ret = stat((char *) __stringVal(encodedPathName), &buf); |
3940 } while ((ret < 0) && (errno == EINTR)); |
3972 } while ((ret < 0) && (errno == EINTR)); |
3941 __END_INTERRUPTABLE__ |
3973 __END_INTERRUPTABLE__ |
3942 |
3974 |
3943 if (ret < 0) { |
3975 if (ret < 0) { |
3944 @global(LastErrorNumber) = __mkSmallInteger(errno); |
3976 @global(LastErrorNumber) = __mkSmallInteger(errno); |
3945 RETURN ( nil ); |
3977 RETURN ( nil ); |
3946 } |
3978 } |
3947 RETURN ( __mkSmallInteger(buf.st_mode & 0777) ); |
3979 RETURN ( __mkSmallInteger(buf.st_mode & 0777) ); |
3948 } |
3980 } |
3949 %}. |
3981 %}. |
3950 ^ self primitiveFailed |
3982 ^ self primitiveFailed |
3951 |
3983 |
3952 " |
3984 " |
4464 |
4501 |
4465 infoOf:aPathName |
4502 infoOf:aPathName |
4466 "return some object filled with info for the file 'aPathName'; |
4503 "return some object filled with info for the file 'aPathName'; |
4467 the info (for which corresponding access methods are understood by |
4504 the info (for which corresponding access methods are understood by |
4468 the returned object) is: |
4505 the returned object) is: |
4469 type - a symbol giving the files type |
4506 type - a symbol giving the files type |
4470 mode - numeric access mode |
4507 mode - numeric access mode |
4471 uid - owners user id |
4508 uid - owners user id |
4472 gid - owners group id |
4509 gid - owners group id |
4473 size - files size |
4510 size - files size |
4474 id - files number (i.e. inode number) |
4511 id - files number (i.e. inode number) |
4475 accessed - last access time (as Timestamp) |
4512 accessed - last access time (as Timestamp) |
4476 modified - last modification time (as Timestamp) |
4513 modified - last modification time (as Timestamp) |
4477 statusChanged - last status change time (as Timestamp) |
4514 statusChanged - last status change time (as Timestamp) |
4478 alternativeName - (windows only:) the MSDOS name of the file |
4515 alternativeName - (windows only:) the MSDOS name of the file |
4479 recordFormatNumeric - (VMS only:) numeric value of the recordFormat |
4516 recordFormatNumeric - (VMS only:) numeric value of the recordFormat |
4480 recordFormat - (VMS only:) symbolic value of the recordFormat |
4517 recordFormat - (VMS only:) symbolic value of the recordFormat |
4481 recordAttributes - (VMS only:) recordAttributes |
4518 recordAttributes - (VMS only:) recordAttributes |
4482 fixedHeaderSize - (VMS only:) fixed header size in a variable record format |
4519 fixedHeaderSize - (VMS only:) fixed header size in a variable record format |
4483 recordSize - (VMS only:) record size. |
4520 recordSize - (VMS only:) record size. |
4484 |
4521 |
4485 Some of the fields may be returned as nil on systems which do not provide |
4522 Some of the fields may be returned as nil on systems which do not provide |
4486 all of the information. |
4523 all of the information. |
4487 Return nil if such a file does not exist. |
4524 Return nil if such a file does not exist. |
4488 For symbolic links (if supported by the OS), |
4525 For symbolic links (if supported by the OS), |
4489 the info of the pointed-to-file (i.e. the target) is returned; |
4526 the info of the pointed-to-file (i.e. the target) is returned; |
4490 use #linkInfoOf: to get info about the link itself. |
4527 use #linkInfoOf: to get info about the link itself. |
4491 " |
4528 " |
4492 |
4529 |
4493 |type mode uid gid size id nLink aOStime mOStime cOStime error| |
4530 |type mode uid gid size id nLink aOStime mOStime cOStime error encodedPathName| |
|
4531 |
|
4532 encodedPathName := self encodePath:aPathName. |
4494 %{ |
4533 %{ |
4495 struct stat buf; |
4534 struct stat buf; |
4496 int ret; |
4535 int ret; |
4497 |
4536 |
4498 if (!__isStringLike(aPathName)) { |
4537 if (!__isStringLike(encodedPathName)) { |
4499 error = @symbol(badArgument); |
4538 error = @symbol(badArgument); |
4500 goto out; |
4539 goto out; |
4501 } |
4540 } |
4502 |
4541 |
4503 # ifdef TRACE_STAT_CALLS |
4542 # ifdef TRACE_STAT_CALLS |
4504 printf("stat on '%s' for info\n", __stringVal(aPathName)); |
4543 printf("stat on '%s' for info\n", __stringVal(aPathName)); |
4505 # endif |
4544 # endif |
4506 __BEGIN_INTERRUPTABLE__ |
4545 __BEGIN_INTERRUPTABLE__ |
4507 do { |
4546 do { |
4508 ret = stat((char *) __stringVal(aPathName), &buf); |
4547 ret = stat((char *) __stringVal(encodedPathName), &buf); |
4509 } while ((ret < 0) && (errno == EINTR)); |
4548 } while ((ret < 0) && (errno == EINTR)); |
4510 __END_INTERRUPTABLE__ |
4549 __END_INTERRUPTABLE__ |
4511 |
4550 |
4512 if (ret < 0) { |
4551 if (ret < 0) { |
4513 error = __mkSmallInteger(errno); |
4552 error = __mkSmallInteger(errno); |
4514 @global(LastErrorNumber) = error; |
4553 @global(LastErrorNumber) = error; |
4515 goto out; |
4554 goto out; |
4516 } |
4555 } |
4517 switch (buf.st_mode & S_IFMT) { |
4556 switch (buf.st_mode & S_IFMT) { |
4518 case S_IFDIR: |
4557 case S_IFDIR: |
4519 type = @symbol(directory); |
4558 type = @symbol(directory); |
4520 break; |
4559 break; |
4521 |
4560 |
4522 case S_IFREG: |
4561 case S_IFREG: |
4523 type = @symbol(regular); |
4562 type = @symbol(regular); |
4524 break; |
4563 break; |
4525 # ifdef S_IFCHR |
4564 # ifdef S_IFCHR |
4526 case S_IFCHR: |
4565 case S_IFCHR: |
4527 type = @symbol(characterSpecial); |
4566 type = @symbol(characterSpecial); |
4528 break; |
4567 break; |
4529 # endif |
4568 # endif |
4530 # ifdef S_IFBLK |
4569 # ifdef S_IFBLK |
4531 case S_IFBLK: |
4570 case S_IFBLK: |
4532 type = @symbol(blockSpecial); |
4571 type = @symbol(blockSpecial); |
4533 break; |
4572 break; |
4534 # endif |
4573 # endif |
4535 # ifdef S_IFMPC |
4574 # ifdef S_IFMPC |
4536 case S_IFMPC: |
4575 case S_IFMPC: |
4537 type = @symbol(multiplexedCharacterSpecial); |
4576 type = @symbol(multiplexedCharacterSpecial); |
4538 break; |
4577 break; |
4539 # endif |
4578 # endif |
4540 # ifdef S_IFMPB |
4579 # ifdef S_IFMPB |
4541 case S_IFMPB: |
4580 case S_IFMPB: |
4542 type = @symbol(multiplexedBlockSpecial); |
4581 type = @symbol(multiplexedBlockSpecial); |
4543 break; |
4582 break; |
4544 # endif |
4583 # endif |
4545 # ifdef S_IFLNK |
4584 # ifdef S_IFLNK |
4546 case S_IFLNK: |
4585 case S_IFLNK: |
4547 type = @symbol(symbolicLink); |
4586 type = @symbol(symbolicLink); |
4548 break; |
4587 break; |
4549 # endif |
4588 # endif |
4550 # ifdef S_IFSOCK |
4589 # ifdef S_IFSOCK |
4551 case S_IFSOCK: |
4590 case S_IFSOCK: |
4552 type = @symbol(socket); |
4591 type = @symbol(socket); |
4553 break; |
4592 break; |
4554 # endif |
4593 # endif |
4555 # ifdef S_IFIFO |
4594 # ifdef S_IFIFO |
4556 case S_IFIFO: |
4595 case S_IFIFO: |
4557 type = @symbol(fifo); |
4596 type = @symbol(fifo); |
4558 break; |
4597 break; |
4559 # endif |
4598 # endif |
4560 default: |
4599 default: |
4561 type = @symbol(unknown); |
4600 type = @symbol(unknown); |
4562 break; |
4601 break; |
4563 } |
4602 } |
4564 |
4603 |
4565 if (sizeof(buf.st_ino) == 8) { |
4604 if (sizeof(buf.st_ino) == 8) { |
4566 id = __MKUINT64(&buf.st_ino); |
4605 id = __MKUINT64(&buf.st_ino); |
4567 } else { |
4606 } else { |
4568 id = __MKUINT(buf.st_ino); |
4607 id = __MKUINT(buf.st_ino); |
4569 } |
4608 } |
4570 mode = __mkSmallInteger(buf.st_mode & 0777); |
4609 mode = __mkSmallInteger(buf.st_mode & 0777); |
4571 uid = __mkSmallInteger(buf.st_uid); |
4610 uid = __mkSmallInteger(buf.st_uid); |
4572 gid = __mkSmallInteger(buf.st_gid); |
4611 gid = __mkSmallInteger(buf.st_gid); |
4573 nLink = __mkSmallInteger(buf.st_nlink); |
4612 nLink = __mkSmallInteger(buf.st_nlink); |
4574 if (sizeof(buf.st_size) == 8) { |
4613 if (sizeof(buf.st_size) == 8) { |
4575 size = __MKINT64(&buf.st_size); |
4614 size = __MKINT64(&buf.st_size); |
4576 } else { |
4615 } else { |
4577 size = __MKINT(buf.st_size); |
4616 size = __MKINT(buf.st_size); |
4578 } |
4617 } |
4579 aOStime = __MKUINT(buf.st_atime); |
4618 aOStime = __MKUINT(buf.st_atime); |
4580 mOStime = __MKUINT(buf.st_mtime); |
4619 mOStime = __MKUINT(buf.st_mtime); |
4581 cOStime = __MKUINT(buf.st_ctime); |
4620 cOStime = __MKUINT(buf.st_ctime); |
4582 |
4621 |
4583 out:; |
4622 out:; |
4584 %}. |
4623 %}. |
4585 mode notNil ifTrue:[ |
4624 mode notNil ifTrue:[ |
4586 "/ now done lazy in FileStatusInfo |
4625 "/ now done lazy in FileStatusInfo |
4587 "/ atime := Timestamp fromOSTime:(aOStime * 1000). |
4626 "/ atime := Timestamp fromOSTime:(aOStime * 1000). |
4588 "/ mtime := Timestamp fromOSTime:(mOStime * 1000). |
4627 "/ mtime := Timestamp fromOSTime:(mOStime * 1000). |
4589 "/ ctime := Timestamp fromOSTime:(cOStime * 1000). |
4628 "/ ctime := Timestamp fromOSTime:(cOStime * 1000). |
4590 |
4629 |
4591 ^ FileStatusInfo |
4630 ^ FileStatusInfo |
4592 type:type |
4631 type:type |
4593 mode:mode |
4632 mode:mode |
4594 uid:uid |
4633 uid:uid |
4595 gid:gid |
4634 gid:gid |
4596 size:size |
4635 size:size |
4597 id:id |
4636 id:id |
4598 accessed:aOStime |
4637 accessed:aOStime |
4599 modified:mOStime |
4638 modified:mOStime |
4600 statusChanged:cOStime |
4639 statusChanged:cOStime |
4601 path:nil |
4640 path:nil |
4602 numLinks:nLink. |
4641 numLinks:nLink. |
4603 ]. |
4642 ]. |
4604 error notNil ifTrue:[ |
4643 error notNil ifTrue:[ |
4605 ^ nil. |
4644 ^ nil. |
4606 ]. |
4645 ]. |
4607 |
4646 |
4608 ^ self primitiveFailed |
4647 ^ self primitiveFailed |
4609 |
4648 |
4610 " |
4649 " |
4618 "return true, if 'aPathName' is a valid directory path name. |
4657 "return true, if 'aPathName' is a valid directory path name. |
4619 (i.e. exists and is a directory). |
4658 (i.e. exists and is a directory). |
4620 This also returns true for symbolic links pointing to a directory; |
4659 This also returns true for symbolic links pointing to a directory; |
4621 if you need to check for this, use #linkInfo:." |
4660 if you need to check for this, use #linkInfo:." |
4622 |
4661 |
|
4662 |encodedPathName| |
|
4663 |
|
4664 encodedPathName := self encodePath:aPathName. |
|
4665 |
4623 %{ |
4666 %{ |
4624 int ret; |
4667 int ret; |
4625 |
4668 |
4626 if (__isStringLike(aPathName)) { |
4669 if (__isStringLike(encodedPathName)) { |
4627 struct stat buf; |
4670 struct stat buf; |
4628 |
4671 |
4629 # ifdef TRACE_STAT_CALLS |
4672 # ifdef TRACE_STAT_CALLS |
4630 printf("stat on '%s' for isDirectory\n", __stringVal(aPathName)); |
4673 printf("stat on '%s' for isDirectory\n", __stringVal(encodedPathName)); |
4631 # endif |
4674 # endif |
4632 __BEGIN_INTERRUPTABLE__ |
4675 __BEGIN_INTERRUPTABLE__ |
4633 do { |
4676 do { |
4634 ret = stat((char *) __stringVal(aPathName), &buf); |
4677 ret = stat((char *) __stringVal(encodedPathName), &buf); |
4635 } while ((ret < 0) && (errno == EINTR)); |
4678 } while ((ret < 0) && (errno == EINTR)); |
4636 __END_INTERRUPTABLE__ |
4679 __END_INTERRUPTABLE__ |
4637 if (ret < 0) { |
4680 if (ret < 0) { |
4638 @global(LastErrorNumber) = __mkSmallInteger(errno); |
4681 @global(LastErrorNumber) = __mkSmallInteger(errno); |
4639 RETURN ( false ); |
4682 RETURN ( false ); |
4640 } |
4683 } |
4641 RETURN ( ((buf.st_mode & S_IFMT) == S_IFDIR) ? true : false); |
4684 RETURN ( ((buf.st_mode & S_IFMT) == S_IFDIR) ? true : false); |
4642 } |
4685 } |
4643 %}. |
4686 %}. |
4644 ^ self primitiveFailed |
4687 ^ self primitiveFailed |
4645 |
4688 |
4646 "an alternative implementation would be: |
4689 "an alternative implementation would be: |
4647 ^ (self infoOf:aPathName) type == #directory |
4690 ^ (self infoOf:aPathName) type == #directory |
4648 " |
4691 " |
4649 ! |
4692 ! |
4650 |
4693 |
4651 isExecutable:aPathName |
4694 isExecutable:aPathName |
4652 "return true, if the given file is executable. |
4695 "return true, if the given file is executable. |
4653 For symbolic links, the pointed-to-file is checked." |
4696 For symbolic links, the pointed-to-file is checked." |
4654 |
4697 |
|
4698 |encodedPathName| |
|
4699 |
|
4700 encodedPathName := self encodePath:aPathName. |
|
4701 |
4655 %{ |
4702 %{ |
4656 int ret; |
4703 int ret; |
4657 |
4704 |
4658 if (__isStringLike(aPathName)) { |
4705 if (__isStringLike(encodedPathName)) { |
4659 # ifdef TRACE_ACCESS_CALLS |
4706 # ifdef TRACE_ACCESS_CALLS |
4660 printf("access on '%s' for executable\n", __stringVal(aPathName)); |
4707 printf("access on '%s' for executable\n", __stringVal(encodedPathName)); |
4661 # endif |
4708 # endif |
4662 __BEGIN_INTERRUPTABLE__ |
4709 __BEGIN_INTERRUPTABLE__ |
4663 do { |
4710 do { |
4664 ret = access(__stringVal(aPathName), X_OK); |
4711 ret = access(__stringVal(encodedPathName), X_OK); |
4665 } while ((ret < 0) && (errno == EINTR)); |
4712 } while ((ret < 0) && (errno == EINTR)); |
4666 __END_INTERRUPTABLE__ |
4713 __END_INTERRUPTABLE__ |
4667 if (ret < 0) { |
4714 if (ret < 0) { |
4668 @global(LastErrorNumber) = __mkSmallInteger(errno); |
4715 @global(LastErrorNumber) = __mkSmallInteger(errno); |
4669 } |
4716 } |
4670 RETURN ( ((ret == 0) ? true : false) ); |
4717 RETURN ( ((ret == 0) ? true : false) ); |
4671 } |
4718 } |
4672 %}. |
4719 %}. |
4673 ^ self primitiveFailed |
4720 ^ self primitiveFailed |
4674 ! |
4721 ! |
4675 |
4722 |
4676 isReadable:aPathName |
4723 isReadable:aPathName |
4677 "return true, if the file/dir 'aPathName' is readable. |
4724 "return true, if the file/dir 'aPathName' is readable. |
4678 For symbolic links, the pointed-to-file is checked." |
4725 For symbolic links, the pointed-to-file is checked." |
4679 |
4726 |
|
4727 |encodedPathName| |
|
4728 |
|
4729 encodedPathName := self encodePath:aPathName. |
4680 %{ |
4730 %{ |
4681 int ret; |
4731 int ret; |
4682 |
4732 |
4683 if (__isStringLike(aPathName)) { |
4733 if (__isStringLike(encodedPathName)) { |
4684 # ifdef TRACE_ACCESS_CALLS |
4734 # ifdef TRACE_ACCESS_CALLS |
4685 printf("access on '%s' for readable\n", __stringVal(aPathName)); |
4735 printf("access on '%s' for readable\n", __stringVal(encodedPathName)); |
4686 # endif |
4736 # endif |
4687 __BEGIN_INTERRUPTABLE__ |
4737 __BEGIN_INTERRUPTABLE__ |
4688 do { |
4738 do { |
4689 ret = access(__stringVal(aPathName), R_OK); |
4739 ret = access(__stringVal(encodedPathName), R_OK); |
4690 } while ((ret < 0) && (errno == EINTR)); |
4740 } while ((ret < 0) && (errno == EINTR)); |
4691 __END_INTERRUPTABLE__ |
4741 __END_INTERRUPTABLE__ |
4692 if (ret < 0) { |
4742 if (ret < 0) { |
4693 @global(LastErrorNumber) = __mkSmallInteger(errno); |
4743 @global(LastErrorNumber) = __mkSmallInteger(errno); |
4694 } |
4744 } |
4695 RETURN ( ((ret == 0) ? true : false) ); |
4745 RETURN ( ((ret == 0) ? true : false) ); |
4696 } |
4746 } |
4697 %}. |
4747 %}. |
4698 ^ self primitiveFailed |
4748 ^ self primitiveFailed |
4699 ! |
4749 ! |
4700 |
4750 |
4701 isValidPath:aPathName |
4751 isValidPath:aPathName |
4702 "return true, if 'aPathName' is a valid path name |
4752 "return true, if 'aPathName' is a valid path name |
4703 (i.e. the file or directory exists)" |
4753 (i.e. the file or directory exists)" |
4704 |
4754 |
|
4755 |encodedPathName| |
|
4756 |
|
4757 encodedPathName := self encodePath:aPathName. |
4705 %{ |
4758 %{ |
4706 struct stat buf; |
4759 struct stat buf; |
4707 int ret; |
4760 int ret; |
4708 |
4761 |
4709 if (__isStringLike(aPathName)) { |
4762 if (__isStringLike(encodedPathName)) { |
4710 # ifdef TRACE_STAT_CALLS |
4763 # ifdef TRACE_STAT_CALLS |
4711 printf("stat on '%s' for isValidPath\n", __stringVal(aPathName)); |
4764 printf("stat on '%s' for isValidPath\n", __stringVal(encodedPathName)); |
4712 # endif |
4765 # endif |
4713 __BEGIN_INTERRUPTABLE__ |
4766 __BEGIN_INTERRUPTABLE__ |
4714 do { |
4767 do { |
4715 ret = stat((char *) __stringVal(aPathName), &buf); |
4768 ret = stat((char *) __stringVal(encodedPathName), &buf); |
4716 } while ((ret < 0) && (errno == EINTR)); |
4769 } while ((ret < 0) && (errno == EINTR)); |
4717 __END_INTERRUPTABLE__ |
4770 __END_INTERRUPTABLE__ |
4718 if (ret < 0) { |
4771 if (ret < 0) { |
4719 @global(LastErrorNumber) = __mkSmallInteger(errno); |
4772 @global(LastErrorNumber) = __mkSmallInteger(errno); |
4720 RETURN (false); |
4773 RETURN (false); |
4721 } |
4774 } |
4722 RETURN ( ret ? false : true ); |
4775 RETURN ( ret ? false : true ); |
4723 } |
4776 } |
4724 %}. |
4777 %}. |
4725 ^ self primitiveFailed |
4778 ^ self primitiveFailed |
4726 |
4779 |
4727 "/ alternative: |
4780 "/ alternative: |
4730 |
4783 |
4731 isWritable:aPathName |
4784 isWritable:aPathName |
4732 "return true, if the given file is writable. |
4785 "return true, if the given file is writable. |
4733 For symbolic links, the pointed-to-file is checked." |
4786 For symbolic links, the pointed-to-file is checked." |
4734 |
4787 |
|
4788 |encodedPathName| |
|
4789 |
|
4790 encodedPathName := self encodePath:aPathName. |
4735 %{ |
4791 %{ |
4736 int ret; |
4792 int ret; |
4737 |
4793 |
4738 if (__isStringLike(aPathName)) { |
4794 if (__isStringLike(encodedPathName)) { |
4739 # ifdef TRACE_ACCESS_CALLS |
4795 # ifdef TRACE_ACCESS_CALLS |
4740 printf("access on '%s' for writable\n", __stringVal(aPathName)); |
4796 printf("access on '%s' for writable\n", __stringVal(encodedPathName)); |
4741 # endif |
4797 # endif |
4742 __BEGIN_INTERRUPTABLE__ |
4798 __BEGIN_INTERRUPTABLE__ |
4743 do { |
4799 do { |
4744 ret = access(__stringVal(aPathName), W_OK); |
4800 ret = access(__stringVal(encodedPathName), W_OK); |
4745 } while ((ret < 0) && (errno == EINTR)); |
4801 } while ((ret < 0) && (errno == EINTR)); |
4746 __END_INTERRUPTABLE__ |
4802 __END_INTERRUPTABLE__ |
4747 if (ret < 0) { |
4803 if (ret < 0) { |
4748 @global(LastErrorNumber) = __mkSmallInteger(errno); |
4804 @global(LastErrorNumber) = __mkSmallInteger(errno); |
4749 } |
4805 } |
4750 RETURN ( ((ret == 0) ? true : false) ); |
4806 RETURN ( ((ret == 0) ? true : false) ); |
4751 } |
4807 } |
4752 %}. |
4808 %}. |
4753 ^ self primitiveFailed |
4809 ^ self primitiveFailed |
4754 ! |
4810 ! |
4755 |
4811 |
4782 |
4838 |
4783 Return the info about the link itself, |
4839 Return the info about the link itself, |
4784 on contrast to #infoOf:, which returns the info of the pointed to file |
4840 on contrast to #infoOf:, which returns the info of the pointed to file |
4785 in case of a symbolic link." |
4841 in case of a symbolic link." |
4786 |
4842 |
4787 |type mode uid gid size id nLink aOStime mOStime cOStime path| |
4843 |type mode uid gid size id nLink aOStime mOStime cOStime path encodedPathName| |
|
4844 |
|
4845 encodedPathName := self encodePath:aPathName. |
4788 |
4846 |
4789 %{ /* STACK: 1200 */ |
4847 %{ /* STACK: 1200 */ |
4790 #if defined(S_IFLNK) |
4848 #if defined(S_IFLNK) |
4791 struct stat buf; |
4849 struct stat buf; |
4792 int ret; |
4850 int ret; |
4793 char pathBuffer[1024]; |
4851 char pathBuffer[1024]; |
4794 |
4852 |
4795 if (__isStringLike(aPathName)) { |
4853 if (__isStringLike(encodedPathName)) { |
4796 __BEGIN_INTERRUPTABLE__ |
4854 __BEGIN_INTERRUPTABLE__ |
4797 do { |
4855 do { |
4798 ret = lstat((char *) __stringVal(aPathName), &buf); |
4856 ret = lstat((char *) __stringVal(encodedPathName), &buf); |
4799 } while ((ret < 0) && (errno == EINTR)); |
4857 } while ((ret < 0) && (errno == EINTR)); |
4800 __END_INTERRUPTABLE__ |
4858 __END_INTERRUPTABLE__ |
4801 |
4859 |
4802 if (ret < 0) { |
4860 if (ret < 0) { |
4803 @global(LastErrorNumber) = __mkSmallInteger(errno); |
4861 @global(LastErrorNumber) = __mkSmallInteger(errno); |
4955 Notice: if symbolic links are involved, the result may look different |
5004 Notice: if symbolic links are involved, the result may look different |
4956 from what you expect." |
5005 from what you expect." |
4957 |
5006 |
4958 |p path command| |
5007 |p path command| |
4959 |
5008 |
|
5009 path = '.' ifTrue:[ |
|
5010 ^ self getCurrentDirectory. |
|
5011 ]. |
|
5012 |
4960 "some systems have a convenient function for this ..." |
5013 "some systems have a convenient function for this ..." |
4961 path := self primPathNameOf:pathName. |
5014 path := self primPathNameOf:(self encodePath:pathName). |
4962 |
5015 |
4963 path isNil ifTrue:[ |
5016 path isNil ifTrue:[ |
4964 (self isValidPath:pathName) ifFalse:[ |
5017 (self isValidPath:pathName) ifFalse:[ |
4965 p := pathName. |
5018 p := pathName. |
4966 [(p size > 1) |
5019 [(p size > 1) |
4967 and:[p endsWith:(self fileSeparator)] |
5020 and:[p endsWith:(self fileSeparator)] |
4968 ] whileTrue:[ |
5021 ] whileTrue:[ |
4969 p := p copyWithoutLast:1. |
5022 p := p copyWithoutLast:1. |
4970 ]. |
5023 ]. |
4971 ^ p |
5024 ^ p |
4972 ]. |
5025 ]. |
4973 |
5026 |
4974 (SlowFork==true or:[PipeFailed==true]) ifFalse:[ |
5027 (SlowFork==true or:[PipeFailed==true]) ifFalse:[ |
4975 PipeStream openErrorSignal handle:[:ex | |
5028 PipeStream openErrorSignal handle:[:ex | |
4976 PipeFailed := true. |
5029 PipeFailed := true. |
4977 'UnixOperatingSystem [warning]: cannot fork/popen' errorPrintCR. |
5030 'UnixOperatingSystem [warning]: cannot fork/popen' errorPrintCR. |
4978 ex return. |
5031 ex return. |
4979 ] do:[ |
5032 ] do:[ |
4980 "have to fall back ..." |
5033 "have to fall back ..." |
4981 command := 'cd "' , pathName , '"; pwd'. |
5034 command := 'cd "' , pathName , '"; pwd'. |
4982 p := PipeStream readingFrom:command. |
5035 p := PipeStream readingFrom:command. |
4983 ]. |
5036 ]. |
4984 |
5037 |
4985 (p isNil or:[p atEnd]) ifTrue:[ |
5038 (p isNil or:[p atEnd]) ifTrue:[ |
4986 ('UnixOperatingSystem [warning]: PipeStream for <' , command , '> failed') errorPrintCR. |
5039 ('UnixOperatingSystem [warning]: PipeStream for <' , command , '> failed') errorPrintCR. |
4987 ] ifFalse:[ |
5040 ] ifFalse:[ |
4988 path := p nextLine. |
5041 path := p nextLine. |
4989 p close. |
5042 p close. |
4990 ] |
5043 ] |
4991 ]. |
5044 ]. |
4992 path isNil ifTrue:[ |
5045 path isNil ifTrue:[ |
4993 "/ |
5046 "/ |
4994 "/ return the original - there is nothing else can we do |
5047 "/ return the original - there is nothing else can we do |
4995 "/ |
5048 "/ |
4996 path := pathName |
5049 path := pathName |
4997 ]. |
5050 ]. |
4998 (SlowFork==true or:[ForkFailed==true]) ifTrue:[ |
5051 (SlowFork==true or:[ForkFailed==true]) ifTrue:[ |
4999 path := self compressPath:path |
5052 path := self compressPath:path |
5000 ] |
5053 ] |
5001 ]. |
5054 ]. |
5002 ^ path. |
5055 ^ path. |
5003 |
5056 |
5004 " |
5057 " |
5005 OperatingSystem pathNameOf:'.' |
5058 OperatingSystem pathNameOf:'.' |
5060 This method here returns nil, if the OS does not provide a |
5116 This method here returns nil, if the OS does not provide a |
5061 realPath library function. |
5117 realPath library function. |
5062 Notice: if symbolic links are involved, the result may look different |
5118 Notice: if symbolic links are involved, the result may look different |
5063 from what you expect." |
5119 from what you expect." |
5064 |
5120 |
5065 |path| |
|
5066 |
|
5067 %{ /* UNLIMITEDSTACK */ |
5121 %{ /* UNLIMITEDSTACK */ |
5068 |
5122 |
5069 if (__isStringLike(pathName)) { |
5123 if (__isStringLike(pathName)) { |
5070 if (strcmp(__stringVal(pathName), ".") == 0) { |
|
5071 char nameBuffer[MAXPATHLEN + 1]; |
|
5072 |
|
5073 if (@global(CurrentDirectory) == nil) { |
|
5074 if (getcwd(nameBuffer, MAXPATHLEN)) { |
|
5075 OBJ d; |
|
5076 |
|
5077 @global(CurrentDirectory) = d = __MKSTRING(nameBuffer); |
|
5078 __GSTORE(d); |
|
5079 } |
|
5080 } |
|
5081 RETURN (@global(CurrentDirectory)); |
|
5082 } |
|
5083 |
|
5084 #ifdef HAS_REALPATH |
5124 #ifdef HAS_REALPATH |
5085 { |
5125 { |
5086 char nameBuffer[MAXPATHLEN+1]; |
5126 char nameBuffer[MAXPATHLEN+1]; |
5087 |
5127 |
5088 if (realpath(__stringVal(pathName), nameBuffer)) { |
5128 if (realpath(__stringVal(pathName), nameBuffer)) { |
5089 RETURN ( __MKSTRING(nameBuffer) ); |
5129 RETURN ( __MKSTRING(nameBuffer) ); |
5090 } |
5130 } |
5091 RETURN ( nil ); |
|
5092 } |
5131 } |
5093 #endif /* ! HAS_REALPATH */ |
5132 #endif /* ! HAS_REALPATH */ |
5094 } |
5133 } |
5095 %}. |
5134 %}. |
5096 ^ nil |
5135 ^ nil |
5099 timeOfLastAccess:aPathName |
5138 timeOfLastAccess:aPathName |
5100 "return the time, when the file was last accessed. |
5139 "return the time, when the file was last accessed. |
5101 For nonexistent files, nil is returned." |
5140 For nonexistent files, nil is returned." |
5102 |
5141 |
5103 "could be implemented as: |
5142 "could be implemented as: |
5104 (self infoOf:aPathName) accessed |
5143 (self infoOf:aPathName) accessed |
5105 " |
5144 " |
5106 |osSeconds i| |
5145 |osSeconds i encodedPathName| |
|
5146 |
|
5147 encodedPathName := self encodePath:aPathName. |
|
5148 |
5107 %{ |
5149 %{ |
5108 struct stat buf; |
5150 struct stat buf; |
5109 time_t mtime; |
5151 time_t mtime; |
5110 int ret; |
5152 int ret; |
5111 |
5153 |
5112 if (__isStringLike(aPathName)) { |
5154 if (__isStringLike(encodedPathName)) { |
5113 # ifdef TRACE_STAT_CALLS |
5155 # ifdef TRACE_STAT_CALLS |
5114 printf("stat on '%s' for timeOfLastAccess\n", __stringVal(aPathName)); |
5156 printf("stat on '%s' for timeOfLastAccess\n", __stringVal(encodedPathName)); |
5115 # endif |
5157 # endif |
5116 __BEGIN_INTERRUPTABLE__ |
5158 __BEGIN_INTERRUPTABLE__ |
5117 do { |
5159 do { |
5118 ret = stat((char *) __stringVal(aPathName), &buf); |
5160 ret = stat((char *) __stringVal(encodedPathName), &buf); |
5119 } while (ret < 0 && errno == EINTR); |
5161 } while (ret < 0 && errno == EINTR); |
5120 __END_INTERRUPTABLE__ |
5162 __END_INTERRUPTABLE__ |
5121 if (ret < 0) { |
5163 if (ret < 0) { |
5122 @global(LastErrorNumber) = __mkSmallInteger(errno); |
5164 @global(LastErrorNumber) = __mkSmallInteger(errno); |
5123 RETURN (nil); |
5165 RETURN (nil); |
5124 } |
5166 } |
5125 osSeconds = __MKUINT(buf.st_atime); |
5167 osSeconds = __MKUINT(buf.st_atime); |
5126 } |
5168 } |
5127 %}. |
5169 %}. |
5128 osSeconds notNil ifTrue:[^ Timestamp fromOSTime:(osSeconds * 1000)]. |
5170 osSeconds notNil ifTrue:[^ Timestamp fromOSTime:(osSeconds * 1000)]. |
5129 |
5171 |
5130 i := self infoOf:aPathName. |
5172 i := self infoOf:aPathName. |
5139 timeOfLastChange:aPathName |
5181 timeOfLastChange:aPathName |
5140 "return the time, when the file was last changed. |
5182 "return the time, when the file was last changed. |
5141 For nonexistent files, nil is returned." |
5183 For nonexistent files, nil is returned." |
5142 |
5184 |
5143 "could be implemented as: |
5185 "could be implemented as: |
5144 (self infoOf:aPathName) modified |
5186 (self infoOf:aPathName) modified |
5145 " |
5187 " |
5146 |
5188 |
5147 |osSeconds i| |
5189 |osSeconds i encodedPathName| |
|
5190 |
|
5191 encodedPathName := self encodePath:aPathName. |
5148 %{ |
5192 %{ |
5149 struct stat buf; |
5193 struct stat buf; |
5150 int ret; |
5194 int ret; |
5151 time_t mtime; |
5195 time_t mtime; |
5152 |
5196 |
5153 if (__isStringLike(aPathName)) { |
5197 if (__isStringLike(encodedPathName)) { |
5154 # ifdef TRACE_STAT_CALLS |
5198 # ifdef TRACE_STAT_CALLS |
5155 printf("stat on '%s' for timeOfLastChange\n", __stringVal(aPathName)); |
5199 printf("stat on '%s' for timeOfLastChange\n", __stringVal(encodedPathName)); |
5156 # endif |
5200 # endif |
5157 __BEGIN_INTERRUPTABLE__ |
5201 __BEGIN_INTERRUPTABLE__ |
5158 do { |
5202 do { |
5159 ret = stat((char *) __stringVal(aPathName), &buf); |
5203 ret = stat((char *) __stringVal(encodedPathName), &buf); |
5160 } while (ret < 0 && errno == EINTR); |
5204 } while (ret < 0 && errno == EINTR); |
5161 __END_INTERRUPTABLE__ |
5205 __END_INTERRUPTABLE__ |
5162 if (ret < 0) { |
5206 if (ret < 0) { |
5163 @global(LastErrorNumber) = __mkSmallInteger(errno); |
5207 @global(LastErrorNumber) = __mkSmallInteger(errno); |
5164 RETURN ( nil ); |
5208 RETURN ( nil ); |
5165 } |
5209 } |
5166 osSeconds = __MKUINT(buf.st_mtime); |
5210 osSeconds = __MKUINT(buf.st_mtime); |
5167 } |
5211 } |
5168 %}. |
5212 %}. |
5169 osSeconds notNil ifTrue:[^ Timestamp fromOSTime:(osSeconds * 1000)]. |
5213 osSeconds notNil ifTrue:[^ Timestamp fromOSTime:(osSeconds * 1000)]. |
5170 |
5214 |
5171 i := self infoOf:aPathName. |
5215 i := self infoOf:aPathName. |
5180 typeOf:aPathName |
5224 typeOf:aPathName |
5181 "return the type of a file as a symbol; for nonexistent files, |
5225 "return the type of a file as a symbol; for nonexistent files, |
5182 nil is returned. |
5226 nil is returned. |
5183 Notice: for symbolic links, the type of the pointed-to file is returned." |
5227 Notice: for symbolic links, the type of the pointed-to file is returned." |
5184 |
5228 |
5185 |i| |
5229 |i osSeconds encodedPathName| |
|
5230 |
|
5231 encodedPathName := self encodePath:aPathName. |
5186 |
5232 |
5187 " |
5233 " |
5188 this could have been implemented as: |
5234 this could have been implemented as: |
5189 (self infoOf:aPathName) type |
5235 (self infoOf:aPathName) type |
5190 but for huge directory searches the code below is faster |
5236 but for huge directory searches the code below is faster |
5191 " |
5237 " |
5192 |
5238 |
5193 %{ |
5239 %{ |
5194 struct stat buf; |
5240 struct stat buf; |
5195 int ret; |
5241 int ret; |
5196 |
5242 |
5197 if (__isStringLike(aPathName)) { |
5243 if (__isStringLike(encodedPathName)) { |
5198 # ifdef TRACE_STAT_CALLS |
5244 # ifdef TRACE_STAT_CALLS |
5199 printf("stat on '%s' for type\n", __stringVal(aPathName)); |
5245 printf("stat on '%s' for type\n", __stringVal(encodedPathName)); |
5200 # endif |
5246 # endif |
5201 __BEGIN_INTERRUPTABLE__ |
5247 __BEGIN_INTERRUPTABLE__ |
5202 do { |
5248 do { |
5203 ret = stat((char *) __stringVal(aPathName), &buf); |
5249 ret = stat((char *) __stringVal(encodedPathName), &buf); |
5204 } while (ret < 0 && errno == EINTR); |
5250 } while (ret < 0 && errno == EINTR); |
5205 __END_INTERRUPTABLE__ |
5251 __END_INTERRUPTABLE__ |
5206 if (ret < 0) { |
5252 if (ret < 0) { |
5207 @global(LastErrorNumber) = __mkSmallInteger(errno); |
5253 @global(LastErrorNumber) = __mkSmallInteger(errno); |
5208 RETURN ( nil ); |
5254 RETURN ( nil ); |
5209 } |
5255 } |
5210 switch (buf.st_mode & S_IFMT) { |
5256 switch (buf.st_mode & S_IFMT) { |
5211 case S_IFDIR: |
5257 case S_IFDIR: |
5212 RETURN ( @symbol(directory) ); |
5258 RETURN ( @symbol(directory) ); |
5213 case S_IFREG: |
5259 case S_IFREG: |
5214 RETURN ( @symbol(regular) ); |
5260 RETURN ( @symbol(regular) ); |
5215 # ifdef S_IFCHR |
5261 # ifdef S_IFCHR |
5216 case S_IFCHR: |
5262 case S_IFCHR: |
5217 RETURN ( @symbol(characterSpecial) ); |
5263 RETURN ( @symbol(characterSpecial) ); |
5218 # endif |
5264 # endif |
5219 # ifdef S_IFBLK |
5265 # ifdef S_IFBLK |
5220 case S_IFBLK: |
5266 case S_IFBLK: |
5221 RETURN ( @symbol(blockSpecial) ); |
5267 RETURN ( @symbol(blockSpecial) ); |
5222 # endif |
5268 # endif |
5223 # ifdef S_IFLNK |
5269 # ifdef S_IFLNK |
5224 case S_IFLNK: |
5270 case S_IFLNK: |
5225 RETURN ( @symbol(symbolicLink) ); |
5271 RETURN ( @symbol(symbolicLink) ); |
5226 # endif |
5272 # endif |
5227 # ifdef S_IFSOCK |
5273 # ifdef S_IFSOCK |
5228 case S_IFSOCK: |
5274 case S_IFSOCK: |
5229 RETURN ( @symbol(socket) ); |
5275 RETURN ( @symbol(socket) ); |
5230 # endif |
5276 # endif |
5231 # ifdef S_IFIFO |
5277 # ifdef S_IFIFO |
5232 case S_IFIFO: |
5278 case S_IFIFO: |
5233 RETURN ( @symbol(fifo) ); |
5279 RETURN ( @symbol(fifo) ); |
5234 # endif |
5280 # endif |
5235 default: |
5281 default: |
5236 RETURN ( @symbol(unknown) ); |
5282 RETURN ( @symbol(unknown) ); |
5237 } |
5283 } |
5238 } |
5284 } |
5239 %}. |
5285 %}. |
5240 i := self infoOf:aPathName. |
5286 i := self infoOf:aPathName. |
5241 i notNil ifTrue:[^ i type]. |
5287 i notNil ifTrue:[^ i type]. |
5242 ^ nil. |
5288 ^ nil. |