569 printf("no child\r\n"); |
569 printf("no child\r\n"); |
570 #endif |
570 #endif |
571 return 0; |
571 return 0; |
572 } |
572 } |
573 |
573 |
|
574 # ifndef HAS_OPENDIR |
|
575 |
|
576 # define lib$find_file LIB$FIND_FILE |
|
577 |
|
578 /* |
|
579 ** VMS readdir() routines. |
|
580 ** Written by Rich $alz, <rsalz@bbn.com> in August, 1990. |
|
581 ** This code has no copyright. |
|
582 */ |
|
583 |
|
584 /* 12-NOV-1990 added d_namlen field and special case "." name -GJC@MITECH.COM |
|
585 */ |
|
586 |
|
587 # ifndef _STDIO_H_INCLUDED_ |
|
588 # include <stdio.h> |
|
589 # define _STDIO_H_INCLUDED_ |
|
590 # endif |
|
591 |
|
592 # ifndef _CTYPE_H_INCLUDED_ |
|
593 # include <ctype.h> |
|
594 # define _CTYPE_H_INCLUDED_ |
|
595 # endif |
|
596 |
|
597 # ifndef _ERRNO_H_INCLUDED_ |
|
598 # include <errno.h> |
|
599 # define _ERRNO_H_INCLUDED_ |
|
600 # endif |
|
601 |
|
602 # ifndef _DESCRIP_H_INCLUDED_ |
|
603 # include <descrip.h> |
|
604 # define _DESCRIP_H_INCLUDED_ |
|
605 # endif |
|
606 |
|
607 # ifndef _RMSDEF_H_INCLUDED_ |
|
608 # include <rmsdef.h> |
|
609 # define _RMSDEF_H_INCLUDED_ |
|
610 # endif |
|
611 |
|
612 /* |
|
613 * actually, the following has to go into dirent.h ... |
|
614 */ |
|
615 /* BEGIN included dirent.h |
|
616 * |
|
617 ** Header file for VMS readdir() routines. |
|
618 ** Written by Rich $alz, <rsalz@bbn.com> in August, 1990. |
|
619 ** This code has no copyright. |
|
620 ** |
|
621 ** You must #include <descrip.h> before this file. |
|
622 */ |
|
623 |
|
624 /* 12-NOV-1990 added d_namlen field -GJC@MITECH.COM */ |
|
625 |
|
626 /* Data structure returned by READDIR(). */ |
|
627 struct dirent { |
|
628 char d_name[100]; /* File name */ |
|
629 int d_namlen; |
|
630 int vms_verscount; /* Number of versions */ |
|
631 int vms_versions[20]; /* Version numbers */ |
|
632 }; |
|
633 |
|
634 /* Handle returned by opendir(), used by the other routines. You |
|
635 * are not supposed to care what's inside this structure. */ |
|
636 typedef struct _dirdesc { |
|
637 long context; |
|
638 int vms_wantversions; |
|
639 char *pattern; |
|
640 struct dirent entry; |
|
641 struct dsc$descriptor_s pat; |
|
642 } DIR; |
|
643 |
|
644 |
|
645 #define rewinddir(dirp) seekdir((dirp), 0L) |
|
646 |
|
647 |
|
648 extern DIR *opendir(); |
|
649 extern struct dirent *readdir(); |
|
650 extern long telldir(); |
|
651 extern void seekdir(); |
|
652 extern void closedir(); |
|
653 extern void vmsreaddirversions(); |
|
654 /* |
|
655 * END dirent.h |
|
656 */ |
|
657 #define _DIRENT_H_INCLUDED_ |
|
658 |
|
659 |
|
660 /* Number of elements in vms_versions array */ |
|
661 #define VERSIZE(e) (sizeof e->vms_versions / sizeof e->vms_versions[0]) |
|
662 |
|
663 /* Linked in later. */ |
|
664 extern char *strrchr(); |
|
665 extern char *strcpy(); |
|
666 /* Don't need this when all these programs are lumped together. RLD |
|
667 extern char *malloc(); |
|
668 */ |
|
669 |
|
670 /* |
|
671 ** Open a directory, return a handle for later use. |
|
672 */ |
|
673 DIR * |
|
674 opendir(name) |
|
675 char *name; |
|
676 { |
|
677 DIR *dd; |
|
678 |
|
679 /* Get memory for the handle, and the pattern. */ |
|
680 if ((dd = (DIR *)malloc(sizeof *dd)) == NULL) { |
|
681 __threadErrno = ENOMEM; |
|
682 return NULL; |
|
683 } |
|
684 |
|
685 if (strcmp(".",name) == 0) name = ""; |
|
686 |
|
687 dd->pattern = malloc((unsigned int)(strlen(name) + sizeof "*.*" + 1)); |
|
688 if (dd->pattern == NULL) { |
|
689 free((char *)dd); |
|
690 __threadErrno = ENOMEM; |
|
691 return NULL; |
|
692 } |
|
693 |
|
694 /* Fill in the fields; mainly playing with the descriptor. */ |
|
695 (void)sprintf(dd->pattern, "%s*.*", name); |
|
696 dd->context = 0; |
|
697 dd->vms_wantversions = 0; |
|
698 dd->pat.dsc$a_pointer = dd->pattern; |
|
699 dd->pat.dsc$w_length = strlen(dd->pattern); |
|
700 dd->pat.dsc$b_dtype = DSC$K_DTYPE_T; |
|
701 dd->pat.dsc$b_class = DSC$K_CLASS_S; |
|
702 |
|
703 return dd; |
|
704 } |
|
705 |
|
706 /* |
|
707 ** Set the flag to indicate we want versions or not. |
|
708 */ |
|
709 void |
|
710 vmsreaddirversions(dd, flag) |
|
711 DIR *dd; |
|
712 int flag; |
|
713 { |
|
714 dd->vms_wantversions = flag; |
|
715 } |
|
716 |
|
717 /* |
|
718 ** Free up an opened directory. |
|
719 */ |
|
720 void |
|
721 closedir(dd) |
|
722 DIR *dd; |
|
723 { |
|
724 free(dd->pattern); |
|
725 free((char *)dd); |
|
726 } |
|
727 |
|
728 /* |
|
729 ** Collect all the version numbers for the current file. |
|
730 */ |
|
731 static void |
|
732 collectversions(dd) |
|
733 DIR *dd; |
|
734 { |
|
735 struct dsc$descriptor_s pat; |
|
736 struct dsc$descriptor_s res; |
|
737 struct dirent *e; |
|
738 char *p; |
|
739 char buff[sizeof dd->entry.d_name]; |
|
740 int i; |
|
741 char *text; |
|
742 long context; |
|
743 |
|
744 /* Convenient shorthand. */ |
|
745 e = &dd->entry; |
|
746 |
|
747 /* Add the version wildcard, ignoring the "*.*" put on before */ |
|
748 i = strlen(dd->pattern); |
|
749 text = malloc((unsigned int)(i + strlen(e->d_name)+ 2 + 1)); |
|
750 if (text == NULL) |
|
751 return; |
|
752 (void)strcpy(text, dd->pattern); |
|
753 (void)sprintf(&text[i - 3], "%s;*", e->d_name); |
|
754 |
|
755 /* Set up the pattern descriptor. */ |
|
756 pat.dsc$a_pointer = text; |
|
757 pat.dsc$w_length = strlen(text); |
|
758 pat.dsc$b_dtype = DSC$K_DTYPE_T; |
|
759 pat.dsc$b_class = DSC$K_CLASS_S; |
|
760 |
|
761 /* Set up result descriptor. */ |
|
762 res.dsc$a_pointer = buff; |
|
763 res.dsc$w_length = sizeof buff - 2; |
|
764 res.dsc$b_dtype = DSC$K_DTYPE_T; |
|
765 res.dsc$b_class = DSC$K_CLASS_S; |
|
766 |
|
767 /* Read files, collecting versions. */ |
|
768 for (context = 0; e->vms_verscount < VERSIZE(e); e->vms_verscount++) { |
|
769 if (lib$find_file(&pat, &res, &context) == RMS$_NMF || context == 0) |
|
770 break; |
|
771 buff[sizeof buff - 1] = '\0'; |
|
772 if (p = strchr(buff, ';')) |
|
773 e->vms_versions[e->vms_verscount] = atoi(p + 1); |
|
774 else |
|
775 e->vms_versions[e->vms_verscount] = -1; |
|
776 } |
|
777 |
|
778 free(text); |
|
779 } |
|
780 |
|
781 /* |
|
782 ** Read the next entry from the directory. |
|
783 */ |
|
784 struct dirent * |
|
785 readdir(dd) |
|
786 DIR *dd; |
|
787 { |
|
788 struct dsc$descriptor_s res; |
|
789 char *p; |
|
790 char buff[sizeof dd->entry.d_name + 10]; |
|
791 int i; |
|
792 |
|
793 /* Set up result descriptor, and get next file. */ |
|
794 res.dsc$a_pointer = buff; |
|
795 res.dsc$w_length = sizeof buff - 2; |
|
796 res.dsc$b_dtype = DSC$K_DTYPE_T; |
|
797 res.dsc$b_class = DSC$K_CLASS_S; |
|
798 if (lib$find_file(&dd->pat, &res, &dd->context) == RMS$_NMF |
|
799 || dd->context == 0L) |
|
800 /* None left... */ |
|
801 return NULL; |
|
802 |
|
803 /* Force the buffer to end with a NUL. */ |
|
804 buff[sizeof buff - 1] = '\0'; |
|
805 for (p = buff; !isspace(*p); p++) |
|
806 ; |
|
807 *p = '\0'; |
|
808 |
|
809 /* Skip any directory component and just copy the name. */ |
|
810 if (p = strchr(buff, ']')) |
|
811 (void)strcpy(dd->entry.d_name, p + 1); |
|
812 else |
|
813 (void)strcpy(dd->entry.d_name, buff); |
|
814 |
|
815 /* Clobber the version. */ |
|
816 if (p = strchr(dd->entry.d_name, ';')) |
|
817 *p = '\0'; |
|
818 |
|
819 /* claus: empty dirs seems to leave *.* in the buffer ... */ |
|
820 if (strcmp(dd->entry.d_name, "*.*") == 0) { |
|
821 return NULL; |
|
822 } |
|
823 |
|
824 dd->entry.d_namlen = strlen(dd->entry.d_name); |
|
825 |
|
826 dd->entry.vms_verscount = 0; |
|
827 if (dd->vms_wantversions) |
|
828 collectversions(dd); |
|
829 return &dd->entry; |
|
830 } |
|
831 |
|
832 /* |
|
833 ** Return something that can be used in a seekdir later. |
|
834 */ |
|
835 long |
|
836 telldir(dd) |
|
837 DIR *dd; |
|
838 { |
|
839 return dd->context; |
|
840 } |
|
841 |
|
842 /* |
|
843 ** Return to a spot where we used to be. |
|
844 */ |
|
845 void |
|
846 seekdir(dd, pos) |
|
847 DIR *dd; |
|
848 long pos; |
|
849 { |
|
850 dd->context = pos; |
|
851 } |
|
852 |
|
853 # define HAS_OPENDIR |
|
854 |
|
855 # endif /* not HAS_OPENDIR */ |
|
856 |
574 #endif /* __VMS__ */ |
857 #endif /* __VMS__ */ |
575 %} |
858 %} |
576 ! ! |
859 ! ! |
577 |
860 |
578 !OpenVMSOperatingSystem class methodsFor:'documentation'! |
861 !OpenVMSOperatingSystem class methodsFor:'documentation'! |
2923 |
3206 |
2924 "Created: 29.2.1996 / 12:31:29 / cg" |
3207 "Created: 29.2.1996 / 12:31:29 / cg" |
2925 "Modified: 21.3.1997 / 10:04:35 / dq" |
3208 "Modified: 21.3.1997 / 10:04:35 / dq" |
2926 "Modified: 2.5.1997 / 12:18:20 / cg" |
3209 "Modified: 2.5.1997 / 12:18:20 / cg" |
2927 "Modified: 15.7.1997 / 16:03:51 / stefan" |
3210 "Modified: 15.7.1997 / 16:03:51 / stefan" |
|
3211 ! ! |
|
3212 |
|
3213 !OpenVMSOperatingSystem class methodsFor:'directory access'! |
|
3214 |
|
3215 nextLinkInfoFrom:aDirectoryStream dirPointer:dirPointer |
|
3216 "return a FileStatusInfo entry for the next entry, when reading from a directory. |
|
3217 Under UNIX, the returned fileStatuInfo ONLY contains the name of the file, |
|
3218 whereas under Windows, it contains the full info (incl. fileSize, access rights etc.). |
|
3219 The reason is that under wndows, the ReadNextEntry system call does this, whereas the |
|
3220 the corresponding unix read from a readdir only returns the name." |
|
3221 |
|
3222 |entry isUnix error| |
|
3223 %{ |
|
3224 #ifdef HAS_OPENDIR |
|
3225 DIR *d; |
|
3226 DIRENT_STRUCT *dp; |
|
3227 |
|
3228 if ((dirPointer != nil) |
|
3229 && __isExternalAddressLike(dirPointer)) { |
|
3230 d = (DIR *)__FILEVal(dirPointer); |
|
3231 |
|
3232 __BEGIN_INTERRUPTABLE__ |
|
3233 do { |
|
3234 do { |
|
3235 __threadErrno = 0; |
|
3236 dp = readdir(d); |
|
3237 /* |
|
3238 * for compatibility with ST-80, |
|
3239 * skip entries for '.' and '..'. |
|
3240 * If wanted, these must be added synthetically. |
|
3241 */ |
|
3242 } while (dp && ((strcmp(dp->d_name, ".")==0) || (strcmp(dp->d_name, "..")==0))); |
|
3243 } while ((dp == NULL) && (__threadErrno == EINTR)); |
|
3244 __END_INTERRUPTABLE__ |
|
3245 |
|
3246 if (dp != NULL) { |
|
3247 entry = __MKSTRING((char *)(dp->d_name)); |
|
3248 } else { |
|
3249 if (__threadErrno) { |
|
3250 error = __mkSmallInteger(__threadErrno); |
|
3251 } |
|
3252 } |
|
3253 } |
|
3254 #endif /* HAS_OPENDIR */ |
|
3255 %}. |
|
3256 error notNil ifTrue:[ |
|
3257 ^ StreamIOError newException |
|
3258 errorCode:error; |
|
3259 osErrorHolder:(OperatingSystem errorHolderForNumber:error); |
|
3260 parameter:aDirectoryStream; |
|
3261 raiseRequest |
|
3262 ]. |
|
3263 entry notNil ifTrue:[ |
|
3264 ^ entry. |
|
3265 ]. |
|
3266 ^ aDirectoryStream pastEndRead |
2928 ! ! |
3267 ! ! |
2929 |
3268 |
2930 !OpenVMSOperatingSystem class methodsFor:'file access'! |
3269 !OpenVMSOperatingSystem class methodsFor:'file access'! |
2931 |
3270 |
2932 closeFd:anInteger |
3271 closeFd:anInteger |