Added static method to File used to list directory content.

git-svn-id: http://yate.null.ro/svn/yate/trunk@2517 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
marian 2009-03-06 17:20:09 +00:00
parent 995efa2e63
commit fdf919acbe
2 changed files with 103 additions and 0 deletions

View File

@ -43,6 +43,7 @@
#ifndef _WINDOWS
#include <dirent.h>
#include <sys/stat.h>
#include <sys/un.h>
#define HAS_AF_UNIX
@ -944,6 +945,94 @@ bool File::mkDir(const char* path, int* error)
return getLastError(error);
}
// Skip special directories (. or ..)
static inline bool skipSpecial(const char* s)
{
return *s && *s == '.' && (!s[1] || (s[1] == '.' && !s[2]));
}
// Enumerate a folder (directory) content
bool File::listDirectory(const char* path, ObjList* dirs, ObjList* files, int* error)
{
if (!(dirs || files))
return true;
if (!fileNameOk(path,error))
return false;
bool ok = false;
#ifdef _WINDOWS
String name(path);
if (!name.endsWith("\\"))
name << "\\";
name << "*";
// Init find
WIN32_FIND_DATAA d;
HANDLE hFind = ::FindFirstFileA(name,&d);
if (hFind == INVALID_HANDLE_VALUE) {
if (::GetLastError() == ERROR_NO_MORE_FILES)
return true;
return getLastError(error);
}
// Enumerate content
::SetLastError(0);
do {
if (d.dwFileAttributes & FILE_ATTRIBUTE_DEVICE ||
skipSpecial(d.cFileName))
continue;
if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (dirs)
dirs->append(new String(d.cFileName));
}
else if (files)
files->append(new String(d.cFileName));
}
while (::FindNextFileA(hFind,&d));
int code = ::GetLastError();
ok = !code || code == ERROR_NO_MORE_FILES;
// Get error before closing the handle to avoid having a wrong one
if (!ok && error)
*error = code;
::FindClose(hFind);
#else
DIR* dir = ::opendir(path);
if (!dir) {
if (!errno)
return true;
return getLastError(error);
}
struct dirent* entry;
while ((entry = ::readdir(dir)) != 0) {
if (skipSpecial(entry->d_name))
continue;
#ifdef _DIRENT_HAVE_D_TYPE
if (entry->d_type == DT_DIR) {
if (dirs)
dirs->append(new String(entry->d_name));
}
else if (entry->d_type == DT_REG && files)
files->append(new String(entry->d_name));
#else
struct stat stat_buf;
String p;
p << path << "/" << entry->d_name;
if (::stat(p,&stat_buf))
break;
if (S_ISDIR(stat_buf.st_mode)) {
if (dirs)
dirs->append(new String(entry->d_name));
}
else if (S_ISREG(stat_buf.st_mode) && files)
files->append(new String(entry->d_name));
#endif // _DIRENT_HAVE_D_TYPE
}
ok = !errno;
// Get error before closing DIR to avoid having a wrong one
if (!ok && error)
*error = errno;
::closedir(dir);
#endif // _WINDOWS
return ok;
}
Socket::Socket()
: m_handle(invalidHandle())

View File

@ -4569,6 +4569,20 @@ public:
*/
static bool mkDir(const char* path, int* error = 0);
/**
* Enumerate a folder (directory) content.
* Fill the given lists with children item names
* @param path The folder path
* @param dirs List to be filled with child directories.
* It can be NULL if not requested
* @param files List to be filled with child files.
* It can be NULL if not requested
* @param error Optional pointer to error code to be filled on failure
* @return True on success
*/
static bool listDirectory(const char* path, ObjList* dirs, ObjList* files,
int* error = 0);
/**
* Create a pair of unidirectionally pipe connected streams
* @param reader Reference to a File that becomes the reading side of the pipe