did more migrating works
This commit is contained in:
@ -9,12 +9,10 @@ lib_LTLIBRARIES = libqsecmn.la
|
||||
noinst_HEADERS = \
|
||||
cp949.h \
|
||||
cp950.h \
|
||||
fmt.h \
|
||||
fmt-prv.h \
|
||||
fmt-intmax.h \
|
||||
fmt-out.h \
|
||||
fs.h \
|
||||
glob.h \
|
||||
mem.h \
|
||||
mem-prv.h \
|
||||
str-cat.h \
|
||||
str-dyn.h \
|
||||
str-fcpy.h \
|
||||
@ -39,7 +37,6 @@ libqsecmn_la_SOURCES = \
|
||||
alg-sort.c \
|
||||
assert.c \
|
||||
chr.c \
|
||||
dir.c \
|
||||
dll.c \
|
||||
env.c \
|
||||
gdl.c \
|
||||
@ -47,14 +44,6 @@ libqsecmn_la_SOURCES = \
|
||||
fma.c \
|
||||
fmt-intmax.c \
|
||||
fmt-out.c \
|
||||
fs.c \
|
||||
fs-attr.c \
|
||||
fs-copy.c \
|
||||
fs-delete.c \
|
||||
fs-err.c \
|
||||
fs-make.c \
|
||||
fs-move.c \
|
||||
glob.c \
|
||||
hton.c \
|
||||
ipad.c \
|
||||
lda.c \
|
||||
|
@ -133,35 +133,32 @@ am__DEPENDENCIES_1 =
|
||||
libqsecmn_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
|
||||
$(am__DEPENDENCIES_1)
|
||||
am__libqsecmn_la_SOURCES_DIST = alg-base64.c alg-rand.c alg-search.c \
|
||||
alg-sort.c assert.c chr.c dir.c dll.c env.c gdl.c htb.c fma.c \
|
||||
fmt-intmax.c fmt-out.c fs.c fs-attr.c fs-copy.c fs-delete.c \
|
||||
fs-err.c fs-make.c fs-move.c glob.c hton.c ipad.c lda.c main.c \
|
||||
mb8.c mbwc.c mbwc-str.c mem.c oht.c opt.c path-base.c \
|
||||
path-canon.c path-core.c path-merge.c pma.c rbt.c rex.c sll.c \
|
||||
slmb.c str-beg.c str-cat.c str-chr.c str-cnv.c str-cmp.c \
|
||||
str-cpy.c str-del.c str-dup.c str-dyn.c str-end.c str-excl.c \
|
||||
str-fcpy.c str-fmt.c str-fnmat.c str-incl.c str-join.c \
|
||||
str-len.c str-pac.c str-pbrk.c str-put.c str-rev.c str-rot.c \
|
||||
str-set.c str-spl.c str-spn.c str-str.c str-subst.c str-tok.c \
|
||||
str-trm.c str-word.c time.c tmr.c tre.c tre-ast.c \
|
||||
tre-compile.c tre-match-bt.c tre-match-pa.c tre-parse.c \
|
||||
tre-stack.c uri.c utf8.c xma.c uni.c cp949.c cp950.c
|
||||
alg-sort.c assert.c chr.c dll.c env.c gdl.c htb.c fma.c \
|
||||
fmt-intmax.c fmt-out.c hton.c ipad.c lda.c main.c mb8.c mbwc.c \
|
||||
mbwc-str.c mem.c oht.c opt.c path-base.c path-canon.c \
|
||||
path-core.c path-merge.c pma.c rbt.c rex.c sll.c slmb.c \
|
||||
str-beg.c str-cat.c str-chr.c str-cnv.c str-cmp.c str-cpy.c \
|
||||
str-del.c str-dup.c str-dyn.c str-end.c str-excl.c str-fcpy.c \
|
||||
str-fmt.c str-fnmat.c str-incl.c str-join.c str-len.c \
|
||||
str-pac.c str-pbrk.c str-put.c str-rev.c str-rot.c str-set.c \
|
||||
str-spl.c str-spn.c str-str.c str-subst.c str-tok.c str-trm.c \
|
||||
str-word.c time.c tmr.c tre.c tre-ast.c tre-compile.c \
|
||||
tre-match-bt.c tre-match-pa.c tre-parse.c tre-stack.c uri.c \
|
||||
utf8.c xma.c uni.c cp949.c cp950.c
|
||||
@ENABLE_BUNDLED_UNICODE_TRUE@am__objects_1 = uni.lo
|
||||
@ENABLE_XCMGRS_TRUE@am__objects_2 = cp949.lo cp950.lo
|
||||
am_libqsecmn_la_OBJECTS = alg-base64.lo alg-rand.lo alg-search.lo \
|
||||
alg-sort.lo assert.lo chr.lo dir.lo dll.lo env.lo gdl.lo \
|
||||
htb.lo fma.lo fmt-intmax.lo fmt-out.lo fs.lo fs-attr.lo \
|
||||
fs-copy.lo fs-delete.lo fs-err.lo fs-make.lo fs-move.lo \
|
||||
glob.lo hton.lo ipad.lo lda.lo main.lo mb8.lo mbwc.lo \
|
||||
mbwc-str.lo mem.lo oht.lo opt.lo path-base.lo path-canon.lo \
|
||||
path-core.lo path-merge.lo pma.lo rbt.lo rex.lo sll.lo slmb.lo \
|
||||
str-beg.lo str-cat.lo str-chr.lo str-cnv.lo str-cmp.lo \
|
||||
str-cpy.lo str-del.lo str-dup.lo str-dyn.lo str-end.lo \
|
||||
str-excl.lo str-fcpy.lo str-fmt.lo str-fnmat.lo str-incl.lo \
|
||||
str-join.lo str-len.lo str-pac.lo str-pbrk.lo str-put.lo \
|
||||
str-rev.lo str-rot.lo str-set.lo str-spl.lo str-spn.lo \
|
||||
str-str.lo str-subst.lo str-tok.lo str-trm.lo str-word.lo \
|
||||
time.lo tmr.lo tre.lo tre-ast.lo tre-compile.lo \
|
||||
alg-sort.lo assert.lo chr.lo dll.lo env.lo gdl.lo htb.lo \
|
||||
fma.lo fmt-intmax.lo fmt-out.lo hton.lo ipad.lo lda.lo main.lo \
|
||||
mb8.lo mbwc.lo mbwc-str.lo mem.lo oht.lo opt.lo path-base.lo \
|
||||
path-canon.lo path-core.lo path-merge.lo pma.lo rbt.lo rex.lo \
|
||||
sll.lo slmb.lo str-beg.lo str-cat.lo str-chr.lo str-cnv.lo \
|
||||
str-cmp.lo str-cpy.lo str-del.lo str-dup.lo str-dyn.lo \
|
||||
str-end.lo str-excl.lo str-fcpy.lo str-fmt.lo str-fnmat.lo \
|
||||
str-incl.lo str-join.lo str-len.lo str-pac.lo str-pbrk.lo \
|
||||
str-put.lo str-rev.lo str-rot.lo str-set.lo str-spl.lo \
|
||||
str-spn.lo str-str.lo str-subst.lo str-tok.lo str-trm.lo \
|
||||
str-word.lo time.lo tmr.lo tre.lo tre-ast.lo tre-compile.lo \
|
||||
tre-match-bt.lo tre-match-pa.lo tre-parse.lo tre-stack.lo \
|
||||
uri.lo utf8.lo xma.lo $(am__objects_1) $(am__objects_2)
|
||||
libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS)
|
||||
@ -448,12 +445,10 @@ lib_LTLIBRARIES = libqsecmn.la $(am__append_3)
|
||||
noinst_HEADERS = \
|
||||
cp949.h \
|
||||
cp950.h \
|
||||
fmt.h \
|
||||
fmt-prv.h \
|
||||
fmt-intmax.h \
|
||||
fmt-out.h \
|
||||
fs.h \
|
||||
glob.h \
|
||||
mem.h \
|
||||
mem-prv.h \
|
||||
str-cat.h \
|
||||
str-dyn.h \
|
||||
str-fcpy.h \
|
||||
@ -472,19 +467,18 @@ noinst_HEADERS = \
|
||||
uni-trait.h
|
||||
|
||||
libqsecmn_la_SOURCES = alg-base64.c alg-rand.c alg-search.c alg-sort.c \
|
||||
assert.c chr.c dir.c dll.c env.c gdl.c htb.c fma.c \
|
||||
fmt-intmax.c fmt-out.c fs.c fs-attr.c fs-copy.c fs-delete.c \
|
||||
fs-err.c fs-make.c fs-move.c glob.c hton.c ipad.c lda.c main.c \
|
||||
mb8.c mbwc.c mbwc-str.c mem.c oht.c opt.c path-base.c \
|
||||
path-canon.c path-core.c path-merge.c pma.c rbt.c rex.c sll.c \
|
||||
slmb.c str-beg.c str-cat.c str-chr.c str-cnv.c str-cmp.c \
|
||||
str-cpy.c str-del.c str-dup.c str-dyn.c str-end.c str-excl.c \
|
||||
str-fcpy.c str-fmt.c str-fnmat.c str-incl.c str-join.c \
|
||||
str-len.c str-pac.c str-pbrk.c str-put.c str-rev.c str-rot.c \
|
||||
str-set.c str-spl.c str-spn.c str-str.c str-subst.c str-tok.c \
|
||||
str-trm.c str-word.c time.c tmr.c tre.c tre-ast.c \
|
||||
tre-compile.c tre-match-bt.c tre-match-pa.c tre-parse.c \
|
||||
tre-stack.c uri.c utf8.c xma.c $(am__append_1) $(am__append_2)
|
||||
assert.c chr.c dll.c env.c gdl.c htb.c fma.c fmt-intmax.c \
|
||||
fmt-out.c hton.c ipad.c lda.c main.c mb8.c mbwc.c mbwc-str.c \
|
||||
mem.c oht.c opt.c path-base.c path-canon.c path-core.c \
|
||||
path-merge.c pma.c rbt.c rex.c sll.c slmb.c str-beg.c \
|
||||
str-cat.c str-chr.c str-cnv.c str-cmp.c str-cpy.c str-del.c \
|
||||
str-dup.c str-dyn.c str-end.c str-excl.c str-fcpy.c str-fmt.c \
|
||||
str-fnmat.c str-incl.c str-join.c str-len.c str-pac.c \
|
||||
str-pbrk.c str-put.c str-rev.c str-rot.c str-set.c str-spl.c \
|
||||
str-spn.c str-str.c str-subst.c str-tok.c str-trm.c str-word.c \
|
||||
time.c tmr.c tre.c tre-ast.c tre-compile.c tre-match-bt.c \
|
||||
tre-match-pa.c tre-parse.c tre-stack.c uri.c utf8.c xma.c \
|
||||
$(am__append_1) $(am__append_2)
|
||||
libqsecmn_la_LDFLAGS = -version-info 1:0:0 -no-undefined
|
||||
libqsecmn_la_LIBADD = $(SOCKET_LIBS) $(QUADMATH_LIBS)
|
||||
@ENABLE_CXX_TRUE@libqsecmnxx_la_SOURCES = \
|
||||
@ -588,21 +582,12 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chr.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cp949.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cp950.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dir.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dll.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/env.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fma.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmt-intmax.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmt-out.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs-attr.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs-copy.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs-delete.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs-err.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs-make.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs-move.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gdl.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glob.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hton.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipad.Plo@am__quote@
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include <qse/cmn/Mmgr.hpp>
|
||||
#include <qse/cmn/StdMmgr.hpp>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
/////////////////////////////////
|
||||
QSE_BEGIN_NAMESPACE(QSE)
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/String.hpp>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#if !defined(QSE_HAVE_CONFIG_H)
|
||||
# if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/str.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#if defined(HAVE_EXECINFO_H)
|
||||
# include <execinfo.h>
|
||||
|
@ -1,898 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <qse/cmn/dir.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include <qse/cmn/path.h>
|
||||
#include <qse/cmn/lda.h>
|
||||
#include "mem.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#elif defined(__OS2__)
|
||||
# define INCL_DOSFILEMGR
|
||||
# define INCL_ERRORS
|
||||
# include <os2.h>
|
||||
#elif defined(__DOS__)
|
||||
# include <dos.h>
|
||||
# include <errno.h>
|
||||
#else
|
||||
# include "syscall.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define STATUS_OPENED (1 << 0)
|
||||
#define STATUS_DONE (1 << 1)
|
||||
#define STATUS_DONE_ERR (1 << 2)
|
||||
#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;
|
||||
qse_dir_errnum_t errnum;
|
||||
int flags;
|
||||
|
||||
qse_wcs_t wbuf;
|
||||
qse_mbs_t mbuf;
|
||||
|
||||
qse_lda_t* stab;
|
||||
int status;
|
||||
|
||||
#if defined(_WIN32)
|
||||
HANDLE h;
|
||||
WIN32_FIND_DATA wfd;
|
||||
#elif defined(__OS2__)
|
||||
HDIR h;
|
||||
#if defined(FIL_STANDARDL)
|
||||
FILEFINDBUF3L ffb;
|
||||
#else
|
||||
FILEFINDBUF3 ffb;
|
||||
#endif
|
||||
ULONG count;
|
||||
#elif defined(__DOS__)
|
||||
struct find_t f;
|
||||
#else
|
||||
QSE_DIR* dp;
|
||||
#endif
|
||||
};
|
||||
|
||||
int qse_dir_init (qse_dir_t* dir, qse_mmgr_t* mmgr, const qse_char_t* path, int flags);
|
||||
void qse_dir_fini (qse_dir_t* dir);
|
||||
|
||||
static void close_dir_safely (qse_dir_t* dir);
|
||||
static int reset_to_path (qse_dir_t* dir, const qse_char_t* path);
|
||||
static int read_ahead_and_sort (qse_dir_t* dir, const qse_char_t* path);
|
||||
|
||||
#include "syserr.h"
|
||||
IMPLEMENT_SYSERR_TO_ERRNUM (dir, DIR)
|
||||
|
||||
qse_dir_t* qse_dir_open (
|
||||
qse_mmgr_t* mmgr, qse_size_t xtnsize,
|
||||
const qse_char_t* path, int flags, qse_dir_errnum_t* errnum)
|
||||
{
|
||||
qse_dir_t* dir;
|
||||
|
||||
dir = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(*dir) + xtnsize);
|
||||
if (dir)
|
||||
{
|
||||
if (qse_dir_init (dir, mmgr, path, flags) <= -1)
|
||||
{
|
||||
if (errnum) *errnum = qse_dir_geterrnum (dir);
|
||||
QSE_MMGR_FREE (mmgr, dir);
|
||||
dir = QSE_NULL;
|
||||
}
|
||||
else QSE_MEMSET (dir + 1, 0, xtnsize);
|
||||
}
|
||||
else if (errnum) *errnum = QSE_DIR_ENOMEM;
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
void qse_dir_close (qse_dir_t* dir)
|
||||
{
|
||||
qse_dir_fini (dir);
|
||||
QSE_MMGR_FREE (dir->mmgr, dir);
|
||||
}
|
||||
|
||||
qse_mmgr_t* qse_dir_getmmgr (qse_dir_t* dir)
|
||||
{
|
||||
return dir->mmgr;
|
||||
}
|
||||
|
||||
void* qse_dir_getxtn (qse_dir_t* dir)
|
||||
{
|
||||
return QSE_XTN (dir);
|
||||
}
|
||||
|
||||
qse_dir_errnum_t qse_dir_geterrnum (qse_dir_t* dir)
|
||||
{
|
||||
return dir->errnum;
|
||||
}
|
||||
|
||||
static int compare_dirent (qse_lda_t* lda, const void* dptr1, qse_size_t dlen1, const void* dptr2, qse_size_t dlen2)
|
||||
{
|
||||
int n = QSE_MEMCMP (dptr1, dptr2, ((dlen1 < dlen2)? dlen1: dlen2));
|
||||
if (n == 0 && dlen1 != dlen2) n = (dlen1 > dlen2)? 1: -1;
|
||||
return -n;
|
||||
}
|
||||
|
||||
int qse_dir_init (qse_dir_t* dir, qse_mmgr_t* mmgr, const qse_char_t* path, int flags)
|
||||
{
|
||||
int n;
|
||||
int path_flags;
|
||||
|
||||
path_flags = flags & (QSE_DIR_MBSPATH | QSE_DIR_WCSPATH);
|
||||
if (path_flags == (QSE_DIR_MBSPATH | QSE_DIR_WCSPATH) || path_flags == 0)
|
||||
{
|
||||
/* if both are set or none are set, force it to the default */
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
flags |= QSE_DIR_MBSPATH;
|
||||
flags &= ~QSE_DIR_WCSPATH;
|
||||
#else
|
||||
flags |= QSE_DIR_WCSPATH;
|
||||
flags &= ~QSE_DIR_MBSPATH;
|
||||
#endif
|
||||
}
|
||||
|
||||
QSE_MEMSET (dir, 0, QSE_SIZEOF(*dir));
|
||||
|
||||
dir->mmgr = mmgr;
|
||||
dir->flags = flags;
|
||||
|
||||
if (qse_wcs_init (&dir->wbuf, mmgr, 256) <= -1) goto oops_0;
|
||||
if (qse_mbs_init (&dir->mbuf, mmgr, 256) <= -1) goto oops_1;
|
||||
|
||||
#if defined(_WIN32)
|
||||
dir->h = INVALID_HANDLE_VALUE;
|
||||
#endif
|
||||
|
||||
n = reset_to_path (dir, path);
|
||||
if (n <= -1) goto oops_2;
|
||||
|
||||
if (dir->flags & QSE_DIR_SORT)
|
||||
{
|
||||
dir->stab = qse_lda_open (dir->mmgr, 0, 128);
|
||||
if (dir->stab == QSE_NULL) goto oops_3;
|
||||
|
||||
/*qse_lda_setscale (dir->stab, 1);*/
|
||||
qse_lda_setcopier (dir->stab, QSE_LDA_COPIER_INLINE);
|
||||
qse_lda_setcomper (dir->stab, compare_dirent);
|
||||
if (read_ahead_and_sort (dir, path) <= -1) goto oops_4;
|
||||
}
|
||||
|
||||
return n;
|
||||
|
||||
oops_4:
|
||||
qse_lda_close (dir->stab);
|
||||
oops_3:
|
||||
close_dir_safely (dir);
|
||||
oops_2:
|
||||
qse_mbs_fini (&dir->mbuf);
|
||||
oops_1:
|
||||
qse_wcs_fini (&dir->wbuf);
|
||||
oops_0:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void close_dir_safely (qse_dir_t* dir)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
if (dir->h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FindClose (dir->h);
|
||||
dir->h = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#elif defined(__OS2__)
|
||||
if (dir->status & STATUS_OPENED)
|
||||
{
|
||||
DosFindClose (dir->h);
|
||||
dir->status &= ~STATUS_OPENED;
|
||||
}
|
||||
#elif defined(__DOS__)
|
||||
if (dir->status & STATUS_OPENED)
|
||||
{
|
||||
_dos_findclose (&dir->f);
|
||||
dir->status &= ~STATUS_OPENED;
|
||||
}
|
||||
#else
|
||||
if (dir->dp)
|
||||
{
|
||||
QSE_CLOSEDIR (dir->dp);
|
||||
dir->dp = QSE_NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void qse_dir_fini (qse_dir_t* dir)
|
||||
{
|
||||
close_dir_safely (dir);
|
||||
|
||||
qse_mbs_fini (&dir->mbuf);
|
||||
qse_wcs_fini (&dir->wbuf);
|
||||
|
||||
if (dir->stab) qse_lda_close (dir->stab);
|
||||
}
|
||||
|
||||
static qse_mchar_t* wcs_to_mbuf (qse_dir_t* dir, const qse_wchar_t* wcs, qse_mbs_t* mbuf)
|
||||
{
|
||||
qse_size_t ml, wl;
|
||||
|
||||
if (qse_wcstombs (wcs, &wl, QSE_NULL, &ml) <= -1)
|
||||
{
|
||||
dir->errnum = QSE_DIR_EINVAL;
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
if (qse_mbs_setlen (mbuf, ml) == (qse_size_t)-1)
|
||||
{
|
||||
dir->errnum = QSE_DIR_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
qse_wcstombs (wcs, &wl, QSE_MBS_PTR(mbuf), &ml);
|
||||
return QSE_MBS_PTR(mbuf);
|
||||
}
|
||||
|
||||
static qse_wchar_t* mbs_to_wbuf (qse_dir_t* dir, const qse_mchar_t* mbs, qse_wcs_t* wbuf)
|
||||
{
|
||||
qse_size_t ml, wl;
|
||||
|
||||
if (qse_mbstowcs (mbs, &ml, QSE_NULL, &wl) <= -1)
|
||||
{
|
||||
dir->errnum = QSE_DIR_EINVAL;
|
||||
return QSE_NULL;
|
||||
}
|
||||
if (qse_wcs_setlen (wbuf, wl) == (qse_size_t)-1)
|
||||
{
|
||||
dir->errnum = QSE_DIR_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
qse_mbstowcs (mbs, &ml, QSE_WCS_PTR(wbuf), &wl);
|
||||
return QSE_WCS_PTR(wbuf);
|
||||
}
|
||||
|
||||
static qse_wchar_t* wcs_to_wbuf (qse_dir_t* dir, const qse_wchar_t* wcs, qse_wcs_t* wbuf)
|
||||
{
|
||||
if (qse_wcs_cpy (&dir->wbuf, wcs) == (qse_size_t)-1)
|
||||
{
|
||||
dir->errnum = QSE_DIR_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
return QSE_WCS_PTR(wbuf);
|
||||
}
|
||||
|
||||
static qse_mchar_t* mbs_to_mbuf (qse_dir_t* dir, const qse_mchar_t* mbs, qse_mbs_t* mbuf)
|
||||
{
|
||||
if (qse_mbs_cpy (&dir->mbuf, mbs) == (qse_size_t)-1)
|
||||
{
|
||||
dir->errnum = QSE_DIR_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
return QSE_MBS_PTR(mbuf);
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||
static qse_mchar_t* make_mbsdos_path (qse_dir_t* dir, const qse_mchar_t* mpath)
|
||||
{
|
||||
if (mpath[0] == QSE_MT('\0'))
|
||||
{
|
||||
if (qse_mbs_cpy (&dir->mbuf, QSE_MT("*.*")) == (qse_size_t)-1)
|
||||
{
|
||||
dir->errnum = QSE_DIR_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_size_t len;
|
||||
if ((len = qse_mbs_cpy (&dir->mbuf, mpath)) == (qse_size_t)-1 ||
|
||||
(!QSE_ISPATHMBSEP(mpath[len - 1]) &&
|
||||
!qse_ismbsdrivecurpath(mpath) &&
|
||||
qse_mbs_ccat (&dir->mbuf, QSE_MT('\\')) == (qse_size_t)-1) ||
|
||||
qse_mbs_cat (&dir->mbuf, QSE_MT("*.*")) == (qse_size_t)-1)
|
||||
{
|
||||
dir->errnum = QSE_DIR_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return QSE_MBS_PTR(&dir->mbuf);
|
||||
}
|
||||
|
||||
static qse_wchar_t* make_wcsdos_path (qse_dir_t* dir, const qse_wchar_t* wpath)
|
||||
{
|
||||
if (wpath[0] == QSE_WT('\0'))
|
||||
{
|
||||
if (qse_wcs_cpy (&dir->wbuf, QSE_WT("*.*")) == (qse_size_t)-1)
|
||||
{
|
||||
dir->errnum = QSE_DIR_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_size_t len;
|
||||
if ((len = qse_wcs_cpy (&dir->wbuf, wpath)) == (qse_size_t)-1 ||
|
||||
(!QSE_ISPATHWCSEP(wpath[len - 1]) &&
|
||||
!qse_iswcsdrivecurpath(wpath) &&
|
||||
qse_wcs_ccat (&dir->wbuf, QSE_WT('\\')) == (qse_size_t)-1) ||
|
||||
qse_wcs_cat (&dir->wbuf, QSE_WT("*.*")) == (qse_size_t)-1)
|
||||
{
|
||||
dir->errnum = QSE_DIR_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return QSE_WCS_PTR(&dir->wbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
static qse_char_t* make_dos_path (qse_dir_t* dir, const qse_char_t* path)
|
||||
{
|
||||
if (path[0] == QSE_T('\0'))
|
||||
{
|
||||
if (qse_str_cpy (&dir->tbuf, QSE_T("*.*")) == (qse_size_t)-1)
|
||||
{
|
||||
dir->errnum = QSE_DIR_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_size_t len;
|
||||
if ((len = qse_str_cpy (&dir->tbuf, path)) == (qse_size_t)-1 ||
|
||||
(!QSE_ISPATHSEP(path[len - 1]) &&
|
||||
!qse_isdrivecurpath(path) &&
|
||||
qse_str_ccat (&dir->tbuf, QSE_T('\\')) == (qse_size_t)-1) ||
|
||||
qse_str_cat (&dir->tbuf, QSE_T("*.*")) == (qse_size_t)-1)
|
||||
{
|
||||
dir->errnum = QSE_DIR_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return QSE_STR_PTR(&dir->tbuf);
|
||||
}
|
||||
|
||||
static qse_mchar_t* mkdospath (qse_dir_t* dir, const qse_char_t* path)
|
||||
{
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
return make_dos_path (dir, path);
|
||||
#else
|
||||
if (dir->flags & QSE_DIR_MBSPATH)
|
||||
{
|
||||
return make_mbsdos_path (dir, (const qse_mchar_t*) path);
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_char_t* tptr;
|
||||
qse_mchar_t* mptr;
|
||||
|
||||
tptr = make_dos_path (dir, path);
|
||||
if (tptr == QSE_NULL) return QSE_NULL;
|
||||
|
||||
mptr = wcs_to_mbuf (dir, QSE_STR_PTR(&dir->tbuf), &dir->mbuf);
|
||||
if (mptr == QSE_NULL) return QSE_NULL;
|
||||
|
||||
return mptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
static int reset_to_path (qse_dir_t* dir, const qse_char_t* path)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
/* ------------------------------------------------------------------- */
|
||||
const qse_char_t* tptr;
|
||||
|
||||
dir->status &= ~STATUS_DONE;
|
||||
dir->status &= ~STATUS_DONE_ERR;
|
||||
|
||||
if (dir->flags & QSE_DIR_MBSPATH)
|
||||
{
|
||||
qse_mchar_t* mptr;
|
||||
|
||||
mptr = make_mbsdos_path (dir, (const qse_mchar_t*)path);
|
||||
if (mptr == QSE_NULL) return -1;
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
tptr = mptr;
|
||||
#else
|
||||
tptr = mbs_to_wbuf (dir, mptr, &dir->wbuf);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_wchar_t* wptr;
|
||||
QSE_ASSERT (dir->flags & QSE_DIR_WCSPATH);
|
||||
|
||||
wptr = make_wcsdos_path (dir, (const qse_wchar_t*)path);
|
||||
if (wptr == QSE_NULL) return -1;
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
tptr = wcs_to_mbuf (dir, wptr, &dir->mbuf);
|
||||
#else
|
||||
tptr = wptr;
|
||||
#endif
|
||||
}
|
||||
if (tptr == QSE_NULL) return -1;
|
||||
|
||||
dir->h = FindFirstFile (tptr, &dir->wfd);
|
||||
if (dir->h == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
dir->errnum = syserr_to_errnum (GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
#elif defined(__OS2__)
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
APIRET rc;
|
||||
const qse_mchar_t* mptr;
|
||||
|
||||
dir->h = HDIR_CREATE;
|
||||
dir->count = 1;
|
||||
|
||||
if (dir->flags & QSE_DIR_MBSPATH)
|
||||
{
|
||||
mptr = make_mbsdos_path (dir, (const qse_mchar_t*)path);
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_wchar_t* wptr;
|
||||
QSE_ASSERT (dir->flags & QSE_DIR_WCSPATH);
|
||||
|
||||
wptr = make_wcsdos_path (dir, (const qse_wchar_t*)path);
|
||||
if (wptr == QSE_NULL) return -1;
|
||||
mptr = wcs_to_mbuf (dir, wptr, &dir->mbuf);
|
||||
}
|
||||
if (mptr == QSE_NULL) return -1;
|
||||
|
||||
rc = DosFindFirst (
|
||||
mptr,
|
||||
&dir->h,
|
||||
FILE_DIRECTORY | FILE_READONLY,
|
||||
&dir->ffb,
|
||||
QSE_SIZEOF(dir->ffb),
|
||||
&dir->count,
|
||||
#if defined(FIL_STANDARDL)
|
||||
FIL_STANDARDL
|
||||
#else
|
||||
FIL_STANDARD
|
||||
#endif
|
||||
);
|
||||
|
||||
if (rc != NO_ERROR)
|
||||
{
|
||||
dir->errnum = syserr_to_errnum (rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir->status |= STATUS_OPENED;
|
||||
return 0;
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
#elif defined(__DOS__)
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
unsigned int rc;
|
||||
const qse_mchar_t* mptr;
|
||||
|
||||
dir->status &= ~STATUS_DONE;
|
||||
dir->status &= ~STATUS_DONE_ERR;
|
||||
|
||||
if (dir->flags & QSE_DIR_MBSPATH)
|
||||
{
|
||||
mptr = make_mbsdos_path (dir, (const qse_mchar_t*)path);
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_wchar_t* wptr;
|
||||
|
||||
QSE_ASSERT (dir->flags & QSE_DIR_WCSPATH);
|
||||
|
||||
wptr = make_wcsdos_path (dir, (const qse_wchar_t*)path);
|
||||
if (wptr == QSE_NULL) return -1;
|
||||
mptr = wcs_to_mbuf (dir, wptr, &dir->mbuf);
|
||||
}
|
||||
if (mptr == QSE_NULL) return -1;
|
||||
|
||||
rc = _dos_findfirst (mptr, _A_NORMAL | _A_SUBDIR, &dir->f);
|
||||
if (rc != 0)
|
||||
{
|
||||
dir->errnum = syserr_to_errnum (errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir->status |= STATUS_OPENED;
|
||||
return 0;
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
#else
|
||||
DIR* dp;
|
||||
|
||||
if (dir->flags & QSE_DIR_MBSPATH)
|
||||
{
|
||||
const qse_mchar_t* mpath;
|
||||
|
||||
mpath = (const qse_mchar_t*)path;
|
||||
dp = QSE_OPENDIR (mpath == QSE_MT('\0')? QSE_MT("."): mpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
const qse_wchar_t* wpath;
|
||||
QSE_ASSERT (dir->flags & QSE_DIR_WCSPATH);
|
||||
|
||||
wpath = (const qse_wchar_t*)path;
|
||||
if (wpath[0] == QSE_WT('\0'))
|
||||
{
|
||||
dp = QSE_OPENDIR (QSE_MT("."));
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_mchar_t* mptr;
|
||||
|
||||
mptr = wcs_to_mbuf (dir, wpath, &dir->mbuf);
|
||||
if (mptr == QSE_NULL) return -1;
|
||||
|
||||
dp = QSE_OPENDIR (mptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (dp == QSE_NULL)
|
||||
{
|
||||
dir->errnum = syserr_to_errnum (errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dir->dp = dp;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int qse_dir_reset (qse_dir_t* dir, const qse_char_t* path)
|
||||
{
|
||||
close_dir_safely (dir);
|
||||
if (reset_to_path (dir, path) <= -1) return -1;
|
||||
|
||||
if (dir->flags & QSE_DIR_SORT)
|
||||
{
|
||||
qse_lda_clear (dir->stab);
|
||||
if (read_ahead_and_sort (dir, path) <= -1)
|
||||
{
|
||||
dir->status |= STATUS_SORT_ERR;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dir->status &= ~STATUS_SORT_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_dir_to_buf (qse_dir_t* dir, void** name)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
if (dir->status & STATUS_DONE) return (dir->status & STATUS_DONE_ERR)? -1: 0;
|
||||
|
||||
if (dir->flags & QSE_DIR_SKIPSPCDIR)
|
||||
{
|
||||
/* 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 (dir->flags & QSE_DIR_MBSPATH)
|
||||
{
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
if (mbs_to_mbuf (dir, dir->wfd.cFileName, &dir->mbuf) == QSE_NULL) return -1;
|
||||
#else
|
||||
if (wcs_to_mbuf (dir, dir->wfd.cFileName, &dir->mbuf) == QSE_NULL) return -1;
|
||||
#endif
|
||||
*name = QSE_MBS_PTR(&dir->mbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
QSE_ASSERT (dir->flags & QSE_DIR_WCSPATH);
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
if (mbs_to_wbuf (dir, dir->wfd.cFileName, &dir->wbuf) == QSE_NULL) return -1;
|
||||
#else
|
||||
if (wcs_to_wbuf (dir, dir->wfd.cFileName, &dir->wbuf) == QSE_NULL) return -1;
|
||||
#endif
|
||||
*name = QSE_WCS_PTR(&dir->wbuf);
|
||||
}
|
||||
|
||||
if (FindNextFile (dir->h, &dir->wfd) == FALSE)
|
||||
{
|
||||
DWORD x = GetLastError();
|
||||
if (x == ERROR_NO_MORE_FILES) dir->status |= STATUS_DONE;
|
||||
else
|
||||
{
|
||||
dir->errnum = syserr_to_errnum (x);
|
||||
dir->status |= STATUS_DONE;
|
||||
dir->status |= STATUS_DONE_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
#elif defined(__OS2__)
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
APIRET rc;
|
||||
|
||||
if (dir->count <= 0) return 0;
|
||||
|
||||
if (dir->flags & QSE_DIR_SKIPSPCDIR)
|
||||
{
|
||||
/* 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 (dir->flags & QSE_DIR_MBSPATH)
|
||||
{
|
||||
if (mbs_to_mbuf (dir, dir->ffb.achName, &dir->mbuf) == QSE_NULL) return -1;
|
||||
*name = QSE_MBS_PTR(&dir->mbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
QSE_ASSERT (dir->flags & QSE_DIR_WCSPATH);
|
||||
if (mbs_to_wbuf (dir, dir->ffb.achName, &dir->wbuf) == QSE_NULL) return -1;
|
||||
*name = QSE_WCS_PTR(&dir->wbuf);
|
||||
}
|
||||
|
||||
|
||||
rc = DosFindNext (dir->h, &dir->ffb, QSE_SIZEOF(dir->ffb), &dir->count);
|
||||
if (rc == ERROR_NO_MORE_FILES) dir->count = 0;
|
||||
else if (rc != NO_ERROR)
|
||||
{
|
||||
dir->errnum = syserr_to_errnum (rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
#elif defined(__DOS__)
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
if (dir->status & STATUS_DONE) return (dir->status & STATUS_DONE_ERR)? -1: 0;
|
||||
|
||||
if (dir->flags & QSE_DIR_SKIPSPCDIR)
|
||||
{
|
||||
/* 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 (dir->flags & QSE_DIR_MBSPATH)
|
||||
{
|
||||
if (mbs_to_mbuf (dir, dir->f.name, &dir->mbuf) == QSE_NULL) return -1;
|
||||
*name = QSE_MBS_PTR(&dir->mbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
QSE_ASSERT (dir->flags & QSE_DIR_WCSPATH);
|
||||
|
||||
if (mbs_to_wbuf (dir, dir->f.name, &dir->wbuf) == QSE_NULL) return -1;
|
||||
*name = QSE_WCS_PTR(&dir->wbuf);
|
||||
}
|
||||
|
||||
if (_dos_findnext (&dir->f) != 0)
|
||||
{
|
||||
if (errno == ENOENT) dir->status |= STATUS_DONE;
|
||||
else
|
||||
{
|
||||
dir->errnum = syserr_to_errnum (errno);
|
||||
dir->status |= STATUS_DONE;
|
||||
dir->status |= STATUS_DONE_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
#else
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
qse_dirent_t* de;
|
||||
|
||||
read:
|
||||
errno = 0;
|
||||
de = QSE_READDIR (dir->dp);
|
||||
if (de == NULL)
|
||||
{
|
||||
if (errno == 0) return 0;
|
||||
dir->errnum = syserr_to_errnum (errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dir->flags & QSE_DIR_SKIPSPCDIR)
|
||||
{
|
||||
/* skip . and .. */
|
||||
if (IS_CURDIR_M(de->d_name) ||
|
||||
IS_PREVDIR_M(de->d_name)) goto read;
|
||||
}
|
||||
|
||||
if (dir->flags & QSE_DIR_MBSPATH)
|
||||
{
|
||||
if (mbs_to_mbuf (dir, de->d_name, &dir->mbuf) == QSE_NULL) return -1;
|
||||
*name = QSE_MBS_PTR(&dir->mbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
QSE_ASSERT (dir->flags & QSE_DIR_WCSPATH);
|
||||
|
||||
if (mbs_to_wbuf (dir, de->d_name, &dir->wbuf) == QSE_NULL) return -1;
|
||||
*name = QSE_WCS_PTR(&dir->wbuf);
|
||||
}
|
||||
|
||||
return 1;
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static int read_ahead_and_sort (qse_dir_t* dir, const qse_char_t* path)
|
||||
{
|
||||
int x;
|
||||
void* name;
|
||||
|
||||
while (1)
|
||||
{
|
||||
x = read_dir_to_buf (dir, &name);
|
||||
if (x >= 1)
|
||||
{
|
||||
qse_size_t size;
|
||||
|
||||
if (dir->flags & QSE_DIR_MBSPATH)
|
||||
size = (qse_mbslen(name) + 1) * QSE_SIZEOF(qse_mchar_t);
|
||||
else
|
||||
size = (qse_wcslen(name) + 1) * QSE_SIZEOF(qse_wchar_t);
|
||||
|
||||
if (qse_lda_pushheap (dir->stab, name, size) == (qse_size_t)-1)
|
||||
{
|
||||
dir->errnum = QSE_DIR_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (x == 0) break;
|
||||
else return -1;
|
||||
}
|
||||
|
||||
dir->status &= ~STATUS_POPHEAP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int qse_dir_read (qse_dir_t* dir, qse_dir_ent_t* ent)
|
||||
{
|
||||
if (dir->flags & QSE_DIR_SORT)
|
||||
{
|
||||
if (dir->status & STATUS_SORT_ERR) return -1;
|
||||
|
||||
if (dir->status & STATUS_POPHEAP) qse_lda_popheap (dir->stab);
|
||||
else dir->status |= STATUS_POPHEAP;
|
||||
|
||||
if (QSE_LDA_SIZE(dir->stab) <= 0) return 0; /* no more entry */
|
||||
|
||||
ent->name = QSE_LDA_DPTR(dir->stab, 0);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int x;
|
||||
void* name;
|
||||
|
||||
x = read_dir_to_buf (dir, &name);
|
||||
if (x >= 1)
|
||||
{
|
||||
QSE_MEMSET (ent, 0, QSE_SIZEOF(ent));
|
||||
ent->name = name;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/dll.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#define TOB(dll,len) ((len)*(dll)->scale)
|
||||
#define DPTR(node) QSE_DLL_DPTR(node)
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include <qse/cmn/env.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/fma.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
qse_fma_t* qse_fma_open (
|
||||
qse_mmgr_t* mmgr, qse_size_t xtnsize,
|
||||
|
@ -29,8 +29,8 @@
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include <stdarg.h>
|
||||
#include "mem.h"
|
||||
#include "fmt.h"
|
||||
#include "mem-prv.h"
|
||||
#include "fmt-prv.h"
|
||||
|
||||
#include <stdio.h> /* for snrintf(). used for floating-point number formatting */
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__) || (defined(__WATCOMC__) && (__WATCOMC__ < 1200))
|
||||
|
@ -24,8 +24,8 @@
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _QSE_LIB_CMN_FMT_H_
|
||||
#define _QSE_LIB_CMN_FMT_H_
|
||||
#ifndef _QSE_LIB_CMN_FMT_PRV_H_
|
||||
#define _QSE_LIB_CMN_FMT_PRV_H_
|
||||
|
||||
#include <qse/cmn/fmt.h>
|
||||
#include <stdarg.h>
|
@ -1,134 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "fs.h"
|
||||
#include "mem.h"
|
||||
|
||||
int qse_fs_sysgetattr (qse_fs_t* fs, const qse_fs_char_t* fspath, qse_fs_attr_t* attr)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
|
||||
fs->errnum = QSE_FS_ENOIMPL;
|
||||
return -1;
|
||||
|
||||
#elif defined(__OS2__)
|
||||
|
||||
/* TODO */
|
||||
fs->errnum = QSE_FS_ENOIMPL;
|
||||
return -1;
|
||||
|
||||
#elif defined(__DOS__)
|
||||
|
||||
fs->errnum = QSE_FS_ENOIMPL;
|
||||
return -1;
|
||||
|
||||
#else
|
||||
#if defined(HAVE_LSTAT)
|
||||
qse_lstat_t st;
|
||||
#else
|
||||
qse_stat_t st;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LSTAT)
|
||||
if (QSE_LSTAT (fspath, &st) == -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
/* is this ok to use stat? */
|
||||
if (QSE_STAT (fspath, &st) == -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
QSE_MEMSET (attr, 0, QSE_SIZEOF(*attr));
|
||||
|
||||
if (S_ISDIR(st.st_mode)) attr->isdir = 1;
|
||||
if (S_ISLNK(st.st_mode)) attr->islnk = 1;
|
||||
if (S_ISREG(st.st_mode)) attr->isreg = 1;
|
||||
if (S_ISBLK(st.st_mode)) attr->isblk = 1;
|
||||
if (S_ISCHR(st.st_mode)) attr->ischr = 1;
|
||||
|
||||
attr->mode = st.st_mode;
|
||||
attr->size = st.st_size;
|
||||
attr->ino = st.st_ino;
|
||||
attr->dev = st.st_dev;
|
||||
attr->uid = st.st_uid;
|
||||
attr->gid = st.st_gid;
|
||||
|
||||
#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
|
||||
attr->atime.sec = st.st_atim.tv_sec;
|
||||
attr->atime.nsec = st.st_atim.tv_nsec;
|
||||
attr->mtime.sec = st.st_mtim.tv_sec;
|
||||
attr->mtime.nsec = st.st_mtim.tv_nsec;
|
||||
attr->ctime.sec = st.st_ctim.tv_sec;
|
||||
attr->ctime.nsec = st.st_ctim.tv_nsec;
|
||||
#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
|
||||
attr->atime.sec = st.st_atimespec.tv_sec;
|
||||
attr->atime.nsec = st.st_atimespec.tv_nsec;
|
||||
attr->mtime.sec = st.st_mtimespec.tv_sec;
|
||||
attr->mtime.nsec = st.st_mtimespec.tv_nsec;
|
||||
attr->ctime.sec = st.st_ctimespec.tv_sec;
|
||||
attr->ctime.nsec = st.st_ctimespec.tv_nsec;
|
||||
#else
|
||||
attr->atime.sec = st.st_atime;
|
||||
attr->mtime.sec = st.st_mtime;
|
||||
attr->ctime.sec = st.st_ctime;
|
||||
#endif
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int qse_fs_getattrmbs (qse_fs_t* fs, const qse_mchar_t* path, qse_fs_attr_t* attr)
|
||||
{
|
||||
qse_fs_char_t* fspath;
|
||||
int ret;
|
||||
|
||||
fspath = qse_fs_makefspathformbs (fs, path);
|
||||
if (!fspath) return -1;
|
||||
|
||||
ret = qse_fs_sysgetattr (fs, fspath, attr);
|
||||
|
||||
qse_fs_freefspathformbs (fs, path, fspath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qse_fs_getattrwcs (qse_fs_t* fs, const qse_wchar_t* path, qse_fs_attr_t* attr)
|
||||
{
|
||||
qse_fs_char_t* fspath;
|
||||
int ret;
|
||||
|
||||
fspath = qse_fs_makefspathforwcs (fs, path);
|
||||
if (!fspath) return -1;
|
||||
|
||||
ret = qse_fs_sysgetattr (fs, fspath, attr);
|
||||
|
||||
qse_fs_freefspathforwcs (fs, path, fspath);
|
||||
return ret;
|
||||
}
|
@ -1,636 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "fs.h"
|
||||
#include <qse/cmn/path.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include "mem.h"
|
||||
|
||||
#define NO_RECURSION 1
|
||||
|
||||
/* internal flags. it must not overlap with qse_fs_cpfile_flag_t enumerators */
|
||||
#define CPFILE_DST_ATTR (1 << 29)
|
||||
#define CPFILE_DST_FSPATH_MERGED (1 << 30)
|
||||
|
||||
struct cpfile_t
|
||||
{
|
||||
int flags;
|
||||
|
||||
qse_fs_char_t* src_fspath;
|
||||
qse_fs_char_t* dst_fspath;
|
||||
|
||||
qse_fs_attr_t src_attr;
|
||||
qse_fs_attr_t dst_attr;
|
||||
};
|
||||
typedef struct cpfile_t cpfile_t;
|
||||
|
||||
|
||||
static int merge_dstdir_and_file (qse_fs_t* fs, cpfile_t* cpfile)
|
||||
{
|
||||
qse_fs_char_t* fstmp;
|
||||
|
||||
/* if the destination is directory, copy the base name of the source
|
||||
* and append it to the end of the destination, targetting at an entry
|
||||
* in the directory */
|
||||
QSE_ASSERT (cpfile->dst_attr.isdir);
|
||||
|
||||
fstmp = merge_fspath_dup (cpfile->dst_fspath, get_fspath_base (cpfile->src_fspath), fs->mmgr);
|
||||
if (!fstmp)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
qse_fs_freefspath (fs, QSE_NULL, cpfile->dst_fspath);
|
||||
cpfile->dst_fspath = fstmp;
|
||||
|
||||
if (qse_fs_sysgetattr (fs, cpfile->dst_fspath, &cpfile->dst_attr) <= -1)
|
||||
{
|
||||
/* attribute on the new destination is not available */
|
||||
cpfile->flags &= ~CPFILE_DST_ATTR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the attribute has been updated to reflect the new destination */
|
||||
cpfile->flags |= CPFILE_DST_ATTR;
|
||||
}
|
||||
|
||||
cpfile->flags |= CPFILE_DST_FSPATH_MERGED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
#if defined(_WIN32)
|
||||
DWORD copy_file_progress (
|
||||
LARGE_INTEGER TotalFileSize,
|
||||
LARGE_INTEGER TotalBytesTransferred,
|
||||
LARGE_INTEGER StreamSize,
|
||||
LARGE_INTEGER StreamBytesTransferred,
|
||||
DWORD dwStreamNumber,
|
||||
DWORD dwCallbackReason,
|
||||
HANDLE hSourceFile,
|
||||
HANDLE hDestinationFile,
|
||||
LPVOID lpData)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* copy
|
||||
* -> progress
|
||||
* -> abort/cancel
|
||||
* -> replace/overwrite
|
||||
* -> symbolic link
|
||||
*/
|
||||
|
||||
#if defined(_WIN32) && !defined(COPY_FILE_COPY_SYMLINK)
|
||||
/* winbase.h defines this only if _WIN32_WINNT >= 0x0600 */
|
||||
# define COPY_FILE_COPY_SYMLINK 0x00000800L
|
||||
#endif
|
||||
|
||||
static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
/* ------------------------------------------------------ */
|
||||
DWORD copy_flags = 0;
|
||||
|
||||
if (cpfile->flags & QSE_FS_CPFILE_SYMLINK)
|
||||
copy_flags |= COPY_FILE_COPY_SYMLINK;
|
||||
if (!(cpfile->flags & QSE_FS_CPFILE_REPLACE))
|
||||
copy_flags |= COPY_FILE_FAIL_IF_EXISTS;
|
||||
|
||||
/*
|
||||
if (fs->cbs.cp)
|
||||
{
|
||||
Specify callback???
|
||||
}
|
||||
*/
|
||||
|
||||
if (CopyFileEx (cpfile->src_fspath, cpfile->dst_fspath, QSE_NULL, QSE_NULL, QSE_NULL, copy_flags) == FALSE)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
#elif defined(__OS2__)
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
APIRET rc;
|
||||
ULONG opmode = 0;
|
||||
|
||||
if (cpfile->flags & QSE_FS_CPFILE_REPLACE) opmode |= 1; /* set bit 0 */
|
||||
|
||||
rc = DosCopy (cpfile->src_fspath, cpfile->dst_fspath, opmode);
|
||||
if (rc != NO_ERROR)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
#elif defined(__DOS__)
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
/* TOOD: IMPLEMENT THIS */
|
||||
fs->errnum = QSE_FS_ENOIMPL;
|
||||
return -1;
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
#else
|
||||
if ((cpfile->flags & QSE_FS_CPFILE_SYMLINK) && cpfile->src_attr.islnk)
|
||||
{
|
||||
qse_fs_char_t* tmpbuf;
|
||||
|
||||
/* TODO: use a static buffer is size is small enough */
|
||||
tmpbuf = QSE_MMGR_ALLOC (fs->mmgr, QSE_SIZEOF(*tmpbuf) * (cpfile->src_attr.size + 1));
|
||||
if (tmpbuf == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (QSE_READLINK (cpfile->src_fspath, tmpbuf, cpfile->src_attr.size) <= -1 ||
|
||||
QSE_SYMLINK (tmpbuf, cpfile->dst_fspath) <= -1)
|
||||
{
|
||||
QSE_MMGR_FREE (fs->mmgr, tmpbuf);
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
QSE_MMGR_FREE (fs->mmgr, tmpbuf);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int in = -1, out = -1;
|
||||
qse_ssize_t in_len, out_len;
|
||||
qse_uint8_t* bp;
|
||||
|
||||
in = QSE_OPEN (cpfile->src_fspath, O_RDONLY, 0);
|
||||
if (in <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
out = QSE_OPEN (cpfile->dst_fspath, O_CREAT | O_WRONLY | O_TRUNC, cpfile->src_attr.mode);
|
||||
if (out <= -1 && (cpfile->flags & QSE_FS_CPFILE_FORCE))
|
||||
{
|
||||
/* if forced, delete it and try to open it again */
|
||||
QSE_UNLINK (cpfile->dst_fspath);
|
||||
out = QSE_OPEN (cpfile->dst_fspath, O_CREAT | O_WRONLY | O_TRUNC, cpfile->src_attr.mode);
|
||||
}
|
||||
if (out <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
in_len = QSE_READ (in, fs->cpbuf, QSE_SIZEOF(fs->cpbuf));
|
||||
if (in_len <= 0) break;
|
||||
|
||||
/* TODO: call progress callback */
|
||||
|
||||
bp = fs->cpbuf;
|
||||
while (in_len > 0)
|
||||
{
|
||||
out_len = QSE_WRITE (out, bp, in_len);
|
||||
if (out_len <= -1) goto oops;
|
||||
bp += out_len;
|
||||
in_len -= out_len;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpfile->flags & QSE_FS_CPFILE_PRESERVE)
|
||||
{
|
||||
#if defined(HAVE_FUTIMENS) && defined(HAVE_STRUCT_TIMESPEC)
|
||||
struct timespec ts[2];
|
||||
#elif defined(HAVE_FUTIMES)
|
||||
struct timeval tv[2];
|
||||
#elif defined(HAVE_UTIME)
|
||||
struct utimbuf ub;
|
||||
#elif defined(HAVE_UTIMES)
|
||||
struct timeval tv[2];
|
||||
#endif
|
||||
|
||||
if (QSE_FCHOWN (out, cpfile->src_attr.uid, cpfile->src_attr.gid) <= -1 ||
|
||||
QSE_FCHMOD (out, cpfile->src_attr.mode) <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
#if defined(HAVE_FUTIMENS) && defined(HAVE_STRUCT_TIMESPEC)
|
||||
|
||||
QSE_MEMSET (&ts, 0, QSE_SIZEOF(ts));
|
||||
ts[0].tv_sec = cpfile->src_attr.atime.sec;
|
||||
ts[0].tv_nsec = cpfile->src_attr.atime.nsec;
|
||||
ts[1].tv_sec = cpfile->src_attr.mtime.sec;
|
||||
ts[1].tv_nsec = cpfile->src_attr.mtime.nsec;
|
||||
if (QSE_FUTIMENS (out, ts) <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_FUTIMES)
|
||||
|
||||
QSE_MEMSET (&tv, 0, QSE_SIZEOF(tv));
|
||||
tv[0].tv_sec = cpfile->src_attr.atime.sec;
|
||||
tv[0].tv_usec = QSE_NSEC_TO_USEC(cpfile->src_attr.atime.nsec);
|
||||
tv[1].tv_sec = cpfile->src_attr.mtime.sec;
|
||||
tv[1].tv_usec = QSE_NSEC_TO_USEC(cpfile->src_attr.mtime.nsec);
|
||||
if (QSE_FUTIMES (out, tv) <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_UTIME)
|
||||
|
||||
QSE_MEMSET (&ub, 0, QSE_SIZEOF(ub));
|
||||
ub.actime = cpfile->src_attr.atime.sec;
|
||||
ub.modtime = cpfile->src_attr.mtime.sec;
|
||||
if (QSE_UTIME (cpfile->dst_fspath, &ub) <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_UTIMES)
|
||||
|
||||
QSE_MEMSET (&tv, 0, QSE_SIZEOF(tv));
|
||||
tv[0].tv_sec = cpfile->src_attr.atime.sec;
|
||||
tv[0].tv_usec = QSE_NSEC_TO_USEC(cpfile->src_attr.atime.nsec);
|
||||
tv[1].tv_sec = cpfile->src_attr.mtime.sec;
|
||||
tv[1].tv_usec = QSE_NSEC_TO_USEC(cpfile->src_attr.mtime.nsec);
|
||||
// work on the file name not on the file descriptor.
|
||||
if (QSE_UTIMES (cpfile->dst_fspath, tv) <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
#else
|
||||
# error none of futimens, futimes, utime, utimes exist
|
||||
#endif
|
||||
}
|
||||
|
||||
QSE_CLOSE (out);
|
||||
QSE_CLOSE (in);
|
||||
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
if (out >= 0) QSE_CLOSE (out);
|
||||
if (in >= 0) QSE_CLOSE (in);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int prepare_cpfile (qse_fs_t* fs, cpfile_t* cpfile)
|
||||
{
|
||||
/* error if the source file can't be stat'ed.
|
||||
* ok if the destination file can't be stat'ed */
|
||||
if (qse_fs_sysgetattr (fs, cpfile->src_fspath, &cpfile->src_attr) <= -1) return -1;
|
||||
if (qse_fs_sysgetattr (fs, cpfile->dst_fspath, &cpfile->dst_attr) >= 0) cpfile->flags |= CPFILE_DST_ATTR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void clear_cpfile (qse_fs_t* fs, cpfile_t* cpfile)
|
||||
{
|
||||
if (cpfile->src_fspath)
|
||||
{
|
||||
QSE_MMGR_FREE (fs->mmgr, cpfile->src_fspath);
|
||||
cpfile->src_fspath = QSE_NULL;
|
||||
}
|
||||
if (cpfile->dst_fspath)
|
||||
{
|
||||
QSE_MMGR_FREE (fs->mmgr, cpfile->dst_fspath);
|
||||
cpfile->dst_fspath = QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* copy file stack - stack for file copying */
|
||||
typedef struct cfs_t cfs_t;
|
||||
struct cfs_t
|
||||
{
|
||||
cpfile_t cpfile;
|
||||
qse_dir_t* dir;
|
||||
cfs_t* next;
|
||||
};
|
||||
|
||||
static cfs_t* push_cfs (qse_fs_t* fs, const cpfile_t* cpfile, qse_dir_t* dir)
|
||||
{
|
||||
cfs_t* cfs;
|
||||
|
||||
cfs = (cfs_t*)QSE_MMGR_ALLOC (fs->mmgr, QSE_SIZEOF(*cfs));
|
||||
if (cfs == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
cfs->cpfile = *cpfile;
|
||||
cfs->dir = dir;
|
||||
cfs->next = fs->cfs;
|
||||
|
||||
fs->cfs = cfs;
|
||||
return cfs;
|
||||
}
|
||||
|
||||
static void pop_cfs (qse_fs_t* fs, cpfile_t* cpfile, qse_dir_t** dir)
|
||||
{
|
||||
cfs_t* cfs;
|
||||
|
||||
cfs = fs->cfs;
|
||||
QSE_ASSERT (cfs != QSE_NULL);
|
||||
fs->cfs = cfs->next;
|
||||
|
||||
if (cpfile) *cpfile = cfs->cpfile;
|
||||
else clear_cpfile (fs, &cfs->cpfile);
|
||||
|
||||
if (dir) *dir = cfs->dir;
|
||||
else qse_dir_close (cfs->dir);
|
||||
|
||||
QSE_MMGR_FREE (fs->mmgr, cfs);
|
||||
}
|
||||
|
||||
|
||||
static int copy_file (qse_fs_t* fs, cpfile_t* cpfile)
|
||||
{
|
||||
#if defined(NO_RECURSION)
|
||||
cfs_t* cfs;
|
||||
#else
|
||||
cpfile_t sub_cpfile;
|
||||
#endif
|
||||
qse_dir_t* dir;
|
||||
qse_dir_errnum_t direrr;
|
||||
qse_dir_ent_t dirent;
|
||||
int x;
|
||||
|
||||
start_over:
|
||||
if (cpfile->src_attr.isdir)
|
||||
{
|
||||
/* source is a directory */
|
||||
copy_dir:
|
||||
if (cpfile->flags & CPFILE_DST_ATTR)
|
||||
{
|
||||
if (!cpfile->dst_attr.isdir)
|
||||
{
|
||||
/* cannot copy a directory to a file */
|
||||
fs->errnum = QSE_FS_ENOTDIR;
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if (!(cpfile->flags & QSE_FS_CPFILE_NOTGTDIR) &&
|
||||
cpfile->dst_attr.isdir)
|
||||
{
|
||||
if (cpfile->flags & CPFILE_DST_FSPATH_MERGED)
|
||||
{
|
||||
/* merge_dstdir_and_file() has been called already.
|
||||
* no more getting into a subdirectory */
|
||||
fs->errnum = QSE_FS_EISDIR;
|
||||
goto oops;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* arrange to copy a file into a directory */
|
||||
if (merge_dstdir_and_file (fs, cpfile) <= -1) return -1;
|
||||
goto copy_dir;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (!(cpfile->flags & QSE_FS_CPFILE_REPLACE))
|
||||
{
|
||||
fs->errnum = QSE_FS_EEXIST;
|
||||
return -1;
|
||||
}*/
|
||||
}
|
||||
|
||||
if (!(cpfile->flags & QSE_FS_CPFILE_RECURSIVE))
|
||||
{
|
||||
/* cannot copy a directory without recursion */
|
||||
fs->errnum = QSE_FS_EISDIR;
|
||||
goto oops;
|
||||
}
|
||||
|
||||
dir = qse_dir_open (
|
||||
fs->mmgr, 0, (const qse_char_t*)cpfile->src_fspath,
|
||||
#if defined(QSE_FS_CHAR_IS_MCHAR)
|
||||
QSE_DIR_SKIPSPCDIR | QSE_DIR_MBSPATH,
|
||||
#else
|
||||
QSE_DIR_SKIPSPCDIR | QSE_DIR_WCSPATH,
|
||||
#endif
|
||||
&direrr
|
||||
);
|
||||
if (!dir)
|
||||
{
|
||||
fs->errnum = qse_fs_direrrtoerrnum (fs, direrr);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if (qse_fs_sysmkdir (fs, cpfile->dst_fspath) <= -1) goto oops;
|
||||
|
||||
while (1)
|
||||
{
|
||||
x = qse_dir_read (dir, &dirent);
|
||||
if (x <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_direrrtoerrnum (fs, qse_dir_geterrnum(dir));
|
||||
goto oops;
|
||||
}
|
||||
if (x == 0) break; /* no more entries */
|
||||
|
||||
#if defined(NO_RECURSION)
|
||||
cfs = push_cfs (fs, cpfile, dir);
|
||||
if (!cfs) goto oops;
|
||||
|
||||
QSE_MEMSET (cpfile, 0, QSE_SIZEOF(*cpfile));
|
||||
dir = QSE_NULL;
|
||||
|
||||
cpfile->flags = cfs->cpfile.flags & QSE_FS_CPFILE_ALL; /* inherit public flags */
|
||||
cpfile->src_fspath = merge_fspath_dup (cfs->cpfile.src_fspath, (qse_fs_char_t*)dirent.name, fs->mmgr);
|
||||
cpfile->dst_fspath = merge_fspath_dup (cfs->cpfile.dst_fspath, (qse_fs_char_t*)dirent.name, fs->mmgr);
|
||||
if (!cpfile->src_fspath || !cpfile->dst_fspath || prepare_cpfile (fs, cpfile) <= -1)
|
||||
{
|
||||
clear_cpfile (fs, cpfile);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
goto start_over;
|
||||
|
||||
resume_copy_dir:
|
||||
/* do nothing. loop over */
|
||||
;
|
||||
|
||||
#else
|
||||
QSE_MEMSET (&sub_cpfile, 0, QSE_SIZEOF(sub_cpfile));
|
||||
sub_cpfile.flags = cpfile->flags & QSE_FS_CPFILE_ALL; /* inherit public flags */
|
||||
sub_cpfile.src_fspath = merge_fspath_dup (cpfile->src_fspath, (qse_fs_char_t*)dirent.name, fs->mmgr);
|
||||
sub_cpfile.dst_fspath = merge_fspath_dup (cpfile->dst_fspath, (qse_fs_char_t*)dirent.name, fs->mmgr);
|
||||
if (!sub_cpfile.src_fspath || !sub_cpfile.dst_fspath || prepare_cpfile (fs, &sub_cpfile) <= -1)
|
||||
{
|
||||
clear_cpfile (fs, &sub_cpfile);
|
||||
qse_dir_close (dir);
|
||||
return -1;
|
||||
}
|
||||
x = copy_file (fs, &sub_cpfile); /* TODO: remove recursion */
|
||||
|
||||
clear_cpfile (fs, &sub_cpfile);
|
||||
if (x <= -1)
|
||||
{
|
||||
qse_dir_close (dir);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
qse_dir_close (dir);
|
||||
dir = QSE_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* source is a file */
|
||||
|
||||
copy_file:
|
||||
if (cpfile->flags & CPFILE_DST_ATTR)
|
||||
{
|
||||
if (cpfile->src_attr.ino == cpfile->dst_attr.ino &&
|
||||
cpfile->src_attr.dev == cpfile->dst_attr.dev)
|
||||
{
|
||||
/* cannot copy a file to itself */
|
||||
fs->errnum = QSE_FS_EINVAL; /* TODO: better error code */
|
||||
goto oops;
|
||||
}
|
||||
|
||||
if (!(cpfile->flags & QSE_FS_CPFILE_NOTGTDIR) &&
|
||||
cpfile->dst_attr.isdir)
|
||||
{
|
||||
if (cpfile->flags & CPFILE_DST_FSPATH_MERGED)
|
||||
{
|
||||
/* merge_dstdir_and_file() has been called already.
|
||||
* no more getting into a subdirectory */
|
||||
fs->errnum = QSE_FS_EISDIR;
|
||||
goto oops;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* arrange to copy a file into a directory */
|
||||
if (merge_dstdir_and_file (fs, cpfile) <= -1) return -1;
|
||||
goto copy_file;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(cpfile->flags & QSE_FS_CPFILE_REPLACE))
|
||||
{
|
||||
fs->errnum = QSE_FS_EEXIST;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* both source and target are files */
|
||||
if (copy_file_in_fs (fs, cpfile) <= -1) goto oops;
|
||||
}
|
||||
|
||||
#if defined(NO_RECURSION)
|
||||
if (fs->cfs)
|
||||
{
|
||||
clear_cpfile (fs, cpfile); /* clear key data created for subitems in the directory */
|
||||
pop_cfs (fs, cpfile, &dir); /* restore key data for the original directory*/
|
||||
goto resume_copy_dir;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
oops:
|
||||
#if defined(NO_RECURSION)
|
||||
while (fs->cfs) pop_cfs (fs, QSE_NULL, QSE_NULL);
|
||||
#endif
|
||||
if (dir) qse_dir_close (dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int qse_fs_cpfilembs (qse_fs_t* fs, const qse_mchar_t* srcpath, const qse_mchar_t* dstpath, int flags)
|
||||
{
|
||||
cpfile_t cpfile;
|
||||
int ret;
|
||||
|
||||
QSE_MEMSET (&cpfile, 0, QSE_SIZEOF(cpfile));
|
||||
|
||||
cpfile.flags = flags & QSE_FS_CPFILE_ALL; /* keep public flags only */
|
||||
|
||||
cpfile.src_fspath = (qse_fs_char_t*)qse_fs_dupfspathformbs (fs, srcpath);
|
||||
cpfile.dst_fspath = (qse_fs_char_t*)qse_fs_dupfspathformbs (fs, dstpath);
|
||||
if (!cpfile.src_fspath || !cpfile.dst_fspath || prepare_cpfile (fs, &cpfile) <= -1) goto oops;
|
||||
|
||||
ret = copy_file (fs, &cpfile);
|
||||
|
||||
clear_cpfile (fs, &cpfile);
|
||||
return ret;
|
||||
|
||||
oops:
|
||||
clear_cpfile (fs, &cpfile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int qse_fs_cpfilewcs (qse_fs_t* fs, const qse_wchar_t* srcpath, const qse_wchar_t* dstpath, int flags)
|
||||
{
|
||||
cpfile_t cpfile;
|
||||
int ret;
|
||||
|
||||
QSE_MEMSET (&cpfile, 0, QSE_SIZEOF(cpfile));
|
||||
|
||||
cpfile.flags = flags & QSE_FS_CPFILE_ALL; /* keep public flags only */
|
||||
|
||||
cpfile.src_fspath = (qse_fs_char_t*)qse_fs_dupfspathforwcs (fs, srcpath);
|
||||
cpfile.dst_fspath = (qse_fs_char_t*)qse_fs_dupfspathforwcs (fs, dstpath);
|
||||
if (!cpfile.src_fspath || !cpfile.dst_fspath || prepare_cpfile (fs, &cpfile) <= -1) goto oops;
|
||||
|
||||
ret = copy_file (fs, &cpfile);
|
||||
|
||||
clear_cpfile (fs, &cpfile);
|
||||
return ret;
|
||||
|
||||
oops:
|
||||
clear_cpfile (fs, &cpfile);
|
||||
return -1;
|
||||
}
|
@ -1,587 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "fs.h"
|
||||
|
||||
/* NOTE:
|
||||
* The current implementation require mbs/wcs conversion as
|
||||
* qse_dir_xxx() and qse_glob() don't support mbs and wcs separately.
|
||||
* while the functions here support them. */
|
||||
|
||||
int qse_fs_sysrmfile (qse_fs_t* fs, const qse_fs_char_t* fspath)
|
||||
{
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
if (DeleteFile (fspath) == FALSE)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
#elif defined(__OS2__)
|
||||
|
||||
APIRET rc;
|
||||
|
||||
rc = DosDelete (fspath);
|
||||
if (rc != NO_ERROR)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#elif defined(__DOS__)
|
||||
|
||||
if (unlink (fspath) <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (QSE_UNLINK (fspath) <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qse_fs_sysrmdir (qse_fs_t* fs, const qse_fs_char_t* fspath)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
|
||||
if (RemoveDirectory (fspath) == FALSE)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
#elif defined(__OS2__)
|
||||
|
||||
APIRET rc;
|
||||
|
||||
rc = DosRmDir (fspath);
|
||||
if (rc != NO_ERROR)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#elif defined(__DOS__)
|
||||
|
||||
if (rmdir (fspath) <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (QSE_RMDIR (fspath) <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static int purge_directory_contents (qse_fs_t* fs, const qse_char_t* path);
|
||||
static int purge_path (qse_fs_t* fs, const qse_char_t* path);
|
||||
static int delete_directory_nocbs (qse_fs_t* fs, const qse_char_t* path);
|
||||
|
||||
static int delete_file (qse_fs_t* fs, const qse_char_t* path, int purge)
|
||||
{
|
||||
qse_fs_char_t* fspath;
|
||||
int ret;
|
||||
|
||||
if (fs->cbs.del)
|
||||
{
|
||||
int x;
|
||||
x = fs->cbs.del (fs, path);
|
||||
if (x <= -1) return -1;
|
||||
if (x == 0) return 0; /* skipped */
|
||||
}
|
||||
|
||||
fspath = qse_fs_makefspath(fs, path);
|
||||
if (!fspath) return -1;
|
||||
|
||||
ret = qse_fs_sysrmfile (fs, fspath);
|
||||
qse_fs_freefspath (fs, path, fspath);
|
||||
|
||||
if (ret <= -1 && purge)
|
||||
{
|
||||
ret = purge_directory_contents (fs, path);
|
||||
if (ret == -99)
|
||||
{
|
||||
/* it has attempted to delete path as a file above.
|
||||
* i don't attempt to delete it as a file again here
|
||||
* unlike purge path. */
|
||||
ret = -1;
|
||||
}
|
||||
else if (ret <= -1)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* path is a directory name and contents have been purged.
|
||||
* call delete_directory_nocbs() instead of delete_directory()
|
||||
* to avoid double calls to cb.del(). it has been called for
|
||||
* 'path' * in this function above. */
|
||||
ret = delete_directory_nocbs (fs, path);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int delete_directory_nocbs (qse_fs_t* fs, const qse_char_t* path)
|
||||
{
|
||||
qse_fs_char_t* fspath;
|
||||
int ret;
|
||||
|
||||
fspath = qse_fs_makefspath(fs, path);
|
||||
if (!fspath) return -1;
|
||||
|
||||
ret = qse_fs_sysrmdir (fs, fspath);
|
||||
qse_fs_freefspath (fs, path, fspath);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int delete_directory (qse_fs_t* fs, const qse_char_t* path)
|
||||
{
|
||||
if (fs->cbs.del)
|
||||
{
|
||||
int x;
|
||||
x = fs->cbs.del (fs, path);
|
||||
if (x <= -1) return -1;
|
||||
if (x == 0) return 0; /* skipped */
|
||||
}
|
||||
|
||||
return delete_directory_nocbs (fs, path);
|
||||
}
|
||||
|
||||
static int purge_directory_contents (qse_fs_t* fs, const qse_char_t* path)
|
||||
{
|
||||
qse_dir_t* dir;
|
||||
qse_dir_errnum_t errnum;
|
||||
|
||||
/* 'dir' is asked to skip special entries like . and .. */
|
||||
dir = qse_dir_open (fs->mmgr, 0, path, QSE_DIR_SKIPSPCDIR, &errnum);
|
||||
if (dir)
|
||||
{
|
||||
/* it must be a directory. delete all entries under it */
|
||||
int ret, x;
|
||||
qse_dir_ent_t ent;
|
||||
const qse_char_t* seg[4];
|
||||
qse_char_t* joined_path;
|
||||
|
||||
while (1)
|
||||
{
|
||||
x = qse_dir_read (dir, &ent);
|
||||
if (x <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_direrrtoerrnum (fs, qse_dir_geterrnum(dir));
|
||||
goto oops;
|
||||
}
|
||||
if (x == 0) break; /* no more entries */
|
||||
|
||||
/* join path and ent->name.... */
|
||||
seg[0] = path;
|
||||
seg[1] = DEFAULT_PATH_SEPARATOR;
|
||||
seg[2] = ent.name;
|
||||
seg[3] = QSE_NULL;
|
||||
|
||||
joined_path = qse_stradup (seg, QSE_NULL, fs->mmgr);
|
||||
if (!joined_path)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
goto oops;
|
||||
}
|
||||
|
||||
ret = delete_file (fs, joined_path, 1);
|
||||
|
||||
QSE_MMGR_FREE (fs->mmgr, joined_path);
|
||||
if (ret <= -1) goto oops;
|
||||
}
|
||||
|
||||
qse_dir_close (dir);
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
qse_dir_close (dir);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fs->errnum = qse_fs_direrrtoerrnum (fs, errnum);
|
||||
return -99; /* special return code to indicate no directory */
|
||||
}
|
||||
|
||||
static int purge_path (qse_fs_t* fs, const qse_char_t* path)
|
||||
{
|
||||
int x;
|
||||
|
||||
x = purge_directory_contents (fs, path);
|
||||
if (x == -99)
|
||||
{
|
||||
/* purge_directory_contents() failed
|
||||
* because path is not a directory */
|
||||
return delete_file (fs, path, 0);
|
||||
}
|
||||
else if (x <= -1)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* path is a directory name and contents have been purged */
|
||||
return delete_directory (fs, path);
|
||||
}
|
||||
}
|
||||
|
||||
static int delete_from_fs_with_mbs (qse_fs_t* fs, const qse_mchar_t* path, int dir)
|
||||
{
|
||||
qse_fs_char_t* fspath;
|
||||
int ret;
|
||||
|
||||
fspath = qse_fs_makefspathformbs (fs, path);
|
||||
if (!fspath) return -1;
|
||||
|
||||
if (fs->cbs.del)
|
||||
{
|
||||
qse_char_t* xpath;
|
||||
int x;
|
||||
|
||||
xpath = (qse_char_t*)make_str_with_mbs (fs, path);
|
||||
if (!xpath)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
x = fs->cbs.del (fs, xpath);
|
||||
|
||||
free_str_with_mbs (fs, path, xpath);
|
||||
|
||||
if (x <= -1) return -1;
|
||||
if (x == 0) return 0; /* skipped */
|
||||
}
|
||||
|
||||
ret = dir? qse_fs_sysrmdir (fs, fspath):
|
||||
qse_fs_sysrmfile (fs, fspath);
|
||||
|
||||
qse_fs_freefspathformbs (fs, path, fspath);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int delete_from_fs_with_wcs (qse_fs_t* fs, const qse_wchar_t* path, int dir)
|
||||
{
|
||||
qse_fs_char_t* fspath;
|
||||
int ret;
|
||||
|
||||
if (fs->cbs.del)
|
||||
{
|
||||
qse_char_t* xpath;
|
||||
int x;
|
||||
|
||||
xpath = (qse_char_t*)make_str_with_wcs (fs, path);
|
||||
if (!xpath)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
x = fs->cbs.del (fs, xpath);
|
||||
|
||||
free_str_with_wcs (fs, path, xpath);
|
||||
|
||||
if (x <= -1) return -1;
|
||||
if (x == 0) return 0; /* skipped */
|
||||
}
|
||||
|
||||
fspath = qse_fs_makefspathforwcs (fs, path);
|
||||
if (!fspath) return -1;
|
||||
|
||||
ret = dir? qse_fs_sysrmdir (fs, fspath):
|
||||
qse_fs_sysrmfile (fs, fspath);
|
||||
|
||||
qse_fs_freefspathforwcs (fs, path, fspath);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static int delete_file_for_glob (const qse_cstr_t* path, void* ctx)
|
||||
{
|
||||
qse_fs_t* fs = (qse_fs_t*)ctx;
|
||||
return delete_file (fs, path->ptr, 0);
|
||||
}
|
||||
|
||||
static int delete_directory_for_glob (const qse_cstr_t* path, void* ctx)
|
||||
{
|
||||
qse_fs_t* fs = (qse_fs_t*)ctx;
|
||||
return delete_directory (fs, path->ptr);
|
||||
}
|
||||
|
||||
static int purge_path_for_glob (const qse_cstr_t* path, void* ctx)
|
||||
{
|
||||
qse_fs_t* fs = (qse_fs_t*)ctx;
|
||||
return purge_path (fs, path->ptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
int qse_fs_delfilembs (qse_fs_t* fs, const qse_mchar_t* path, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (flags & QSE_FS_DELFILEMBS_GLOB)
|
||||
{
|
||||
qse_char_t* xpath;
|
||||
|
||||
xpath = (qse_char_t*)make_str_with_mbs (fs, path);
|
||||
if (!xpath)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & QSE_FS_DELFILEMBS_RECURSIVE)
|
||||
{
|
||||
ret = qse_glob (xpath, purge_path_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr, fs->cmgr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = qse_glob (xpath, delete_file_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr, fs->cmgr);
|
||||
}
|
||||
|
||||
free_str_with_mbs (fs, path, xpath);
|
||||
|
||||
if (ret <= -1)
|
||||
{
|
||||
fs->errnum = QSE_FS_EGLOB;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (flags & QSE_FS_DELFILEMBS_RECURSIVE)
|
||||
{
|
||||
qse_char_t* xpath;
|
||||
|
||||
/* if RECURSIVE is set, it's not differnt from qse_fs_deldirmbs() */
|
||||
xpath = (qse_char_t*)make_str_with_mbs (fs, path);
|
||||
if (!xpath)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = purge_path (fs, xpath);
|
||||
|
||||
free_str_with_mbs (fs, path, xpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = delete_from_fs_with_mbs (fs, path, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qse_fs_delfilewcs (qse_fs_t* fs, const qse_wchar_t* path, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (flags & QSE_FS_DELFILEWCS_GLOB)
|
||||
{
|
||||
qse_char_t* xpath;
|
||||
|
||||
xpath = (qse_char_t*)make_str_with_wcs (fs, path);
|
||||
if (!xpath)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & QSE_FS_DELFILEWCS_RECURSIVE)
|
||||
{
|
||||
ret = qse_glob (xpath, purge_path_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr, fs->cmgr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = qse_glob (xpath, delete_file_for_glob, fs, DEFAULT_GLOB_FLAGS, fs->mmgr, fs->cmgr);
|
||||
}
|
||||
|
||||
free_str_with_wcs (fs, path, xpath);
|
||||
|
||||
if (ret <= -1)
|
||||
{
|
||||
fs->errnum = QSE_FS_EGLOB;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (flags & QSE_FS_DELFILEWCS_RECURSIVE)
|
||||
{
|
||||
qse_char_t* xpath;
|
||||
|
||||
/* if RECURSIVE is set, it's not differnt from qse_fs_deldirwcs() */
|
||||
xpath = (qse_char_t*)make_str_with_wcs (fs, path);
|
||||
if (!xpath)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = purge_path (fs, xpath);
|
||||
|
||||
free_str_with_wcs (fs, path, xpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = delete_from_fs_with_wcs (fs, path, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
int qse_fs_deldirmbs (qse_fs_t* fs, const qse_mchar_t* path, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (flags & QSE_FS_DELDIRMBS_GLOB)
|
||||
{
|
||||
qse_char_t* xpath;
|
||||
|
||||
xpath = (qse_char_t*)make_str_with_mbs (fs, path);
|
||||
if (!xpath)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & QSE_FS_DELDIRMBS_RECURSIVE)
|
||||
{
|
||||
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, fs->cmgr);
|
||||
}
|
||||
|
||||
free_str_with_mbs (fs, path, xpath);
|
||||
|
||||
if (ret <= -1) fs->errnum = QSE_FS_EGLOB;
|
||||
}
|
||||
else if (flags & QSE_FS_DELDIRMBS_RECURSIVE)
|
||||
{
|
||||
qse_char_t* xpath;
|
||||
|
||||
/* if RECURSIVE is set, it's not differnt from qse_fs_delfilembs() */
|
||||
xpath = (qse_char_t*)make_str_with_mbs (fs, path);
|
||||
if (!xpath)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = purge_path (fs, xpath);
|
||||
|
||||
free_str_with_mbs (fs, path, xpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = delete_from_fs_with_mbs (fs, path, 1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qse_fs_deldirwcs (qse_fs_t* fs, const qse_wchar_t* path, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (flags & QSE_FS_DELDIRWCS_GLOB)
|
||||
{
|
||||
qse_char_t* xpath;
|
||||
|
||||
xpath = (qse_char_t*)make_str_with_wcs (fs, path);
|
||||
if (!xpath)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & QSE_FS_DELDIRWCS_RECURSIVE)
|
||||
{
|
||||
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, fs->cmgr);
|
||||
}
|
||||
|
||||
free_str_with_wcs (fs, path, xpath);
|
||||
|
||||
if (ret <= -1) fs->errnum = QSE_FS_EGLOB;
|
||||
}
|
||||
else if (flags & QSE_FS_DELDIRWCS_RECURSIVE)
|
||||
{
|
||||
qse_char_t* xpath;
|
||||
|
||||
/* if RECURSIVE is set, it's not differnt from qse_fs_delfilewcs() */
|
||||
xpath = (qse_char_t*)make_str_with_wcs (fs, path);
|
||||
if (!xpath)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = purge_path (fs, xpath);
|
||||
|
||||
free_str_with_wcs (fs, path, xpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = delete_from_fs_with_wcs (fs, path, 1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
@ -1,220 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "fs.h"
|
||||
|
||||
qse_fs_errnum_t qse_fs_geterrnum (qse_fs_t* fs)
|
||||
{
|
||||
return fs->errnum;
|
||||
}
|
||||
|
||||
qse_fs_errnum_t qse_fs_syserrtoerrnum (qse_fs_t* fs, qse_fs_syserr_t e)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
switch (e)
|
||||
{
|
||||
case ERROR_NOT_ENOUGH_MEMORY:
|
||||
case ERROR_OUTOFMEMORY:
|
||||
return QSE_FS_ENOMEM;
|
||||
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
case ERROR_INVALID_HANDLE:
|
||||
case ERROR_INVALID_NAME:
|
||||
case ERROR_DIRECTORY:
|
||||
return QSE_FS_EINVAL;
|
||||
|
||||
case ERROR_ACCESS_DENIED:
|
||||
case ERROR_SHARING_VIOLATION:
|
||||
return QSE_FS_EACCES;
|
||||
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
return QSE_FS_ENOENT;
|
||||
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
case ERROR_FILE_EXISTS:
|
||||
return QSE_FS_EEXIST;
|
||||
|
||||
case ERROR_NOT_SAME_DEVICE:
|
||||
return QSE_FS_EXDEV;
|
||||
|
||||
case ERROR_DIR_NOT_EMPTY:
|
||||
return QSE_FS_ENOTVOID;
|
||||
|
||||
default:
|
||||
return QSE_FS_ESYSERR;
|
||||
}
|
||||
#elif defined(__OS2__)
|
||||
|
||||
switch (e)
|
||||
{
|
||||
case ERROR_NOT_ENOUGH_MEMORY:
|
||||
return QSE_FS_ENOMEM;
|
||||
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
case ERROR_INVALID_HANDLE:
|
||||
case ERROR_INVALID_NAME:
|
||||
return QSE_FS_EINVAL;
|
||||
|
||||
case ERROR_ACCESS_DENIED:
|
||||
case ERROR_SHARING_VIOLATION:
|
||||
return QSE_FS_EACCES;
|
||||
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
case ERROR_PATH_NOT_FOUND:
|
||||
return QSE_FS_ENOENT;
|
||||
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
return QSE_FS_EEXIST;
|
||||
|
||||
case ERROR_NOT_SAME_DEVICE:
|
||||
return QSE_FS_EXDEV;
|
||||
|
||||
default:
|
||||
return QSE_FS_ESYSERR;
|
||||
}
|
||||
|
||||
#elif defined(__DOS__)
|
||||
|
||||
switch (e)
|
||||
{
|
||||
case ENOMEM:
|
||||
return QSE_FS_ENOMEM;
|
||||
|
||||
case EINVAL:
|
||||
return QSE_FS_EINVAL;
|
||||
|
||||
case EACCES:
|
||||
case EPERM:
|
||||
return QSE_FS_EACCES;
|
||||
|
||||
case ENOENT:
|
||||
return QSE_FS_ENOENT;
|
||||
|
||||
case EEXIST:
|
||||
return QSE_FS_EEXIST;
|
||||
|
||||
case EISDIR:
|
||||
return QSE_FS_EISDIR;
|
||||
|
||||
case ENOTDIR:
|
||||
return QSE_FS_ENOTDIR;
|
||||
|
||||
case EXDEV:
|
||||
return QSE_FS_EXDEV;
|
||||
|
||||
default:
|
||||
return QSE_FS_ESYSERR;
|
||||
}
|
||||
|
||||
#else
|
||||
switch (e)
|
||||
{
|
||||
case ENOMEM:
|
||||
return QSE_FS_ENOMEM;
|
||||
|
||||
case EINVAL:
|
||||
return QSE_FS_EINVAL;
|
||||
|
||||
case EACCES:
|
||||
case EPERM:
|
||||
return QSE_FS_EACCES;
|
||||
|
||||
case ENOENT:
|
||||
return QSE_FS_ENOENT;
|
||||
|
||||
case EEXIST:
|
||||
return QSE_FS_EEXIST;
|
||||
|
||||
case EINTR:
|
||||
return QSE_FS_EINTR;
|
||||
|
||||
case EISDIR:
|
||||
return QSE_FS_EISDIR;
|
||||
|
||||
case ENOTDIR:
|
||||
return QSE_FS_ENOTDIR;
|
||||
|
||||
case ENOTEMPTY:
|
||||
return QSE_FS_ENOTVOID;
|
||||
|
||||
case EXDEV:
|
||||
return QSE_FS_EXDEV;
|
||||
|
||||
default:
|
||||
return QSE_FS_ESYSERR;
|
||||
}
|
||||
#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;
|
||||
}
|
||||
}
|
@ -1,216 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "fs.h"
|
||||
|
||||
int qse_fs_sysmkdir (qse_fs_t* fs, const qse_fs_char_t* fspath)
|
||||
{
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
if (CreateDirectory (fspath, QSE_NULL) == FALSE)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
#elif defined(__OS2__)
|
||||
|
||||
APIRET rc;
|
||||
|
||||
rc = DosMkDir (fspath, QSE_NULL);
|
||||
if (rc != NO_ERROR)
|
||||
{
|
||||
FILESTATUS3L ffb;
|
||||
if (DosQueryPathInfo (fspath, FIL_STANDARDL, &ffb, QSE_SIZEOF(ffb)) == NO_ERROR)
|
||||
{
|
||||
if (ffb.attrFile & FILE_DIRECTORY)
|
||||
{
|
||||
fs->errnum = QSE_FS_EEXIST;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#elif defined(__DOS__)
|
||||
|
||||
if (mkdir (fspath) <= -1)
|
||||
{
|
||||
struct stat st;
|
||||
if (errno != EEXIST && stat (fspath, &st) >= 0)
|
||||
{
|
||||
if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
fs->errnum = QSE_FS_EEXIST;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (QSE_MKDIR (fspath, 0777) <= -1) /* TODO: proper mode?? */
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
static int make_directory_chain (qse_fs_t* fs, qse_fs_char_t* fspath)
|
||||
{
|
||||
qse_fs_char_t* core, * p, c;
|
||||
int ret = 0;
|
||||
|
||||
core = get_fspath_core (fspath);
|
||||
canon_fspath (core, core, 0);
|
||||
|
||||
if (*core == QSE_FS_T('\0'))
|
||||
{
|
||||
fs->errnum = QSE_FS_EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = core;
|
||||
if (IS_FSPATHSEP(*p)) p++;
|
||||
for (; *p; p++)
|
||||
{
|
||||
if (IS_FSPATHSEP(*p))
|
||||
{
|
||||
#if defined(_WIN32) || defined(__DOS__) || defined(__OS2__)
|
||||
/* exclude the separator from the path name */
|
||||
c = *p;
|
||||
*p = QSE_FS_T('\0');
|
||||
#else
|
||||
/* include the separater in the path name */
|
||||
c = *(p + 1);
|
||||
*(p + 1) = QSE_FS_T('\0');
|
||||
#endif
|
||||
ret = qse_fs_sysmkdir (fs, fspath);
|
||||
if (ret <= -1 && fs->errnum != QSE_FS_EEXIST)
|
||||
{
|
||||
return -1;
|
||||
goto done; /* abort */
|
||||
}
|
||||
#if defined(_WIN32) || defined(__DOS__) || defined(__OS2__)
|
||||
*p = c;
|
||||
#else
|
||||
*(p + 1) = c;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_FSPATHSEP(*(p - 1))) ret = qse_fs_sysmkdir (fs, fspath);
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qse_fs_mkdirmbs (qse_fs_t* fs, const qse_mchar_t* path, int flags)
|
||||
{
|
||||
qse_fs_char_t* fspath;
|
||||
int ret;
|
||||
|
||||
if (*path == QSE_MT('\0'))
|
||||
{
|
||||
fs->errnum = QSE_FS_EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & QSE_FS_MKDIRMBS_PARENT)
|
||||
{
|
||||
/* make_directory_chain changes the input path.
|
||||
* ensure to create a modifiable string for it. */
|
||||
fspath = qse_fs_dupfspathformbs (fs, path);
|
||||
if (!fspath) return -1;
|
||||
|
||||
ret = make_directory_chain (fs, fspath);
|
||||
}
|
||||
else
|
||||
{
|
||||
fspath = (qse_fs_char_t*)qse_fs_makefspathformbs (fs, path);
|
||||
if (!fspath) return -1;
|
||||
|
||||
ret = qse_fs_sysmkdir (fs, fspath);
|
||||
}
|
||||
|
||||
qse_fs_freefspathformbs (fs, path, fspath);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qse_fs_mkdirwcs (qse_fs_t* fs, const qse_wchar_t* path, int flags)
|
||||
{
|
||||
qse_fs_char_t* fspath;
|
||||
int ret;
|
||||
|
||||
if (*path == QSE_WT('\0'))
|
||||
{
|
||||
fs->errnum = QSE_FS_EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & QSE_FS_MKDIRWCS_PARENT)
|
||||
{
|
||||
/* make_directory_chain changes the input path.
|
||||
* ensure to create a modifiable string for it. */
|
||||
fspath = qse_fs_dupfspathforwcs (fs, path);
|
||||
if (!fspath) return -1;
|
||||
|
||||
ret = make_directory_chain (fs, fspath);
|
||||
}
|
||||
else
|
||||
{
|
||||
fspath = (qse_fs_char_t*)qse_fs_makefspathforwcs (fs, path);
|
||||
if (!fspath) return -1;
|
||||
|
||||
ret = qse_fs_sysmkdir (fs, fspath);
|
||||
}
|
||||
|
||||
qse_fs_freefspathforwcs (fs, path, fspath);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
/*
|
||||
mknodmbs
|
||||
mkfifombs
|
||||
mknodwcs
|
||||
mknodwcs
|
||||
*/
|
@ -1,463 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "fs.h"
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include <qse/cmn/path.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include "mem.h"
|
||||
|
||||
/*
|
||||
OVERWRITE AND FORCE handled by callback???
|
||||
QSE_FS_MOVE_UPDATE
|
||||
QSE_FS_MOVE_BACKUP_SIMPLE
|
||||
QSE_FS_MOVE_BACKUP_NUMBERED
|
||||
*/
|
||||
enum fop_flag_t
|
||||
{
|
||||
FOP_OLD_STAT = (1 << 0),
|
||||
FOP_NEW_STAT = (1 << 1),
|
||||
|
||||
FOP_CROSS_DEV = (1 << 2)
|
||||
};
|
||||
|
||||
struct fop_t
|
||||
{
|
||||
int flags;
|
||||
|
||||
#if defined(_WIN32)
|
||||
/* nothing yet */
|
||||
#elif defined(__OS2__)
|
||||
qse_fs_char_t* old_path;
|
||||
qse_fs_char_t* new_path;
|
||||
#elif defined(__DOS__)
|
||||
qse_fs_char_t* old_path;
|
||||
qse_fs_char_t* new_path;
|
||||
#else
|
||||
qse_fs_char_t* old_path;
|
||||
qse_fs_char_t* new_path;
|
||||
qse_fs_char_t* new_path2;
|
||||
|
||||
#if defined(HAVE_LSTAT)
|
||||
qse_lstat_t old_stat;
|
||||
qse_lstat_t new_stat;
|
||||
#else
|
||||
qse_stat_t old_stat;
|
||||
qse_stat_t new_stat;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct fop_t fop_t;
|
||||
|
||||
int qse_fs_move (qse_fs_t* fs, const qse_char_t* oldpath, const qse_char_t* newpath)
|
||||
{
|
||||
|
||||
#if defined(_WIN32)
|
||||
/* ------------------------------------------------------ */
|
||||
/* TODO: improve it... */
|
||||
|
||||
/* TODO: support cross-volume move, move by copy/delete, etc ... */
|
||||
if (MoveFile (oldpath, newpath) == FALSE)
|
||||
{
|
||||
DWORD e = GetLastError();
|
||||
if (e == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
DeleteFile (newpath);
|
||||
if (MoveFile (oldpath, newpath) == FALSE)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, GetLastError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
#elif defined(__OS2__)
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
/* TODO: improve it */
|
||||
int ret = 0;
|
||||
fop_t fop;
|
||||
|
||||
QSE_MEMSET (&fop, 0, QSE_SIZEOF(fop));
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
fop.old_path = oldpath;
|
||||
fop.new_path = newpath;
|
||||
#else
|
||||
fop.old_path = qse_wcstombsdup (oldpath, QSE_NULL, fs->mmgr);
|
||||
fop.new_path = qse_wcstombsdup (newpath, QSE_NULL, fs->mmgr);
|
||||
if (fop.old_path == QSE_NULL || fop.old_path == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
ret = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
APIRET rc;
|
||||
|
||||
rc = DosMove (fop.old_path, fop.new_path);
|
||||
if (rc == ERROR_ALREADY_EXISTS || rc == ERROR_ACCESS_DENIED)
|
||||
{
|
||||
DosDelete (fop.new_path);
|
||||
rc = DosMove (fop.old_path, fop.new_path);
|
||||
}
|
||||
if (rc != NO_ERROR)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, rc);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
/* nothing special */
|
||||
#else
|
||||
if (fop.old_path) QSE_MMGR_FREE (fs->mmgr, fop.old_path);
|
||||
if (fop.new_path) QSE_MMGR_FREE (fs->mmgr, fop.new_path);
|
||||
#endif
|
||||
return ret;
|
||||
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
#elif defined(__DOS__)
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
/* TODO: improve it */
|
||||
fop_t fop;
|
||||
int ret = 0;
|
||||
|
||||
QSE_MEMSET (&fop, 0, QSE_SIZEOF(fop));
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
fop.old_path = oldpath;
|
||||
fop.new_path = newpath;
|
||||
#else
|
||||
fop.old_path = qse_wcstombsdup (oldpath, QSE_NULL, fs->mmgr);
|
||||
fop.new_path = qse_wcstombsdup (newpath, QSE_NULL, fs->mmgr);
|
||||
if (fop.old_path == QSE_NULL || fop.old_path == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
ret = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
if (rename (fop.old_path, fop.new_path) <= -1)
|
||||
{
|
||||
/* FYI, rename() on watcom seems to set
|
||||
* errno to EACCES when the new path exists. */
|
||||
|
||||
unlink (fop.new_path);
|
||||
if (rename (fop.old_path, fop.new_path) <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
/* nothing special */
|
||||
#else
|
||||
if (fop.old_path) QSE_MMGR_FREE (fs->mmgr, fop.old_path);
|
||||
if (fop.new_path) QSE_MMGR_FREE (fs->mmgr, fop.new_path);
|
||||
#endif
|
||||
return ret;
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
#else
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
fop_t fop;
|
||||
QSE_MEMSET (&fop, 0, QSE_SIZEOF(fop));
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
fop.old_path = oldpath;
|
||||
fop.new_path = newpath;
|
||||
#else
|
||||
fop.old_path = qse_wcstombsdup (oldpath, QSE_NULL, fs->mmgr);
|
||||
fop.new_path = qse_wcstombsdup (newpath, QSE_NULL, fs->mmgr);
|
||||
if (fop.old_path == QSE_NULL || fop.old_path == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
goto oops;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* TOOD: implement confirmatio
|
||||
if (overwrite_callback is set)
|
||||
{
|
||||
checkif the the mbsnewpat exists.
|
||||
if (it exists)
|
||||
{
|
||||
call fs->confirm_overwrite_callback (....)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/* use lstat because we need to move the symbolic link
|
||||
* itself if the file is a symbolic link */
|
||||
#if defined(HAVE_LSTAT)
|
||||
if (QSE_LSTAT (fop.old_path, &fop.old_stat) == -1)
|
||||
#else
|
||||
if (QSE_STAT (fop.old_path, &fop.old_stat) == -1) /* is this ok to use stat? */
|
||||
#endif
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
goto oops;
|
||||
}
|
||||
else fop.flags |= FOP_OLD_STAT;
|
||||
|
||||
#if defined(HAVE_LSTAT)
|
||||
if (QSE_LSTAT (fop.new_path, &fop.new_stat) == -1)
|
||||
#else
|
||||
if (QSE_STAT (fop.new_path, &fop.new_stat) == -1)
|
||||
#endif
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
/* entry doesn't exist */
|
||||
}
|
||||
}
|
||||
else fop.flags |= FOP_NEW_STAT;
|
||||
|
||||
if (fop.flags & FOP_NEW_STAT)
|
||||
{
|
||||
/* destination file exits */
|
||||
if (fop.old_stat.st_dev != fop.new_stat.st_dev)
|
||||
{
|
||||
/* cross-device */
|
||||
fop.flags |= FOP_CROSS_DEV;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fop.old_stat.st_ino == fop.new_stat.st_ino)
|
||||
{
|
||||
/* both source and destination are the same.
|
||||
* this operation is not allowed */
|
||||
fs->errnum = QSE_FS_EACCES;
|
||||
goto oops;
|
||||
}
|
||||
|
||||
/* TODO: destination should point to an actual file or directory for this check to work */
|
||||
/* TOOD: ask to overwrite the source */
|
||||
if (S_ISDIR(fop.new_stat.st_mode))
|
||||
{
|
||||
/* the destination is a directory. move the source file
|
||||
* into the destination directory */
|
||||
const qse_wchar_t* arr[4];
|
||||
|
||||
arr[0] = newpath;
|
||||
arr[1] = QSE_T("/");
|
||||
arr[2] = qse_basename(oldpath);
|
||||
arr[3] = QSE_NULL;
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
fop.new_path2 = qse_stradup (arr, QSE_NULL, fs->mmgr);
|
||||
#else
|
||||
fop.new_path2 = qse_wcsatombsdup (arr, QSE_NULL, fs->mmgr);
|
||||
#endif
|
||||
if (fop.new_path2 == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
goto oops;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* the destination file is not directory, unlink first
|
||||
* TODO: but is this necessary? RENAME will do it */
|
||||
QSE_UNLINK (fop.new_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(fop.flags & FOP_CROSS_DEV))
|
||||
{
|
||||
/* TODO: make it better to be able to move non-empty diretories
|
||||
improve it to be able to move by copy/delete across volume */
|
||||
if (QSE_RENAME (fop.old_path, fop.new_path) == -1)
|
||||
{
|
||||
if (errno != EXDEV)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
fop.flags |= FOP_CROSS_DEV;
|
||||
}
|
||||
else goto done;
|
||||
}
|
||||
|
||||
QSE_ASSERT (fop.flags & FOP_CROSS_DEV);
|
||||
|
||||
if (!S_ISDIR(fop.old_stat.st_mode))
|
||||
{
|
||||
/* copy a single file */
|
||||
/* ............ */
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (!recursive)
|
||||
{
|
||||
fs->errnum = QSE_FS_E....;
|
||||
goto oops;
|
||||
}
|
||||
|
||||
copy recursively...
|
||||
#endif
|
||||
|
||||
|
||||
done:
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
if (fop.new_path2) QSE_MMGR_FREE (fs->mmgr, fop.new_path2);
|
||||
#else
|
||||
if (fop.new_path2) QSE_MMGR_FREE (fs->mmgr, fop.new_path2);
|
||||
QSE_MMGR_FREE (fs->mmgr, fop.old_path);
|
||||
QSE_MMGR_FREE (fs->mmgr, fop.new_path);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
if (fop.new_path2) QSE_MMGR_FREE (fs->mmgr, fop.new_path2);
|
||||
#else
|
||||
if (fop.new_path2) QSE_MMGR_FREE (fs->mmgr, fop.new_path2);
|
||||
if (fop.old_path) QSE_MMGR_FREE (fs->mmgr, fop.old_path);
|
||||
if (fop.new_path) QSE_MMGR_FREE (fs->mmgr, fop.new_path);
|
||||
#endif
|
||||
return -1;
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int move_file_in_fs (qse_fs_t* fs, const qse_fs_char_t* oldpath, const qse_fs_char_t* newpath, int flags)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
if (MoveFile (oldpath, newpath) == FALSE)
|
||||
{
|
||||
DWORD e = GetLastError();
|
||||
if (e == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
DeleteFile (newpath);
|
||||
if (MoveFile (oldpath, newpath) == FALSE)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, GetLastError());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
#elif defined(__OS2__)
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
/* TODO: improve it */
|
||||
APIRET rc;
|
||||
|
||||
rc = DosMove (oldpath, newpath);
|
||||
if (rc == ERROR_ALREADY_EXISTS || rc == ERROR_ACCESS_DENIED)
|
||||
{
|
||||
DosDelete (fop.new_path);
|
||||
rc = DosMove (oldpath, newpath);
|
||||
}
|
||||
if (rc != NO_ERROR)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
#elif defined(__DOS__)
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
if (rename (oldpath, newpath) <= -1)
|
||||
{
|
||||
/* FYI, rename() on watcom seems to set
|
||||
* errno to EACCES when the new path exists. */
|
||||
|
||||
unlink (newpath);
|
||||
if (rename (oldpath, newpath) <= -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
/* ------------------------------------------------------ */
|
||||
|
||||
#else
|
||||
|
||||
if (!(flags & QSE_FS_CPFILE_REPLACE))
|
||||
{
|
||||
qse_lstat_t st;
|
||||
if (QSE_LSTAT (newpath, &st) >= 0)
|
||||
{
|
||||
fs->errnum = QSE_FS_EEXIST;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (QSE_RENAME (oldpath, newpath) == -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
825
qse/lib/cmn/fs.c
825
qse/lib/cmn/fs.c
@ -1,825 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "fs.h"
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include <qse/cmn/path.h>
|
||||
#include "mem.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
/* nothing else */
|
||||
#elif defined(__OS2__)
|
||||
/* nothing else */
|
||||
#elif defined(__DOS__)
|
||||
/* nothing else */
|
||||
#else
|
||||
# include <dirent.h>
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
typedef struct info_t info_t;
|
||||
struct info_t
|
||||
{
|
||||
qse_cstr_t name;
|
||||
|
||||
#if defined(_WIN32)
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATA wfd;
|
||||
int just_changed_fs;
|
||||
#elif defined(__OS2__)
|
||||
#elif defined(__DOS__)
|
||||
#else
|
||||
DIR* handle;
|
||||
qse_mchar_t* mcurdir;
|
||||
#endif
|
||||
};
|
||||
|
||||
qse_fs_t* qse_fs_open (qse_mmgr_t* mmgr, qse_size_t xtnsize)
|
||||
{
|
||||
qse_fs_t* fs;
|
||||
|
||||
fs = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(*fs) + xtnsize);
|
||||
if (fs == QSE_NULL) return QSE_NULL;
|
||||
|
||||
if (qse_fs_init (fs, mmgr) <= -1)
|
||||
{
|
||||
QSE_MMGR_FREE (mmgr, fs);
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
QSE_MEMSET (fs + 1, 0, xtnsize);
|
||||
return fs;
|
||||
}
|
||||
|
||||
void qse_fs_close (qse_fs_t* fs)
|
||||
{
|
||||
qse_fs_fini (fs);
|
||||
QSE_MMGR_FREE (fs->mmgr, fs);
|
||||
}
|
||||
|
||||
int qse_fs_init (qse_fs_t* fs, qse_mmgr_t* mmgr)
|
||||
{
|
||||
QSE_MEMSET (fs, 0, QSE_SIZEOF(*fs));
|
||||
fs->mmgr = mmgr;
|
||||
fs->cmgr = qse_getdflcmgr();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qse_fs_fini (qse_fs_t* fs)
|
||||
{
|
||||
info_t* info;
|
||||
|
||||
info = fs->info;
|
||||
if (info)
|
||||
{
|
||||
if (info->name.ptr)
|
||||
{
|
||||
QSE_ASSERT (info->name.len > 0);
|
||||
QSE_MMGR_FREE (fs->mmgr, info->name.ptr);
|
||||
info->name.ptr = QSE_NULL;
|
||||
info->name.len = 0;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (info->handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
FindClose (info->handle);
|
||||
info->handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#elif defined(__OS2__)
|
||||
/* TODO: implement this */
|
||||
#elif defined(__DOS__)
|
||||
/* TODO: implement this */
|
||||
#else
|
||||
if (info->mcurdir && info->mcurdir != fs->curdir)
|
||||
QSE_MMGR_FREE (fs->mmgr, info->mcurdir);
|
||||
info->mcurdir = QSE_NULL;
|
||||
|
||||
if (info->handle)
|
||||
{
|
||||
closedir (info->handle);
|
||||
info->handle = QSE_NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
QSE_MMGR_FREE (fs->mmgr, info);
|
||||
fs->info = QSE_NULL;
|
||||
}
|
||||
|
||||
if (fs->curdir)
|
||||
{
|
||||
QSE_MMGR_FREE (fs->mmgr, fs->curdir);
|
||||
fs->curdir = QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
qse_mmgr_t* qse_fs_getmmgr (qse_fs_t* fs)
|
||||
{
|
||||
return fs->mmgr;
|
||||
}
|
||||
|
||||
void* qse_fs_getxtn (qse_fs_t* fs)
|
||||
{
|
||||
return QSE_XTN (fs);
|
||||
}
|
||||
|
||||
int qse_fs_getopt (qse_fs_t* fs, qse_fs_opt_t id, void* value)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case QSE_FS_TRAIT:
|
||||
*(int*)value = fs->trait;
|
||||
return 0;
|
||||
|
||||
case QSE_FS_CBS:
|
||||
*(qse_fs_cbs_t*)value = fs->cbs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
fs->errnum = QSE_FS_EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int qse_fs_setopt (qse_fs_t* fs, qse_fs_opt_t id, const void* value)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case QSE_FS_TRAIT:
|
||||
fs->trait = *(const int*)value;
|
||||
return 0;
|
||||
|
||||
|
||||
case QSE_FS_CBS:
|
||||
fs->cbs = *(qse_fs_cbs_t*)value;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
fs->errnum = QSE_FS_EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static QSE_INLINE info_t* get_info (qse_fs_t* fs)
|
||||
{
|
||||
info_t* info;
|
||||
|
||||
info = fs->info;
|
||||
if (info == QSE_NULL)
|
||||
{
|
||||
info = QSE_MMGR_ALLOC (fs->mmgr, QSE_SIZEOF(*info));
|
||||
if (info == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
QSE_MEMSET (info, 0, QSE_SIZEOF(*info));
|
||||
#if defined(_WIN32)
|
||||
info->handle = INVALID_HANDLE_VALUE;
|
||||
#endif
|
||||
fs->info = info;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
int qse_fs_chdir (qse_fs_t* fs, const qse_char_t* name)
|
||||
{
|
||||
qse_char_t* fsname;
|
||||
info_t* info;
|
||||
|
||||
#if defined(_WIN32)
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATA wfd;
|
||||
const qse_char_t* tmp_name[4];
|
||||
qse_size_t idx;
|
||||
#elif defined(__OS2__)
|
||||
/* TODO: implement this */
|
||||
#elif defined(__DOS__)
|
||||
/* TODO: implement this */
|
||||
#else
|
||||
DIR* handle;
|
||||
qse_mchar_t* mfsname;
|
||||
const qse_char_t* tmp_name[4];
|
||||
qse_size_t idx;
|
||||
#endif
|
||||
|
||||
if (name[0] == QSE_T('\0'))
|
||||
{
|
||||
fs->errnum = QSE_FS_EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
info = get_info (fs);
|
||||
if (info == QSE_NULL) return -1;
|
||||
|
||||
#if defined(_WIN32)
|
||||
idx = 0;
|
||||
if (!qse_isabspath(name) && fs->curdir)
|
||||
tmp_name[idx++] = fs->curdir;
|
||||
tmp_name[idx++] = name;
|
||||
|
||||
if (qse_isdrivecurpath(name))
|
||||
tmp_name[idx++] = QSE_T(" ");
|
||||
else
|
||||
tmp_name[idx++] = QSE_T("\\ ");
|
||||
|
||||
tmp_name[idx] = QSE_NULL;
|
||||
|
||||
fsname = qse_stradup (tmp_name, QSE_NULL, fs->mmgr);
|
||||
if (fsname == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
idx = qse_canonpath (fsname, fsname, 0);
|
||||
/* Put an asterisk after canonicalization to prevent side-effects.
|
||||
* otherwise, .\* would be transformed to * by qse_canonpath() */
|
||||
fsname[idx-1] = QSE_T('*');
|
||||
|
||||
/* Using FindExInfoBasic won't resolve cAlternatFileName.
|
||||
* so it can get faster a little bit. The problem is that
|
||||
* it is not supported on old windows. just stick to the
|
||||
* simple API instead. */
|
||||
#if 0
|
||||
handle = FindFirstFileEx (
|
||||
fsname, FindExInfoBasic,
|
||||
&wfd, FindExSearchNameMatch,
|
||||
NULL, 0/*FIND_FIRST_EX_CASE_SENSITIVE*/);
|
||||
#endif
|
||||
handle = FindFirstFile (fsname, &wfd);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, GetLastError());
|
||||
QSE_MMGR_FREE (fs->mmgr, fsname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (info->handle != INVALID_HANDLE_VALUE)
|
||||
FindClose (info->handle);
|
||||
|
||||
QSE_MEMSET (info, 0, QSE_SIZEOF(*info));
|
||||
info->handle = handle;
|
||||
info->wfd = wfd;
|
||||
info->just_changed_fs = 1;
|
||||
|
||||
if (fs->curdir) QSE_MMGR_FREE (fs->mmgr, fs->curdir);
|
||||
fsname[idx-1] = QSE_T('\0'); /* drop the asterisk */
|
||||
fs->curdir = fsname;
|
||||
|
||||
return 0;
|
||||
|
||||
#elif defined(__OS2__)
|
||||
/* TODO: implement this */
|
||||
return 0;
|
||||
#elif defined(__DOS__)
|
||||
/* TODO: implement this */
|
||||
return 0;
|
||||
#else
|
||||
|
||||
idx = 0;
|
||||
if (!qse_isabspath(name) && fs->curdir)
|
||||
{
|
||||
tmp_name[idx++] = fs->curdir;
|
||||
tmp_name[idx++] = QSE_T("/");
|
||||
}
|
||||
tmp_name[idx++] = name;
|
||||
tmp_name[idx] = QSE_NULL;
|
||||
|
||||
fsname = qse_stradup (tmp_name, QSE_NULL, fs->mmgr);
|
||||
if (fsname == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
qse_canonpath (fsname, fsname, 0);
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
mfsname = fsname;
|
||||
#else
|
||||
mfsname = qse_wcstombsdup (fsname, QSE_NULL, fs->mmgr);
|
||||
if (mfsname == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
QSE_MMGR_FREE (fs->mmgr, fsname);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
handle = opendir (mfsname);
|
||||
|
||||
if (handle == QSE_NULL)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
if (mfsname != fsname)
|
||||
QSE_MMGR_FREE (fs->mmgr, mfsname);
|
||||
QSE_MMGR_FREE (fs->mmgr, fsname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (info->handle) closedir (info->handle);
|
||||
info->handle = handle;
|
||||
|
||||
if (info->mcurdir && info->mcurdir != fs->curdir)
|
||||
QSE_MMGR_FREE (fs->mmgr, info->mcurdir);
|
||||
info->mcurdir = mfsname;
|
||||
|
||||
if (fs->curdir) QSE_MMGR_FREE (fs->mmgr, fs->curdir);
|
||||
fs->curdir = fsname;
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR) || defined(_WIN32)
|
||||
static int set_entry_name (qse_fs_t* fs, const qse_char_t* name)
|
||||
#else
|
||||
static int set_entry_name (qse_fs_t* fs, const qse_mchar_t* name)
|
||||
#endif
|
||||
{
|
||||
info_t* info;
|
||||
qse_size_t len;
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR) || defined(_WIN32)
|
||||
/* nothing more to declare */
|
||||
#else
|
||||
qse_size_t mlen;
|
||||
#endif
|
||||
|
||||
info = fs->info;
|
||||
QSE_ASSERT (info != QSE_NULL);
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR) || defined(_WIN32)
|
||||
len = qse_strlen (name);
|
||||
#else
|
||||
/* TODO: ignore MBWCERR */
|
||||
if (qse_mbstowcs (name, &mlen, QSE_NULL, &len) <= -1)
|
||||
{
|
||||
/* invalid name ??? */
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len > info->name.len)
|
||||
{
|
||||
qse_char_t* tmp;
|
||||
|
||||
/* TOOD: round up len to the nearlest multiples of something (32, 64, ??)*/
|
||||
tmp = QSE_MMGR_REALLOC (
|
||||
fs->mmgr,
|
||||
info->name.ptr,
|
||||
(len + 1) * QSE_SIZEOF(*tmp)
|
||||
);
|
||||
if (tmp == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
info->name.len = len;
|
||||
info->name.ptr = tmp;
|
||||
}
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR) || defined(_WIN32)
|
||||
qse_strcpy (info->name.ptr, name);
|
||||
#else
|
||||
len++; /* for terminating null */
|
||||
qse_mbstowcs (name, &mlen, info->name.ptr, &len);
|
||||
#endif
|
||||
|
||||
fs->ent.name.base = info->name.ptr;
|
||||
fs->ent.flags |= QSE_FS_ENT_NAME;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
static QSE_INLINE void filetime_to_ntime (const FILETIME* ft, qse_ntime_t* nt)
|
||||
{
|
||||
/* reverse of http://support.microsoft.com/kb/167296/en-us */
|
||||
ULARGE_INTEGER li;
|
||||
|
||||
li.LowPart = ft->dwLowDateTime;
|
||||
li.HighPart = ft->dwHighDateTime;
|
||||
|
||||
#if (QSE_SIZEOF_LONG_LONG>=8)
|
||||
li.QuadPart -= 116444736000000000ull;
|
||||
#elif (QSE_SIZEOF___INT64>=8)
|
||||
li.QuadPart -= 116444736000000000ui64;
|
||||
#else
|
||||
# error Unsupported 64bit integer type
|
||||
#endif
|
||||
/*li.QuadPart /= 10000000;*/
|
||||
/*li.QuadPart /= 10000;
|
||||
return li.QuadPart;*/
|
||||
|
||||
/* li.QuadPart is in the 100-nanosecond intervals */
|
||||
nt->sec = li.QuadPart / (QSE_NSECS_PER_SEC / 100);
|
||||
nt->nsec = (li.QuadPart % (QSE_NSECS_PER_SEC / 100)) * 100;
|
||||
}
|
||||
#endif
|
||||
|
||||
qse_fs_ent_t* qse_fs_read (qse_fs_t* fs, int flags)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
info_t* info;
|
||||
|
||||
info = fs->info;
|
||||
if (info == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOENT; /* TODO: is this correct? */
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
if (info->just_changed_fs)
|
||||
{
|
||||
info->just_changed_fs = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FindNextFile (info->handle, &info->wfd) == FALSE)
|
||||
{
|
||||
DWORD e = GetLastError();
|
||||
if (e == ERROR_NO_MORE_FILES)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOERR;
|
||||
return QSE_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, e);
|
||||
return QSE_NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* call set_entry_name before changing other fields
|
||||
* in fs->ent not to pollute it in case set_entry_name fails */
|
||||
QSE_MEMSET (&fs->ent, 0, QSE_SIZEOF(fs->ent));
|
||||
if (set_entry_name (fs, info->wfd.cFileName) <= -1) return QSE_NULL;
|
||||
|
||||
if (flags & QSE_FS_ENT_TYPE)
|
||||
{
|
||||
#if !defined(IO_REPARSE_TAG_SYMLINK)
|
||||
# define IO_REPARSE_TAG_SYMLINK 0xA000000C
|
||||
#endif
|
||||
#if !defined(FILE_ATTRIBUTE_REPARSE_POINT)
|
||||
# define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
|
||||
#endif
|
||||
if (info->wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
fs->ent.type = QSE_FS_ENT_SUBDIR;
|
||||
}
|
||||
else if ((info->wfd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
|
||||
(info->wfd.dwReserved0 == IO_REPARSE_TAG_SYMLINK))
|
||||
{
|
||||
fs->ent.type = QSE_FS_ENT_SYMLINK;
|
||||
}
|
||||
else
|
||||
{
|
||||
HANDLE h;
|
||||
qse_char_t* tmp_name[4];
|
||||
qse_char_t* fname;
|
||||
|
||||
/* TODO: use a buffer in info... instead of allocating an deallocating every time */
|
||||
tmp_name[0] = fs->curdir;
|
||||
tmp_name[1] = QSE_T("\\");
|
||||
tmp_name[2] = info->wfd.cFileName;
|
||||
tmp_name[3] = QSE_NULL;
|
||||
fname = qse_stradup (tmp_name, QSE_NULL, fs->mmgr);
|
||||
if (fname == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
h = CreateFile (
|
||||
fname,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
QSE_NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0
|
||||
);
|
||||
|
||||
QSE_MMGR_FREE (fs->mmgr, fname);
|
||||
|
||||
if (h != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD t = GetFileType (h);
|
||||
switch (t)
|
||||
{
|
||||
case FILE_TYPE_CHAR:
|
||||
fs->ent.type = QSE_FS_ENT_CHRDEV;
|
||||
break;
|
||||
case FILE_TYPE_DISK:
|
||||
fs->ent.type = QSE_FS_ENT_BLKDEV;
|
||||
break;
|
||||
case FILE_TYPE_PIPE:
|
||||
fs->ent.type = QSE_FS_ENT_PIPE;
|
||||
break;
|
||||
default:
|
||||
fs->ent.type = QSE_FS_ENT_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
CloseHandle (h);
|
||||
}
|
||||
else
|
||||
{
|
||||
fs->ent.type = QSE_FS_ENT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
fs->ent.type |= QSE_FS_ENT_TYPE;
|
||||
}
|
||||
|
||||
if (flags & QSE_FS_ENT_SIZE)
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
li.LowPart = info->wfd.nFileSizeLow;
|
||||
li.HighPart = info->wfd.nFileSizeHigh;
|
||||
fs->ent.size = li.QuadPart;
|
||||
fs->ent.type |= QSE_FS_ENT_SIZE;
|
||||
}
|
||||
|
||||
if (flags & QSE_FS_ENT_TIME)
|
||||
{
|
||||
filetime_to_ntime (&info->wfd.ftCreationTime, &fs->ent.time.create);
|
||||
filetime_to_ntime (&info->wfd.ftLastAccessTime, &fs->ent.time.access);
|
||||
filetime_to_ntime (&info->wfd.ftLastWriteTime, &fs->ent.time.modify);
|
||||
fs->ent.type |= QSE_FS_ENT_TIME;
|
||||
}
|
||||
|
||||
#elif defined(__OS2__)
|
||||
/* TODO: implement this */
|
||||
#elif defined(__DOS__)
|
||||
/* TODO: implement this */
|
||||
#else
|
||||
|
||||
info_t* info;
|
||||
struct dirent* ent;
|
||||
int x;
|
||||
|
||||
int stat_needed;
|
||||
qse_lstat_t st;
|
||||
|
||||
info = fs->info;
|
||||
if (info == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOTDIR;
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
ent = readdir (info->handle);
|
||||
if (ent == QSE_NULL)
|
||||
{
|
||||
if (errno != 0) fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
QSE_MEMSET (&fs->ent, 0, QSE_SIZEOF(fs->ent));
|
||||
if (set_entry_name (fs, ent->d_name) <= -1) return QSE_NULL;
|
||||
|
||||
stat_needed =
|
||||
#if !defined(HAVE_STRUCT_DIRENT_D_TYPE)
|
||||
(flags & QSE_FS_ENT_TYPE) ||
|
||||
#endif
|
||||
(flags & QSE_FS_ENT_SIZE) ||
|
||||
(flags & QSE_FS_ENT_TIME);
|
||||
if (stat_needed)
|
||||
{
|
||||
qse_mchar_t* tmp_name[4];
|
||||
qse_mchar_t* mfname;
|
||||
|
||||
/* 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, QSE_NULL, fs->mmgr);
|
||||
if (mfname == QSE_NULL)
|
||||
{
|
||||
fs->errnum = QSE_FS_ENOMEM;
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
#if defined(HAVE_LSTAT)
|
||||
x = QSE_LSTAT (mfname, &st);
|
||||
#else
|
||||
x = QSE_STAT (mfname, &st);
|
||||
#endif
|
||||
QSE_MMGR_FREE (fs->mmgr, mfname);
|
||||
|
||||
if (x == -1)
|
||||
{
|
||||
fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
|
||||
return QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & QSE_FS_ENT_TYPE)
|
||||
{
|
||||
#if defined(HAVE_STRUCT_DIRENT_D_TYPE) && defined(DT_DIR) && defined(DT_REG) /* and more */
|
||||
switch (ent->d_type)
|
||||
{
|
||||
case DT_DIR:
|
||||
fs->ent.type = QSE_FS_ENT_SUBDIR;
|
||||
break;
|
||||
|
||||
case DT_REG:
|
||||
fs->ent.type = QSE_FS_ENT_REGULAR;
|
||||
break;
|
||||
|
||||
case DT_LNK:
|
||||
fs->ent.type = QSE_FS_ENT_SYMLINK;
|
||||
break;
|
||||
|
||||
case DT_BLK:
|
||||
fs->ent.type = QSE_FS_ENT_BLKDEV;
|
||||
break;
|
||||
|
||||
case DT_CHR:
|
||||
fs->ent.type = QSE_FS_ENT_CHRDEV;
|
||||
break;
|
||||
|
||||
case DT_FIFO:
|
||||
#if defined(DT_SOCK)
|
||||
case DT_SOCK:
|
||||
#endif
|
||||
fs->ent.type = QSE_FS_ENT_PIPE;
|
||||
break;
|
||||
|
||||
default:
|
||||
fs->ent.type = QSE_FS_ENT_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
#else
|
||||
#if defined(__S_IFMT) && !defined(S_IFMT)
|
||||
# define S_IFMT __S_IFMT
|
||||
#endif
|
||||
#if defined(__S_IFDIR) && !defined(S_IFDIR)
|
||||
# define S_IFDIR __S_IFDIR
|
||||
#endif
|
||||
#define IS_TYPE(st,type) ((st.st_mode & S_IFMT) == S_IFDIR)
|
||||
fs->ent.type = IS_TYPE(st,S_IFDIR)? QSE_FS_ENT_SUBDIR:
|
||||
IS_TYPE(st,S_IFREG)? QSE_FS_ENT_REGULAR:
|
||||
IS_TYPE(st,S_IFLNK)? QSE_FS_ENT_SYMLINK:
|
||||
IS_TYPE(st,S_IFCHR)? QSE_FS_ENT_CHRDEV:
|
||||
IS_TYPE(st,S_IFBLK)? QSE_FS_ENT_BLKDEV:
|
||||
IS_TYPE(st,S_IFIFO)? QSE_FS_ENT_PIPE:
|
||||
#if defined(S_IFSOCK)
|
||||
IS_TYPE(st,S_IFSOCK)? QSE_FS_ENT_PIPE:
|
||||
#endif
|
||||
QSE_FS_ENT_UNKNOWN;
|
||||
#undef IS_TYPE
|
||||
#endif
|
||||
fs->ent.flags |= QSE_FS_ENT_TYPE;
|
||||
}
|
||||
|
||||
if (flags & QSE_FS_ENT_SIZE)
|
||||
{
|
||||
fs->ent.size = st.st_size;
|
||||
fs->ent.flags |= QSE_FS_ENT_SIZE;
|
||||
}
|
||||
|
||||
if (flags & QSE_FS_ENT_TIME)
|
||||
{
|
||||
#if defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
|
||||
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIM_TV_NSEC)
|
||||
fs->ent.time.create.sec = st.st_birthtim.tv_sec;
|
||||
fs->ent.time.create.nsec = st.st_birthtim.tv_nsec;
|
||||
#endif
|
||||
|
||||
fs->ent.time.access.sec = st.st_atim.tv_sec;
|
||||
fs->ent.time.access.nsec = st.st_atim.tv_nsec;
|
||||
fs->ent.time.modify.sec = st.st_mtim.tv_sec;
|
||||
fs->ent.time.modify.nsec = st.st_mtim.tv_nsec;
|
||||
fs->ent.time.change.sec = st.st_ctim.tv_sec;
|
||||
fs->ent.time.change.nsec = st.st_ctim.tv_nsec;
|
||||
#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
|
||||
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
|
||||
fs->ent.time.create.sec = st.st_birthtimespec.tv_sec;
|
||||
fs->ent.time.create.nsec = st.st_birthtimespec.tv_nsec;
|
||||
#endif
|
||||
|
||||
fs->ent.time.access.sec = st.st_atimespec.tv_sec;
|
||||
fs->ent.time.access.nsec = st.st_atimespec.tv_nsec;
|
||||
fs->ent.time.modify.sec = st.st_mtimespec.tv_sec;
|
||||
fs->ent.time.modify.nsec = st.st_mtimespec.tv_nsec;
|
||||
fs->ent.time.change.sec = st.st_ctimespec.tv_sec;
|
||||
fs->ent.time.change.nsec = st.st_ctimespec.tv_nsec;
|
||||
#else
|
||||
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
|
||||
fs->ent.time.create.sec = st.st_birthtime;
|
||||
#endif
|
||||
fs->ent.time.access.sec = st.st_atime;
|
||||
fs->ent.time.modify.sec = st.st_mtime;
|
||||
fs->ent.time.change.sec = st.st_ctime;
|
||||
#endif
|
||||
fs->ent.flags |= QSE_FS_ENT_TIME;
|
||||
}
|
||||
#endif
|
||||
|
||||
return &fs->ent;
|
||||
}
|
||||
|
||||
int qse_fs_rewind (qse_fs_t* fs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
qse_fs_char_t* qse_fs_makefspathformbs (qse_fs_t* fs, const qse_mchar_t* path)
|
||||
{
|
||||
qse_fs_char_t* fspath;
|
||||
|
||||
#if defined(QSE_FS_CHAR_IS_MCHAR)
|
||||
fspath = path;
|
||||
#else
|
||||
fspath = qse_mbstowcsdupwithcmgr (path, QSE_NULL, fs->mmgr, fs->cmgr);
|
||||
if (!fspath) fs->errnum = QSE_FS_ENOMEM;
|
||||
#endif
|
||||
|
||||
return fspath;
|
||||
}
|
||||
|
||||
qse_fs_char_t* qse_fs_makefspathforwcs (qse_fs_t* fs, const qse_wchar_t* path)
|
||||
{
|
||||
qse_fs_char_t* fspath;
|
||||
|
||||
#if defined(QSE_FS_CHAR_IS_MCHAR)
|
||||
fspath = qse_wcstombsdupwithcmgr (path, QSE_NULL, fs->mmgr, fs->cmgr);
|
||||
if (!fspath) fs->errnum = QSE_FS_ENOMEM;
|
||||
#else
|
||||
fspath = path;
|
||||
#endif
|
||||
|
||||
return fspath;
|
||||
}
|
||||
|
||||
qse_fs_char_t* qse_fs_dupfspathformbs (qse_fs_t* fs, const qse_mchar_t* path)
|
||||
{
|
||||
qse_fs_char_t* fspath;
|
||||
|
||||
#if defined(QSE_FS_CHAR_IS_MCHAR)
|
||||
fspath = qse_mbsdup (path, fs->mmgr);
|
||||
#else
|
||||
fspath = qse_mbstowcsdupwithcmgr (path, QSE_NULL, fs->mmgr, fs->cmgr);
|
||||
if (!fspath) fs->errnum = QSE_FS_ENOMEM;
|
||||
#endif
|
||||
|
||||
return fspath;
|
||||
}
|
||||
|
||||
qse_fs_char_t* qse_fs_dupfspathforwcs (qse_fs_t* fs, const qse_wchar_t* path)
|
||||
{
|
||||
qse_fs_char_t* fspath;
|
||||
|
||||
#if defined(QSE_FS_CHAR_IS_MCHAR)
|
||||
fspath = qse_wcstombsdupwithcmgr (path, QSE_NULL, fs->mmgr, fs->cmgr);
|
||||
if (!fspath) fs->errnum = QSE_FS_ENOMEM;
|
||||
#else
|
||||
fspath = qse_wcsdup (path, fs->mmgr);
|
||||
#endif
|
||||
|
||||
return fspath;
|
||||
}
|
||||
|
||||
void qse_fs_freefspathformbs (qse_fs_t* fs, const qse_mchar_t* path, qse_fs_char_t* fspath)
|
||||
{
|
||||
if (path != (const qse_mchar_t*)fspath) QSE_MMGR_FREE (fs->mmgr, fspath);
|
||||
}
|
||||
|
||||
void qse_fs_freefspathforwcs (qse_fs_t* fs, const qse_wchar_t* path, qse_fs_char_t* fspath)
|
||||
{
|
||||
if (path != (const qse_wchar_t*)fspath) QSE_MMGR_FREE (fs->mmgr, fspath);
|
||||
}
|
||||
|
||||
|
175
qse/lib/cmn/fs.h
175
qse/lib/cmn/fs.h
@ -1,175 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <qse/cmn/fs.h>
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include <qse/cmn/glob.h>
|
||||
#include <qse/cmn/dir.h>
|
||||
#include <qse/cmn/mem.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/path.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
typedef DWORD qse_fs_syserr_t;
|
||||
#elif defined(__OS2__)
|
||||
# define INCL_DOSERRORS
|
||||
# define INCL_DOSFILEMGR
|
||||
# include <os2.h>
|
||||
typedef APIRET qse_fs_syserr_t;
|
||||
#elif defined(__DOS__)
|
||||
# include <errno.h>
|
||||
# include <io.h>
|
||||
# include <stdio.h> /* for rename() */
|
||||
typedef int qse_fs_syserr_t;
|
||||
#else
|
||||
# include "syscall.h"
|
||||
typedef int qse_fs_syserr_t;
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||
# define DEFAULT_GLOB_FLAGS (QSE_GLOB_PERIOD | QSE_GLOB_SKIPSPCDIR | QSE_GLOB_NOESCAPE | QSE_GLOB_IGNORECASE)
|
||||
# define DEFAULT_PATH_SEPARATOR QSE_T("\\")
|
||||
#else
|
||||
# define DEFAULT_GLOB_FLAGS (QSE_GLOB_PERIOD | QSE_GLOB_SKIPSPCDIR)
|
||||
# define DEFAULT_PATH_SEPARATOR QSE_T("/")
|
||||
#endif
|
||||
|
||||
#define IS_CURDIR(x) ((x)[0] == QSE_T('.') && (x)[1] == QSE_T('\0'))
|
||||
#define IS_PREVDIR(x) ((x)[0] == QSE_T('.') && (x)[1] == QSE_T('.') && (x)[2] == QSE_T('\0'))
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
# define make_str_with_wcs(fs,wcs) qse_wcstombsdupwithcmgr(wcs,QSE_NULL,(fs)->mmgr,(fs)->cmgr)
|
||||
# define make_str_with_mbs(fs,mbs) (mbs)
|
||||
# define free_str_with_wcs(fs,wcs,str) QSE_MMGR_FREE((fs)->mmgr,str)
|
||||
# define free_str_with_mbs(fs,mbs,str)
|
||||
#else
|
||||
# define make_str_with_wcs(fs,wcs) (wcs)
|
||||
# define make_str_with_mbs(fs,mbs) qse_mbstowcsdupwithcmgr(mbs,QSE_NULL,(fs)->mmgr,(fs)->cmgr)
|
||||
# define free_str_with_wcs(fs,wcs,str)
|
||||
# define free_str_with_mbs(fs,mbs,str) QSE_MMGR_FREE((fs)->mmgr,str)
|
||||
#endif
|
||||
|
||||
#if defined(QSE_FS_CHAR_IS_MCHAR)
|
||||
# define canon_fspath(path,canon,flags) qse_canonmbspath(path,canon,flags)
|
||||
# define merge_fspath_dup(dir,file,mmgr) qse_mergembspathdup(dir,file,mmgr)
|
||||
# define get_fspath_core(fspath) qse_mbspathcore(fspath)
|
||||
# define get_fspath_base(fspath) qse_mbsbasename(fspath)
|
||||
# define IS_FSPATHSEP(x) QSE_ISPATHMBSEP(x)
|
||||
# define QSE_FS_T(x) QSE_MT(x)
|
||||
#else
|
||||
# define canon_fspath(fspath,canon,flags) qse_canonwcspath(fspath,canon,flags)
|
||||
# define merge_fspath_dup(dir,file,mmgr) qse_mergewcspathdup(dir,file,mmgr)
|
||||
# define get_fspath_core(fspath) qse_wcspathcore(fspath)
|
||||
# define get_fspath_base(fspath) qse_wcsbasename(fspath)
|
||||
# define IS_FSPATHSEP(x) QSE_ISPATHWCSEP(x)
|
||||
# define QSE_FS_T(x) QSE_WT(x)
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
qse_fs_errnum_t qse_fs_syserrtoerrnum (
|
||||
qse_fs_t* fs,
|
||||
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
|
||||
);
|
||||
|
||||
qse_fs_char_t* qse_fs_makefspathforwcs (
|
||||
qse_fs_t* fs,
|
||||
const qse_wchar_t* path
|
||||
);
|
||||
|
||||
qse_fs_char_t* qse_fs_dupfspathformbs (
|
||||
qse_fs_t* fs,
|
||||
const qse_mchar_t* path
|
||||
);
|
||||
|
||||
qse_fs_char_t* qse_fs_dupfspathforwcs (
|
||||
qse_fs_t* fs,
|
||||
const qse_wchar_t* path
|
||||
);
|
||||
|
||||
void qse_fs_freefspathformbs (
|
||||
qse_fs_t* fs,
|
||||
const qse_mchar_t* path,
|
||||
qse_fs_char_t* fspath
|
||||
);
|
||||
|
||||
void qse_fs_freefspathforwcs (
|
||||
qse_fs_t* fs,
|
||||
const qse_wchar_t* path,
|
||||
qse_fs_char_t* fspath
|
||||
);
|
||||
|
||||
#if defined(QSE_CHAR_IS_MCHAR)
|
||||
# define qse_fs_makefspath(fs,path) qse_fs_makefspathformbs(fs,path)
|
||||
# define qse_fs_freefspath(fs,path,fspath) qse_fs_freefspathformbs(fs,path,fspath);
|
||||
#else
|
||||
# define qse_fs_makefspath(fs,path) qse_fs_makefspathforwcs(fs,path)
|
||||
# define qse_fs_freefspath(fs,path,fspath) qse_fs_freefspathforwcs(fs,path,fspath);
|
||||
#endif
|
||||
|
||||
int qse_fs_sysgetattr (
|
||||
qse_fs_t* fs,
|
||||
const qse_fs_char_t* fspath,
|
||||
qse_fs_attr_t* attr
|
||||
);
|
||||
|
||||
int qse_fs_syscpfile (
|
||||
qse_fs_t* fs,
|
||||
const qse_fs_char_t* srcpath,
|
||||
const qse_fs_char_t* dstpath
|
||||
);
|
||||
|
||||
int qse_fs_sysmkdir (
|
||||
qse_fs_t* fs,
|
||||
const qse_fs_char_t* fspath
|
||||
);
|
||||
|
||||
int qse_fs_sysrmfile (
|
||||
qse_fs_t* fs,
|
||||
const qse_fs_char_t* fspath
|
||||
);
|
||||
|
||||
int qse_fs_sysrmdir (
|
||||
qse_fs_t* fs,
|
||||
const qse_fs_char_t* fspath
|
||||
);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
@ -1,203 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <qse/cmn/glob.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include <qse/cmn/path.h>
|
||||
#include <qse/cmn/dir.h>
|
||||
#include "mem.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#elif defined(__OS2__)
|
||||
# define INCL_DOSFILEMGR
|
||||
# define INCL_ERRORS
|
||||
# include <os2.h>
|
||||
#elif defined(__DOS__)
|
||||
# include <dos.h>
|
||||
# include <errno.h>
|
||||
#elif defined(macintosh)
|
||||
# include <Files.h>
|
||||
#else
|
||||
# include "syscall.h"
|
||||
#endif
|
||||
|
||||
#define NO_RECURSION 1
|
||||
|
||||
enum segment_type_t
|
||||
{
|
||||
NONE,
|
||||
ROOT,
|
||||
NORMAL
|
||||
};
|
||||
typedef enum segment_type_t segment_type_t;
|
||||
|
||||
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||
/* i don't support escaping in these systems */
|
||||
# define IS_ESC_MBS(c) (0)
|
||||
# define IS_ESC_WCS(c) (0)
|
||||
#else
|
||||
# define IS_ESC_MBS(c) ((c) == QSE_MT('\\'))
|
||||
# define IS_ESC_WCS(c) ((c) == QSE_WT('\\'))
|
||||
#endif
|
||||
|
||||
#define IS_NIL_MBS(c) ((c) == QSE_MT('\0'))
|
||||
#define IS_NIL_WCS(c) ((c) == QSE_WT('\0'))
|
||||
|
||||
/* this macro only checks for top-level wild-cards among these.
|
||||
* *, ?, [], !, -
|
||||
* see str-fnmat.c for more wild-card letters
|
||||
*/
|
||||
#define IS_WILD_MBS(c) ((c) == QSE_MT('*') || (c) == QSE_MT('?') || (c) == QSE_MT('['))
|
||||
#define IS_WILD_WCS(c) ((c) == QSE_WT('*') || (c) == QSE_WT('?') || (c) == QSE_WT('['))
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
#define glob qse_globmbs
|
||||
#define cbimpl_t qse_glob_mbscbimpl_t
|
||||
#define glob_t mbs_glob_t
|
||||
#define segment_t mbs_segment_t
|
||||
#define stack_node_t mbs_stack_node_t
|
||||
#define char_t qse_mchar_t
|
||||
#define cstr_t qse_mcstr_t
|
||||
#define T(x) QSE_MT(x)
|
||||
#define IS_ESC(x) IS_ESC_MBS(x)
|
||||
#define IS_DRIVE(x) QSE_ISPATHMBDRIVE(x)
|
||||
#define IS_SEP(x) QSE_ISPATHMBSEP(x)
|
||||
#define IS_SEP_OR_NIL(x) QSE_ISPATHMBSEPORNIL(x)
|
||||
#define IS_NIL(x) IS_NIL_MBS(x)
|
||||
#define IS_WILD(x) IS_WILD_MBS(x)
|
||||
#define str_t qse_mbs_t
|
||||
#define str_open qse_mbs_open
|
||||
#define str_close qse_mbs_close
|
||||
#define str_init qse_mbs_init
|
||||
#define str_fini qse_mbs_fini
|
||||
#define str_cat qse_mbs_cat
|
||||
#define str_ccat qse_mbs_ccat
|
||||
#define str_ncat qse_mbs_ncat
|
||||
#define str_setcapa qse_mbs_setcapa
|
||||
#define str_setlen qse_mbs_setlen
|
||||
#define STR_CAPA(x) QSE_MBS_CAPA(x)
|
||||
#define STR_LEN(x) QSE_MBS_LEN(x)
|
||||
#define STR_PTR(x) QSE_MBS_PTR(x)
|
||||
#define STR_XSTR(x) QSE_MBS_XSTR(x)
|
||||
#define STR_CPTR(x,y) QSE_MBS_CPTR(x,y)
|
||||
#define strnfnmat qse_mbsnfnmat
|
||||
#define DIR_CHAR_FLAGS QSE_DIR_MBSPATH
|
||||
#define path_exists mbs_path_exists
|
||||
#define search mbs_search
|
||||
#define get_next_segment mbs_get_next_segment
|
||||
#define handle_non_wild_segments mbs_handle_non_wild_segments
|
||||
#define CHAR_IS_MCHAR
|
||||
#undef INCLUDE_MBUF
|
||||
#include "glob.h"
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
#undef glob
|
||||
#undef cbimpl_t
|
||||
#undef glob_t
|
||||
#undef segment_t
|
||||
#undef stack_node_t
|
||||
#undef char_t
|
||||
#undef cstr_t
|
||||
#undef T
|
||||
#undef IS_ESC
|
||||
#undef IS_DRIVE
|
||||
#undef IS_SEP
|
||||
#undef IS_SEP_OR_NIL
|
||||
#undef IS_NIL
|
||||
#undef IS_WILD
|
||||
#undef str_t
|
||||
#undef str_open
|
||||
#undef str_close
|
||||
#undef str_init
|
||||
#undef str_fini
|
||||
#undef str_cat
|
||||
#undef str_ccat
|
||||
#undef str_ncat
|
||||
#undef str_setcapa
|
||||
#undef str_setlen
|
||||
#undef STR_CAPA
|
||||
#undef STR_LEN
|
||||
#undef STR_PTR
|
||||
#undef STR_XSTR
|
||||
#undef STR_CPTR
|
||||
#undef strnfnmat
|
||||
#undef DIR_CHAR_FLAGS
|
||||
#undef path_exists
|
||||
#undef search
|
||||
#undef get_next_segment
|
||||
#undef handle_non_wild_segments
|
||||
#undef CHAR_IS_MCHAR
|
||||
#undef INCLUDE_MBUF
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
#define glob qse_globwcs
|
||||
#define cbimpl_t qse_glob_wcscbimpl_t
|
||||
#define glob_t wcs_glob_t
|
||||
#define segment_t wcs_segment_t
|
||||
#define stack_node_t wcs_stack_node_t
|
||||
#define char_t qse_wchar_t
|
||||
#define cstr_t qse_wcstr_t
|
||||
#define T(x) QSE_WT(x)
|
||||
#define IS_ESC(x) IS_ESC_WCS(x)
|
||||
#define IS_DRIVE(x) QSE_ISPATHWCDRIVE(x)
|
||||
#define IS_SEP(x) QSE_ISPATHWCSEP(x)
|
||||
#define IS_SEP_OR_NIL(x) QSE_ISPATHWCSEPORNIL(x)
|
||||
#define IS_NIL(x) IS_NIL_WCS(x)
|
||||
#define IS_WILD(x) IS_WILD_WCS(x)
|
||||
#define str_t qse_wcs_t
|
||||
#define str_open qse_wcs_open
|
||||
#define str_close qse_wcs_close
|
||||
#define str_init qse_wcs_init
|
||||
#define str_fini qse_wcs_fini
|
||||
#define str_cat qse_wcs_cat
|
||||
#define str_ccat qse_wcs_ccat
|
||||
#define str_ncat qse_wcs_ncat
|
||||
#define str_setcapa qse_wcs_setcapa
|
||||
#define str_setlen qse_wcs_setlen
|
||||
#define STR_CAPA(x) QSE_WCS_CAPA(x)
|
||||
#define STR_LEN(x) QSE_WCS_LEN(x)
|
||||
#define STR_PTR(x) QSE_WCS_PTR(x)
|
||||
#define STR_XSTR(x) QSE_WCS_XSTR(x)
|
||||
#define STR_CPTR(x,y) QSE_WCS_CPTR(x,y)
|
||||
|
||||
#define strnfnmat qse_wcsnfnmat
|
||||
#define DIR_CHAR_FLAGS QSE_DIR_WCSPATH
|
||||
#define path_exists wcs_path_exists
|
||||
#define search wcs_search
|
||||
#define get_next_segment wcs_get_next_segment
|
||||
#define handle_non_wild_segments wcs_handle_non_wild_segments
|
||||
#undef CHAR_IS_MCHAR
|
||||
#if !defined(_WIN32)
|
||||
# define INCLUDE_MBUF 1
|
||||
#endif
|
||||
#include "glob.h"
|
@ -1,591 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#if defined(NO_RECURSION)
|
||||
typedef struct stack_node_t stack_node_t;
|
||||
#endif
|
||||
|
||||
struct glob_t
|
||||
{
|
||||
cbimpl_t cbimpl;
|
||||
void* cbctx;
|
||||
|
||||
qse_mmgr_t* mmgr;
|
||||
qse_cmgr_t* cmgr;
|
||||
int flags;
|
||||
|
||||
str_t path;
|
||||
str_t tbuf; /* temporary buffer */
|
||||
|
||||
#if defined(INCLUDE_MBUF)
|
||||
qse_mbs_t mbuf;
|
||||
#endif
|
||||
|
||||
int expanded;
|
||||
int fnmat_flags;
|
||||
|
||||
#if defined(NO_RECURSION)
|
||||
stack_node_t* stack;
|
||||
stack_node_t* free;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct glob_t glob_t;
|
||||
|
||||
struct segment_t
|
||||
{
|
||||
segment_type_t type;
|
||||
|
||||
const char_t* ptr;
|
||||
qse_size_t len;
|
||||
|
||||
char_t sep; /* preceeding separator */
|
||||
unsigned int wild: 1; /* indicate that it contains wildcards */
|
||||
unsigned int esc: 1; /* indicate that it contains escaped letters */
|
||||
unsigned int next: 1; /* indicate that it has the following segment */
|
||||
};
|
||||
|
||||
typedef struct segment_t segment_t;
|
||||
|
||||
#if defined(NO_RECURSION)
|
||||
struct stack_node_t
|
||||
{
|
||||
qse_size_t tmp;
|
||||
qse_size_t tmp2;
|
||||
qse_dir_t* dp;
|
||||
segment_t seg;
|
||||
|
||||
stack_node_t* next;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(INCLUDE_MBUF)
|
||||
static qse_mchar_t* wcs_to_mbuf (glob_t* g, const qse_wchar_t* wcs, qse_mbs_t* mbs)
|
||||
{
|
||||
qse_size_t ml, wl;
|
||||
|
||||
if (qse_wcstombswithcmgr (wcs, &wl, QSE_NULL, &ml, g->cmgr) <= -1 ||
|
||||
qse_mbs_setlen (mbs, ml) == (qse_size_t)-1) return QSE_NULL;
|
||||
|
||||
qse_wcstombswithcmgr (wcs, &wl, QSE_MBS_PTR(mbs), &ml, g->cmgr);
|
||||
return QSE_MBS_PTR(mbs);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int path_exists (glob_t* g, const char_t* name)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
#if !defined(INVALID_FILE_ATTRIBUTES)
|
||||
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
|
||||
#endif
|
||||
|
||||
#if defined(CHAR_IS_MCHAR)
|
||||
return (GetFileAttributesA(name) != INVALID_FILE_ATTRIBUTES)? 1: 0;
|
||||
#else
|
||||
return (GetFileAttributesW(name) != INVALID_FILE_ATTRIBUTES)? 1: 0;
|
||||
#endif
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
#elif defined(__OS2__)
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
FILESTATUS3 fs;
|
||||
APIRET rc;
|
||||
const qse_mchar_t* mptr;
|
||||
|
||||
#if defined(CHAR_IS_MCHAR)
|
||||
mptr = name;
|
||||
#else
|
||||
mptr = wcs_to_mbuf (g, name, &g->mbuf);
|
||||
if (mptr == QSE_NULL) return -1;
|
||||
#endif
|
||||
|
||||
rc = DosQueryPathInfo (mptr, FIL_STANDARD, &fs, QSE_SIZEOF(fs));
|
||||
|
||||
return (rc == NO_ERROR)? 1:
|
||||
(rc == ERROR_PATH_NOT_FOUND)? 0: -1;
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
#elif defined(__DOS__)
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
unsigned int x, attr;
|
||||
const qse_mchar_t* mptr;
|
||||
|
||||
#if defined(CHAR_IS_MCHAR)
|
||||
mptr = name;
|
||||
#else
|
||||
mptr = wcs_to_mbuf (g, name, &g->mbuf);
|
||||
if (mptr == QSE_NULL) return -1;
|
||||
#endif
|
||||
|
||||
x = _dos_getfileattr (mptr, &attr);
|
||||
return (x == 0)? 1:
|
||||
(errno == ENOENT)? 0: -1;
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
#elif defined(macintosh)
|
||||
HFileInfo fpb;
|
||||
const qse_mchar_t* mptr;
|
||||
|
||||
#if defined(CHAR_IS_MCHAR)
|
||||
mptr = name;
|
||||
#else
|
||||
mptr = wcs_to_mbuf (g, name, &g->mbuf);
|
||||
if (mptr == QSE_NULL) return -1;
|
||||
#endif
|
||||
|
||||
QSE_MEMSET (&fpb, 0, QSE_SIZEOF(fpb));
|
||||
fpb.ioNamePtr = (unsigned char*)mptr;
|
||||
|
||||
return (PBGetCatInfoSync ((CInfoPBRec*)&fpb) == noErr)? 1: 0;
|
||||
#else
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
#if defined(HAVE_LSTAT)
|
||||
qse_lstat_t st;
|
||||
#else
|
||||
qse_stat_t st;
|
||||
#endif
|
||||
const qse_mchar_t* mptr;
|
||||
|
||||
#if defined(CHAR_IS_MCHAR)
|
||||
mptr = name;
|
||||
#else
|
||||
mptr = wcs_to_mbuf (g, name, &g->mbuf);
|
||||
if (mptr == QSE_NULL) return -1;
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LSTAT)
|
||||
return (QSE_LSTAT (mptr, &st) <= -1)? 0: 1;
|
||||
#else
|
||||
/* use stat() if no lstat() is available. */
|
||||
return (QSE_STAT (mptr, &st) <= -1)? 0: 1;
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int get_next_segment (glob_t* g, segment_t* seg)
|
||||
{
|
||||
if (seg->type == NONE)
|
||||
{
|
||||
/* seg->ptr must point to the beginning of the pattern
|
||||
* and seg->len must be zero when seg->type is NONE. */
|
||||
if (IS_NIL(seg->ptr[0]))
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
else if (IS_SEP(seg->ptr[0]))
|
||||
{
|
||||
seg->type = ROOT;
|
||||
seg->len = 1;
|
||||
seg->next = IS_NIL(seg->ptr[1])? 0: 1;
|
||||
seg->sep = T('\0');
|
||||
seg->wild = 0;
|
||||
seg->esc = 0;
|
||||
}
|
||||
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||
else if (IS_DRIVE(seg->ptr))
|
||||
{
|
||||
seg->type = ROOT;
|
||||
seg->len = 2;
|
||||
if (IS_SEP(seg->ptr[2])) seg->len++;
|
||||
seg->next = IS_NIL(seg->ptr[seg->len])? 0: 1;
|
||||
seg->sep = T('\0');
|
||||
seg->wild = 0;
|
||||
seg->esc = 0;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
int escaped = 0;
|
||||
seg->type = NORMAL;
|
||||
seg->sep = T('\0');
|
||||
seg->wild = 0;
|
||||
seg->esc = 0;
|
||||
do
|
||||
{
|
||||
if (escaped) escaped = 0;
|
||||
else
|
||||
{
|
||||
if (IS_ESC(seg->ptr[seg->len]))
|
||||
{
|
||||
escaped = 1;
|
||||
seg->esc = 1;
|
||||
}
|
||||
else if (IS_WILD(seg->ptr[seg->len])) seg->wild = 1;
|
||||
}
|
||||
|
||||
seg->len++;
|
||||
}
|
||||
while (!IS_SEP_OR_NIL(seg->ptr[seg->len]));
|
||||
seg->next = IS_NIL(seg->ptr[seg->len])? 0: 1;
|
||||
}
|
||||
}
|
||||
else if (seg->type == ROOT)
|
||||
{
|
||||
int escaped = 0;
|
||||
seg->type = NORMAL;
|
||||
seg->ptr = &seg->ptr[seg->len];
|
||||
seg->len = 0;
|
||||
seg->sep = T('\0');
|
||||
seg->wild = 0;
|
||||
seg->esc = 0;
|
||||
|
||||
while (!IS_SEP_OR_NIL(seg->ptr[seg->len]))
|
||||
{
|
||||
if (escaped) escaped = 0;
|
||||
else
|
||||
{
|
||||
if (IS_ESC(seg->ptr[seg->len]))
|
||||
{
|
||||
escaped = 1;
|
||||
seg->esc = 1;
|
||||
}
|
||||
else if (IS_WILD(seg->ptr[seg->len])) seg->wild = 1;
|
||||
}
|
||||
seg->len++;
|
||||
}
|
||||
seg->next = IS_NIL(seg->ptr[seg->len])? 0: 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
QSE_ASSERT (seg->type == NORMAL);
|
||||
|
||||
seg->ptr = &seg->ptr[seg->len + 1];
|
||||
seg->len = 0;
|
||||
seg->wild = 0;
|
||||
seg->esc = 0;
|
||||
if (IS_NIL(seg->ptr[-1]))
|
||||
{
|
||||
seg->type = NONE;
|
||||
seg->next = 0;
|
||||
seg->sep = T('\0');
|
||||
}
|
||||
else
|
||||
{
|
||||
int escaped = 0;
|
||||
seg->sep = seg->ptr[-1];
|
||||
while (!IS_SEP_OR_NIL(seg->ptr[seg->len]))
|
||||
{
|
||||
if (escaped) escaped = 0;
|
||||
else
|
||||
{
|
||||
if (IS_ESC(seg->ptr[seg->len]))
|
||||
{
|
||||
escaped = 1;
|
||||
seg->esc = 1;
|
||||
}
|
||||
else if (IS_WILD(seg->ptr[seg->len])) seg->wild = 1;
|
||||
}
|
||||
seg->len++;
|
||||
}
|
||||
seg->next = IS_NIL(seg->ptr[seg->len])? 0: 1;
|
||||
}
|
||||
}
|
||||
|
||||
return seg->type;
|
||||
}
|
||||
|
||||
static int handle_non_wild_segments (glob_t* g, segment_t* seg)
|
||||
{
|
||||
while (get_next_segment(g, seg) != NONE && !seg->wild)
|
||||
{
|
||||
QSE_ASSERT (seg->type != NONE && !seg->wild);
|
||||
|
||||
if (seg->sep && str_ccat (&g->path, seg->sep) == (qse_size_t)-1) return -1;
|
||||
if (seg->esc)
|
||||
{
|
||||
/* if the segment contains escape sequences,
|
||||
* strip the escape letters off the segment */
|
||||
|
||||
cstr_t tmp;
|
||||
qse_size_t i;
|
||||
int escaped = 0;
|
||||
|
||||
if (STR_CAPA(&g->tbuf) < seg->len &&
|
||||
str_setcapa (&g->tbuf, seg->len) == (qse_size_t)-1) return -1;
|
||||
|
||||
tmp.ptr = STR_PTR(&g->tbuf);
|
||||
tmp.len = 0;
|
||||
|
||||
/* the following loop drops the last character
|
||||
* if it is the escape character */
|
||||
for (i = 0; i < seg->len; i++)
|
||||
{
|
||||
if (escaped)
|
||||
{
|
||||
escaped = 0;
|
||||
tmp.ptr[tmp.len++] = seg->ptr[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IS_ESC(seg->ptr[i]))
|
||||
escaped = 1;
|
||||
else
|
||||
tmp.ptr[tmp.len++] = seg->ptr[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (str_ncat (&g->path, tmp.ptr, tmp.len) == (qse_size_t)-1) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if the segmetn doesn't contain escape sequences,
|
||||
* append the segment to the path without special handling */
|
||||
if (str_ncat (&g->path, seg->ptr, seg->len) == (qse_size_t)-1) return -1;
|
||||
}
|
||||
|
||||
if (!seg->next && path_exists (g, STR_PTR(&g->path)) > 0)
|
||||
{
|
||||
/* reached the last segment. match if the path exists */
|
||||
if (g->cbimpl (STR_XSTR(&g->path), g->cbctx) <= -1) return -1;
|
||||
g->expanded = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int search (glob_t* g, segment_t* seg)
|
||||
{
|
||||
qse_dir_t* dp;
|
||||
qse_size_t tmp, tmp2;
|
||||
qse_dir_ent_t ent;
|
||||
int x;
|
||||
|
||||
#if defined(NO_RECURSION)
|
||||
stack_node_t* r;
|
||||
|
||||
entry:
|
||||
#endif
|
||||
|
||||
dp = QSE_NULL;
|
||||
|
||||
if (handle_non_wild_segments (g, seg) <= -1) goto oops;
|
||||
|
||||
if (seg->wild)
|
||||
{
|
||||
int dir_flags = DIR_CHAR_FLAGS;
|
||||
if (g->flags & QSE_GLOB_SKIPSPCDIR) dir_flags |= QSE_DIR_SKIPSPCDIR;
|
||||
|
||||
dp = qse_dir_open (
|
||||
g->mmgr, 0, (const qse_char_t*)STR_PTR(&g->path),
|
||||
dir_flags, QSE_NULL);
|
||||
if (dp)
|
||||
{
|
||||
tmp = STR_LEN(&g->path);
|
||||
|
||||
if (seg->sep && str_ccat (&g->path, seg->sep) == (qse_size_t)-1) goto oops;
|
||||
tmp2 = STR_LEN(&g->path);
|
||||
|
||||
while (1)
|
||||
{
|
||||
str_setlen (&g->path, tmp2);
|
||||
|
||||
x = qse_dir_read (dp, &ent);
|
||||
if (x <= -1)
|
||||
{
|
||||
if (g->flags & QSE_GLOB_TOLERANT) break;
|
||||
else goto oops;
|
||||
}
|
||||
if (x == 0) break;
|
||||
|
||||
if (str_cat (&g->path, (const char_t*)ent.name) == (qse_size_t)-1) goto oops;
|
||||
|
||||
if (strnfnmat (STR_CPTR(&g->path,tmp2), seg->ptr, seg->len, g->fnmat_flags) > 0)
|
||||
{
|
||||
if (seg->next)
|
||||
{
|
||||
#if defined(NO_RECURSION)
|
||||
if (g->free)
|
||||
{
|
||||
r = g->free;
|
||||
g->free = r->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = QSE_MMGR_ALLOC (g->mmgr, QSE_SIZEOF(*r));
|
||||
if (r == QSE_NULL) goto oops;
|
||||
}
|
||||
|
||||
/* push key variables that must be restored
|
||||
* into the stack. */
|
||||
r->tmp = tmp;
|
||||
r->tmp2 = tmp2;
|
||||
r->dp = dp;
|
||||
r->seg = *seg;
|
||||
|
||||
r->next = g->stack;
|
||||
g->stack = r;
|
||||
|
||||
/* move to the function entry point as if
|
||||
* a recursive call has been made */
|
||||
goto entry;
|
||||
|
||||
resume:
|
||||
;
|
||||
|
||||
#else
|
||||
segment_t save;
|
||||
int x;
|
||||
|
||||
save = *seg;
|
||||
x = search (g, seg);
|
||||
*seg = save;
|
||||
if (x <= -1) goto oops;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g->cbimpl (STR_XSTR(&g->path), g->cbctx) <= -1) goto oops;
|
||||
g->expanded = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
str_setlen (&g->path, tmp);
|
||||
qse_dir_close (dp); dp = QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
QSE_ASSERT (dp == QSE_NULL);
|
||||
|
||||
#if defined(NO_RECURSION)
|
||||
if (g->stack)
|
||||
{
|
||||
/* the stack is not empty. the emulated recusive call
|
||||
* must have been made. restore the variables pushed
|
||||
* and jump to the resumption point */
|
||||
r = g->stack;
|
||||
g->stack = r->next;
|
||||
|
||||
tmp = r->tmp;
|
||||
tmp2 = r->tmp2;
|
||||
dp = r->dp;
|
||||
*seg = r->seg;
|
||||
|
||||
/* link the stack node to the free list
|
||||
* instead of freeing it here */
|
||||
r->next = g->free;
|
||||
g->free = r;
|
||||
|
||||
goto resume;
|
||||
}
|
||||
|
||||
while (g->free)
|
||||
{
|
||||
/* destory the free list */
|
||||
r = g->free;
|
||||
g->free = r->next;
|
||||
QSE_MMGR_FREE (g->mmgr, r);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
oops:
|
||||
if (dp) qse_dir_close (dp);
|
||||
|
||||
#if defined(NO_RECURSION)
|
||||
while (g->stack)
|
||||
{
|
||||
r = g->stack;
|
||||
g->stack = r->next;
|
||||
qse_dir_close (r->dp);
|
||||
QSE_MMGR_FREE (g->mmgr, r);
|
||||
}
|
||||
|
||||
while (g->free)
|
||||
{
|
||||
r = g->stack;
|
||||
g->free = r->next;
|
||||
QSE_MMGR_FREE (g->mmgr, r);
|
||||
}
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int glob (const char_t* pattern, cbimpl_t cbimpl, void* cbctx, int flags, qse_mmgr_t* mmgr, qse_cmgr_t* cmgr)
|
||||
{
|
||||
segment_t seg;
|
||||
glob_t g;
|
||||
int x;
|
||||
|
||||
QSE_MEMSET (&g, 0, QSE_SIZEOF(g));
|
||||
g.cbimpl = cbimpl;
|
||||
g.cbctx = cbctx;
|
||||
g.mmgr = mmgr;
|
||||
g.cmgr = cmgr;
|
||||
g.flags = flags;
|
||||
|
||||
#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||
g.fnmat_flags |= QSE_STRFNMAT_IGNORECASE;
|
||||
g.fnmat_flags |= QSE_STRFNMAT_NOESCAPE;
|
||||
#else
|
||||
if (flags & QSE_GLOB_IGNORECASE) g.fnmat_flags |= QSE_STRFNMAT_IGNORECASE;
|
||||
if (flags & QSE_GLOB_NOESCAPE) g.fnmat_flags |= QSE_STRFNMAT_NOESCAPE;
|
||||
#endif
|
||||
if (flags & QSE_GLOB_PERIOD) g.fnmat_flags |= QSE_STRFNMAT_PERIOD;
|
||||
|
||||
if (str_init (&g.path, mmgr, 512) <= -1) return -1;
|
||||
if (str_init (&g.tbuf, mmgr, 256) <= -1)
|
||||
{
|
||||
str_fini (&g.path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(INCLUDE_MBUF)
|
||||
if (qse_mbs_init (&g.mbuf, mmgr, 512) <= -1)
|
||||
{
|
||||
str_fini (&g.path);
|
||||
str_fini (&g.path);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
QSE_MEMSET (&seg, 0, QSE_SIZEOF(seg));
|
||||
seg.type = NONE;
|
||||
seg.ptr = pattern;
|
||||
seg.len = 0;
|
||||
|
||||
x = search (&g, &seg);
|
||||
|
||||
#if defined(INCLUDE_MBUF)
|
||||
qse_mbs_fini (&g.mbuf);
|
||||
#endif
|
||||
str_fini (&g.tbuf);
|
||||
str_fini (&g.path);
|
||||
|
||||
if (x <= -1) return -1;
|
||||
return g.expanded;
|
||||
}
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/htb.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
|
||||
#define htb_t qse_htb_t
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include <qse/cmn/hton.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/fmt.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#if 0
|
||||
const qse_ip4ad_t qse_ip4ad_any =
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/lda.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#define lda_t qse_lda_t
|
||||
#define slot_t qse_lda_slot_t
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <qse/cmn/main.h>
|
||||
#include <qse/cmn/mbwc.h>
|
||||
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
int qse_runmain (
|
||||
int argc, qse_achar_t* argv[], qse_runmain_handler_t handler)
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
static int mbsn_to_wcsn_with_cmgr (
|
||||
const qse_mchar_t* mbs, qse_size_t* mbslen,
|
||||
|
@ -24,8 +24,8 @@
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _QSE_LIB_CMN_MEM_H_
|
||||
#define _QSE_LIB_CMN_MEM_H_
|
||||
#ifndef _QSE_LIB_CMN_MEM_PRV_H_
|
||||
#define _QSE_LIB_CMN_MEM_PRV_H_
|
||||
|
||||
#include <qse/cmn/mem.h>
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <qse/cmn/oht.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#define DATA_PTR(oht,index) \
|
||||
((void*)(((qse_byte_t*)(oht)->data) + ((index) * (oht)->scale)))
|
||||
|
@ -44,7 +44,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/pma.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
/* Returns number of bytes to add to (char *)ptr to make it
|
||||
properly aligned for the type. */
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/rbt.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#define rbt_t qse_rbt_t
|
||||
#define pair_t qse_rbt_pair_t
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include <qse/cmn/chr.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/lda.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#define OCC_MAX QSE_TYPE_MAX(qse_size_t)
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/sll.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#define sll_t qse_sll_t
|
||||
#define node_t qse_sll_node_t
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include <qse/cmn/slmb.h>
|
||||
#include <qse/cmn/utf8.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#if !defined(QSE_HAVE_CONFIG_H)
|
||||
# if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/chr.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/str.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
qse_size_t qse_mbscpy (qse_mchar_t* buf, const qse_mchar_t* str)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/str.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
qse_mchar_t* qse_mbsdup (const qse_mchar_t* str, qse_mmgr_t* mmgr)
|
||||
{
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#if !defined(QSE_HAVE_CONFIG_H)
|
||||
# if defined(_WIN32) || defined(__OS2__) || defined(__DOS__)
|
||||
|
@ -25,8 +25,8 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/str.h>
|
||||
#include "mem.h"
|
||||
#include "fmt.h"
|
||||
#include "mem-prv.h"
|
||||
#include "fmt-prv.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
str_t* str_open (qse_mmgr_t* mmgr, qse_size_t xtnsize, qse_size_t capa)
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include "fmt.h"
|
||||
#include "fmt-prv.h"
|
||||
|
||||
struct mbuf_t
|
||||
{
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/chr.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
qse_mchar_t* qse_mbstrmx (qse_mchar_t* str, int opt)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/time.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/tmr.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#define HEAP_PARENT(x) (((x) - 1) / 2)
|
||||
#define HEAP_LEFT(x) ((x) * 2 + 1)
|
||||
|
@ -153,7 +153,7 @@ SUBMATCH[4] = [defg]
|
||||
#include <qse/cmn/chr.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/pma.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#define tre_islower(c) QSE_ISLOWER(c)
|
||||
#define tre_isupper(c) QSE_ISUPPER(c)
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/uri.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
int qse_mbstouri (const qse_mchar_t* str, qse_muri_t* uri, int flags)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include <qse/cmn/xma.h>
|
||||
#include "mem.h"
|
||||
#include "mem-prv.h"
|
||||
|
||||
#define ALIGN QSE_SIZEOF(qse_size_t) /* this must be a power of 2 */
|
||||
#define HDRSIZE QSE_SIZEOF(qse_xma_blk_t)
|
||||
|
Reference in New Issue
Block a user