OpenVMSOperatingSystem.st
changeset 17283 877a84a76a52
parent 13778 8e34483d10dd
child 18120 e3a375d5f6a8
child 19860 324edacff5cc
equal deleted inserted replaced
17282:3e6b5f0df9e6 17283:877a84a76a52
   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
  7513 ! !
  7852 ! !
  7514 
  7853 
  7515 !OpenVMSOperatingSystem class methodsFor:'documentation'!
  7854 !OpenVMSOperatingSystem class methodsFor:'documentation'!
  7516 
  7855 
  7517 version
  7856 version
  7518     ^ '$Header: /cvs/stx/stx/libbasic/OpenVMSOperatingSystem.st,v 1.17 2011-10-07 13:57:55 cg Exp $'
  7857     ^ '$Header: /cvs/stx/stx/libbasic/OpenVMSOperatingSystem.st,v 1.18 2015-01-12 12:50:08 cg Exp $'
  7519 ! !
  7858 ! !
  7520 OpenVMSOperatingSystem initialize!
  7859 OpenVMSOperatingSystem initialize!