Operating System - OpenVMS
1828622 Members
1507 Online
109983 Solutions
New Discussion

Re: Getting block size of a data file, from within COBOL.

 
SOLVED
Go to solution
John T. Farmer
Regular Advisor

Getting block size of a data file, from within COBOL.

Is there an RTL available that returns file-level information (i.e., SYS$, LIB$, etc)? In COBOL, I am processing a file containing a list of data files from my system. I need to get the file size (disk blocks) for each file in my list. Trying to avoid doing this at the DCL level. Also trying to avoid having to open each file and count characters, some are fixed length, and some are variable length RMS files.

Thanks,

John
OpenVMS (Alpha) v7.2-1
Compaq Cobol v2.6-1060
RMS File System
15 REPLIES 15
Kris Clippeleyr
Honored Contributor

Re: Getting block size of a data file, from within COBOL.

John,

> Also trying to avoid having to open each file

Going to be difficult. But you can always open the file using RMS routine $OPEN, specifying a FAB and an associated XABFHC, and immediately closing it again with $CLOSE.
In the XABFHC is returned (among others) XAB$L_EBK (end of file block) and XAB$L_HBK (highest virtual block in the file). That might give you an idea on the size of the file.

Regards,
Kris (aka Qkcl)
I'm gonna hit the highway like a battering ram on a silver-black phantom bike...
Hein van den Heuvel
Honored Contributor
Solution

Re: Getting block size of a data file, from within COBOL.

Unfortunately there is no system provides calleable function like the DCL F$FILE to do this. Several folks have rolled their own. Not sure whether there is a nice package out there.

Cobol really is the worst language to do this in. If this is just for a one-off run then please just use DCL, PERL, C, or BASIC

Cobol does not have a 'flexible' file open (BASIC and C do) which woudl allow you to just open the file and look in that RMS FAB what the size is.

Cobol also does not have proper pointer support play with RMS control blocks, because that is want needs to be done.

You need to craft a FAB, fill in a name, call SYS$OPEN and read the ALQ field in the FAB.

Compare to PERL (which has a 'stat' function)
$ perl -e "print -s ""test.mai"""
8139264

or, if you don't like the double-double quotes:
$ perl -e "print -s q(test.mai)"
8139264


Or DCL
$ write sys$output 512*f$file("test.mai","alq")
8139264

I would cheat and just SPAWN 'directory, perl, dcl or whatever, unless you need it several times per hour.

I have been know to cheat in COBOL and call LIB$FIND_FILE which, indirectly through the CTX points to a FAB which can be hi-jacked.

FDL$PARSE can also be used to make a FAB on the fly from a piece of string.

And if you know enough to be open the file in CObol, then you can ask it kindly where the FAB is and use that (see full example below).

But what problem are you really trying to solve?
What are you going to to, knowing the files allocated sizes? Report and be done? Whoopie!

Or did you want the 'used bytes' ... you'll need to hook up an XABFHC!
Or did you want to know how many data bytes there where?.. count 'm!
(There is an RMS hint to help)

"cobol only" example below...

Cheers,
Hein.

IDENTIFICATION DIVISION.
PROGRAM-ID. HEIN.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT THE-FILE
ASSIGN TO "TEST"
FILE STATUS IS FILE-STATUS.
DATA DIVISION.
FILE SECTION.
FD THE-FILE.
01 THE-RECORD.
03 THE-KEY PIC X(4).
03 SOME-DATA PIC X(66).
WORKING-STORAGE SECTION.
01 FILE-STATUS PIC XX.
01 FAB_PT POINTER.
01 ALQ_PT POINTER.
01 ALQ PIC 9(9) COMP VALUE 0.

PROCEDURE DIVISION.

MAIN-CONTROL SECTION.
BEGIN-HERE.
OPEN I-O THE-FILE ALLOWING ALL.
CALL "DCOB$RMS_CURRENT_FAB" GIVING FAB_PT
ADD 16 to FAB_PT GIVING ALQ_PT.
CALL "OTS$MOVE3" USING BY VALUE 4, BY VALUE ALQ_PT, BY REFERENCE ALQ.
DISPLAY "ALQ=", ALQ WITH CONVERSION.

John T. Farmer
Regular Advisor

Re: Getting block size of a data file, from within COBOL.

Hein,

Great example!!! This will give me what I need. The end result is that I will have a file list, several times a month, where I need to report names & sizes. A called routine using your code, does the trick.

Thanks,

John
Hein van den Heuvel
Honored Contributor

Re: Getting block size of a data file, from within COBOL.

>> Great example!!! This will give me what I need.

Hmmm, and here I was thinking I would just throw that in to scare of off!
:-)

The hard-coded '16' in there was found using:

$ libr/extr=$fabdef/out=fabdef.mar sys$library:starlet.mlb
$ sea fabdef.mar _alq
$EQU FAB$L_ALQ 16

Most folks would prefer to neatly declare a 'value is external' symbolic value, but if you had written a Macro program, then a hardoced 16 is really all you would be using.

The hardcoded 4 in the move is of course related to the 4 bytes which a $L = long symbol suggests.

> A called routine using your code, does the trick.

Glad it works for you!
Cheers,

Hein.

John T. Farmer
Regular Advisor

Re: Getting block size of a data file, from within COBOL.

You guys are way smarter than me. I attached my callable program implementing your logic example. Feel free to use and/or critique.

Thanks, John
Richard J Maher
Trusted Contributor

Re: Getting block size of a data file, from within COBOL.

Hi John,

A couple of quick points: -

1) You may want to pass the status to lib$stop By Value

2) A Declaratives section couldn't hurt and you could then crash with the RMS-STS special register.

3) I think there is another option where you could use the the $qio (io$_acp_control? io$_access?) to do a directory lookup of the file and I think the allocation is in the statistics info. (See i/o reference manual and disk driver for more) Probably best to stick with what your currently doing, but with this method I believe IIRC that you can $parse the filename and then get the allocation without ever having opened the file. If you're interested, search this forum for DIR_WATCH for more.

Regards Richard Maher

PS. The Caps-Lock key is on the left side of your keyboard :-)
John T. Farmer
Regular Advisor

Re: Getting block size of a data file, from within COBOL.

RICHARD,

THANK YOU.

JOHN ;)
Pallavi Akundi
Occasional Advisor

Re: Getting block size of a data file, from within COBOL.

Hi,

I might be a bit late.. but well i just became a member. I am a new comer in to this field and here is a program I have written. Please tell me if this works for you :)

I have attached the .cob,

and here is the .COM
DETSIZE.COM
-----------------------------
$FILE = SAMPLE.TXT
$FILE_SIZE = F$FILE_ATTRIBUTES("''FILE'","EOF")
-----------------------------
People with goals succeed because they know where they are going-- as quoted by some one
John T. Farmer
Regular Advisor

Re: Getting block size of a data file, from within COBOL.

Pallavi,

Never too late. That's a nice approach too.

Thanks,

John
Jan van den Ende
Honored Contributor

Re: Getting block size of a data file, from within COBOL.

Pallavi,

for many visitors in this forum, (those behind a strict ruled firewall, and those running M$ systems, others maybe) it is impossible, or impracticle, if teh appended text is anything else as ".TXT"
For future postings, please rename the file accordingly.

Thanks in advance.

Proost.

Have one on me.

jpe
Don't rust yours pelled jacker to fine doll missed aches.
Pallavi Akundi
Occasional Advisor

Re: Getting block size of a data file, from within COBOL.

Hello,

Sorry,I did not know about that.

Here is the .COB again renamed as .txt :)

Pallavi
People with goals succeed because they know where they are going-- as quoted by some one
Hein van den Heuvel
Honored Contributor

Re: Getting block size of a data file, from within COBOL.

Hi there Pallavi,

Welcome to the OpenVMS Forum.
Always good to see new names!

Unfortunately there are several issues with your proposed solution.

Most importantly a spawned process has its own symbol space which is not visible to the parent. You would have to define a LOGICAL, not a symbol, in the JOB table to get information from child to parent.

Actually... if you only need to return 1 integer value you can 'cheat' and return it as the status.

Minor problems
- diplay : typo
- moving spaces in command after setting text.
- command file need := to for string asssignment
- f$file: Why pass string with expanded variable if you can just pass the variable:
...f$file (file, "eof")
(Answer: because you want to see the text with 'set verify')

Try the following. It 'encodes' the size into a status to make it look succesful and have to OPTION (not done here) to detect failure.

$ type detsize.com
$FILE := tmp.exe
$FILE_SIZE == F$FILE_ATTRIBUTES("''FILE'","EOF")
$exit 2*file_size + 1

$Type test.cob
IDENTIFICATION DIVISION.
PROGRAM-ID. DETSIZE.
AUTHOR. PALLAVI.
ENVIRONMENT DIVISION.

INPUT-OUTPUT SECTION.

FILE-CONTROL.
I-O-CONTROL.
DATA DIVISION.
FILE SECTION.
WORKING-STORAGE SECTION.
01 SUBMIT-COMMAND PIC X(100).
01 FILE-SIZE PIC 9(9).
01 stat pic s9(9) comp.
PROCEDURE DIVISION.
MAINLINE.
MOVE SPACES TO SUBMIT-COMMAND.
STRING "@DETSIZE" DELIMITED BY SIZE
INTO SUBMIT-COMMAND.
CALL "LIB$SPAWN" USING BY DESCRIPTOR SUBMIT-COMMAND,
omitted,omitted,omitted,omitted,omitted, by reference stat.
subtract 1 from stat.
divide stat by 2 giving FILE-SIZE.
DISPLAY "--------- \ \ \ \ \ / / / /________".
DISPLAY "THE FILE SIZE IS:::" FILE-SIZE.
MAINLINE-EXIT.
EXIT.


(I needed cobol/ansi due to tab/spaces/whatever).

Hein.
Pallavi Akundi
Occasional Advisor

Re: Getting block size of a data file, from within COBOL.

Hello Hein,

Please ignore the typos (last min attaching of wrong file) But, thanks for elaborating on why we can't read the symbol back into the cob with lib$get_symbol.
But I did not get why we needed to do the
$exit 2*file_size + 1

Could we not have done it as

$exit file_size ?

Regards,
Pallavi
People with goals succeed because they know where they are going-- as quoted by some one
Hein van den Heuvel
Honored Contributor

Re: Getting block size of a data file, from within COBOL.

The 'odd' status is used to help testing the program and as a way to convey TWO flavors of data.

In VMS odd exit status values indicate success, even indicate a problem.

If the tool simply used the files size as exit, then how can it indicate a problem (for example: file-not-found)?

Looking at it from the other side, what if the file size is even (for example 12). Try it...
$ exit 12
%SYSTEM-F-ACCVIO, access violation,
That would be rather confusing no?
Did the process die a horrible death or was the size 12? Knowing that it is not a C program, but a DCL script and ACCVIO is very unlikely, so we 'guess' it is a size?
Now $exit 25 --> silence.

Cheers,
Hein.


John T. Farmer
Regular Advisor

Re: Getting block size of a data file, from within COBOL.

Thanks for the help from all who responded.