Command built-in can parse output into list (no need to Match it now)
[k8jam.git] / filevms.c
blob807d21bc6a09f4aed3c3f6e83504bed61e4cdb6b
1 /*
2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
7 /*
8 * filevms.c - scan directories and libaries on VMS
10 * External routines:
12 * file_dirscan() - scan a directory for files
13 * file_time() - get timestamp of file, if not done by file_dirscan()
14 * file_archscan() - scan an archive for files
16 * File_dirscan() and file_archscan() call back a caller provided function
17 * for each file found. A flag to this callback function lets file_dirscan()
18 * and file_archscan() indicate that a timestamp is being provided with the
19 * file. If file_dirscan() or file_archscan() do not provide the file's
20 * timestamp, interested parties may later call file_time().
22 * 02/09/95 (seiwald) - bungled R=[xxx] - was using directory length!
23 * 05/03/96 (seiwald) - split into pathvms.c
24 * 01/08/01 (seiwald) - closure param for file_dirscan/file_archscan
25 * 03/23/01 (seiwald) - VMS C++ changes.
26 * 11/04/02 (seiwald) - const-ing for string literals
29 # include "jam.h"
30 # include "filesys.h"
31 # include "pathsys.h"
33 # ifdef OS_VMS
35 # include <rms.h>
36 # include <iodef.h>
37 # include <ssdef.h>
38 # include <string.h>
39 # include <stdlib.h>
40 # include <stdio.h>
41 # include <descrip.h>
43 #include <lbrdef.h>
44 #include <credef.h>
45 #include <mhddef.h>
46 #include <lhidef.h>
47 #include <lib$routines.h>
48 #include <starlet.h>
50 /* Supply missing prototypes for lbr$-routines*/
52 extern "C" {
54 int lbr$set_module(
55 void **,
56 unsigned long *,
57 struct dsc$descriptor_s *,
58 unsigned short *,
59 void * );
61 int lbr$open( void **,
62 struct dsc$descriptor_s *,
63 void *,
64 void *,
65 void *,
66 void *,
67 void * );
69 int lbr$ini_control(
70 void **,
71 unsigned long *,
72 unsigned long *,
73 void * );
75 int lbr$get_index(
76 void **,
77 unsigned long *,
78 int (*func)( struct dsc$descriptor_s *, unsigned long *),
79 void * );
81 int lbr$close(
82 void ** );
86 static void
87 file_cvttime(
88 unsigned int *curtime,
89 time_t *unixtime )
91 static const size_t divisor = 10000000;
92 static unsigned int bastim[2] = { 0x4BEB4000, 0x007C9567 }; /* 1/1/1970 */
93 int delta[2], remainder;
95 lib$subx( curtime, bastim, delta );
96 lib$ediv( &divisor, delta, unixtime, &remainder );
99 # define DEFAULT_FILE_SPECIFICATION "[]*.*;0"
101 # define min( a,b ) ((a)<(b)?(a):(b))
103 void
104 file_dirscan(
105 const char *dir,
106 scanback func,
107 void *closure )
110 struct FAB xfab;
111 struct NAM xnam;
112 struct XABDAT xab;
113 char esa[256];
114 char filename[256];
115 char filename2[256];
116 char dirname[256];
117 register int status;
118 PATHNAME f;
120 memset( (char *)&f, '\0', sizeof( f ) );
122 f.f_root.ptr = dir;
123 f.f_root.len = strlen( dir );
125 /* get the input file specification
127 xnam = cc$rms_nam;
128 xnam.nam$l_esa = esa;
129 xnam.nam$b_ess = sizeof( esa ) - 1;
130 xnam.nam$l_rsa = filename;
131 xnam.nam$b_rss = min( sizeof( filename ) - 1, NAM$C_MAXRSS );
133 xab = cc$rms_xabdat; /* initialize extended attributes */
134 xab.xab$b_cod = XAB$C_DAT; /* ask for date */
135 xab.xab$l_nxt = NULL; /* terminate XAB chain */
137 xfab = cc$rms_fab;
138 xfab.fab$l_dna = DEFAULT_FILE_SPECIFICATION;
139 xfab.fab$b_dns = sizeof( DEFAULT_FILE_SPECIFICATION ) - 1;
140 xfab.fab$l_fop = FAB$M_NAM;
141 xfab.fab$l_fna = (char *)dir; /* address of file name */
142 xfab.fab$b_fns = strlen( dir ); /* length of file name */
143 xfab.fab$l_nam = &xnam; /* address of NAB block */
144 xfab.fab$l_xab = (char *)&xab; /* address of XAB block */
147 status = sys$parse( &xfab );
149 if( DEBUG_BINDSCAN )
150 printf( "scan directory %s\n", dir );
152 if ( !( status & 1 ) )
153 return;
157 /* Add bogus directory for [000000] */
159 if( !strcmp( dir, "[000000]" ) )
161 (*func)( closure, "[000000]", 1 /* time valid */, 1 /* old but true */ );
164 /* Add bogus directory for [] */
166 if( !strcmp( dir, "[]" ) )
168 (*func)( closure, "[]", 1 /* time valid */, 1 /* old but true */ );
169 (*func)( closure, "[-]", 1 /* time valid */, 1 /* old but true */ );
172 while ( (status = sys$search( &xfab )) & 1 )
174 char *s;
175 time_t time;
177 /* "I think that might work" - eml */
179 sys$open( &xfab );
180 sys$close( &xfab );
182 file_cvttime( (unsigned int *)&xab.xab$q_rdt, &time );
184 filename[xnam.nam$b_rsl] = '\0';
186 /* What we do with the name depends on the suffix: */
187 /* .dir is a directory */
188 /* .xxx is a file with a suffix */
189 /* . is no suffix at all */
191 if( xnam.nam$b_type == 4 && !strncmp( xnam.nam$l_type, ".DIR", 4 ) )
193 /* directory */
194 sprintf( dirname, "[.%.*s]", xnam.nam$b_name, xnam.nam$l_name );
195 f.f_dir.ptr = dirname;
196 f.f_dir.len = strlen( dirname );
197 f.f_base.ptr = 0;
198 f.f_base.len = 0;
199 f.f_suffix.ptr = 0;
200 f.f_suffix.len = 0;
202 else
204 /* normal file with a suffix */
205 f.f_dir.ptr = 0;
206 f.f_dir.len = 0;
207 f.f_base.ptr = xnam.nam$l_name;
208 f.f_base.len = xnam.nam$b_name;
209 f.f_suffix.ptr = xnam.nam$l_type;
210 f.f_suffix.len = xnam.nam$b_type;
213 path_build( &f, filename2, 0 );
216 if( DEBUG_SEARCH )
217 printf("root '%s' base %.*s suf %.*s = %s\n",
218 dir,
219 xnam.nam$b_name, xnam.nam$l_name,
220 xnam.nam$b_type, xnam.nam$l_type,
221 filename2);
224 (*func)( closure, filename2, 1 /* time valid */, time );
229 file_time(
230 const char *filename,
231 time_t *time )
233 /* This should never be called, as all files are */
234 /* timestampped in file_dirscan() and file_archscan() */
235 return -1;
238 static char *VMS_archive = 0;
239 static scanback VMS_func;
240 static void *VMS_closure;
241 static void *context;
243 static int
244 file_archmember(
245 struct dsc$descriptor_s *module,
246 unsigned long *rfa )
248 static struct dsc$descriptor_s bufdsc =
249 {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
251 struct mhddef *mhd;
252 char filename[128];
253 char buf[ MAXJPATH ];
255 int status;
256 time_t library_date;
258 register int i;
259 register char *p;
261 bufdsc.dsc$a_pointer = filename;
262 bufdsc.dsc$w_length = sizeof( filename );
263 status = lbr$set_module( &context, rfa, &bufdsc,
264 &bufdsc.dsc$w_length, NULL );
266 if ( !(status & 1) )
267 return ( 1 );
269 mhd = (struct mhddef *)filename;
271 file_cvttime( &mhd->mhd$l_datim, &library_date );
273 for ( i = 0, p = module->dsc$a_pointer; i < module->dsc$w_length; i++, p++ )
274 filename[i] = *p;
276 filename[i] = '\0';
278 sprintf( buf, "%s(%s.obj)", VMS_archive, filename );
280 (*VMS_func)( VMS_closure, buf, 1 /* time valid */, (time_t)library_date );
282 return ( 1 );
285 void
286 file_archscan(
287 const char *archive,
288 scanback func,
289 void *closure )
291 static struct dsc$descriptor_s library =
292 {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL};
294 unsigned long lfunc = LBR$C_READ;
295 unsigned long typ = LBR$C_TYP_UNK;
296 unsigned long index = 1;
298 register int status;
300 VMS_archive = (char *)archive;
301 VMS_func = func;
302 VMS_closure = closure;
304 status = lbr$ini_control( &context, &lfunc, &typ, NULL );
305 if ( !( status & 1 ) )
306 return;
308 library.dsc$a_pointer = (char *)archive;
309 library.dsc$w_length = strlen( archive );
311 status = lbr$open( &context, &library, NULL, NULL, NULL, NULL, NULL );
312 if ( !( status & 1 ) )
313 return;
315 (void) lbr$get_index( &context, &index, file_archmember, NULL );
317 (void) lbr$close( &context );
320 # endif /* VMS */