enhanced qse_dir_t
This commit is contained in:
parent
67e9eb8d9f
commit
f2d60b9366
@ -70,6 +70,22 @@ int qse_isabspath (
|
|||||||
const qse_char_t* path
|
const qse_char_t* path
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_isdrivepath() function determines if a path name begins with
|
||||||
|
* a drive letter followed by a colon like A:.
|
||||||
|
*/
|
||||||
|
int qse_isdrivepath (
|
||||||
|
const qse_char_t* path
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_isdrivecurpath() function determines if a path name is in the form
|
||||||
|
* of a drive letter followed by a colon like A:, without any trailing path.
|
||||||
|
*/
|
||||||
|
int qse_isdrivecurpath (
|
||||||
|
const qse_char_t* path
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_canonpath() function canonicalizes a path name @a path by deleting
|
* The qse_canonpath() function canonicalizes a path name @a path by deleting
|
||||||
* unnecessary path segments from it and stores the result to a memory buffer
|
* unnecessary path segments from it and stores the result to a memory buffer
|
||||||
|
@ -33,7 +33,7 @@ enum qse_dir_errnum_t
|
|||||||
QSE_DIR_EINVAL,
|
QSE_DIR_EINVAL,
|
||||||
QSE_DIR_EACCES,
|
QSE_DIR_EACCES,
|
||||||
QSE_DIR_ENOENT,
|
QSE_DIR_ENOENT,
|
||||||
QSE_DIR_ENOTDIR,
|
QSE_DIR_ENODIR,
|
||||||
QSE_DIR_ESYSTEM
|
QSE_DIR_ESYSTEM
|
||||||
};
|
};
|
||||||
typedef enum qse_dir_errnum_t qse_dir_errnum_t;
|
typedef enum qse_dir_errnum_t qse_dir_errnum_t;
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#define ISDRIVE(s) \
|
#define ISDRIVE(s) \
|
||||||
(((s[0] >= QSE_T('A') && s[0] <= QSE_T('Z')) || \
|
(((s[0] >= QSE_T('A') && s[0] <= QSE_T('Z')) || \
|
||||||
(s[0] >= QSE_T('a') && s[0] <= QSE_T('a'))) && \
|
(s[0] >= QSE_T('a') && s[0] <= QSE_T('z'))) && \
|
||||||
s[1] == QSE_T(':'))
|
s[1] == QSE_T(':'))
|
||||||
|
|
||||||
int qse_isabspath (const qse_char_t* path)
|
int qse_isabspath (const qse_char_t* path)
|
||||||
@ -45,12 +45,30 @@ int qse_isabspath (const qse_char_t* path)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qse_isdrivepath (const qse_char_t* path)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||||
|
if (ISDRIVE(path)) return 1;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qse_isdrivecurpath (const qse_char_t* path)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||||
|
if (ISDRIVE(path) && path[2] == QSE_T('\0')) return 1;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
qse_size_t qse_canonpath (const qse_char_t* path, qse_char_t* canon)
|
qse_size_t qse_canonpath (const qse_char_t* path, qse_char_t* canon)
|
||||||
{
|
{
|
||||||
const qse_char_t* ptr;
|
const qse_char_t* ptr;
|
||||||
qse_char_t* dst;
|
qse_char_t* dst;
|
||||||
qse_char_t* non_root_start;
|
qse_char_t* non_root_start;
|
||||||
int has_root = 0;
|
int has_root = 0;
|
||||||
|
int begins_with_curdir = 0;
|
||||||
|
qse_size_t canon_len;
|
||||||
|
|
||||||
ptr = path;
|
ptr = path;
|
||||||
dst = canon;
|
dst = canon;
|
||||||
@ -94,12 +112,20 @@ qse_size_t qse_canonpath (const qse_char_t* path, qse_char_t* canon)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
else if (ptr[0] == QSE_T('.') && ISSEPNIL(ptr[1]))
|
||||||
|
{
|
||||||
|
begins_with_curdir = 1;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
if (ISSEP(*ptr))
|
if (ISSEP(*ptr))
|
||||||
{
|
{
|
||||||
*dst++ = *ptr++; /* root directory */
|
*dst++ = *ptr++; /* root directory */
|
||||||
has_root = 1;
|
has_root = 1;
|
||||||
}
|
}
|
||||||
|
else if (ptr[0] == QSE_T('.') && ISSEPNIL(ptr[1]))
|
||||||
|
{
|
||||||
|
begins_with_curdir = 1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* non_root_start points to the beginning of the canonicalized
|
/* non_root_start points to the beginning of the canonicalized
|
||||||
@ -228,14 +254,25 @@ qse_size_t qse_canonpath (const qse_char_t* path, qse_char_t* canon)
|
|||||||
* the origial path ends with a separator
|
* the origial path ends with a separator
|
||||||
*/
|
*/
|
||||||
dst[-1] = QSE_T('\0');
|
dst[-1] = QSE_T('\0');
|
||||||
return dst - canon - 1;
|
canon_len = dst - canon - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* just null-terminate the canonical path normally */
|
/* just null-terminate the canonical path normally */
|
||||||
dst[0] = QSE_T('\0');
|
dst[0] = QSE_T('\0');
|
||||||
return dst - canon;
|
canon_len = dst - canon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (canon_len <= 0 && begins_with_curdir)
|
||||||
|
{
|
||||||
|
/* when resolving to a single dot, a trailing separator is not
|
||||||
|
* retained though the orignal path name contains it */
|
||||||
|
dst[0] = QSE_T('.');
|
||||||
|
dst[1] = QSE_T('\0');
|
||||||
|
canon_len = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return canon_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_size_t qse_realpath (const qse_char_t* path, qse_char_t* real)
|
qse_size_t qse_realpath (const qse_char_t* path, qse_char_t* real)
|
||||||
|
288
qse/lib/fs/dir.c
288
qse/lib/fs/dir.c
@ -44,14 +44,63 @@ struct info_t
|
|||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
WIN32_FIND_DATA wfd;
|
WIN32_FIND_DATA wfd;
|
||||||
unsigned int first_after_change;
|
int just_changed_dir;
|
||||||
#elif defined(__OS2__)
|
#elif defined(__OS2__)
|
||||||
#elif defined(__DOS__)
|
#elif defined(__DOS__)
|
||||||
#else
|
#else
|
||||||
DIR* handle;
|
DIR* handle;
|
||||||
|
qse_mchar_t* mcurdir;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
static QSE_INLINE qse_dir_errnum_t syserr_to_errnum (DWORD e)
|
||||||
|
{
|
||||||
|
switch (e)
|
||||||
|
{
|
||||||
|
case ERROR_INVALID_NAME:
|
||||||
|
case ERROR_DIRECTORY:
|
||||||
|
return QSE_DIR_EINVAL;
|
||||||
|
|
||||||
|
case ERROR_ACCESS_DENIED:
|
||||||
|
return QSE_DIR_EACCES;
|
||||||
|
|
||||||
|
case ERROR_FILE_NOT_FOUND:
|
||||||
|
case ERROR_PATH_NOT_FOUND:
|
||||||
|
return QSE_DIR_ENOENT;
|
||||||
|
|
||||||
|
case ERROR_NOT_ENOUGH_MEMORY:
|
||||||
|
case ERROR_OUTOFMEMORY:
|
||||||
|
return QSE_DIR_ENOMEM;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return QSE_DIR_ESYSTEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static QSE_INLINE qse_dir_errnum_t syserr_to_errnum (int e)
|
||||||
|
{
|
||||||
|
switch (e)
|
||||||
|
{
|
||||||
|
case EINVAL:
|
||||||
|
return QSE_DIR_EINVAL;
|
||||||
|
|
||||||
|
case EACCES:
|
||||||
|
return QSE_DIR_EACCES;
|
||||||
|
|
||||||
|
case ENOENT:
|
||||||
|
case ENOTDIR:
|
||||||
|
return QSE_DIR_ENOENT;
|
||||||
|
|
||||||
|
case ENOMEM:
|
||||||
|
return QSE_DIR_ENOMEM;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return QSE_DIR_ESYSTEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
QSE_IMPLEMENT_COMMON_FUNCTIONS (dir)
|
QSE_IMPLEMENT_COMMON_FUNCTIONS (dir)
|
||||||
|
|
||||||
qse_dir_t* qse_dir_open (qse_mmgr_t* mmgr, qse_size_t xtnsize)
|
qse_dir_t* qse_dir_open (qse_mmgr_t* mmgr, qse_size_t xtnsize)
|
||||||
@ -119,6 +168,10 @@ void qse_dir_fini (qse_dir_t* dir)
|
|||||||
#elif defined(__DOS__)
|
#elif defined(__DOS__)
|
||||||
# error NOT IMPLEMENTED
|
# error NOT IMPLEMENTED
|
||||||
#else
|
#else
|
||||||
|
if (info->mcurdir && info->mcurdir != dir->curdir)
|
||||||
|
QSE_MMGR_FREE (dir->mmgr, info->mcurdir);
|
||||||
|
info->mcurdir = QSE_NULL;
|
||||||
|
|
||||||
if (info->handle)
|
if (info->handle)
|
||||||
{
|
{
|
||||||
closedir (info->handle);
|
closedir (info->handle);
|
||||||
@ -137,6 +190,30 @@ void qse_dir_fini (qse_dir_t* dir)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QSE_INLINE info_t* get_info (qse_dir_t* dir)
|
||||||
|
{
|
||||||
|
info_t* info;
|
||||||
|
|
||||||
|
info = dir->info;
|
||||||
|
if (info == QSE_NULL)
|
||||||
|
{
|
||||||
|
info = QSE_MMGR_ALLOC (dir->mmgr, QSE_SIZEOF(*info));
|
||||||
|
if (info == QSE_NULL)
|
||||||
|
{
|
||||||
|
dir->errnum = QSE_DIR_ENOMEM;
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_MEMSET (info, 0, QSE_SIZEOF(*info));
|
||||||
|
#if defined(_WIN32)
|
||||||
|
info->handle = INVALID_HANDLE_VALUE;
|
||||||
|
#endif
|
||||||
|
dir->info = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
int qse_dir_change (qse_dir_t* dir, const qse_char_t* name)
|
int qse_dir_change (qse_dir_t* dir, const qse_char_t* name)
|
||||||
{
|
{
|
||||||
qse_char_t* dirname;
|
qse_char_t* dirname;
|
||||||
@ -153,7 +230,9 @@ int qse_dir_change (qse_dir_t* dir, const qse_char_t* name)
|
|||||||
# error NOT IMPLEMENTED
|
# error NOT IMPLEMENTED
|
||||||
#else
|
#else
|
||||||
DIR* handle;
|
DIR* handle;
|
||||||
qse_mchar_t* mbsdirname;
|
qse_mchar_t* mdirname;
|
||||||
|
const qse_char_t* tmp_name[4];
|
||||||
|
qse_size_t idx;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (name[0] == QSE_T('\0'))
|
if (name[0] == QSE_T('\0'))
|
||||||
@ -162,29 +241,20 @@ int qse_dir_change (qse_dir_t* dir, const qse_char_t* name)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
info = dir->info;
|
info = get_info (dir);
|
||||||
if (info == QSE_NULL)
|
if (info == QSE_NULL) return -1;
|
||||||
{
|
|
||||||
info = QSE_MMGR_ALLOC (dir->mmgr, QSE_SIZEOF(*info));
|
|
||||||
if (info == QSE_NULL)
|
|
||||||
{
|
|
||||||
dir->errnum = QSE_DIR_ENOMEM;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSE_MEMSET (info, 0, QSE_SIZEOF(*info));
|
|
||||||
#if defined(_WIN32)
|
|
||||||
info->handle = INVALID_HANDLE_VALUE;
|
|
||||||
#endif
|
|
||||||
dir->info = info;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
idx = 0;
|
idx = 0;
|
||||||
if (!qse_isabspath(name) && dir->curdir)
|
if (!qse_isabspath(name) && dir->curdir)
|
||||||
tmp_name[idx++] = dir->curdir;
|
tmp_name[idx++] = dir->curdir;
|
||||||
tmp_name[idx++] = name;
|
tmp_name[idx++] = name;
|
||||||
|
|
||||||
|
if (qse_isdrivecurpath(name))
|
||||||
|
tmp_name[idx++] = QSE_T(" ");
|
||||||
|
else
|
||||||
tmp_name[idx++] = QSE_T("\\ ");
|
tmp_name[idx++] = QSE_T("\\ ");
|
||||||
|
|
||||||
tmp_name[idx] = QSE_NULL;
|
tmp_name[idx] = QSE_NULL;
|
||||||
|
|
||||||
dirname = qse_stradup (tmp_name, dir->mmgr);
|
dirname = qse_stradup (tmp_name, dir->mmgr);
|
||||||
@ -195,26 +265,24 @@ int qse_dir_change (qse_dir_t* dir, const qse_char_t* name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
idx = qse_canonpath (dirname, dirname);
|
idx = qse_canonpath (dirname, dirname);
|
||||||
/* Put the asterisk after canonicalization to prevent side-effects.
|
/* Put an asterisk after canonicalization to prevent side-effects.
|
||||||
* otherwise, .\* would be transformed to * by qse_canonpath() */
|
* otherwise, .\* would be transformed to * by qse_canonpath() */
|
||||||
dirname[idx-1] = QSE_T('*');
|
dirname[idx-1] = QSE_T('*');
|
||||||
|
|
||||||
/*
|
/* Using FindExInfoBasic won't resolve cAlternatFileName.
|
||||||
I don't return a short name so FindExInfoBasic can speed up the function.
|
* so it can get faster a little bit. The problem is that
|
||||||
FindFirstFileEx (
|
* it is not supported on old windows. just stick to the
|
||||||
|
* simple API instead. */
|
||||||
|
#if 0
|
||||||
|
handle = FindFirstFileEx (
|
||||||
dirname, FindExInfoBasic,
|
dirname, FindExInfoBasic,
|
||||||
&wfd, FindExSearchNameMatch,
|
&wfd, FindExSearchNameMatch,
|
||||||
NULL, FIND_FIRST_EX_CASE_SENSITIVE);
|
NULL, 0/*FIND_FIRST_EX_CASE_SENSITIVE*/);
|
||||||
*/
|
#endif
|
||||||
handle = FindFirstFile (dirname, &wfd);
|
handle = FindFirstFile (dirname, &wfd);
|
||||||
if (handle == INVALID_HANDLE_VALUE)
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
DWORD e = GetLastError();
|
dir->errnum = syserr_to_errnum (GetLastError());
|
||||||
dir->errnum = (e == ERROR_ACCESS_DENIED)? QSE_DIR_EACCES:
|
|
||||||
(e == ERROR_FILE_NOT_FOUND)? QSE_DIR_ENOENT:
|
|
||||||
(e == ERROR_INVALID_NAME)? QSE_DIR_EINVAL:
|
|
||||||
(e == ERROR_DIRECTORY)? QSE_DIR_EINVAL:
|
|
||||||
QSE_DIR_ESYSTEM;
|
|
||||||
QSE_MMGR_FREE (dir->mmgr, dirname);
|
QSE_MMGR_FREE (dir->mmgr, dirname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -225,11 +293,11 @@ int qse_dir_change (qse_dir_t* dir, const qse_char_t* name)
|
|||||||
QSE_MEMSET (info, 0, QSE_SIZEOF(*info));
|
QSE_MEMSET (info, 0, QSE_SIZEOF(*info));
|
||||||
info->handle = handle;
|
info->handle = handle;
|
||||||
info->wfd = wfd;
|
info->wfd = wfd;
|
||||||
|
info->just_changed_dir = 1;
|
||||||
|
|
||||||
if (dir->curdir) QSE_MMGR_FREE (dir->mmgr, dir->curdir);
|
if (dir->curdir) QSE_MMGR_FREE (dir->mmgr, dir->curdir);
|
||||||
dirname[idx-1] = QSE_T('\0'); /* drop the asterisk */
|
dirname[idx-1] = QSE_T('\0'); /* drop the asterisk */
|
||||||
dir->curdir = dirname;
|
dir->curdir = dirname;
|
||||||
dir->first_after_change = 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -238,7 +306,17 @@ int qse_dir_change (qse_dir_t* dir, const qse_char_t* name)
|
|||||||
#elif defined(__DOS__)
|
#elif defined(__DOS__)
|
||||||
# error NOT IMPLEMENTED
|
# error NOT IMPLEMENTED
|
||||||
#else
|
#else
|
||||||
dirname = qse_strdup (name, dir->mmgr);
|
|
||||||
|
idx = 0;
|
||||||
|
if (!qse_isabspath(name) && dir->curdir)
|
||||||
|
{
|
||||||
|
tmp_name[idx++] = dir->curdir;
|
||||||
|
tmp_name[idx++] = QSE_T("/");
|
||||||
|
}
|
||||||
|
tmp_name[idx++] = name;
|
||||||
|
tmp_name[idx] = QSE_NULL;
|
||||||
|
|
||||||
|
dirname = qse_stradup (tmp_name, dir->mmgr);
|
||||||
if (dirname == QSE_NULL)
|
if (dirname == QSE_NULL)
|
||||||
{
|
{
|
||||||
dir->errnum = QSE_DIR_ENOMEM;
|
dir->errnum = QSE_DIR_ENOMEM;
|
||||||
@ -248,10 +326,10 @@ int qse_dir_change (qse_dir_t* dir, const qse_char_t* name)
|
|||||||
qse_canonpath (dirname, dirname);
|
qse_canonpath (dirname, dirname);
|
||||||
|
|
||||||
#if defined(QSE_CHAR_IS_MCHAR)
|
#if defined(QSE_CHAR_IS_MCHAR)
|
||||||
mbsdirname = dirname;
|
mdirname = dirname;
|
||||||
#else
|
#else
|
||||||
mbsdirname = qse_wcstombsdup (name, dir->mmgr);
|
mdirname = qse_wcstombsdup (dirname, dir->mmgr);
|
||||||
if (mbsdirname == QSE_NULL)
|
if (mdirname == QSE_NULL)
|
||||||
{
|
{
|
||||||
dir->errnum = QSE_DIR_ENOMEM;
|
dir->errnum = QSE_DIR_ENOMEM;
|
||||||
QSE_MMGR_FREE (dir->mmgr, dirname);
|
QSE_MMGR_FREE (dir->mmgr, dirname);
|
||||||
@ -259,22 +337,13 @@ int qse_dir_change (qse_dir_t* dir, const qse_char_t* name)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
handle = opendir (mbsdirname);
|
handle = opendir (mdirname);
|
||||||
|
|
||||||
#if defined(QSE_CHAR_IS_MCHAR)
|
|
||||||
/* do nothing */
|
|
||||||
#else
|
|
||||||
QSE_MMGR_FREE (dir->mmgr, mbsdirname);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (handle == QSE_NULL)
|
if (handle == QSE_NULL)
|
||||||
{
|
{
|
||||||
dir->errnum = (errno == EACCES)? QSE_DIR_EACCES:
|
dir->errnum = syserr_to_errnum (errno);
|
||||||
(errno == ENOENT)? QSE_DIR_ENOENT:
|
if (mdirname != dirname)
|
||||||
(errno == ENOTDIR)? QSE_DIR_ENOTDIR:
|
QSE_MMGR_FREE (dir->mmgr, mdirname);
|
||||||
(errno == ENOMEM)? QSE_DIR_ENOMEM:
|
|
||||||
QSE_DIR_ESYSTEM;
|
|
||||||
|
|
||||||
QSE_MMGR_FREE (dir->mmgr, dirname);
|
QSE_MMGR_FREE (dir->mmgr, dirname);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -282,6 +351,10 @@ int qse_dir_change (qse_dir_t* dir, const qse_char_t* name)
|
|||||||
if (info->handle) closedir (info->handle);
|
if (info->handle) closedir (info->handle);
|
||||||
info->handle = handle;
|
info->handle = handle;
|
||||||
|
|
||||||
|
if (info->mcurdir && info->mcurdir != dir->curdir)
|
||||||
|
QSE_MMGR_FREE (dir->mmgr, info->mcurdir);
|
||||||
|
info->mcurdir = mdirname;
|
||||||
|
|
||||||
if (dir->curdir) QSE_MMGR_FREE (dir->mmgr, dir->curdir);
|
if (dir->curdir) QSE_MMGR_FREE (dir->mmgr, dir->curdir);
|
||||||
dir->curdir = dirname;
|
dir->curdir = dirname;
|
||||||
|
|
||||||
@ -349,34 +422,19 @@ static int set_entry_name (qse_dir_t* dir, const qse_mchar_t* name)
|
|||||||
|
|
||||||
qse_dir_ent_t* qse_dir_read (qse_dir_t* dir)
|
qse_dir_ent_t* qse_dir_read (qse_dir_t* dir)
|
||||||
{
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
info_t* info;
|
info_t* info;
|
||||||
|
|
||||||
info = dir->info;
|
info = dir->info;
|
||||||
if (info == QSE_NULL)
|
if (info == QSE_NULL)
|
||||||
{
|
{
|
||||||
/*
|
dir->errnum = QSE_DIR_ENODIR;
|
||||||
dir->errnum = NO CHANGE DIR YET;
|
|
||||||
*/
|
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_WIN32)
|
if (info->just_changed_dir)
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (info->no_more_files)
|
|
||||||
{
|
{
|
||||||
dir->errnum = QSE_DIR_ENOERR;
|
info->just_changed_dir = 0;
|
||||||
return QSE_NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (info->first_after_change)
|
|
||||||
{
|
|
||||||
/* call set_entry_name before changing other fields
|
|
||||||
* in dir->ent not to pollute it in case set_entry_name fails */
|
|
||||||
if (set_entry_name (dir, info->wfd.cFileName) <= -1) return QSE_NULL;
|
|
||||||
|
|
||||||
info->first_after_change = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -385,32 +443,32 @@ qse_dir_ent_t* qse_dir_read (qse_dir_t* dir)
|
|||||||
DWORD e = GetLastError();
|
DWORD e = GetLastError();
|
||||||
if (e == ERROR_NO_MORE_FILES)
|
if (e == ERROR_NO_MORE_FILES)
|
||||||
{
|
{
|
||||||
//info->no_more_files = 1;
|
|
||||||
dir->errnum = QSE_DIR_ENOERR;
|
dir->errnum = QSE_DIR_ENOERR;
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dir->errnum = (e == ERROR_ACCESS_DENIED)? QSE_DIR_EACCES:
|
dir->errnum = syserr_to_errnum (GetLastError());
|
||||||
(e == ERROR_FILE_NOT_FOUND)? QSE_DIR_ENOENT:
|
|
||||||
(e == ERROR_INVALID_NAME)? QSE_DIR_EINVAL:
|
|
||||||
(e == ERROR_DIRECTORY)? QSE_DIR_EINVAL:
|
|
||||||
QSE_DIR_ESYSTEM;
|
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* call set_entry_name before changing other fields
|
/* call set_entry_name before changing other fields
|
||||||
* in dir->ent not to pollute it in case set_entry_name fails */
|
* in dir->ent not to pollute it in case set_entry_name fails */
|
||||||
if (set_entry_name (dir, info->wfd.cFileName) <= -1) return QSE_NULL;
|
if (set_entry_name (dir, info->wfd.cFileName) <= -1) return QSE_NULL;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (info->wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
if (info->wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
{
|
{
|
||||||
dir->ent.size = 0;
|
dir->ent.size = 0;
|
||||||
dir->ent.type = QSE_DIR_ENT_DIRECTORY;
|
dir->ent.type = QSE_DIR_ENT_DIRECTORY;
|
||||||
}
|
}
|
||||||
|
else if ((info->wfd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
|
||||||
|
(info->wfd.dwReserved0 == IO_REPARSE_TAG_SYMLINK))
|
||||||
|
{
|
||||||
|
dir->ent.size = 0;
|
||||||
|
dir->ent.type = QSE_DIR_ENT_LINK;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LARGE_INTEGER li;
|
LARGE_INTEGER li;
|
||||||
@ -425,56 +483,78 @@ qse_dir_ent_t* qse_dir_read (qse_dir_t* dir)
|
|||||||
#elif defined(__DOS__)
|
#elif defined(__DOS__)
|
||||||
# error NOT IMPLEMENTED
|
# error NOT IMPLEMENTED
|
||||||
#else
|
#else
|
||||||
struct dirent* ent;
|
|
||||||
|
|
||||||
|
info_t* info;
|
||||||
|
struct dirent* ent;
|
||||||
|
int x;
|
||||||
|
#if defined(HAVE_LSTAT64)
|
||||||
|
struct stat64 st;
|
||||||
|
#else
|
||||||
|
struct stat st;
|
||||||
|
#endif
|
||||||
|
qse_mchar_t* tmp_name[4];
|
||||||
|
qse_mchar_t* mfname;
|
||||||
|
|
||||||
|
info = dir->info;
|
||||||
|
if (info == QSE_NULL)
|
||||||
|
{
|
||||||
|
dir->errnum = QSE_DIR_ENODIR;
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
ent = readdir (info->handle);
|
ent = readdir (info->handle);
|
||||||
if (ent == QSE_NULL)
|
if (ent == QSE_NULL)
|
||||||
{
|
{
|
||||||
/*dir->errnum = QSE_DIR_ENOENT;*/ /* TODO: to be more specific */
|
if (errno != 0) dir->errnum = syserr_to_errnum (errno);
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_STRUCT_DIRENT_D_TYPE)
|
#if defined(HAVE_STRUCT_DIRENT_D_TYPE)
|
||||||
if (ent->d_type != DT_DIR)
|
/* end->d_type */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* TODO: use a buffer in info... instead of allocating an deallocating every time */
|
||||||
|
tmp_name[0] = info->mcurdir;
|
||||||
|
tmp_name[1] = QSE_MT("/");
|
||||||
|
tmp_name[2] = ent->d_name;
|
||||||
|
tmp_name[3] = QSE_NULL;
|
||||||
|
mfname = qse_mbsadup (tmp_name, dir->mmgr);
|
||||||
|
if (mfname == QSE_NULL)
|
||||||
{
|
{
|
||||||
int x;
|
dir->errnum = QSE_DIR_ENOMEM;
|
||||||
#if defined(HAVE_LSTAT64)
|
|
||||||
struct stat64 st;
|
|
||||||
x = lstat64 (ent->d_name, &st);
|
|
||||||
#else
|
|
||||||
struct stat st;
|
|
||||||
x = lstat (ent->d_name, &st);
|
|
||||||
#endif
|
|
||||||
if (x == -1)
|
|
||||||
{
|
|
||||||
/*TODO: dir->errnum = ... */
|
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_LSTAT64)
|
||||||
|
x = lstat64 (mfname, &st);
|
||||||
|
#else
|
||||||
|
x = lstat (mfname, &st);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QSE_MMGR_FREE (dir->mmgr, mfname);
|
||||||
|
|
||||||
|
if (x == -1)
|
||||||
|
{
|
||||||
|
dir->errnum = syserr_to_errnum (errno);
|
||||||
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (set_entry_name (dir, ent->d_name) <= -1) return QSE_NULL;
|
if (set_entry_name (dir, ent->d_name) <= -1) return QSE_NULL;
|
||||||
|
|
||||||
#if defined(HAVE_STRUCT_DIRENT_D_TYPE)
|
if (S_ISDIR(st.st_mode))
|
||||||
switch (ent->d_type)
|
|
||||||
{
|
{
|
||||||
case DT_DIR:
|
|
||||||
dir->ent.size = 0;
|
dir->ent.size = 0;
|
||||||
dir->ent.type = QSE_DIR_ENT_DIRECTORY;
|
dir->ent.type = QSE_DIR_ENT_DIRECTORY;
|
||||||
break;
|
|
||||||
|
|
||||||
case DT_REG:
|
|
||||||
dir->ent.type = QSE_DIR_ENT_REGULAR;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
dir->ent.size = 0;
|
|
||||||
dir->ent.type = QSE_DIR_ENT_UNKNOWN;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
#endif
|
else
|
||||||
|
{
|
||||||
|
dir->ent.size = st.st_size;
|
||||||
|
dir->ent.type = QSE_DIR_ENT_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return &dir->ent;
|
return &dir->ent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,7 +579,7 @@ const qse_char_t* qse_dir_geterrmsg (qse_dir_t* dir)
|
|||||||
QSE_T("invalid parameter or data"),
|
QSE_T("invalid parameter or data"),
|
||||||
QSE_T("permission denined"),
|
QSE_T("permission denined"),
|
||||||
QSE_T("no such entry"),
|
QSE_T("no such entry"),
|
||||||
QSE_T("not a directory"),
|
QSE_T("no working directory set"),
|
||||||
QSE_T("system error")
|
QSE_T("system error")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -369,8 +369,9 @@ static int test8 (void)
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
qse_size_t mlen;
|
||||||
memset (buf, 'A', sizeof(buf));
|
memset (buf, 'A', sizeof(buf));
|
||||||
qse_size_t mlen = sizeof(buf);
|
mlen = sizeof(buf);
|
||||||
n = qse_wcstombs (p, buf, &mlen);
|
n = qse_wcstombs (p, buf, &mlen);
|
||||||
if (n == 0) break;
|
if (n == 0) break;
|
||||||
|
|
||||||
@ -576,9 +577,9 @@ static int test14 (void)
|
|||||||
{
|
{
|
||||||
qse_str_cpy (&x, a1);
|
qse_str_cpy (&x, a1);
|
||||||
qse_str_del (&x, 10, i);
|
qse_str_del (&x, 10, i);
|
||||||
qse_printf (QSE_T("deleleted %d from 10 => %llu [%s]\n"),
|
qse_printf (QSE_T("deleleted %d from 10 => %lu [%s]\n"),
|
||||||
i,
|
i,
|
||||||
(unsigned long long)QSE_STR_LEN(&x),
|
(unsigned long)QSE_STR_LEN(&x),
|
||||||
QSE_STR_PTR(&x));
|
QSE_STR_PTR(&x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ static void list (qse_dir_t* dir, const qse_char_t* name)
|
|||||||
|
|
||||||
if (qse_dir_change (dir, name) <= -1)
|
if (qse_dir_change (dir, name) <= -1)
|
||||||
{
|
{
|
||||||
qse_fprintf (QSE_STDERR, QSE_T("Error: Cannot change directory to %s\n"), name);
|
qse_fprintf (QSE_STDERR, QSE_T("Error: Cannot change directory to %s - %s\n"), name, qse_dir_geterrmsg(dir));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,7 +20,13 @@ static void list (qse_dir_t* dir, const qse_char_t* name)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
ent = qse_dir_read (dir);
|
ent = qse_dir_read (dir);
|
||||||
if (ent == QSE_NULL) break;
|
if (ent == QSE_NULL)
|
||||||
|
{
|
||||||
|
qse_dir_errnum_t e = qse_dir_geterrnum(dir);
|
||||||
|
if (e != QSE_DIR_ENOERR)
|
||||||
|
qse_fprintf (QSE_STDERR, QSE_T("Error: Read error - %s\n"), qse_dir_geterrmsg(dir));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (ent->type == QSE_DIR_ENT_DIRECTORY)
|
if (ent->type == QSE_DIR_ENT_DIRECTORY)
|
||||||
qse_printf (QSE_T("<DIR> %16lu %s\n"), (unsigned long)ent->size, ent->name);
|
qse_printf (QSE_T("<DIR> %16lu %s\n"), (unsigned long)ent->size, ent->name);
|
||||||
|
Loading…
Reference in New Issue
Block a user