--- a/OpenVMSOperatingSystem.st Mon Jan 12 13:44:34 2015 +0100
+++ b/OpenVMSOperatingSystem.st Mon Jan 12 13:50:08 2015 +0100
@@ -571,6 +571,289 @@
return 0;
}
+# ifndef HAS_OPENDIR
+
+# define lib$find_file LIB$FIND_FILE
+
+/*
+** VMS readdir() routines.
+** Written by Rich $alz, <rsalz@bbn.com> in August, 1990.
+** This code has no copyright.
+*/
+
+/* 12-NOV-1990 added d_namlen field and special case "." name -GJC@MITECH.COM
+ */
+
+# ifndef _STDIO_H_INCLUDED_
+# include <stdio.h>
+# define _STDIO_H_INCLUDED_
+# endif
+
+# ifndef _CTYPE_H_INCLUDED_
+# include <ctype.h>
+# define _CTYPE_H_INCLUDED_
+# endif
+
+# ifndef _ERRNO_H_INCLUDED_
+# include <errno.h>
+# define _ERRNO_H_INCLUDED_
+# endif
+
+# ifndef _DESCRIP_H_INCLUDED_
+# include <descrip.h>
+# define _DESCRIP_H_INCLUDED_
+# endif
+
+# ifndef _RMSDEF_H_INCLUDED_
+# include <rmsdef.h>
+# define _RMSDEF_H_INCLUDED_
+# endif
+
+/*
+ * actually, the following has to go into dirent.h ...
+ */
+/* BEGIN included dirent.h
+ *
+** Header file for VMS readdir() routines.
+** Written by Rich $alz, <rsalz@bbn.com> in August, 1990.
+** This code has no copyright.
+**
+** You must #include <descrip.h> before this file.
+*/
+
+/* 12-NOV-1990 added d_namlen field -GJC@MITECH.COM */
+
+ /* Data structure returned by READDIR(). */
+struct dirent {
+ char d_name[100]; /* File name */
+ int d_namlen;
+ int vms_verscount; /* Number of versions */
+ int vms_versions[20]; /* Version numbers */
+};
+
+ /* Handle returned by opendir(), used by the other routines. You
+ * are not supposed to care what's inside this structure. */
+typedef struct _dirdesc {
+ long context;
+ int vms_wantversions;
+ char *pattern;
+ struct dirent entry;
+ struct dsc$descriptor_s pat;
+} DIR;
+
+
+#define rewinddir(dirp) seekdir((dirp), 0L)
+
+
+extern DIR *opendir();
+extern struct dirent *readdir();
+extern long telldir();
+extern void seekdir();
+extern void closedir();
+extern void vmsreaddirversions();
+/*
+ * END dirent.h
+ */
+#define _DIRENT_H_INCLUDED_
+
+
+ /* Number of elements in vms_versions array */
+#define VERSIZE(e) (sizeof e->vms_versions / sizeof e->vms_versions[0])
+
+ /* Linked in later. */
+extern char *strrchr();
+extern char *strcpy();
+/* Don't need this when all these programs are lumped together. RLD
+extern char *malloc();
+*/
+
+/*
+** Open a directory, return a handle for later use.
+*/
+DIR *
+opendir(name)
+ char *name;
+{
+ DIR *dd;
+
+ /* Get memory for the handle, and the pattern. */
+ if ((dd = (DIR *)malloc(sizeof *dd)) == NULL) {
+ __threadErrno = ENOMEM;
+ return NULL;
+ }
+
+ if (strcmp(".",name) == 0) name = "";
+
+ dd->pattern = malloc((unsigned int)(strlen(name) + sizeof "*.*" + 1));
+ if (dd->pattern == NULL) {
+ free((char *)dd);
+ __threadErrno = ENOMEM;
+ return NULL;
+ }
+
+ /* Fill in the fields; mainly playing with the descriptor. */
+ (void)sprintf(dd->pattern, "%s*.*", name);
+ dd->context = 0;
+ dd->vms_wantversions = 0;
+ dd->pat.dsc$a_pointer = dd->pattern;
+ dd->pat.dsc$w_length = strlen(dd->pattern);
+ dd->pat.dsc$b_dtype = DSC$K_DTYPE_T;
+ dd->pat.dsc$b_class = DSC$K_CLASS_S;
+
+ return dd;
+}
+
+/*
+** Set the flag to indicate we want versions or not.
+*/
+void
+vmsreaddirversions(dd, flag)
+ DIR *dd;
+ int flag;
+{
+ dd->vms_wantversions = flag;
+}
+
+/*
+** Free up an opened directory.
+*/
+void
+closedir(dd)
+ DIR *dd;
+{
+ free(dd->pattern);
+ free((char *)dd);
+}
+
+/*
+** Collect all the version numbers for the current file.
+*/
+static void
+collectversions(dd)
+ DIR *dd;
+{
+ struct dsc$descriptor_s pat;
+ struct dsc$descriptor_s res;
+ struct dirent *e;
+ char *p;
+ char buff[sizeof dd->entry.d_name];
+ int i;
+ char *text;
+ long context;
+
+ /* Convenient shorthand. */
+ e = &dd->entry;
+
+ /* Add the version wildcard, ignoring the "*.*" put on before */
+ i = strlen(dd->pattern);
+ text = malloc((unsigned int)(i + strlen(e->d_name)+ 2 + 1));
+ if (text == NULL)
+ return;
+ (void)strcpy(text, dd->pattern);
+ (void)sprintf(&text[i - 3], "%s;*", e->d_name);
+
+ /* Set up the pattern descriptor. */
+ pat.dsc$a_pointer = text;
+ pat.dsc$w_length = strlen(text);
+ pat.dsc$b_dtype = DSC$K_DTYPE_T;
+ pat.dsc$b_class = DSC$K_CLASS_S;
+
+ /* Set up result descriptor. */
+ res.dsc$a_pointer = buff;
+ res.dsc$w_length = sizeof buff - 2;
+ res.dsc$b_dtype = DSC$K_DTYPE_T;
+ res.dsc$b_class = DSC$K_CLASS_S;
+
+ /* Read files, collecting versions. */
+ for (context = 0; e->vms_verscount < VERSIZE(e); e->vms_verscount++) {
+ if (lib$find_file(&pat, &res, &context) == RMS$_NMF || context == 0)
+ break;
+ buff[sizeof buff - 1] = '\0';
+ if (p = strchr(buff, ';'))
+ e->vms_versions[e->vms_verscount] = atoi(p + 1);
+ else
+ e->vms_versions[e->vms_verscount] = -1;
+ }
+
+ free(text);
+}
+
+/*
+** Read the next entry from the directory.
+*/
+struct dirent *
+readdir(dd)
+ DIR *dd;
+{
+ struct dsc$descriptor_s res;
+ char *p;
+ char buff[sizeof dd->entry.d_name + 10];
+ int i;
+
+ /* Set up result descriptor, and get next file. */
+ res.dsc$a_pointer = buff;
+ res.dsc$w_length = sizeof buff - 2;
+ res.dsc$b_dtype = DSC$K_DTYPE_T;
+ res.dsc$b_class = DSC$K_CLASS_S;
+ if (lib$find_file(&dd->pat, &res, &dd->context) == RMS$_NMF
+ || dd->context == 0L)
+ /* None left... */
+ return NULL;
+
+ /* Force the buffer to end with a NUL. */
+ buff[sizeof buff - 1] = '\0';
+ for (p = buff; !isspace(*p); p++)
+ ;
+ *p = '\0';
+
+ /* Skip any directory component and just copy the name. */
+ if (p = strchr(buff, ']'))
+ (void)strcpy(dd->entry.d_name, p + 1);
+ else
+ (void)strcpy(dd->entry.d_name, buff);
+
+ /* Clobber the version. */
+ if (p = strchr(dd->entry.d_name, ';'))
+ *p = '\0';
+
+ /* claus: empty dirs seems to leave *.* in the buffer ... */
+ if (strcmp(dd->entry.d_name, "*.*") == 0) {
+ return NULL;
+ }
+
+ dd->entry.d_namlen = strlen(dd->entry.d_name);
+
+ dd->entry.vms_verscount = 0;
+ if (dd->vms_wantversions)
+ collectversions(dd);
+ return &dd->entry;
+}
+
+/*
+** Return something that can be used in a seekdir later.
+*/
+long
+telldir(dd)
+ DIR *dd;
+{
+ return dd->context;
+}
+
+/*
+** Return to a spot where we used to be.
+*/
+void
+seekdir(dd, pos)
+ DIR *dd;
+ long pos;
+{
+ dd->context = pos;
+}
+
+# define HAS_OPENDIR
+
+# endif /* not HAS_OPENDIR */
+
#endif /* __VMS__ */
%}
! !
@@ -2927,6 +3210,62 @@
"Modified: 15.7.1997 / 16:03:51 / stefan"
! !
+!OpenVMSOperatingSystem class methodsFor:'directory access'!
+
+nextLinkInfoFrom:aDirectoryStream dirPointer:dirPointer
+ "return a FileStatusInfo entry for the next entry, when reading from a directory.
+ Under UNIX, the returned fileStatuInfo ONLY contains the name of the file,
+ whereas under Windows, it contains the full info (incl. fileSize, access rights etc.).
+ The reason is that under wndows, the ReadNextEntry system call does this, whereas the
+ the corresponding unix read from a readdir only returns the name."
+
+ |entry isUnix error|
+%{
+#ifdef HAS_OPENDIR
+ DIR *d;
+ DIRENT_STRUCT *dp;
+
+ if ((dirPointer != nil)
+ && __isExternalAddressLike(dirPointer)) {
+ d = (DIR *)__FILEVal(dirPointer);
+
+ __BEGIN_INTERRUPTABLE__
+ do {
+ do {
+ __threadErrno = 0;
+ dp = readdir(d);
+ /*
+ * for compatibility with ST-80,
+ * skip entries for '.' and '..'.
+ * If wanted, these must be added synthetically.
+ */
+ } while (dp && ((strcmp(dp->d_name, ".")==0) || (strcmp(dp->d_name, "..")==0)));
+ } while ((dp == NULL) && (__threadErrno == EINTR));
+ __END_INTERRUPTABLE__
+
+ if (dp != NULL) {
+ entry = __MKSTRING((char *)(dp->d_name));
+ } else {
+ if (__threadErrno) {
+ error = __mkSmallInteger(__threadErrno);
+ }
+ }
+ }
+#endif /* HAS_OPENDIR */
+%}.
+ error notNil ifTrue:[
+ ^ StreamIOError newException
+ errorCode:error;
+ osErrorHolder:(OperatingSystem errorHolderForNumber:error);
+ parameter:aDirectoryStream;
+ raiseRequest
+ ].
+ entry notNil ifTrue:[
+ ^ entry.
+ ].
+ ^ aDirectoryStream pastEndRead
+! !
+
!OpenVMSOperatingSystem class methodsFor:'file access'!
closeFd:anInteger
@@ -7515,6 +7854,6 @@
!OpenVMSOperatingSystem class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/OpenVMSOperatingSystem.st,v 1.17 2011-10-07 13:57:55 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/OpenVMSOperatingSystem.st,v 1.18 2015-01-12 12:50:08 cg Exp $'
! !
OpenVMSOperatingSystem initialize!