Implemented filesys::dirEntries()
This commit is contained in:
parent
5a62d884dd
commit
68b8a15714
256
cwFileSys.cpp
256
cwFileSys.cpp
@ -8,6 +8,7 @@
|
||||
#ifdef cwLINUX
|
||||
#include <libgen.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h> // opendir()/readdir()
|
||||
#endif
|
||||
|
||||
namespace cw
|
||||
@ -140,7 +141,7 @@ char* cw::filesys::vMakeFn( const char* dir, const char* fn, const char* ext, va
|
||||
while( (dp = va_arg(vl,const char*)) != nullptr )
|
||||
n += strlen(dp) + 1; // add 1 for ending sep
|
||||
|
||||
// add 1 for terminating zero and allocate memory
|
||||
// add 1 for terminating zero and allocate memory
|
||||
|
||||
if((rp = mem::allocZ<char>( n+1 )) == nullptr )
|
||||
{
|
||||
@ -340,6 +341,257 @@ cw::filesys::pathPart_t* cw::filesys::pathParts( const char* pathStr )
|
||||
rp->extStr = nullptr;
|
||||
|
||||
return rp;
|
||||
|
||||
}
|
||||
|
||||
namespace cw
|
||||
{
|
||||
namespace filesys
|
||||
{
|
||||
typedef struct
|
||||
{
|
||||
unsigned filterFlags;
|
||||
dirEntry_t* rp;
|
||||
char* dataPtr;
|
||||
char* endPtr;
|
||||
unsigned entryCnt;
|
||||
unsigned entryIdx;
|
||||
unsigned dataByteCnt;
|
||||
unsigned passIdx;
|
||||
} deRecd_t;
|
||||
|
||||
cw::rc_t _dirGetEntries( deRecd_t* drp, const char* dirStr )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
DIR* dirp = NULL;
|
||||
struct dirent* dp = NULL;
|
||||
char curDirPtr[] = "./";
|
||||
unsigned dn = 0;
|
||||
|
||||
|
||||
if( dirStr == NULL || strlen(dirStr) == 0 )
|
||||
dirStr = curDirPtr;
|
||||
|
||||
if( isDir(dirStr) == false )
|
||||
return rc;
|
||||
|
||||
unsigned fnCharCnt = strlen(dirStr) + PATH_MAX;
|
||||
char fn[ fnCharCnt + 1 ];
|
||||
|
||||
|
||||
// copy the directory into fn[] ...
|
||||
fn[0] = 0;
|
||||
fn[fnCharCnt] = 0;
|
||||
|
||||
strcpy(fn,dirStr);
|
||||
|
||||
cwAssert( strlen(fn)+2 < fnCharCnt );
|
||||
|
||||
// ... and be sure that it is terminated with a path sep char
|
||||
if( fn[ strlen(fn)-1 ] != cwPathSeparatorChar )
|
||||
{
|
||||
char sep[] = { cwPathSeparatorChar, '\0' };
|
||||
strcat(fn,sep);
|
||||
}
|
||||
// file names will be appended to the path at this location
|
||||
unsigned fni = strlen(fn);
|
||||
|
||||
// open the directory
|
||||
if((dirp = opendir(dirStr)) == NULL)
|
||||
{
|
||||
rc = cwLogSysError(kOpFailRC,errno,"Unable to open the directory:'%s'.",dirStr);
|
||||
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// get the next directory entry
|
||||
while((dp = readdir(dirp)) != NULL )
|
||||
{
|
||||
// validate d_name
|
||||
if( (dn = strlen(dp->d_name)) > 0 )
|
||||
{
|
||||
unsigned flags = 0;
|
||||
|
||||
// handle cases where d_name begins with '.'
|
||||
if( dp->d_name[0] == '.' )
|
||||
{
|
||||
if( strcmp(dp->d_name,".") == 0 )
|
||||
{
|
||||
if( cwIsFlag(drp->filterFlags,kCurDirFsFl) == false )
|
||||
continue;
|
||||
|
||||
flags |= kCurDirFsFl;
|
||||
}
|
||||
|
||||
if( strcmp(dp->d_name,"..") == 0 )
|
||||
{
|
||||
if( cwIsFlag(drp->filterFlags,kParentDirFsFl) == false )
|
||||
continue;
|
||||
|
||||
flags |= kParentDirFsFl;
|
||||
}
|
||||
|
||||
if( flags == 0 )
|
||||
{
|
||||
if( cwIsFlag(drp->filterFlags,kInvisibleFsFl) == false )
|
||||
continue;
|
||||
|
||||
flags |= kInvisibleFsFl;
|
||||
}
|
||||
}
|
||||
|
||||
fn[fni] = 0;
|
||||
strncat( fn, dp->d_name, fnCharCnt-fni );
|
||||
unsigned fnN = strlen(fn);
|
||||
|
||||
// if the filename is too long for the buffer
|
||||
if( fnN > fnCharCnt )
|
||||
{
|
||||
rc = cwLogSysError(kBufTooSmallRC, errno, "The directory entry:'%s' was too long to be processed.",dp->d_name);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// is a link
|
||||
if( isLink(fn) )
|
||||
{
|
||||
if( cwIsFlag(drp->filterFlags,kLinkFsFl) == false )
|
||||
continue;
|
||||
|
||||
flags |= kLinkFsFl;
|
||||
|
||||
if( cwIsFlag(drp->filterFlags,kRecurseLinksFsFl) )
|
||||
if((rc = _dirGetEntries(drp,fn)) != kOkRC )
|
||||
goto errLabel;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// is the entry a file
|
||||
if( isFile(fn) )
|
||||
{
|
||||
if( cwIsFlag(drp->filterFlags,kFileFsFl)==false )
|
||||
continue;
|
||||
|
||||
flags |= kFileFsFl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// is the entry a dir
|
||||
if( isDir(fn) )
|
||||
{
|
||||
if( cwIsFlag(drp->filterFlags,kDirFsFl) == false)
|
||||
continue;
|
||||
|
||||
flags |= kDirFsFl;
|
||||
|
||||
if( cwIsFlag(drp->filterFlags,kRecurseFsFl) )
|
||||
if((rc = _dirGetEntries(drp,fn)) != kOkRC )
|
||||
goto errLabel;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//cwAssert(flags != 0);
|
||||
|
||||
if( drp->passIdx == 0 )
|
||||
{
|
||||
++drp->entryCnt;
|
||||
|
||||
// add 1 for the name terminating zero
|
||||
drp->dataByteCnt += sizeof(dirEntry_t) + 1;
|
||||
|
||||
if( cwIsFlag(drp->filterFlags,kFullPathFsFl) )
|
||||
drp->dataByteCnt += fnN;
|
||||
else
|
||||
drp->dataByteCnt += dn;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
cwAssert( drp->passIdx == 1 );
|
||||
cwAssert( drp->entryIdx < drp->entryCnt );
|
||||
|
||||
unsigned n = 0;
|
||||
if( cwIsFlag(drp->filterFlags,kFullPathFsFl) )
|
||||
{
|
||||
n = fnN+1;
|
||||
cwAssert( drp->dataPtr + n <= drp->endPtr );
|
||||
strcpy(drp->dataPtr,fn);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = dn+1;
|
||||
cwAssert( drp->dataPtr + n <= drp->endPtr );
|
||||
strcpy(drp->dataPtr,dp->d_name);
|
||||
}
|
||||
|
||||
drp->rp[ drp->entryIdx ].flags = flags;
|
||||
drp->rp[ drp->entryIdx ].name = drp->dataPtr;
|
||||
drp->dataPtr += n;
|
||||
cwAssert( drp->dataPtr <= drp->endPtr);
|
||||
++drp->entryIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errLabel:
|
||||
if( dirp != NULL )
|
||||
closedir(dirp);
|
||||
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cw::filesys::dirEntry_t* cw::filesys::dirEntries( const char* dirStr, unsigned filterFlags, unsigned* dirEntryCntPtr )
|
||||
{
|
||||
rc_t rc = kOkRC;
|
||||
deRecd_t r;
|
||||
|
||||
memset(&r,0,sizeof(r));
|
||||
//r.p = _cmFileSysHandleToPtr(h);
|
||||
r.filterFlags = filterFlags;
|
||||
|
||||
cwAssert( dirEntryCntPtr != NULL );
|
||||
*dirEntryCntPtr = 0;
|
||||
|
||||
for(r.passIdx=0; r.passIdx<2; ++r.passIdx)
|
||||
{
|
||||
if((rc = _dirGetEntries( &r, dirStr )) != kOkRC )
|
||||
goto errLabel;
|
||||
|
||||
if( r.passIdx == 0 && r.dataByteCnt>0 )
|
||||
{
|
||||
// allocate memory to hold the return values
|
||||
if(( r.rp = mem::allocZ<dirEntry_t>( r.dataByteCnt )) == NULL )
|
||||
{
|
||||
rc = cwLogError(kObjAllocFailRC, "Unable to allocate %i bytes of dir entry memory.",r.dataByteCnt);
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
r.dataPtr = (char*)(r.rp + r.entryCnt);
|
||||
r.endPtr = ((char*)r.rp) + r.dataByteCnt;
|
||||
}
|
||||
}
|
||||
|
||||
errLabel:
|
||||
|
||||
if( rc == kOkRC )
|
||||
{
|
||||
cwAssert( r.entryIdx == r.entryCnt );
|
||||
*dirEntryCntPtr = r.entryCnt;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( r.rp != NULL )
|
||||
mem::release(r.rp);
|
||||
|
||||
r.rp = NULL;
|
||||
}
|
||||
|
||||
return r.rp;
|
||||
}
|
||||
|
||||
|
33
cwFileSys.h
33
cwFileSys.h
@ -39,6 +39,39 @@ namespace cw
|
||||
// The returned record and the strings it points to are contained in a single block of
|
||||
// memory which must be released by a call to memRelease() or memFree()
|
||||
pathPart_t* pathParts( const char* pathNameStr );
|
||||
|
||||
// Flags used by dirEntries 'includeFlags' parameter.
|
||||
enum
|
||||
{
|
||||
kFileFsFl = 0x001, //< include all visible files
|
||||
kDirFsFl = 0x002, //< include all visible directory
|
||||
kLinkFsFl = 0x004, //< include all symbolic links
|
||||
kInvisibleFsFl = 0x008, //< include file/dir name beginning with a '.'
|
||||
kCurDirFsFl = 0x010, //< include '.' directory
|
||||
kParentDirFsFl = 0x020, //< include '..' directory
|
||||
|
||||
kAllFsFl = 0x02f, //< all type flags
|
||||
|
||||
kFullPathFsFl = 0x040, //< return the full path in the 'name' field of dirEntry_t;
|
||||
kRecurseFsFl = 0x080, //< recurse into directories
|
||||
kRecurseLinksFsFl = 0x100 //< recurse into symbol link directories
|
||||
};
|
||||
|
||||
// The return type for dirEntries().
|
||||
typedef struct
|
||||
{
|
||||
unsigned flags; //< Entry type flags from kXXXFsFl.
|
||||
const char* name; //< Entry name or full path depending on kFullPathFsFl.
|
||||
} dirEntry_t;
|
||||
|
||||
// Return the file and directory names contained in a given subdirectory.
|
||||
//
|
||||
// Set 'includeFlags' with the kXXXFsFl flags of the files to include in the returned
|
||||
// directory entry array. The value pointed to by dirEntryCntPtr will be set to the
|
||||
// number of records in the returned array.
|
||||
dirEntry_t* dirEntries( const char* dirStr, unsigned includeFlags, unsigned* dirEntryCntRef );
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,8 +20,7 @@ namespace cw {
|
||||
|
||||
rc_t destroy( handle_t& h );
|
||||
|
||||
thread::handle_t threadHandle( handle_t h );
|
||||
|
||||
thread::handle_t threadHandle( handle_t h );
|
||||
websock::handle_t websockHandle( handle_t h );
|
||||
|
||||
// Start or unpause the server.
|
||||
|
15
main.cpp
15
main.cpp
@ -160,6 +160,20 @@ void socketSrvTest( cw::object_t* cfg, int argc, const char* argv[] )
|
||||
}
|
||||
}
|
||||
|
||||
void dirEntryTest( cw::object_t* cfg, int argc, const char* argv[] )
|
||||
{
|
||||
if( argc >= 2 )
|
||||
{
|
||||
const char* path = argv[1];
|
||||
unsigned dirEntryN = 0;
|
||||
unsigned includeFlags = cw::filesys::kFileFsFl | cw::filesys::kDirFsFl | cw::filesys::kFullPathFsFl | cw::filesys::kRecurseFsFl;
|
||||
cw::filesys::dirEntry_t* de = cw::filesys::dirEntries( path,includeFlags, &dirEntryN );
|
||||
for(unsigned i=0; i<dirEntryN; ++i)
|
||||
cwLogInfo("%s",de[i].name);
|
||||
|
||||
cw::mem::release(de);
|
||||
}
|
||||
}
|
||||
|
||||
void stubTest( cw::object_t* cfg, int argc, const char* argv[] )
|
||||
{
|
||||
@ -202,6 +216,7 @@ int main( int argc, const char* argv[] )
|
||||
{ "audioDevAlsa", audioDevAlsaTest },
|
||||
{ "socket", socketTest },
|
||||
{ "socketSrv", socketSrvTest },
|
||||
{ "dirEntry", dirEntryTest },
|
||||
{ "stub", stubTest },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user