Working with the IFS from RPG. What is the IFS? What is a Stream File? Why would I want to do that with RPG? Integrated Files System – anything not related in the traditional iSeries world i.e. qsys.lib Could be things on the I, could be things on other servers that follow the PC or Unix world of file structure Every Object is a stream file in that world. Program, data files, text files
File Systems Available on the i /QSYS.LIB – Traditional File Ssystem /QDLS – Document Library System – MS Dos like /QOpenSys – The Open Systems File System / - Root file system – Windows Other File systems i.e. /QNTC any other server connected to your lan QDLS – everything must fit the 8.3 naming convention – no spaces /QNTC same as \\Server\ in the PC world WrkFlr – gets you in the structure starting at /QDSL
Traits of these “non” traditional file systems Folder – Subfolder and a hierarchy of folders or directories Files are all stream files Not fixed length Everything is a stream file – Programs, data, pictures, Even folders or directories are just another stream file No defined fields Stream of Characters XML, comma separated, JSON, Text Another reason to not call DB2 files but call them tables.
IBM – Unix Type API to access the IFS Written for C Programmers C style for data types – c type strings Return type typically integer (10i 0) Return value indicates if the call was successful -1 error Anything else success Can be called as a function in RPG Scot Klements tools are are RPG entry point to access the IFS, Unix type API’s to work with IFS, Unix / C style. These API are written to be accessed from C., or a Unix Environment What Scott has provided is RPG code – nothing really executable but that allows us access to these API’s
IFSIO_H Include source member from Scott Klement Includes constants, data structures and prototypes Access to the API’s for working with stream files Lots of prototypes – we are going to look at open, write and read. Many more functions available – we could spend all day. 85 page tutorial that I will have a link to at the end.
ErrNo_H Mostly error number constants – descriptive names Several prototypes all dealing with errors. Separate because these values are also used in other areas besides the IFS API’s
Open D open PR 10I 0 ExtProc('open') D filename * value options(*string) D openflags 10I 0 value D mode 10U 0 value options(*nopass) D ccsid 10U 0 value options(*nopass) D txtcreatid 10U 0 value options(*nopass) Mode is access rights
D* Flags for use in open() D* D* More than one can be used -- add them together. D* Reading Only D O_RDONLY C 1 D* Writing Only D O_WRONLY C 2 D* Reading & Writing D O_RDWR C 4 D* Create File if not exist D O_CREAT C 8 D* Exclusively create D O_EXCL C 16 D* Assign a CCSID D O_CCSID C 32 D* Truncate File to 0 bytes D O_TRUNC C 64 D* Append to File D O_APPEND C 256 D* Synchronous write D O_SYNC C 1024 D* Sync write, data only D O_DSYNC C 2048 D* Sync read D O_RSYNC C 4096 D* No controlling terminal D O_NOCTTY C 32768 D* Share with readers only D O_SHARE_RDONLY C 65536 D* Share with writers only D O_SHARE_WRONLY C 131072 D* Share with read & write D O_SHARE_RDWR C 262144 D* Share with nobody. D O_SHARE_NONE C 524288 D* Assign a code page D O_CODEPAGE C 8388608 D* Open in text-mode D O_TEXTDATA C 16777216 D* Allow text translation
D* No controlling terminal D O_NOCTTY C 32768 D* Append to File D O_APPEND C 256 D* Synchronous write D O_SYNC C 1024 D* Sync write, data only D O_DSYNC C 2048 D* Sync read D O_RSYNC C 4096 D* No controlling terminal D O_NOCTTY C 32768 D* Share with readers only D O_SHARE_RDONLY C 65536 D* Share with writers only D O_SHARE_WRONLY C 131072 D* Share with read & write D O_SHARE_RDWR C 262144 D* Share with nobody. D O_SHARE_NONE C 524288 D* Assign a code page D O_CODEPAGE C 8388608 D* Open in text-mode D O_TEXTDATA C 16777216 D* Allow text translation
D* Share with writers only D O_SHARE_WRONLY C 131072 D* Share with read & write D O_SHARE_RDWR C 262144 D* Share with nobody. D O_SHARE_NONE C 524288 D* Assign a code page D O_CODEPAGE C 8388608 D* Open in text-mode D O_TEXTDATA C 16777216 D* Allow text translation
P*-------------------------------------------------- P* Procedure name: openXML P* Purpose: Open the file and returns FD P* Returns: File Description P* Parameter: fileName => The file that is to be created P openXML B export D openXML PI 10I 0 D fileName 100A D* Local fields D retField S 10I 0 D Error s 4p 0 // Error Handling parameters d Message s 256a
FullFileName = FileName; retField = -1; d ErrorB ds qualified /FREE ErrorFound = *OFF; FullFileName = FileName; retField = -1; retField = open(%trim(fileName) : O_CREAT+O_TRUNC+O_WRONLY+O_CCSID + O_TEXTDATA + O_TEXT_CREAT : + S_IRWXU + S_IRWXG + S_IRWXO : 819 : 0 ); if RetField = -1; Error = ErrNo(); ErrorFound = *ON; Qp0zLprintf('--> Error Opening File: %s'+LF:%editc(Error:'X')); Qp0zLprintf(' File Name: %s' + LF:%Trim(FullFileName)); Return value – flag for other calls -1 error In order to call errno or strerror, you must bind to the * QC2LE binding directory. See ERRNO_H for the definitions * used to access errno. *
D*-------------------------------------------------------------------- D* Read From a File D* D* ssize_t read(int handle, void *buffer, size_t bytes); D read PR 10I 0 ExtProc('read') D handle 10i 0 value D buffer * value D bytes 10U 0 value
D*-------------------------------------------------------------------- D* Read From a File D* D* ssize_t read(int handle, void *buffer, size_t bytes); D read PR 10I 0 ExtProc('read') D handle 10i 0 value D buffer * value D bytes 10U 0 value
D*-------------------------------------------------------------------- D* Close a file D* D* int close(int fildes) D closef PR 10I 0 ExtProc('close') D handle 10I 0 value
P*-------------------------------------------------- P* Procedure name: writeXML P* Purpose: Write out the lines to the file P* Returns: P* Parameter: fd => File Description to write to P* Parameter: code => Key word that tells the procedure what to do P* Parameter: tag => The xml tag to use P* Parameter: data => The data to write out P writeXML B EXPORT D writeXML PI D fd 10I 0 VALUE D code 10A VALUE D tag 100A VALUE D data 4000A VALUE D attribute 100a value options(*nopass)
WHEN code = 'MIMIC' and %parms() = 4; mydata = %trim(data) + crlf; SELECT; WHEN code = 'MIMIC' and %parms() = 4; mydata = %trim(data) + crlf; callp write(fd: %addr(mydata): %len(%trim(mydata))); WHEN code = 'MIMIC' and %parms() = 5; mydata = %subst(Data : 1 : %len(%trim(Data)) - 1) + ' ' + %trim(Attribute) + %subst(Data: %len(%trim(Data)) : 1) + crlf; '</' + %trim(tag) + '>' + crlf; callp write(fd:%addr(mydata):%len(%trim(mydata))); ENDSL;
WHEN code = 'INFO' and %parms() = 4; Data = XMLScrubStr(data:'N'); Data = XMLFixData(data:BadFound); mydata = '<' + %trim(tag) + '>' + %trim(data) + '</' + %trim(tag) + '>' + crlf; callp write(fd:%addr(mydata):%len(%trim(mydata))); WHEN code = 'INFO' and %parms() = 5; mydata = '<' + %trim(tag) + ' ' + %trim(attribute) + '>' + %trim(data) + Endsl;
Error Handling If Retfield <> -1 Error = ErrNo(); ErrorFound = *ON; Qp0zLprintf('--> Error Opening File: %s'+LF:%editc(Error:'X')); Qp0zLprintf(' File Name: %s' + LF:%Trim(FullFileName)); Endif;
Other Functions Available Checking Existance and Permissions Retrieve Stream File Stats Deleting Files Renaming Files Random File Positioning Record position – create file where all records the same length Reading / Writing / Updating record Reading / creating / removing folders Error Handling ErrNo_H
Other Resources http://www.scottklement.com/rpg/ifs_ebook/ifs_ebook.pdf