Let's look at some additional stat APIs.
In last month's column, "Dependency and Validity-Checking of Command Parameters," we looked at how a validity-checking program could be used to detect the use of conflicting parameter values when running the USEDIRPGM command. It had been my intent for this month's column to continue that discussion of validity-checking programs. However, some readers of this column have encountered a problem with the USEDIRPGM command processing program (CPP), so I'm moving up a topic that I had not planned on discussing for a while yet.
When initially implementing the USEDIRPGM command, in article "When Was an IFS File Last Used or Changed?," we used the Get File Information API stat, which is documented here. I chose to use the stat API as it provides quite a bit of useful information that can be easily utilized by CL developers on V5R4 through 7.1. This information, in addition to the date and time of last use and the date and time of last change (both currently used by USEDIRPGM), includes the size of the file, the CCSID of the file, etc. A problem with the stat API however, and unfortunately one that some users have encountered, is that it returns the size of the file as a 4-byte integer value. This use of a 4-byte integer limits the stat API to working with files that are 2,147,483,647 bytes or less in size. Files that are larger than this value will cause the stat API to return an error indicating that an overflow has been encountered.
There is, however, another implementation of the stat API named Get File Information (Large File Enabled), stat64, which is documented here. Rather than using a 4-byte integer value to return file size information, the stat64 API returns an 8-byte integer value. An 8-byte integer can represent a file size of up to 9,223,372,036,854,775,807 bytes—just a tad larger. The problem is, though, that CL didn't directly support 8-byte integer variables until 7.1 (which is why I initially used the stat API).
This lack of 8-byte integer support in earlier releases may, or may not, be a problem. The stat64 API itself has been available since V4R4, and if you don't need to access the file size (such as how the USEDIRPGM command is not currently utilizing the size), then only a few changes are needed to the DIR3 CPP.
The layout of the second parameter passed to the stat API, declared as &FileInfo in the DIR3 program, does need to be changed. When you're using the stat API, the three subfields used (&LstAccess, &LstDtaChg, and &ObjTyp) are defined as follows:
Dcl Var(&FileInfo) Type(*Char) Len(128)
Dcl Var(&LstAccess) Type(*Int) +
Stg(*Defined) DefVar(&FileInfo 25)
Dcl Var(&LstDtaChg) Type(*Int) +
Stg(*Defined) DefVar(&FileInfo 29)
Dcl Var(&ObjTyp) Type(*Char) Len(10) +
Stg(*Defined) DefVar(&FileInfo 49)
With the stat64 API, the location of the &ObjTyp subfield has changed. Bolding the one change in the DCL for &ObjTyp, the stat64 definition for the three subfields is this:
Dcl Var(&FileInfo) Type(*Char) Len(128)
Dcl Var(&LstAccess) Type(*Int) +
Stg(*Defined) DefVar(&FileInfo 25)
Dcl Var(&LstDtaChg) Type(*Int) +
Stg(*Defined) DefVar(&FileInfo 29)
Dcl Var(&ObjTyp) Type(*Char) Len(10) +
Stg(*Defined) DefVar(&FileInfo 61)
As we're now calling the stat64 API, rather than the stat API, we also need to change the CALLPRC command. Where we previously used…
CallPrc Prc('stat') Parm(&Path &FileInfo) +
RtnVal(&Status)
…the program now needs to…
CallPrc Prc('stat64') Parm(&Path &FileInfo) +
RtnVal(&Status)
Making these two changes to the DIR3 program source and recompiling the program then enables the USEDIRPGM command to run in "Large File Enabled" mode even on V5R4 and 6.1.
As in the earlier article, here is the entire definition for the stat64 &FileInfo parameter so that you can customize your own versions of USEDIRPGM. Remember, though, that you need to be on 7.1 in order to compile the DCLs for &Size, &AlcSiz, &RDev64, and &FSID64. If you do not need these variables, then you can be running on an earlier release by simply not including their declares.
Dcl Var(&FileInfo) Type(*Char) Len(128)
Dcl Var(&Mode) Type(*UInt) +
Stg(*Defined) DefVar(&FileInfo 1)
Dcl Var(&FileID) Type(*UInt) +
Stg(*Defined) DefVar(&FileInfo 5)
Dcl Var(&UID) Type(*UInt) +
Stg(*Defined) DefVar(&FileInfo 9)
Dcl Var(&GID) Type(*UInt) +
Stg(*Defined) DefVar(&FileInfo 13)
Dcl Var(&Size) Type(*Int) Len(8) +
Stg(*Defined) DefVar(&FileInfo 17)
Dcl Var(&LstAccess) Type(*Int) +
Stg(*Defined) DefVar(&FileInfo 25) /* Last open */
Dcl Var(&LstDtaChg) Type(*Int) +
Stg(*Defined) DefVar(&FileInfo 29) /* Last changed*/
Dcl Var(&LstStsChg) Type(*Int) +
Stg(*Defined) DefVar(&FileInfo 33)
Dcl Var(&FSID) Type(*UInt) +
Stg(*Defined) DefVar(&FileInfo 37)
Dcl Var(&BlkSiz) Type(*UInt) +
Stg(*Defined) DefVar(&FileInfo 41)
Dcl Var(&NbrLinks) Type(*UInt) Len(2) +
Stg(*Defined) DefVar(&FileInfo 45)
Dcl Var(&CP) Type(*UInt) Len(2) +
Stg(*Defined) DefVar(&FileInfo 47)
Dcl Var(&AlcSiz) Type(*UInt) Len(8) +
Stg(*Defined) DefVar(&FileInfo 49)
Dcl Var(&GenID) Type(*UInt) +
Stg(*Defined) DefVar(&FileInfo 57)
Dcl Var(&ObjTyp) Type(*Char) Len(10) +
Stg(*Defined) DefVar(&FileInfo 61)
Dcl Var(&ObjTypNul) Type(*Char) Len(1) +
Stg(*Defined) DefVar(&FileInfo 71)
Dcl Var(&Rsv) Type(*Char) Len(5) +
Stg(*Defined) DefVar(&FileInfo 72)
Dcl Var(&RDev) Type(*UInt) +
Stg(*Defined) DefVar(&FileInfo 77)
Dcl Var(&RDev64) Type(*UInt) Len(8) +
Stg(*Defined) DefVar(&FileInfo 81)
Dcl Var(&FSID64) Type(*UInt) Len(8) +
Stg(*Defined) DefVar(&FileInfo 89)
Dcl Var(&NLink32) Type(*UInt) +
Stg(*Defined) DefVar(&FileInfo 97)
Dcl Var(&VFS) Type(*UInt) +
Stg(*Defined) DefVar(&FileInfo 101)
Dcl Var(&Rsv2) Type(*Char) Len(22) +
Stg(*Defined) DefVar(&FileInfo 105)
Dcl Var(&CCSID) Type(*UInt) Len(2) +
Stg(*Defined) DefVar(&FileInfo 127)
In addition to the file size consideration, there is another limitation related to the USEDIRPGM CPP as it's currently coded. The CPP is using the Open Directory (opendir), Read Directory (readdir), and Get File Information (stat) APIs in order to, respectively, open a directory, access the contents of a directory, and then access information concerning files found within a directory. With each of these API calls, the CPP is working with directory and/or file names encoded in the job CCSID (or default job CCSID if the job CCSID is 65535).
For many companies, this may be sufficient, just as only supporting stream files up to 2,147,483,647 bytes in size might be sufficient. Other companies may, however, have directory and/or stream file names that span more than one language—for instance, an English-named directory containing Arabic, Greek, and Korean file names—and really need to be able to work with names encoded in multiple languages during one running of the USEDIRPGM command. For these situations, the i provides National Language Support (NLS)-enabled versions of the stat, stat64, opendir, and readdir APIs. The NLS-enabled versions of these APIs are QlgStat, QlgStat64, QlgOpendir, and QlgReaddir, respectively. We won't demonstrate the use of these APIs in this article, but I did want to make you aware of their existence.
More CL Questions?
Wondering how to accomplish a function in CL? Send your CL-related questions to me at
as/400, os/400, iseries, system i, i5/os, ibm i, power systems, 6.1, 7.1, V7, V6R1
LATEST COMMENTS
MC Press Online