SPECIAL Files - Sources | |||||||||||
These are the source files for the USESPECIAL and DIRREADER programs disussed in the March 2010 edition of IBM i Extra |
|||||||||||
|
SPECIAL File Program DIRREADERH DftActGrp(*No) BndDir('QC2LE') H Option(*NoDebugIO : *SrcStmt) // DirReader // - Used as SPECIAL file to read entries in a specified directory // - Actual directory to open given by the fifth (extra) parm /Copy FSDIRPROT /Copy DIRDATA // Prototype for CEEUTCO API - Obtains current time zone offset D CEEUTCO PR D Hours 10I 0 D Mins 10I 0 D Secs 8F D fc 12A options(*omit) // Prototype to keep the compiler happy D DirReader Pr ExtPGM('DIRREADER') D requestedAction... D 1a D statusFlag 1a D errorCode 5s 0 D recordData LikeDS(directoryData) D directoryToOpen... D 640a Varying // Procedure Interface used instead of *Entry PList D DirReader PI // First four are the standard parameter definitions // passed for SPECIAL files from the RPG program D action 1a D status 1a D error 5s 0 D recordData LikeDS(directoryData) // This is the extra parameter specified within the RPG program // In this case it supplies the name of the directory to open D dirName 640a Varying * Constants for SPECIAL file operation requests D OPEN C 'O' D READ C 'R' D CLOSE C 'C' D EOF C '1' D ERR C '2' D OK C '0' D pdir S * D message S 52a // Definitions for time zone offset calculations D hours S 10i 0 D minutes S 10i 0 D offsetSeconds S 8f D epoch c z'1970-01-01-00.00.00' D adjustedEpoch s z /FREE Select; When action = READ; p_dirEnt = ReadDir( pdir ); // Read next directory entry If p_dirEnt <> *Null; // If pointer is valid we have a record recordData.name = %Subst( dE_name: 1: dE_nameLen ); // Use the stat() function to retrieve informaqtion for the record If Stat( recordData.name: p_statDS ) < 0; // CHeck for failure dirName = 'File: ' + recordData.name; // Identify failing file name ExSr ReportError; Else; // Create required entries in the record buffer recordData.created = adjustedEpoch + %seconds( st_ctime ); recordData.accessed = adjustedEpoch + %seconds( st_atime ); recordData.modified = adjustedEpoch + %seconds( st_mtime ); recordData.type = st_objtype; status = OK; EndIf; Else; // otherwise we're at the end of the "File" status = EOF; Endif; When action = OPEN; pdir = OpenDir( dirName ); If pdir = *Null; // If pointer is null then open failed ExSr ReportError; // Obtains error details and reports failure EndIf; When action = CLOSE; CloseDir( pdir ); EndSl; Return; BegSr ReportError; // Obtains errno and sets it into the file's feedback area status = ERR; p_errno = GetPtr_errno(); error = errno; // Form basic error message If action = OPEN; message = 'Open error: ' + %Str( strError(errno)); Else; message = 'Read error: ' + %Str( strError(errno)); EndIf; Dsply message; EndSr; // Routine calculates an epoch timestamp adjusted to account for // the current time zone offset. This is then used to produce // correct timestamps for dates in the directory entries. BegSr *InzSr; // Call CEEUTCO to obtain current time zone offset in seconds CEEUTCO( hours: minutes: offsetSeconds: *omit ); // Then add them to the base date to form adjusted epoch adjustedEpoch = epoch + %seconds( %int( offsetSeconds ) ); EndSr; Program USESPECIAL - sample program that uses the DIRREADER special fileFDirEntriesIF F 732 SPECIAL PgmName('DIRREADER') F PList(DirReaderParm) F UsrOpn FQPrint O F 132 PRINTER /Copy DirData D directoryName S 640a Varying D Inz('/Partner400') D message S 52a D shortName S 34a /Free Open(E) DirEntries; If %Error; message = 'Directory: ' + directoryName; // Report error and quit Dsply message; *InLR = *On; Return; EndIf; Dou %EOF(DirEntries); Read(E) DirEntries directoryData; If ( not %Error ) AND ( not %EOF(DirEntries) ); shortName = name; except main; ElseIf %Error; message = directoryName; // Report (truncated) file name and quit Dsply message; Leave; // Exit read loop EndIf; EndDo; *InLR = *On; /End-free // SPECIAL files need a PList for extra parms. Sadly we // have to code that in fixed form but we hide it down here! C PListDummy BegSr C DirReaderParm PList C Parm directoryName C EndSr OQPrint E main O type 12 O created 40 O accessed 68 O modified 96 O shortName 132 Source IFSDIRPROT - prototypes for IFS routiines// IFSDIRPROT - Prototypes for IFS directory processing // - Includes DS definitions for directory entry and // stat() data D OpenDir Pr * ExtProc('opendir') D D ppath * Value Options(*String) D ReadDir Pr * ExtProc('readdir') D pdirectory * Value D CloseDir Pr 10I 0 ExtProc('closedir') D pdirectory * Value D Stat Pr 10I 0 ExtProc('stat') D * Value Options(*String) D * Value // Function and data definitions for obtaining current errno value and string D GetPtr_errno Pr * ExtProc('__errno') D D p_errno S * D p_errnoTxt S * D errno S 10I 0 Based(p_errno) D strerror Pr * extproc('strerror') D errno 10I 0 value // RPG Translation of C member STAT from file SYS in library QSYSINC D p_statDS S * Inz(%addr(statDS)) D statDS DS D st_mode 10U 0 D st_ino 10U 0 D st_nlink 5U 0 D st_pad 2A D st_uid 10U 0 D st_gid 10U 0 D st_size 10I 0 D st_atime 10I 0 D st_mtime 10I 0 D st_ctime 10I 0 D st_dev 10U 0 D st_blksize 10U 0 D st_allocsize 10U 0 D st_objtype 12A D st_codepage 5U 0 D st_reserved1 62A D st_ino_gen_id 10U 0 // DS for directory entry information retrieved by readdir D dirEnt DS Based(p_dirEnt) D dE_res1 16a D dE_genId 10u 0 D dE_fileNo 10u 0 D dE_recLen 10u 0 D dE_res3 10i 0 D dE_res4 6a D dE_res5 2a D dE_NLSinfo D dE_CCSID 10i 0 Overlay(dE_NLSInfo) D dE_country 2a Overlay(dE_NLSInfo: *Next) D dE_language 3a Overlay(dE_NLSInfo: *Next) D dE_res6 3a Overlay(dE_NLSInfo: *Next) D dE_nameLen 10u 0 D dE_name 640a // End of source IFSDIRPROT Source DIRDATA Definition of data passed back from special programd directoryData DS 732 d type 12a d name 640a Varying d created z d accessed z d modified z d DIRECTORY c '*DIR' d FILE c '*FILE' d SYMLINK c '*SYM' |
||||||||||
Return to Home Page |
Want
more information? |