diff --git a/qse/cmd/awk/awk.c b/qse/cmd/awk/awk.c index 10d37bff..f11fa2a4 100644 --- a/qse/cmd/awk/awk.c +++ b/qse/cmd/awk/awk.c @@ -511,7 +511,7 @@ static int expand_wildcard (int argc, qse_char_t* argv[], int glob, xarg_t* xarg #else QSE_GLOB_PERIOD, #endif - xarg->mmgr + xarg->mmgr, qse_getdflcmgr() ); if (x <= -1) return -1; } diff --git a/qse/cmd/sed/sed.c b/qse/cmd/sed/sed.c index ba47be29..2773d73a 100644 --- a/qse/cmd/sed/sed.c +++ b/qse/cmd/sed/sed.c @@ -681,7 +681,7 @@ static int expand_wildcards (int argc, qse_char_t* argv[], int glob, xarg_t* xar #else QSE_GLOB_PERIOD, #endif - xarg->mmgr + xarg->mmgr, qse_getdflcmgr() ); if (x <= -1) return -1; diff --git a/qse/include/qse/cmn/dir.h b/qse/include/qse/cmn/dir.h index 31d4169d..4a5c853c 100644 --- a/qse/include/qse/cmn/dir.h +++ b/qse/include/qse/cmn/dir.h @@ -60,7 +60,8 @@ typedef enum qse_dir_errnum_t qse_dir_errnum_t; enum qse_dir_flag_t { QSE_DIR_MBSPATH = (1 << 0), - QSE_DIR_SORT = (1 << 1) + QSE_DIR_SORT = (1 << 1), + QSE_DIR_LIMITED = (1 << 2) /**< limited to normal entries excluding . and .. */ }; struct qse_dir_ent_t diff --git a/qse/include/qse/cmn/fs.h b/qse/include/qse/cmn/fs.h index b18cdf25..68dee2cc 100644 --- a/qse/include/qse/cmn/fs.h +++ b/qse/include/qse/cmn/fs.h @@ -61,6 +61,9 @@ enum qse_fs_errnum_t QSE_FS_ENOENT, /**< no such file or directory */ QSE_FS_EEXIST, /**< already exist */ QSE_FS_EINTR, /**< interrupted */ + QSE_FS_EPIPE, /**< broken pipe */ + QSE_FS_EAGAIN, /**< resource temporarily unavailable */ + QSE_FS_EISDIR, /**< is a directory */ QSE_FS_ENOTDIR, /**< not a directory */ QSE_FS_ENOTVOID, /**< directory not empty */ diff --git a/qse/include/qse/cmn/glob.h b/qse/include/qse/cmn/glob.h index 4556c18a..94b2087b 100644 --- a/qse/include/qse/cmn/glob.h +++ b/qse/include/qse/cmn/glob.h @@ -54,7 +54,11 @@ enum qse_glob_flags_t QSE_GLOB_IGNORECASE = (1 << 2), /** Make the function to be more fault-resistent */ - QSE_GLOB_TOLERANT = (1 << 3) + QSE_GLOB_TOLERANT = (1 << 3), + + /** Exclude special entries from matching. + * Special entries include . and .. */ + QSE_GLOB_LIMITED = (1 << 4) }; #if defined(__cplusplus) @@ -72,7 +76,8 @@ QSE_EXPORT int qse_glob ( qse_glob_cbimpl_t cbimpl, void* cbctx, int flags, - qse_mmgr_t* mmgr + qse_mmgr_t* mmgr, + qse_cmgr_t* cmgr ); #if defined(__cplusplus) diff --git a/qse/lib/cmn/dir.c b/qse/lib/cmn/dir.c index 9842a36b..aaafccfd 100644 --- a/qse/lib/cmn/dir.c +++ b/qse/lib/cmn/dir.c @@ -51,6 +51,20 @@ #define STATUS_POPHEAP (1 << 3) #define STATUS_SORT_ERR (1 << 4) +#define IS_CURDIR_M(x) ((x)[0] == QSE_MT('.') && (x)[1] == QSE_MT('\0')) +#define IS_PREVDIR_M(x) ((x)[0] == QSE_MT('.') && (x)[1] == QSE_MT('.') && (x)[2] == QSE_MT('\0')) + +#define IS_CURDIR_W(x) ((x)[0] == QSE_WT('.') && (x)[1] == QSE_WT('\0')) +#define IS_PREVDIR_W(x) ((x)[0] == QSE_WT('.') && (x)[1] == QSE_WT('.') && (x)[2] == QSE_WT('\0')) + +#if defined(QSE_CHAR_IS_MCHAR) +# define IS_CURDIR(x) IS_CURDIR_M(x) +# define IS_PREVDIR(x) IS_PREVDIR_M(x) +#else +# define IS_CURDIR(x) IS_CURDIR_W(x) +# define IS_PREVDIR(x) IS_PREVDIR_W(x) +#endif + struct qse_dir_t { qse_mmgr_t* mmgr; @@ -533,6 +547,30 @@ static int read_dir_to_tbuf (qse_dir_t* dir, void** name) /* ------------------------------------------------------------------- */ if (dir->status & STATUS_DONE) return (dir->status & STATUS_DONE_ERR)? -1: 0; + if (dir->flags & QSE_DIR_LIMITED) + { + /* skip . and .. */ + while (IS_CURDIR(dir->wfd.cFileName) || IS_PREVDIR(dir->wfd.cFileName)) + { + if (FindNextFile (dir->h, &dir->wfd) == FALSE) + { + DWORD x = GetLastError(); + if (x == ERROR_NO_MORE_FILES) + { + dir->status |= STATUS_DONE; + return 0; + } + else + { + dir->errnum = syserr_to_errnum (x); + dir->status |= STATUS_DONE; + dir->status |= STATUS_DONE_ERR; + return -1; + } + } + } + } + #if defined(QSE_CHAR_IS_MCHAR) if (qse_str_cpy (&dir->tbuf, dir->wfd.cFileName) == (qse_size_t)-1) { @@ -579,6 +617,25 @@ static int read_dir_to_tbuf (qse_dir_t* dir, void** name) if (dir->count <= 0) return 0; + if (dir->flags & QSE_DIR_LIMITED) + { + /* skip . and .. */ + while (IS_CURDIR_M(dir->ffb.achName) || IS_PREVDIR_M(dir->ffb.achName)) + { + rc = DosFindNext (dir->h, &dir->ffb, QSE_SIZEOF(dir->ffb), &dir->count); + if (rc == ERROR_NO_MORE_FILES) + { + dir->count = 0; + return 0; + } + else if (rc != NO_ERROR) + { + dir->errnum = syserr_to_errnum (rc); + return -1; + } + } + } + #if defined(QSE_CHAR_IS_MCHAR) if (qse_str_cpy (&dir->tbuf, dir->ffb.achName) == (qse_size_t)-1) { @@ -620,6 +677,29 @@ static int read_dir_to_tbuf (qse_dir_t* dir, void** name) if (dir->status & STATUS_DONE) return (dir->status & STATUS_DONE_ERR)? -1: 0; + if (dir->flags & QSE_DIR_LIMITED) + { + /* skip . and .. */ + while (IS_CURDIR_M(dir->f.name) || IS_PREVDIR_M(dir->f.name)) + { + if (_dos_findnext (&dir->f) != 0) + { + if (errno == ENOENT) + { + dir->status |= STATUS_DONE; + return 0; + } + else + { + dir->errnum = syserr_to_errnum (errno); + dir->status |= STATUS_DONE; + dir->status |= STATUS_DONE_ERR; + return -1; + } + } + } + } + #if defined(QSE_CHAR_IS_MCHAR) if (qse_str_cpy (&dir->tbuf, dir->f.name) == (qse_size_t)-1) { @@ -663,6 +743,7 @@ static int read_dir_to_tbuf (qse_dir_t* dir, void** name) /* ------------------------------------------------------------------- */ qse_dirent_t* de; +read: errno = 0; de = QSE_READDIR (dir->dp); if (de == NULL) @@ -672,6 +753,13 @@ static int read_dir_to_tbuf (qse_dir_t* dir, void** name) return -1; } + if (dir->flags & QSE_DIR_LIMITED) + { + /* skip . and .. */ + if (IS_CURDIR_M(de->d_name) || + IS_PREVDIR_M(de->d_name)) goto read; + } + #if defined(QSE_CHAR_IS_MCHAR) if (qse_str_cpy (&dir->tbuf, de->d_name) == (qse_size_t)-1) { diff --git a/qse/lib/cmn/fs-delete.c b/qse/lib/cmn/fs-delete.c index 8376b6ba..bc2fece7 100644 --- a/qse/lib/cmn/fs-delete.c +++ b/qse/lib/cmn/fs-delete.c @@ -119,7 +119,8 @@ static int purge_path (qse_fs_t* fs, const qse_char_t* path) qse_fs_char_t* fspath; int ret, x; - dir = qse_dir_open (fs->mmgr, 0, path, 0, &errnum); + /* 'dir' is asked to skip special entries like . and .. */ + dir = qse_dir_open (fs->mmgr, 0, path, QSE_DIR_LIMITED, &errnum); if (!dir) { /* not a directory. attempt to delete it as a file */ @@ -144,14 +145,11 @@ static int purge_path (qse_fs_t* fs, const qse_char_t* path) x = qse_dir_read (dir, &ent); if (x <= -1) { - /* TODO: CONVERT dir->errnum to fs errnum */ + fs->errnum = qse_fs_direrrtoerrnum (fs, qse_dir_geterrnum(dir)); goto oops; } if (x == 0) break; /* no more entries */ - /* skip . and .. */ - if (IS_CURDIR(ent.name) || IS_PREVDIR(ent.name)) continue; - seg[0] = path; seg[1] = DEFAULT_PATH_SEPARATOR; seg[2] = ent.name; @@ -204,8 +202,6 @@ static int delete_file_for_glob (const qse_cstr_t* path, void* ctx) qse_fs_char_t* fspath; int ret; - /* skip . and .. */ - if (IS_CURDIR(path->ptr) || IS_PREVDIR(path->ptr)) return 0; fspath = qse_fs_makefspath (fs, path->ptr); if (!fspath) return -1; @@ -234,7 +230,7 @@ int qse_fs_delfilembs (qse_fs_t* fs, const qse_mchar_t* path, int flags) return -1; } - ret = qse_glob (xpath, delete_file_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr); + ret = qse_glob (xpath, delete_file_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr, fs->cmgr); free_str_with_mbs (fs, path, xpath); @@ -276,7 +272,7 @@ int qse_fs_delfilewcs (qse_fs_t* fs, const qse_wchar_t* path, int flags) return -1; } - ret = qse_glob (xpath, delete_file_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr); + ret = qse_glob (xpath, delete_file_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr, fs->cmgr); free_str_with_wcs (fs, path, xpath); @@ -312,9 +308,6 @@ static int delete_directory_for_glob (const qse_cstr_t* path, void* ctx) qse_fs_char_t* fspath; int ret; - /* skip . and .. */ - if (IS_CURDIR(path->ptr) || IS_PREVDIR(path->ptr)) return 0; - fspath = qse_fs_makefspath (fs, path->ptr); if (!fspath) return -1; @@ -330,10 +323,8 @@ static int delete_directory_for_glob (const qse_cstr_t* path, void* ctx) static int purge_path_for_glob (const qse_cstr_t* path, void* ctx) { qse_fs_t* fs = (qse_fs_t*)ctx; - int ret; - /* skip . and .. */ - if (IS_CURDIR(path->ptr) || IS_PREVDIR(path->ptr)) return 0; +printf ("[%ls]\n", path->ptr); /*TODO query: */ /*if (fs->cb.delete) fs->cb.delete (joined_path);*/ @@ -357,11 +348,11 @@ int qse_fs_deldirmbs (qse_fs_t* fs, const qse_mchar_t* path, int flags) if (flags & QSE_FS_DELDIRMBS_RECURSIVE) { - ret = qse_glob (xpath, purge_path_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr); + ret = qse_glob (xpath, purge_path_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr, fs->cmgr); } else { - ret = qse_glob (xpath, delete_directory_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr); + ret = qse_glob (xpath, delete_directory_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr, fs->cmgr); } free_str_with_mbs (fs, path, xpath); @@ -417,11 +408,11 @@ int qse_fs_deldirwcs (qse_fs_t* fs, const qse_wchar_t* path, int flags) if (flags & QSE_FS_DELDIRWCS_RECURSIVE) { - ret = qse_glob (xpath, purge_path_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr); + ret = qse_glob (xpath, purge_path_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr, fs->cmgr); } else { - ret = qse_glob (xpath, delete_directory_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr); + ret = qse_glob (xpath, delete_directory_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr, fs->cmgr); } free_str_with_wcs (fs, path, xpath); diff --git a/qse/lib/cmn/fs-err.c b/qse/lib/cmn/fs-err.c index cce31aba..b4a368f3 100644 --- a/qse/lib/cmn/fs-err.c +++ b/qse/lib/cmn/fs-err.c @@ -166,3 +166,52 @@ qse_fs_errnum_t qse_fs_syserrtoerrnum (qse_fs_t* fs, qse_fs_syserr_t e) } #endif } + + +qse_fs_errnum_t qse_fs_direrrtoerrnum (qse_fs_t* fs, qse_dir_errnum_t e) +{ + switch (e) + { + case QSE_DIR_ENOERR: + return QSE_FS_ENOERR; + + case QSE_DIR_EOTHER: + return QSE_FS_EOTHER; + + case QSE_DIR_ENOIMPL: + return QSE_FS_ENOIMPL; + + case QSE_DIR_ESYSERR: + return QSE_FS_ESYSERR; + + case QSE_DIR_EINTERN: + return QSE_FS_EINTERN; + + case QSE_DIR_ENOMEM: + return QSE_FS_ENOMEM; + + case QSE_DIR_EINVAL: + return QSE_FS_EINVAL; + + case QSE_DIR_EACCES: + return QSE_FS_EACCES; + + case QSE_DIR_ENOENT: + return QSE_FS_ENOENT; + + case QSE_DIR_EEXIST: + return QSE_FS_EEXIST; + + case QSE_DIR_EINTR: + return QSE_FS_EINTR; + + case QSE_DIR_EPIPE: + return QSE_FS_EPIPE; + + case QSE_DIR_EAGAIN: + return QSE_FS_EAGAIN; + + default: + return QSE_FS_EOTHER; + } +} diff --git a/qse/lib/cmn/fs-move.c b/qse/lib/cmn/fs-move.c index e4de5869..1d243fc1 100644 --- a/qse/lib/cmn/fs-move.c +++ b/qse/lib/cmn/fs-move.c @@ -363,30 +363,3 @@ oops: #endif } -typedef struct del_op_t del_op_t; -struct del_op_t -{ -#if defined(_WIN32) - /* nothing */ - int __dummy; /* just a placeholder */ -#elif defined(__OS2__) - qse_mchar_t* path; -#elif defined(__DOS__) - qse_mchar_t* path; -#else - qse_mchar_t* path; -#endif -}; - -/* -int qse_cpfile -int qse_mvfile -* -int qse_rmdir -qse_mkdir - - -qse_statfile - -qse_rm...???? -*/ diff --git a/qse/lib/cmn/fs.h b/qse/lib/cmn/fs.h index ca30011e..a3f1cc50 100644 --- a/qse/lib/cmn/fs.h +++ b/qse/lib/cmn/fs.h @@ -49,10 +49,10 @@ #endif #if defined(_WIN32) || defined(__OS2__) || defined(__DOS__) -# define DEFAULT_GLOB_FLAGS (QSE_GLOB_PERIOD | QSE_GLOB_NOESCAPE | QSE_GLOB_IGNORECASE) +# define DEFAULT_GLOB_FLAGS (QSE_GLOB_PERIOD | QSE_GLOB_LIMITED | QSE_GLOB_NOESCAPE | QSE_GLOB_IGNORECASE) # define DEFAULT_PATH_SEPARATOR QSE_T("\\") #else -# define DEFAULT_GLOB_FLAGS (QSE_GLOB_PERIOD) +# define DEFAULT_GLOB_FLAGS (QSE_GLOB_PERIOD | QSE_GLOB_LIMITED) # define DEFAULT_PATH_SEPARATOR QSE_T("/") #endif @@ -80,6 +80,11 @@ qse_fs_errnum_t qse_fs_syserrtoerrnum ( qse_fs_syserr_t e ); +qse_fs_errnum_t qse_fs_direrrtoerrnum ( + qse_fs_t* fs, + qse_dir_errnum_t e +); + qse_fs_char_t* qse_fs_makefspathformbs ( qse_fs_t* fs, const qse_mchar_t* path diff --git a/qse/lib/cmn/glob.c b/qse/lib/cmn/glob.c index d6bc9489..58566dce 100644 --- a/qse/lib/cmn/glob.c +++ b/qse/lib/cmn/glob.c @@ -82,6 +82,7 @@ struct glob_t void* cbctx; qse_mmgr_t* mmgr; + qse_cmgr_t* cmgr; int flags; qse_str_t path; @@ -107,10 +108,10 @@ static qse_mchar_t* wcs_to_mbuf (glob_t* g, const qse_wchar_t* wcs, qse_mbs_t* m { qse_size_t ml, wl; - if (qse_wcstombs (wcs, &wl, QSE_NULL, &ml) <= -1 || + if (qse_wcstombswithcmgr (wcs, &wl, QSE_NULL, &ml, g->cmgr) <= -1 || qse_mbs_setlen (mbs, ml) == (qse_size_t)-1) return QSE_NULL; - qse_wcstombs (wcs, &wl, QSE_MBS_PTR(mbs), &ml); + qse_wcstombswithcmgr (wcs, &wl, QSE_MBS_PTR(mbs), &ml, g->cmgr); return QSE_MBS_PTR(mbs); } @@ -437,7 +438,9 @@ entry: if (seg->wild) { - dp = qse_dir_open (g->mmgr, 0, QSE_STR_PTR(&g->path), 0, QSE_NULL); + dp = qse_dir_open ( + g->mmgr, 0, QSE_STR_PTR(&g->path), + ((g->flags & QSE_GLOB_LIMITED)? QSE_DIR_LIMITED: 0), QSE_NULL); if (dp) { tmp = QSE_STR_LEN(&g->path); @@ -572,7 +575,7 @@ oops: return -1; } -int qse_glob (const qse_char_t* pattern, qse_glob_cbimpl_t cbimpl, void* cbctx, int flags, qse_mmgr_t* mmgr) +int qse_glob (const qse_char_t* pattern, qse_glob_cbimpl_t cbimpl, void* cbctx, int flags, qse_mmgr_t* mmgr, qse_cmgr_t* cmgr) { segment_t seg; glob_t g; @@ -582,6 +585,7 @@ int qse_glob (const qse_char_t* pattern, qse_glob_cbimpl_t cbimpl, void* cbctx, g.cbimpl = cbimpl; g.cbctx = cbctx; g.mmgr = mmgr; + g.cmgr = cmgr; g.flags = flags; #if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)