HP OpenVMS Systemsask the wizard |
The Question is: Hello Mr Wizard I am looking for a method of obtaining the size of a file, NOT the allocation from within a Fortran routine. I thought this would be a simple trivial task but alas I am proved wrong. Can you help. Regards Jim The Answer is : RMS does NOT keep track of the number of user data bytes in a file. The only reliable way to obtain that, is to read the file and count! RMS does maintain the ALLOCATED blocks which you can readily find in the FAB for the file (USEROPEN or FOR$FAB). RMS also maintains the EOF block and byte which you can get from the XABFHC. This is a little more tricky, involving address calculations. The EOF often has a close relation to the user bytes, much closer than the ALQ, but it is not the same due to overhead in the file: record-length word per record, fill byte for odd sized records... Sample program which returns some RMS fields for a given file: ! The subroutine get_create_date_siz gets the RMS CDT, RDT, ALQ and EBK ! fields. You can consult SYS$LIBRARY:FORSYSDEF.TLB entry $XABDATDEF and ! $XABFHCDEF to find the field names of other fields, if you should ever ! need them. program rms_test ! test program for get_create_date_siz IMPLICIT NONE character*80 filename integer*2 leng integer*4 cdat(2),rdat(2),status,get_create_date_size integer*4 alq,siz character*23 scdat,srdat print '('' Enter filename: '',$)' accept 10,filename 10 FORMAT(A80) status=get_create_date_size(filename,cdat,rdat,alq,siz) if(status) then call sys$asctim (,scdat,cdat,) call sys$asctim (,srdat,rdat,) print *,filename print *,' created ',scdat print *,' revised ',srdat print *,' ',siz,'/',alq,' blocks' else print *,'Error status=' filename=' ' call sys$getmsg (%val(status),leng,filename,,) print *,filename(1:leng) endif end options /extend_source integer function get_create_date_size(filename,cdat,rdat,alq,siz) implicit none character*(*) filename integer*4 cdat(2),rdat(2),alq,siz include '($FABDEF)' ! RMS definitions from FORSYSDEF.TLB include '($XABDEF)' include '($XABDATDEF)' include '($XABFHCDEF)' include '($XABPRODEF)' integer status,sys$open,sys$close ! RMS routines record/fabdef/fab ! the following structure defines an XAB by overlaying the XABDEF, XABDATDEF ! and XABFHCDEF structures. This allows access to the XABDAT and XABFHC fields ! as well as the common XAB fields which are defined only in XABDEF. STRUCTURE /fullxab/ UNION MAP record/xabdef/xab END MAP MAP record/xabdatdef/xabdat END MAP MAP record/xabfhcdef/xabfhc END MAP MAP record/xabprodef1/xabpro ENDMAP END UNION END STRUCTURE RECORD /fullxab/datxab,fhcxab,proxab ! allocate 3 XABs call lib$movc5(0,0,0,fab$c_bln,fab) ! Clear FAB fab.fab$b_bln=fab$c_bln ! set FAB options (see RMS fab.fab$b_bid=fab$c_bid ! manual for details) fab.fab$b_fac=fab$m_get fab.fab$b_shr=fab$m_shrdel+fab$m_shrget+fab$m_shrput+fab$m_shrUPD fab.fab$l_fop=fab$m_SQO fab.fab$l_fna=%loc(filename) ! set file name to open fab.fab$b_fns=len(filename) ! and length of name fab.fab$l_XAB = %loc(datxab) ! chain to XABDAT call lib$movc5(0,0,0,XAB$C_DATLEN,datxab) ! Clear XAB as XABDAT datxab.xab.xab$b_bln=XAB$C_DATLEN ! set length datxab.xab.xab$b_cod=XAB$C_DAT ! fill as XABDAT datxab.xab.xab$l_nxt=%LOC(fhcxab) ! chain to XABFHC call lib$movc5(0,0,0,XAB$C_FHCLEN,fhcxab) ! Clear XAB as XABFHC fhcxab.xab.xab$b_bln=XAB$C_FHCLEN ! set length fhcxab.xab.xab$b_cod=XAB$C_FHC ! fill as XABFHC fhcxab.xab.xab$l_nxt=%LOC(proxab) ! chain to XABFHC call lib$movc5(0,0,0,XAB$C_PROLEN,proxab) ! Clear XAB as XABPRO proxab.xab.xab$b_bln=XAB$C_PROLEN ! set length proxab.xab.xab$b_cod=XAB$C_PRO ! fill as XABPRO status=sys$open(fab) if(status) then CALL lib$movc3(8,datxab.xab.xab$q_rdt,rdat) ! get revision date CALL lib$movc3(8,datxab.xabdat.xab$q_cdt,cdat)! get creation date alq=fab.fab$l_alq ! get allocated size siz=fhcxab.xabfhc.xab$l_ebk ! get used size (=EOF block) status=sys$close(fab) ! close file endif get_create_date_size=status ! return RMS status return end
|