2 * Copyright © 1994 the Free Software Foundation, Inc.
4 * Author: Richard Levitte (levitte@e.kth.se)
6 * This file is a part of GNU VMSLIB, the GNU library for porting GNU
9 * GNU VMSLIB is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * GNU VMSLIB is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
38 #include <lib$routines.h>
43 /* The following was snarfed from lib-src/alloca.c in GNU Emacs,
47 typedef void procedure;
48 typedef void *pointer;
50 typedef int procedure;
51 typedef char *pointer;
54 /* Different portions of Emacs need to call different versions of
55 malloc. The Emacs executable needs alloca to call xmalloc, because
56 ordinary malloc isn't protected from input signals. On the other
57 hand, the utilities in lib-src need alloca to call malloc; some of
58 them are very simple, and don't have an xmalloc routine.
60 Non-Emacs programs expect this to call use xmalloc.
62 Callers below should use malloc.
64 There is some need for BLOCK_INPUT and UNBLOCK_INPUT, but it is really
65 only used in Emacs, so that's the only time it's used. Otherwise,
66 they are just empty statements. */
70 #define malloc xmalloc
75 extern pointer malloc ();
76 extern procedure free ();
88 static struct direct *vms_low_readdir ();
93 unsigned long context;
95 struct dsc$descriptor_s dir_spec;
96 struct dsc$descriptor_s file_spec;
102 vms_opendir (infilename, filepattern)
103 char *infilename; /* name of directory */
106 register VMS_DIR *dirp; /* -> malloc'ed storage */
107 register unsigned int length = 1024;
108 register int fd; /* file descriptor for read */
110 struct stat sbuf; /* result of fstat */
112 filename = (char *) malloc(length+1);
113 strcpy(filename, infilename);
115 strip_trailing_slashes (filename);
116 if(strcmp(filename, ".") == 0)
118 getcwd(filename, length+1, 1); /* Get a VMS filespec */
119 length = strlen(filename);
123 if ((filename[length-1] != ']'
124 && filename[length-1] != '>'
125 && filename[length-1] != ':'
126 && (stat (filename, &sbuf) < 0
127 || (sbuf.st_mode & S_IFMT) != S_IFDIR)))
132 return 0; /* bad luck today */
135 if ((dirp = (VMS_DIR *) xmalloc (sizeof (VMS_DIR))) == 0)
140 return 0; /* bad luck today */
148 dirp->file_spec.dsc$a_pointer =
149 (char *) xmalloc (strlen (filepattern) + 1);
150 strcpy (dirp->file_spec.dsc$a_pointer, filepattern);
154 dirp->file_spec.dsc$a_pointer =
155 (char *) xmalloc (4);
156 strcpy (dirp->file_spec.dsc$a_pointer, "*.*");
158 dirp->file_spec.dsc$w_length = strlen (dirp->file_spec.dsc$a_pointer);
159 dirp->file_spec.dsc$b_dtype = DSC$K_DTYPE_T;
160 dirp->file_spec.dsc$b_class = DSC$K_CLASS_S;
161 dirp->version_flag = strchr (dirp->file_spec.dsc$a_pointer, ';') != 0;
163 dirp->dir_spec.dsc$a_pointer = (char *) xmalloc (strlen (filename) + 10);
165 file_name_as_directory (dirp->dir_spec.dsc$a_pointer, filename);
166 dirp->dir_spec.dsc$w_length = strlen (dirp->dir_spec.dsc$a_pointer);
167 dirp->dir_spec.dsc$b_dtype = DSC$K_DTYPE_T;
168 dirp->dir_spec.dsc$b_class = DSC$K_CLASS_S;
171 dirp->s_dir.dd_fd = 0;
172 dirp->s_dir.dd_loc = dirp->s_dir.dd_size = 0; /* refill needed */
176 /* In the cases where the filename ended with `]', `>' or `:',
177 we never checked if it really was a directory, so let's do that
178 now, by trying to read the first entry. */
179 if (vms_low_readdir ((DIR *) dirp) == (struct direct *) -1)
181 vms_closedir (dirp); /* was: xfree (dirp); */
185 dirp->s_dir.dd_loc = 0; /* Make sure the entry just read is
186 reused at the next call to readdir. */
188 return (DIR *) dirp; /* I had to cast, for VMS sake. */
193 register DIR *dirp; /* stream from vms_opendir */
196 VMS_DIR *vms_dirp = (VMS_DIR *) dirp;
198 if (vms_dirp->context != 0)
199 lib$find_file_end (&(vms_dirp->context));
200 xfree (vms_dirp->dir_spec.dsc$a_pointer);
201 xfree (vms_dirp->file_spec.dsc$a_pointer);
204 xfree ((char *) dirp);
208 struct direct dir_static; /* simulated directory contents */
210 static struct direct *
211 vms_low_readdir (dirp)
214 static char rbuf[257];
215 static struct dsc$descriptor_s rdsc =
216 { sizeof (rbuf), DSC$K_DTYPE_T, DSC$K_CLASS_S, rbuf };
217 VMS_DIR * vms_dirp = (VMS_DIR *) dirp;
219 if (dirp->dd_size == 0)
222 unsigned long status;
224 status = lib$find_file (&vms_dirp->file_spec, &rdsc, &vms_dirp->context,
225 &vms_dirp->dir_spec, 0, 0, &vms_dirp->uflags);
226 vms_dirp->status = status;
227 if (status == RMS$_NMF || status == RMS$_FNF)
229 if (status != RMS$_NORMAL)
230 return (struct direct *) -1;
233 if (cp = strchr (rbuf, ' '))
235 if ((cp = strchr (rbuf, ';')) != 0
236 && !vms_dirp->version_flag)
239 for (cp2 = rbuf - 1; cp2 != 0;)
243 cp2 = strchr (cp, ']');
245 cp2tmp = strchr (cp2 + 1, '>');
250 /* Propagate names as lower case only,
251 directories have ".dir" truncated,
252 do not propagate null extensions "makefile." */
256 if(strcmp(cp, "CVS.DIR") == 0)
257 strcpy(dirp->dd_buf, "CVS");
260 for(p = cp, q = dirp->dd_buf; *p;)
262 if(strcmp(p, ".DIR") == 0)
265 *q++ = tolower(*p++);
273 strcpy (dirp->dd_buf, cp);
276 dirp->dd_size = strlen (dirp->dd_buf);
280 if (vms_dirp->status != RMS$_NORMAL)
283 dir_static.d_ino = -1; /* Couldn't care less... */
284 dir_static.d_namlen = strlen (dirp->dd_buf);
285 dir_static.d_reclen = sizeof (struct direct)
287 + dir_static.d_namlen - dir_static.d_namlen % 4;
288 strcpy (dir_static.d_name, dirp->dd_buf);
289 dir_static.d_name[dir_static.d_namlen] = '\0';
290 dirp->dd_loc = dirp->dd_size; /* only one record at a time */
298 register DIR *dirp; /* stream from vms_opendir */
300 register struct direct *dp;
304 if (dirp->dd_loc >= dirp->dd_size)
305 dirp->dd_loc = dirp->dd_size = 0;
307 dp = vms_low_readdir (dirp);
308 if (dp == 0 || dp == (struct direct *) -1)