HP OpenVMS Systemsask the wizard |
The Question is: How can I determine, from a program, whether or not a specific filename is a directory file? I do not want to rely on the .DIR extension, because ordinary files can be created with .DIR, and directories can be renamed to something other than *.DIR;1 (alt hough they aren't very useful if you rename them that way, they still keep their "directory file" status). I also do not want to spawn off a "DIR/FULL" command and parse the output. Thanks!! The Answer is :
Options include the following...
struct stat st;
if ( !stat(filename,&st) && S_ISDIR(st.st_mode) )
{
/* this is a directory */
}
Alternatively, check the directory bit via the I/O ACPCONTROL (XQP)
interface. This interface is documented in the OpenVMS I/O User's
Reference Manual, available via:
http://www.openvms.digital.com:8000/
A (very primitive) Macro32 tool that sets the directory bit on a file
(using the XQP interface) is included below.
.title SETDIRBIT fixes the DIRECTORY bit
;
; this program is used to turn on the "DIRECTORY" bit in the
; file header. The file (more correctly, the directory) to be
; reset is specified by FID (file identification) and device.
; (The FID can be retrieved from a DIRECTORY/FULL command.)
;
; a) Put the FID into the "fid" buffer, below.
;
; b) The device the FID is from must also be plugged into
; the "dev" descriptor, below.
;
; The UCHAR field is protected -- see the I/O User's Reference
; Manual, Part I, ACP/QIO Interface. (SYSTEM or OWNER access
; to the file (the directory) is required.)
;
; 11-Apr-1988 Hoffman
; This was written up... No claims to style or content:
; intended simply to solve a one-shot problem. MINIMAL
; error checking and user-hostile!
;
.library 'Sys$Library:LIB.Mlb'
$atrdef ; File attribute definitions
$fchdef ; File characteristics
$fibdef ; File Information Block
$iodef ; I/O definitions
$ssdef ; System Service Definitions
.psect data,wrt,noexe,long,noshr,usr
fid: ; A file id (FID) looks like this: [NUM,SEQ,RVN]
.word 652 ; file NUM
.word 9 ; file SEQ
.word 0 ; file RVN
.word 0 ; (so we can use a MOVQ)
;
dev: ; And the name of the disk the file id is from...
.ascid /HSC000$DUA2:/
;
iosb: .blkw 4 ; garden variety IOSB
;
fchan: .blkw 1 ; channel to the disk
;
FIBSIZE=22 ; use the short FIB
fibbuf: .blkb FIBSIZE ; here's the FIB itself
fib: .long FIBSIZE ; here's the FIB descriptor
.address fibbuf
;
uchar: .blkb ATR$S_UCHAR ; the FAT characteristics buffer
fat: ; The File Attributes itemlist follows:
.word ATR$S_UCHAR ; length of the buffer
.word ATR$C_UCHAR ; address of the buffer
.address uchar ; where the UCHAR field is...
.blkq 0 ; zero marks the end...
;
.psect code,nowrt,exe,long,shr,usr
.entry SETDIRBIT, ^M<R2>
;
; Get a channel to the device
;
$ASSIGN_S -
devnam=dev,-
chan=fchan
blbs r0,10$
ret
;
10$: ;
; Move the two important "bits" of trivia out to the FIB.
;
moval fibbuf,R0
movq fid,FIB$W_FID(R0)
movl #FIB$M_WRITE,FIB$L_ACCTL(R0)
;
; Access the file (directory)
;
$QIOW_S -
chan=fchan,-
func=#<IO$_ACCESS!IO$M_ACCESS>,-
iosb=IOSB,-
p1=fib,-
p5=#fat
blbc r0,19$
blbs iosb,20$
19$: ret
;
20$: ;
; Force the DIRECTORY bit on!
;
bisl2 #FCH$M_DIRECTORY,uchar
;
; Write the modified characteristics out...
;
$QIOW_S -
chan=fchan,-
func=#<IO$_MODIFY>,-
iosb=IOSB,-
p1=fib,-
p5=#fat
blbc r0,29$
blbs iosb,30$
29$: ret
;
30$: ;
; And deaccess the file (directory)
;
$QIOW_S -
chan=fchan,-
func=#<IO$_DEACCESS>,-
iosb=IOSB
blbc r0,39$
blbs iosb,40$
39$: ret
;
40$: ;
; Deassign the channel to the disk
;
$DASSGN_S -
chan=fchan
movzwl #SS$_NORMAL,R0
;
; And bail out...
;
ret
.END SETDIRBIT
Or you can check the bit using the following C example of an RMS call:
#include <rms.h>
#include <stdio.h>
#include <string.h>
typedef struct { short len, cod; void *address; int *retlen; } item;
/*
** Author: Hein van den Heuvel
** Compaq Computer Corporation
*/
main (int argc, char *argv[])
{
int stat, records, directory, SYS$OPEN();
char *is_not;
struct FAB fab;
struct XABITM itm;
item uchar_items[] = { sizeof (int), XAB$_UCHAR_DIRECTORY,
&directory, 0, 0, 0, 0, 0 } ;
fab = cc$rms_fab;
fab.fab$l_xab = (void *) &itm;
fab.fab$b_shr = FAB$M_SHRUPD;
fab.fab$b_fac = FAB$M_GET;
fab.fab$l_fna = argv[1];
fab.fab$b_fns = strlen ( argv[1] );
itm.xab$b_bln = XAB$C_ITMLEN; /* no template available ?! */
itm.xab$b_cod = XAB$C_ITM;
itm.xab$l_itemlist = (char *) &uchar_items;
itm.xab$b_mode = XAB$K_SENSEMODE;
itm.xab$l_nxt = 0;
stat = SYS$OPEN ( &fab );
if (!(stat&1)) return stat;
is_not = directory? "IS" : "is NOT";
printf ("File %s %s a directory\n", argv[1], is_not);
return 1;
}
|