Implemented filesys::dirEntries()
This commit is contained in:
parent
5a62d884dd
commit
68b8a15714
256
cwFileSys.cpp
256
cwFileSys.cpp
@ -8,6 +8,7 @@
|
|||||||
#ifdef cwLINUX
|
#ifdef cwLINUX
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <dirent.h> // opendir()/readdir()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace cw
|
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 )
|
while( (dp = va_arg(vl,const char*)) != nullptr )
|
||||||
n += strlen(dp) + 1; // add 1 for ending sep
|
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 )
|
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;
|
rp->extStr = nullptr;
|
||||||
|
|
||||||
return rp;
|
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
|
// 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()
|
// memory which must be released by a call to memRelease() or memFree()
|
||||||
pathPart_t* pathParts( const char* pathNameStr );
|
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 );
|
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 );
|
websock::handle_t websockHandle( handle_t h );
|
||||||
|
|
||||||
// Start or unpause the server.
|
// 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[] )
|
void stubTest( cw::object_t* cfg, int argc, const char* argv[] )
|
||||||
{
|
{
|
||||||
@ -202,6 +216,7 @@ int main( int argc, const char* argv[] )
|
|||||||
{ "audioDevAlsa", audioDevAlsaTest },
|
{ "audioDevAlsa", audioDevAlsaTest },
|
||||||
{ "socket", socketTest },
|
{ "socket", socketTest },
|
||||||
{ "socketSrv", socketSrvTest },
|
{ "socketSrv", socketSrvTest },
|
||||||
|
{ "dirEntry", dirEntryTest },
|
||||||
{ "stub", stubTest },
|
{ "stub", stubTest },
|
||||||
{ nullptr, nullptr }
|
{ nullptr, nullptr }
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user