Read a Unix File
Files on Unix and z/OS-datasets have complete different design paradigms. Nearly all files on z/OS have records. You read and write records. However, on Unix, you read and write bytes and/or a stream of bytes. When you wish to read, you say to the system how many bytes you want and you will get them until there are no more bytes in the file. Unix has a kind of records though, but they are merely bytes separated by Newline (NL - X’15’).
Unix files on z/OS
When you browse a file on zFS it looks exactly as records on a dataset with the exception that they have variable length. That is because each “record” is suffixed by X’15’ (New Line) and ISPF Browse shows it as a record. The NL is not displayed
********************************* Top of Data ***
------------------------------------------------
MACRO
444444444DCCDD
00000000041396
------------------------------------------------
&LABEL USSSERV &SERVICE,&PARMS
5DCCCD444EEEECDE45ECDECCC65DCDDE
0312530004222595002595935B071942
------------------------------------------------
GBLC &PARM_LABEL
444444444CCDC445DCDD6DCCCD
00000000072330007194D31253
------------------------------------------------
AIF ('&SERVICE' EQ 'PARM').PARM
444444444CCC444475ECDECCC74CD47DCDD754DCDD
000000000196000DD02595935D0580D7194DDB7194
|
Display of Unix file on zFS. (ISPF Browse)
If you enter the same file in edit mode, you see all lines padded with spaces but that is just for you to be able to type in characters after the last character. When you save the file an NL will be placed right after the last character and the spaces after NL will be removed.
****** ***************************** Top of Data *******
000001 MACRO
444444444DCCDD44444444444444444444444444444444444
0000000004139600000000000000000000000000000000000
--------------------------------------------------------
000002 &LABEL USSSERV &SERVICE,&PARMS
5DCCCD444EEEECDE45ECDECCC65DCDDE44444444444444444
0312530004222595002595935B07194200000000000000000
--------------------------------------------------------
|
Same file in edit mode
Assembler program to read a Unix file.
I have made a program that reads a file and write the “records” to operator (WTO). Let’s go through the sections in
the program. I use my macro USSSERV to do the more tedious work of calling the USS services. You can find it in the previous article
General storage fields and instructions
PARM USSSERV PARM,10
RETVAL DS F
RETCODE DS F
RSNCODE DS F
|
Definition of storage for all calls.
PARM as parameter list with 10 fullwords followed by three fullwords to return values from the callable service.
You must check for any error after each call.
ICM R15,B'1111',RETVAL Test RETVAL
BL ERROR Branch if negative
* (-1 = failure)
|
OPEN - BPX1OPN
First of all you must open the file you wish to read. The open will establish a connection between your program and the file. This specific connection is “pointed” to by the result of the open in the fullword FILEDESC which must be used in each of the following commands to the file, - here READ and CLOSE.
FILEDESC DS F Result field that contains a “pointer” to the file.
BUFLENA DS F Length of Path and name of file
BUFFERA DS CL13 Path and name of file
FLAGS DS F Open option. Read only (O_RDONLY)
MODE DS F Is here zero
|
Storage fields used by Open
Open the file for input (read) and save the file descriptor
MVC BUFFERA(14),=CL14'/u/jee/ussserv'
MVC BUFLENA,=F'14'
XC S_MODE,S_MODE
XC O_FLAGS(OPNF_LENGTH),O_FLAGS
MVI O_FLAGS4,O_RDONLY Read only
USSSERV OPEN,(BUFLENA,BUFFERA,FLAGS,MODE,
RETVAL,
RETCODE,
RSNCODE)
ICM R15,B'1111',RETVAL Test RETVAL
BL ERROR Branch if negative
* (-1 = failure)
ST R15,FILEDESC Store the file descriptor
|
Call open for read of “/u/jee/ussserv”. The result (File descriptor) is in register 15.
Remember, that path and file names are case sensitive.
READ - BPX1RED
You can now issue READ as many times you like until End-Of-File. The READ-command takes some fields.
READ_COUNT DS F Saves the result from R15 of bytes read
BUFFER DS CL40 The area with the read bytes
BUFFER_ADR DS F The address of the area above
BUFFER_LENGTH DS F The length of the buffer area
B_ALET DS F Not used. Must be zero
|
READ fields
Before we call the READ service we must initiate some of the fields. The buffer (BUFFER) must be filled with binary zeroes in case we do not get all the bytes into the buffer. This will typically be at the end of the file.
Please note, that we supply the ADDRESS of the buffer rather than the buffer itself. It might be because we could issue another read right after adding the number of bytes read to the buffer address. That would be convenient if the buffer is greater than the number we supply in the BUFFER_LENGTH. We do not do it here!
LA R4,WTOTEXT
LOOP_READ DS 0H
MVC BUFFER_LENGTH,=A(L'BUFFER)
XC B_ALET,B_ALET
XC BUFFER,BUFFER
LA 1,BUFFER
ST 1,BUFFER_ADR
USSSERV READ,(FILEDESC,
BUFFER_ADR,
B_ALET,
BUFFER_LENGTH,
RETVAL,
RETCODE,
RSNCODE)
ICM R15,B'1111',RETVAL Test RETVAL
BM ERROR Branch if negative
* (-1 = failure)
BZ CLOSE End-Of-File
ST R15,READ_COUNT Store the number of bytes read
|
READ code
We check for any errors after the read and saves the number of bytes read in READ_COUNT.
Splitting a buffer into records
We must have a routine to convert the stream input to the record output.
WTO DS 0F
WTOLGD DS H
WTOTEXT DS CL80
|
WTO fields
This routine takes the buffer and separates it into records that can be written to operator (WTO). One buffer can contain several records and a record can be split into two buffers. The routine checks for NL (X’15’) and when it is found it writes the record. However, when the routine comes to the end of the buffer without encountering an NL it goes to read a new buffer full of bytes.
L R6,READ_COUNT
LA R2,BUFFER
NEXT_BYTE DS 0H
CLI 0(R2),X'15'
BE WRITE_BYTES
MVC 0(1,R4),0(R2)
LA R2,1(,R2)
LA R4,1(,R4)
BCT R6,NEXT_BYTE
B LOOP_READ
WRITE_BYTES DS 0H
LA R2,1(,R2)
MVC WTOLGD,=Y(L'WTOTEXT)
WTO TEXT=WTO,ROUTCDE=11
MVI WTOTEXT,C' '
MVC WTOTEXT+1(l'WTOTEXT-1),WTOTEXT
LA R4,WTOTEXT
BCT R6,NEXT_BYTE
B LOOP_READ
|
Use of general registers:
R2 Points to the byte in the input buffer
R4 Points to the byte in the output buffer (WTOTEXT)
R6 Counts down the number of bytes left in the input buffer.
The number of bytes in the input buffer is limited to the input buffer length set on the READ command (BUFFER_LENGTH)
Close BPX1CLO
Nothing special with the CLOSE. It takes the FILEDESC and disconnects the program from the file.
CLOSE DS 0h
USSSERV CLOSE,(FILEDESC,
RETVAL,
RETCODE,
RSNCODE)
ICM R15,B'1111',RETVAL Test RETVAL
BM ERROR Branch if negative (-1 = failure)
BZ RETURN
|
Manuals
UNIX System Services Programming: Assembler Callable Services Reference (SA22-7803-14)
EBCDIC Code Page: https://en.wikipedia.org/wiki/EBCDIC_037
Ingen kommentarer:
Send en kommentar