simplified file copying

This commit is contained in:
hyung-hwan 2014-12-17 15:29:05 +00:00
parent 11f364a6d0
commit 206065f904
8 changed files with 268 additions and 207 deletions

View File

@ -172,6 +172,7 @@
fmt-intmax.c fmt-intmax.c
fmt-out.c fmt-out.c
fs.c fs.c
fs-attr.c
fs-copy.c fs-copy.c
fs-delete.c fs-delete.c
fs-err.c fs-err.c

View File

@ -124,11 +124,15 @@ struct qse_fs_attr_t
unsigned int isreg: 1; unsigned int isreg: 1;
unsigned int isblk: 1; unsigned int isblk: 1;
unsigned int ischr: 1; unsigned int ischr: 1;
qse_uintptr_t mode;
qse_uintmax_t size; qse_uintmax_t size;
qse_uintmax_t ino; qse_uintmax_t ino;
qse_uintmax_t dev; qse_uintmax_t dev;
qse_uintptr_t uid; qse_uintptr_t uid;
qse_uintptr_t gid; qse_uintptr_t gid;
qse_ntime_t atime; /* last access */ qse_ntime_t atime; /* last access */
qse_ntime_t mtime; /* last modification */ qse_ntime_t mtime; /* last modification */
qse_ntime_t ctime; /* last status change */ qse_ntime_t ctime; /* last status change */
@ -314,6 +318,24 @@ QSE_EXPORT int qse_fs_pop (
const qse_char_t* name const qse_char_t* name
); );
QSE_EXPORT int qse_fs_getattrmbs (
qse_fs_t* fs,
const qse_mchar_t* path,
qse_fs_attr_t* attr
);
QSE_EXPORT int qse_fs_getattrwcs (
qse_fs_t* fs,
const qse_wchar_t* path,
qse_fs_attr_t* attr
);
#if defined(QSE_CHAR_IS_MCHAR)
# define qse_fs_getattr(fs,path,attr) qse_fs_getattrmbs(fs,path,attr)
#else
# define qse_fs_getattr(fs,path,attr) qse_fs_getattrwcs(fs,path,attr)
#endif
QSE_EXPORT int qse_fs_move ( QSE_EXPORT int qse_fs_move (
qse_fs_t* fs, qse_fs_t* fs,
const qse_char_t* oldpath, const qse_char_t* oldpath,

View File

@ -46,6 +46,7 @@ libqsecmn_la_SOURCES = \
fmt-intmax.c \ fmt-intmax.c \
fmt-out.c \ fmt-out.c \
fs.c \ fs.c \
fs-attr.c \
fs-copy.c \ fs-copy.c \
fs-delete.c \ fs-delete.c \
fs-err.c \ fs-err.c \

View File

@ -107,38 +107,40 @@ libqsecmn_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
am__libqsecmn_la_SOURCES_DIST = alg-base64.c alg-rand.c alg-search.c \ 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 fio.c \ alg-sort.c assert.c chr.c dir.c dll.c env.c gdl.c htb.c fio.c \
fma.c fmt-intmax.c fmt-out.c fs.c fs-copy.c fs-delete.c \ fma.c fmt-intmax.c fmt-out.c fs.c fs-attr.c fs-copy.c \
fs-err.c fs-make.c fs-move.c glob.c hton.c ipad.c lda.c main.c \ fs-delete.c fs-err.c fs-make.c fs-move.c glob.c hton.c ipad.c \
mb8.c mbwc.c mbwc-str.c mem.c mux.c nwad.c nwad-skad.c nwif.c \ lda.c main.c mb8.c mbwc.c mbwc-str.c mem.c mux.c nwad.c \
nwif-cfg.c nwio.c oht.c opt.c path-base.c path-canon.c \ nwad-skad.c nwif.c nwif-cfg.c nwio.c oht.c opt.c path-base.c \
path-core.c path-merge.c pio.c pma.c rbt.c rex.c sck.c sio.c \ path-canon.c path-core.c path-merge.c pio.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 \ sck.c sio.c sll.c slmb.c str-beg.c str-cat.c str-chr.c \
str-cpy.c str-del.c str-dup.c str-dyn.c str-end.c str-excl.c \ str-cnv.c str-cmp.c str-cpy.c str-del.c str-dup.c str-dyn.c \
str-fcpy.c str-fmt.c str-fnmat.c str-incl.c str-join.c \ str-end.c str-excl.c str-fcpy.c str-fmt.c str-fnmat.c \
str-len.c str-pac.c str-pbrk.c str-put.c str-rev.c str-rot.c \ str-incl.c str-join.c str-len.c str-pac.c str-pbrk.c str-put.c \
str-set.c str-spl.c str-spn.c str-str.c str-subst.c str-tok.c \ str-rev.c str-rot.c str-set.c str-spl.c str-spn.c str-str.c \
str-trm.c str-word.c task.c time.c tio.c tmr.c tre.c tre-ast.c \ str-subst.c str-tok.c str-trm.c str-word.c task.c time.c tio.c \
tre-compile.c tre-match-bt.c tre-match-pa.c tre-parse.c \ tmr.c tre.c tre-ast.c tre-compile.c tre-match-bt.c \
tre-stack.c uri.c utf8.c xma.c uni.c cp949.c cp950.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_BUNDLED_UNICODE_TRUE@am__objects_1 = uni.lo
@ENABLE_XCMGRS_TRUE@am__objects_2 = cp949.lo cp950.lo @ENABLE_XCMGRS_TRUE@am__objects_2 = cp949.lo cp950.lo
am_libqsecmn_la_OBJECTS = alg-base64.lo alg-rand.lo alg-search.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 \ alg-sort.lo assert.lo chr.lo dir.lo dll.lo env.lo gdl.lo \
htb.lo fio.lo fma.lo fmt-intmax.lo fmt-out.lo fs.lo fs-copy.lo \ htb.lo fio.lo fma.lo fmt-intmax.lo fmt-out.lo fs.lo fs-attr.lo \
fs-delete.lo fs-err.lo fs-make.lo fs-move.lo glob.lo hton.lo \ fs-copy.lo fs-delete.lo fs-err.lo fs-make.lo fs-move.lo \
ipad.lo lda.lo main.lo mb8.lo mbwc.lo mbwc-str.lo mem.lo \ glob.lo hton.lo ipad.lo lda.lo main.lo mb8.lo mbwc.lo \
mux.lo nwad.lo nwad-skad.lo nwif.lo nwif-cfg.lo nwio.lo oht.lo \ mbwc-str.lo mem.lo mux.lo nwad.lo nwad-skad.lo nwif.lo \
opt.lo path-base.lo path-canon.lo path-core.lo path-merge.lo \ nwif-cfg.lo nwio.lo oht.lo opt.lo path-base.lo path-canon.lo \
pio.lo pma.lo rbt.lo rex.lo sck.lo sio.lo sll.lo slmb.lo \ path-core.lo path-merge.lo pio.lo pma.lo rbt.lo rex.lo sck.lo \
str-beg.lo str-cat.lo str-chr.lo str-cnv.lo str-cmp.lo \ sio.lo sll.lo slmb.lo str-beg.lo str-cat.lo str-chr.lo \
str-cpy.lo str-del.lo str-dup.lo str-dyn.lo str-end.lo \ str-cnv.lo str-cmp.lo str-cpy.lo str-del.lo str-dup.lo \
str-excl.lo str-fcpy.lo str-fmt.lo str-fnmat.lo str-incl.lo \ str-dyn.lo str-end.lo str-excl.lo str-fcpy.lo str-fmt.lo \
str-join.lo str-len.lo str-pac.lo str-pbrk.lo str-put.lo \ str-fnmat.lo str-incl.lo str-join.lo str-len.lo str-pac.lo \
str-rev.lo str-rot.lo str-set.lo str-spl.lo str-spn.lo \ str-pbrk.lo str-put.lo str-rev.lo str-rot.lo str-set.lo \
str-str.lo str-subst.lo str-tok.lo str-trm.lo str-word.lo \ str-spl.lo str-spn.lo str-str.lo str-subst.lo str-tok.lo \
task.lo time.lo tio.lo tmr.lo tre.lo tre-ast.lo tre-compile.lo \ str-trm.lo str-word.lo task.lo time.lo tio.lo tmr.lo tre.lo \
tre-match-bt.lo tre-match-pa.lo tre-parse.lo tre-stack.lo \ tre-ast.lo tre-compile.lo tre-match-bt.lo tre-match-pa.lo \
uri.lo utf8.lo xma.lo $(am__objects_1) $(am__objects_2) 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) libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@) AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@ -415,9 +417,9 @@ noinst_HEADERS = \
libqsecmn_la_SOURCES = alg-base64.c alg-rand.c alg-search.c alg-sort.c \ 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 fio.c fma.c \ assert.c chr.c dir.c dll.c env.c gdl.c htb.c fio.c fma.c \
fmt-intmax.c fmt-out.c fs.c fs-copy.c fs-delete.c fs-err.c \ fmt-intmax.c fmt-out.c fs.c fs-attr.c fs-copy.c fs-delete.c \
fs-make.c fs-move.c glob.c hton.c ipad.c lda.c main.c mb8.c \ fs-err.c fs-make.c fs-move.c glob.c hton.c ipad.c lda.c main.c \
mbwc.c mbwc-str.c mem.c mux.c nwad.c nwad-skad.c nwif.c \ mb8.c mbwc.c mbwc-str.c mem.c mux.c nwad.c nwad-skad.c nwif.c \
nwif-cfg.c nwio.c oht.c opt.c path-base.c path-canon.c \ nwif-cfg.c nwio.c oht.c opt.c path-base.c path-canon.c \
path-core.c path-merge.c pio.c pma.c rbt.c rex.c sck.c sio.c \ path-core.c path-merge.c pio.c pma.c rbt.c rex.c sck.c sio.c \
sll.c slmb.c str-beg.c str-cat.c str-chr.c str-cnv.c str-cmp.c \ sll.c slmb.c str-beg.c str-cat.c str-chr.c str-cnv.c str-cmp.c \
@ -529,6 +531,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fma.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-intmax.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmt-out.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-copy.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs-delete.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-err.Plo@am__quote@

135
qse/lib/cmn/fs-attr.c Normal file
View File

@ -0,0 +1,135 @@
/*
* $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;
}

View File

@ -30,9 +30,7 @@
#include "mem.h" #include "mem.h"
/* internal flags. it must not overlap with qse_fs_cpfile_flag_t enumerators */ /* internal flags. it must not overlap with qse_fs_cpfile_flag_t enumerators */
#define CPFILE_DST_ATTR (1 << 27) #define CPFILE_DST_ATTR (1 << 29)
#define CPFILE_DST_PATH_DUP (1 << 28)
#define CPFILE_DST_FSPATH_DUP (1 << 29)
#define CPFILE_DST_FSPATH_MERGED (1 << 30) #define CPFILE_DST_FSPATH_MERGED (1 << 30)
struct cpfile_t struct cpfile_t
@ -42,14 +40,12 @@ struct cpfile_t
qse_fs_char_t* src_fspath; qse_fs_char_t* src_fspath;
qse_fs_char_t* dst_fspath; qse_fs_char_t* dst_fspath;
qse_char_t* src_path;
qse_char_t* dst_path;
qse_fs_attr_t src_attr; qse_fs_attr_t src_attr;
qse_fs_attr_t dst_attr; qse_fs_attr_t dst_attr;
}; };
typedef struct cpfile_t cpfile_t; typedef struct cpfile_t cpfile_t;
static int merge_dstdir_and_file (qse_fs_t* fs, cpfile_t* cpfile) static int merge_dstdir_and_file (qse_fs_t* fs, cpfile_t* cpfile)
{ {
qse_fs_char_t* fstmp; qse_fs_char_t* fstmp;
@ -59,25 +55,6 @@ static int merge_dstdir_and_file (qse_fs_t* fs, cpfile_t* cpfile)
* in the directory */ * in the directory */
QSE_ASSERT (cpfile->dst_attr.isdir); QSE_ASSERT (cpfile->dst_attr.isdir);
if (cpfile->dst_path)
{
qse_char_t* tmp;
tmp = qse_mergepathdup (cpfile->dst_path, qse_basename (cpfile->src_path), fs->mmgr);
if (!tmp)
{
fs->errnum = QSE_FS_ENOMEM;
return -1;
}
if (cpfile->flags & CPFILE_DST_PATH_DUP)
QSE_MMGR_FREE (fs->mmgr, cpfile->dst_path);
cpfile->dst_path = tmp;
cpfile->flags |= CPFILE_DST_PATH_DUP;
}
fstmp = merge_fspath_dup (cpfile->dst_fspath, get_fspath_base (cpfile->src_fspath), fs->mmgr); fstmp = merge_fspath_dup (cpfile->dst_fspath, get_fspath_base (cpfile->src_fspath), fs->mmgr);
if (!fstmp) if (!fstmp)
{ {
@ -85,28 +62,25 @@ static int merge_dstdir_and_file (qse_fs_t* fs, cpfile_t* cpfile)
return -1; return -1;
} }
if (cpfile->flags & CPFILE_DST_FSPATH_DUP) qse_fs_freefspath (fs, QSE_NULL, cpfile->dst_fspath);
QSE_MMGR_FREE (fs->mmgr, cpfile->dst_fspath);
cpfile->dst_fspath = fstmp; cpfile->dst_fspath = fstmp;
cpfile->flags |= CPFILE_DST_FSPATH_DUP;
if (qse_fs_getattr (fs, cpfile->dst_fspath, &cpfile->dst_attr) >= 0) if (qse_fs_sysgetattr (fs, cpfile->dst_fspath, &cpfile->dst_attr) <= -1)
{ {
cpfile->flags |= CPFILE_DST_ATTR; /* attribute on the new destination is not available */
cpfile->flags &= ~CPFILE_DST_ATTR;
} }
else else
{ {
cpfile->flags &= ~CPFILE_DST_ATTR; /* the attribute has been updated to reflect the new destination */
cpfile->flags |= CPFILE_DST_ATTR;
} }
cpfile->flags |= CPFILE_DST_FSPATH_MERGED; cpfile->flags |= CPFILE_DST_FSPATH_MERGED;
return 0; return 0;
} }
/* /*
#if defined(_WIN32) #if defined(_WIN32)
DWORD copy_file_progress ( DWORD copy_file_progress (
@ -229,12 +203,12 @@ static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile)
goto oops; goto oops;
} }
out = QSE_OPEN (cpfile->dst_fspath, O_CREAT | O_WRONLY | O_TRUNC, 0777); /* TODO: proper mode */ 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 (out <= -1 && (cpfile->flags & QSE_FS_CPFILE_FORCE))
{ {
/* if forced, delete it and try to open it again */ /* if forced, delete it and try to open it again */
QSE_UNLINK (cpfile->dst_fspath); QSE_UNLINK (cpfile->dst_fspath);
out = QSE_OPEN (cpfile->dst_fspath, O_CREAT | O_WRONLY | O_TRUNC, 0777); /* TODO: proper mode */ out = QSE_OPEN (cpfile->dst_fspath, O_CREAT | O_WRONLY | O_TRUNC, cpfile->src_attr.mode);
} }
if (out <= -1) if (out <= -1)
{ {
@ -267,7 +241,8 @@ static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile)
struct timeval tv[2]; struct timeval tv[2];
#endif #endif
if (QSE_FCHOWN (out, cpfile->src_attr.uid, cpfile->src_attr.gid) <= -1) 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); fs->errnum = qse_fs_syserrtoerrnum (fs, errno);
goto oops; goto oops;
@ -311,6 +286,29 @@ static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile)
#endif #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;
}
}
static int copy_file (qse_fs_t* fs, cpfile_t* cpfile) static int copy_file (qse_fs_t* fs, cpfile_t* cpfile)
{ {
if (cpfile->src_attr.isdir) if (cpfile->src_attr.isdir)
@ -320,7 +318,7 @@ static int copy_file (qse_fs_t* fs, cpfile_t* cpfile)
qse_dir_t* dir; qse_dir_t* dir;
qse_dir_errnum_t direrr; qse_dir_errnum_t direrr;
qse_dir_ent_t dirent; qse_dir_ent_t dirent;
qse_char_t* src_path, * dst_path; cpfile_t sub_cpfile;
int x; int x;
copy_dir: copy_dir:
@ -361,12 +359,20 @@ static int copy_file (qse_fs_t* fs, cpfile_t* cpfile)
if (!(cpfile->flags & QSE_FS_CPFILE_RECURSIVE)) if (!(cpfile->flags & QSE_FS_CPFILE_RECURSIVE))
{ {
/* cann not copy a directory without recursion */ /* cannot copy a directory without recursion */
fs->errnum = QSE_FS_EISDIR; fs->errnum = QSE_FS_EISDIR;
return -1; return -1;
} }
dir = qse_dir_open (fs->mmgr, 0, cpfile->src_path, QSE_DIR_SKIPSPCDIR, &direrr); 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) if (!dir)
{ {
fs->errnum = qse_fs_direrrtoerrnum (fs, direrr); fs->errnum = qse_fs_direrrtoerrnum (fs, direrr);
@ -390,21 +396,21 @@ static int copy_file (qse_fs_t* fs, cpfile_t* cpfile)
} }
if (x == 0) break; /* no more entries */ if (x == 0) break; /* no more entries */
QSE_MEMSET (&sub_cpfile, 0, QSE_SIZEOF(sub_cpfile));
src_path = qse_mergepathdup (cpfile->src_path, dirent.name, fs->mmgr); sub_cpfile.flags = cpfile->flags & QSE_FS_CPFILE_ALL; /* inherit public flags */
dst_path = qse_mergepathdup (cpfile->dst_path, dirent.name, fs->mmgr); sub_cpfile.src_fspath = merge_fspath_dup (cpfile->src_fspath, (qse_fs_char_t*)dirent.name, fs->mmgr);
if (!src_path || !dst_path) 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)
{ {
if (dst_path) QSE_MMGR_FREE (fs->mmgr, dst_path); clear_cpfile (fs, &sub_cpfile);
if (src_path) QSE_MMGR_FREE (fs->mmgr, src_path);
qse_dir_close (dir); qse_dir_close (dir);
return -1; return -1;
} }
x = qse_fs_cpfile (fs, src_path, dst_path, (cpfile->flags & QSE_FS_CPFILE_ALL)); x = copy_file (fs, &sub_cpfile); /* TODO: remove recursion */
clear_cpfile (fs, &sub_cpfile);
QSE_MMGR_FREE (fs->mmgr, dst_path);
QSE_MMGR_FREE (fs->mmgr, src_path);
if (x <= -1) if (x <= -1)
{ {
qse_dir_close (dir); qse_dir_close (dir);
@ -469,34 +475,17 @@ int qse_fs_cpfilembs (qse_fs_t* fs, const qse_mchar_t* srcpath, const qse_mchar_
cpfile.flags = flags & QSE_FS_CPFILE_ALL; /* keep public flags only */ cpfile.flags = flags & QSE_FS_CPFILE_ALL; /* keep public flags only */
cpfile.src_fspath = (qse_fs_char_t*)qse_fs_makefspathformbs (fs, srcpath); cpfile.src_fspath = (qse_fs_char_t*)qse_fs_dupfspathformbs (fs, srcpath);
cpfile.dst_fspath = (qse_fs_char_t*)qse_fs_makefspathformbs (fs, dstpath); cpfile.dst_fspath = (qse_fs_char_t*)qse_fs_dupfspathformbs (fs, dstpath);
cpfile.src_path = (qse_char_t*)make_str_with_mbs (fs, srcpath); if (!cpfile.src_fspath || !cpfile.dst_fspath || prepare_cpfile (fs, &cpfile) <= -1) goto oops;
cpfile.dst_path = (qse_char_t*)make_str_with_mbs (fs, dstpath);
if (!cpfile.src_fspath || !cpfile.dst_fspath || !cpfile.src_path || !cpfile.dst_path) goto oops;
if (cpfile.dst_fspath != dstpath)
{
/* mark that it's been duplicated. */
cpfile.flags |= CPFILE_DST_FSPATH_DUP;
}
if (qse_fs_getattr (fs, cpfile.src_fspath, &cpfile.src_attr) <= -1) goto oops;
if (qse_fs_getattr (fs, cpfile.dst_fspath, &cpfile.dst_attr) >= 0) cpfile.flags |= CPFILE_DST_ATTR;
ret = copy_file (fs, &cpfile); ret = copy_file (fs, &cpfile);
free_str_with_mbs (fs, dstpath, cpfile.dst_path); clear_cpfile (fs, &cpfile);
free_str_with_mbs (fs, srcpath, cpfile.src_path);
qse_fs_freefspathformbs (fs, dstpath, cpfile.dst_fspath);
qse_fs_freefspathformbs (fs, srcpath, cpfile.src_fspath);
return ret; return ret;
oops: oops:
if (cpfile.dst_path) free_str_with_mbs (fs, dstpath, cpfile.dst_path); clear_cpfile (fs, &cpfile);
if (cpfile.src_path) free_str_with_mbs (fs, srcpath, cpfile.src_path);
if (cpfile.dst_fspath) qse_fs_freefspathformbs (fs, srcpath, cpfile.dst_fspath);
if (cpfile.src_fspath) qse_fs_freefspathformbs (fs, dstpath, cpfile.src_fspath);
return -1; return -1;
} }
@ -509,35 +498,16 @@ int qse_fs_cpfilewcs (qse_fs_t* fs, const qse_wchar_t* srcpath, const qse_wchar_
cpfile.flags = flags & QSE_FS_CPFILE_ALL; /* keep public flags only */ cpfile.flags = flags & QSE_FS_CPFILE_ALL; /* keep public flags only */
cpfile.src_fspath = (qse_fs_char_t*)qse_fs_makefspathforwcs (fs, srcpath); cpfile.src_fspath = (qse_fs_char_t*)qse_fs_dupfspathforwcs (fs, srcpath);
cpfile.dst_fspath = (qse_fs_char_t*)qse_fs_makefspathforwcs (fs, dstpath); cpfile.dst_fspath = (qse_fs_char_t*)qse_fs_dupfspathforwcs (fs, dstpath);
cpfile.src_path = (qse_char_t*)make_str_with_wcs (fs, srcpath); if (!cpfile.src_fspath || !cpfile.dst_fspath || prepare_cpfile (fs, &cpfile) <= -1) goto oops;
cpfile.dst_path = (qse_char_t*)make_str_with_wcs (fs, dstpath);
if (!cpfile.src_fspath || !cpfile.dst_fspath || !cpfile.src_path || !cpfile.dst_path) goto oops;
if (cpfile.dst_fspath != dstpath)
{
/* mark that it's been duplicated */
cpfile.flags |= CPFILE_DST_FSPATH_DUP;
}
if (qse_fs_getattr (fs, cpfile.src_fspath, &cpfile.src_attr) <= -1) goto oops;
if (qse_fs_getattr (fs, cpfile.dst_fspath, &cpfile.dst_attr) >= 0) cpfile.flags |= CPFILE_DST_ATTR;
ret = copy_file (fs, &cpfile); ret = copy_file (fs, &cpfile);
free_str_with_wcs (fs, dstpath, cpfile.dst_path); clear_cpfile (fs, &cpfile);
free_str_with_wcs (fs, srcpath, cpfile.src_path);
qse_fs_freefspathforwcs (fs, dstpath, cpfile.dst_fspath);
qse_fs_freefspathforwcs (fs, srcpath, cpfile.src_fspath);
return ret; return ret;
oops: oops:
if (cpfile.dst_path) free_str_with_wcs (fs, dstpath, cpfile.dst_path); clear_cpfile (fs, &cpfile);
if (cpfile.src_path) free_str_with_wcs (fs, srcpath, cpfile.src_path);
if (cpfile.dst_fspath) qse_fs_freefspathforwcs (fs, srcpath, cpfile.dst_fspath);
if (cpfile.src_fspath) qse_fs_freefspathforwcs (fs, dstpath, cpfile.src_fspath);
return -1; return -1;
} }

View File

@ -815,79 +815,3 @@ void qse_fs_freefspathforwcs (qse_fs_t* fs, const qse_wchar_t* path, qse_fs_char
} }
int qse_fs_getattr (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->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
}

View File

@ -143,13 +143,18 @@ void qse_fs_freefspathforwcs (
# define qse_fs_freefspath(fs,path,fspath) qse_fs_freefspathforwcs(fs,path,fspath); # define qse_fs_freefspath(fs,path,fspath) qse_fs_freefspathforwcs(fs,path,fspath);
#endif #endif
int qse_fs_sysgetattr (
int qse_fs_getattr (
qse_fs_t* fs, qse_fs_t* fs,
const qse_fs_char_t* fspath, const qse_fs_char_t* fspath,
qse_fs_attr_t* attr 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 ( int qse_fs_sysmkdir (
qse_fs_t* fs, qse_fs_t* fs,
const qse_fs_char_t* fspath const qse_fs_char_t* fspath