$include (..\lib\compStch.ext) /* *============================================================================ * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE * * Permission to use for any purpose, modify, copy, and make enhancements * and derivative works of the software is granted if attribution is given to * R.M. Gillmore, dba the ACME Software Deli, as the author * * While the ACME Software Deli does not work for money, there is nonetheless * a significant amount of work involved. The ACME Software Deli maintains the * rights to all code written, though it may be used and distributed as long as * the following conditions are maintained. * * 1. The copyright statement at the top of each code block is maintained in * your distribution. * 2. You do not identify yourself as the ACME Software Deli * 3. Any changes made to the software are sent to the ACME Software Deli *============================================================================ */ readdirModule: do; $if not noID declare IDString (*) byte data ( '@(#)pReadDir.p86 $Author: rmgillmore $ $Date:: 2025-05-04 19:35:39#$:', 0 ); $endif $include (..\lib\comnDefs.ext) $set (readdirImplementation=1) $include (..\lib\posixDir.ext) $include (..\lib\mem.ext) $include (..\lib\string.ext) $include (..\lib\arrayMgr.ext) $include (..\lib\dosFind.ext) $include (..\lib\shrt2lng.ext) $if LOGGING $include (..\lib\logger.ext) $include (..\lib\debugHlp.ext) $endif duplicateDataRecord: procedure ( directoryNamePtr, dataRecordPtr ) pointer reentrant public; declare directoryNamePtr pointer, dataRecordPtr pointer, findDataRecord based dataRecordPtr findDataRecordType; declare entryPtr dirEntryPtr_t, dirEntryRecord based entryPtr dirEntry_t, tempName ( MAX_FILENAME ) char, fullNameLength word; entryPtr = malloc( size( dirEntryRecord ) + 1 ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'entryPtr: %p', 0 ), entryPtr ); $endif if ( NULL <> entryPtr ) then do; $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'fullName: "%s"', 0 ), @findDataRecord.fullName ); $endif if ( findDataRecord.fullName( 0 ) = NUL ) then do; /* * the full name is not populated, so we will create it from * the directory name, and the file's dosName */ call strcpy( @findDataRecord.fullName, directoryNamePtr ); fullNameLength = strlen( @findDataRecord.fullName ); if ( findDataRecord.fullName( fullNameLength - 1 ) <> PATH_DELIM ) then do; call strcat( @findDataRecord.fullName, PATH_DELIM_STR ); end; call strcat( @findDataRecord.fullName, @findDataRecord.dosName ); end; else do; /* * the "fullName" field should contain the directory name, too. In * this case, the fullName field already contains the "long name" */ call strcpy( @tempName, @findDataRecord.fullName ); call strcpy( @findDataRecord.fullName, directoryNamePtr ); if ( findDataRecord.fullName( fullNameLength - 1 ) <> PATH_DELIM ) then do; call strcat( @findDataRecord.fullName, PATH_DELIM_STR ); end; call strcat( @findDataRecord.fullName, @tempName ); end; call strcpy( @dirEntryRecord.fileName, @findDataRecord.fullName ); call memcpy( @dirEntryRecord.fileLength, @findDataRecord.fileSize, size( dirEntryRecord.fileLength ) ); call memcpy( @dirEntryRecord.fileDate, @findDataRecord.modifiedTime, size( dirEntryRecord.fileDate ) ); call memcpy( @dirEntryRecord.attributes, @findDataRecord.fileAttr, size( dirEntryRecord.attributes ) ); end; return ( entryPtr ); end duplicateDataRecord; /* * ====================================================================================== * Requirements for the readdir() function * 1. accept the HANDLE for a directory (returned by opendir) * * 2. return a pointer to the information related to the next directory entry * if there are no directory entries (or the last entry has already been returned), * a NULL is returned * * 3. Each entry record will contain: * a. the name of the entry * b. the type of entry - a file, link/shortcut, directory, other special types * c. the size (applies only to a file) * d. the creation time * e. the last modified time * f. other attributes (read-only, hidden, etc) * ====================================================================================== */ swapDwords: procedure ( qwordPtr ) reentrant; declare qwordPtr pointer, qwordValue based qwordPtr qword, tempDword dword; tempDword = qwordValue( 0 ); qwordValue( 0 ) = qwordValue( 1 ); qwordValue( 1 ) = tempDword; end swapDwords; readdir: procedure ( directoryHandlePtr ) dirEntryPtr_t reentrant public; declare directoryHandlePtr dirHandlePtr_t, dirHandle based directoryHandlePtr dirHandle_t, findDataRecord findDataRecordType, returnEntryPtr dirEntryPtr_t, fileRecordPtr dirEntryPtr_t, findReturned word, searchStarted boolean, status word, nameMask ( MAX_PATH ) char; $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'dirHandle.fileRecordArray: %p', 0 ), dirHandle.fileRecordArray ); call addToLog( DEBUG, __FILE__, __LINE__, @( 'read complete: %T', 0 ), dirHandle.readComplete ); $endif if ( not dirHandle.readComplete ) then do; /* * we want to search for everything in the directory */ findDataRecord.fileAttr = ARCHIVE_BIT or DIRECTORY_BIT or HIDDEN_BIT; /* * create the fileRecordArray */ dirHandle.fileRecordArray = createArray( 10, pointertype ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'dirHandle.fileRecordArray: %p', 0 ), dirHandle.fileRecordArray ); $endif /* * create the name mask based on what we learned in the opendir() */ call strcpy( @nameMask, dirHandle.directoryName ); call strcat( @nameMask, PATH_DELIM_STR ); call strcat( @nameMask, dirHandle.fileSearchSpecString ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'nameMask = %s', 0 ), @nameMask ); $endif status = 0; findReturned = findFirst( @nameMask, @findDataRecord ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'findReturned: %x', 0 ), findReturned ); $endif call reportArray( dirHandle.fileRecordArray ); do while ( ( 0 = findReturned ) and ( 0 = status ) ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'name: "%s"', 0 ), @findDataRecord.dosName ); $endif /* * store the record from the last DOS directory find, then * look again */ call swapDwords( @findDataRecord.fileSize ); fileRecordPtr = duplicateDataRecord( dirHandle.directoryName, @findDataRecord ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'full name: "%s"', 0 ), @findDataRecord.fullName ); $endif call appendElement( dirHandle.fileRecordArray, @fileRecordPtr, @status ); call reportArray( dirHandle.fileRecordArray ); findReturned = findNext( @findDataRecord ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'findReturned: %x', 0 ), findReturned ); call addToLog( DEBUG, __FILE__, __LINE__, @( 'status: %x', 0 ), status ); call addToLog( DEBUG, __FILE__, __LINE__, @( 'number directory entries: %d', 0 ), arrayLength( dirHandle.fileRecordArray ) ); $endif end; /* do while findReturned is valid */ call findClose( @findDataRecord ); dirHandle.readComplete = True; $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'read complete: %T', 0 ), dirHandle.readComplete ); $endif end; /* if not read complete */ call nextElement( dirHandle.fileRecordArray, @returnEntryPtr, @status ); $if LOGGING call addToLog( DEBUG, __FILE__, __LINE__, @( 'dirHandle.fileRecordArray: %p', 0 ), dirHandle.fileRecordArray ); call addToLog( DEBUG, __FILE__, __LINE__, @( 'status: %d returnEntryPtr: %p', 0 ), status, returnEntryPtr ); $endif if ( status <> 0 ) then returnEntryPtr = NULL; return ( returnEntryPtr ); end readdir; end readdirModule;