HP OpenVMS Systems

ask the wizard
Content starts here

Determining file (directory) attributes?

» close window

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;
  }
 
 

answer written or last revised on ( 1-SEP-1999 )

» close window