simplified file copying
This commit is contained in:
		| @ -46,6 +46,7 @@ libqsecmn_la_SOURCES = \ | ||||
| 	fmt-intmax.c \ | ||||
| 	fmt-out.c \ | ||||
| 	fs.c \ | ||||
| 	fs-attr.c \ | ||||
| 	fs-copy.c \ | ||||
| 	fs-delete.c \ | ||||
| 	fs-err.c \ | ||||
|  | ||||
| @ -107,38 +107,40 @@ 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 fio.c \ | ||||
| 	fma.c fmt-intmax.c fmt-out.c fs.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 mux.c nwad.c nwad-skad.c nwif.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 \ | ||||
| 	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 task.c time.c tio.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 | ||||
| 	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 mux.c nwad.c \ | ||||
| 	nwad-skad.c nwif.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 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 task.c time.c tio.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 fio.lo fma.lo fmt-intmax.lo fmt-out.lo fs.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 \ | ||||
| 	mux.lo nwad.lo nwad-skad.lo nwif.lo nwif-cfg.lo nwio.lo oht.lo \ | ||||
| 	opt.lo path-base.lo path-canon.lo path-core.lo path-merge.lo \ | ||||
| 	pio.lo pma.lo rbt.lo rex.lo sck.lo sio.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 \ | ||||
| 	task.lo time.lo tio.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) | ||||
| 	htb.lo fio.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 mux.lo nwad.lo nwad-skad.lo nwif.lo \ | ||||
| 	nwif-cfg.lo nwio.lo oht.lo opt.lo path-base.lo path-canon.lo \ | ||||
| 	path-core.lo path-merge.lo pio.lo pma.lo rbt.lo rex.lo sck.lo \ | ||||
| 	sio.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 task.lo time.lo tio.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) | ||||
| AM_V_lt = $(am__v_lt_@AM_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 \ | ||||
| 	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 \ | ||||
| 	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 mux.c nwad.c nwad-skad.c nwif.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 mux.c nwad.c nwad-skad.c nwif.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 \ | ||||
| 	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)/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@ | ||||
|  | ||||
							
								
								
									
										135
									
								
								qse/lib/cmn/fs-attr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								qse/lib/cmn/fs-attr.c
									
									
									
									
									
										Normal 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; | ||||
| } | ||||
| @ -30,9 +30,7 @@ | ||||
| #include "mem.h" | ||||
|  | ||||
| /* internal flags. it must not overlap with qse_fs_cpfile_flag_t enumerators */ | ||||
| #define CPFILE_DST_ATTR (1 << 27) | ||||
| #define CPFILE_DST_PATH_DUP (1 << 28) | ||||
| #define CPFILE_DST_FSPATH_DUP (1 << 29) | ||||
| #define CPFILE_DST_ATTR (1 << 29) | ||||
| #define CPFILE_DST_FSPATH_MERGED (1 << 30) | ||||
|  | ||||
| struct cpfile_t | ||||
| @ -42,14 +40,12 @@ struct cpfile_t | ||||
| 	qse_fs_char_t* src_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 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; | ||||
| @ -59,25 +55,6 @@ static int merge_dstdir_and_file (qse_fs_t* fs, cpfile_t* cpfile) | ||||
| 	 * in the directory */ | ||||
| 	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); | ||||
| 	if (!fstmp) | ||||
| 	{ | ||||
| @ -85,28 +62,25 @@ static int merge_dstdir_and_file (qse_fs_t* fs, cpfile_t* cpfile) | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (cpfile->flags & CPFILE_DST_FSPATH_DUP)  | ||||
| 		QSE_MMGR_FREE (fs->mmgr, cpfile->dst_fspath); | ||||
| 	qse_fs_freefspath (fs, QSE_NULL, cpfile->dst_fspath); | ||||
| 	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 | ||||
| 	{ | ||||
| 		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; | ||||
|  | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* | ||||
| #if defined(_WIN32) | ||||
| DWORD copy_file_progress ( | ||||
| @ -229,12 +203,12 @@ static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile) | ||||
| 			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 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, 0777); /* TODO: proper mode */ | ||||
| 			out = QSE_OPEN (cpfile->dst_fspath, O_CREAT | O_WRONLY | O_TRUNC, cpfile->src_attr.mode);  | ||||
| 		} | ||||
| 		if (out <= -1) | ||||
| 		{ | ||||
| @ -267,7 +241,8 @@ static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile) | ||||
| 			struct timeval tv[2]; | ||||
| 		#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); | ||||
| 				goto oops; | ||||
| @ -311,6 +286,29 @@ static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile) | ||||
| #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) | ||||
| { | ||||
| 	if (cpfile->src_attr.isdir) | ||||
| @ -320,11 +318,11 @@ static int copy_file (qse_fs_t* fs, cpfile_t* cpfile) | ||||
| 		qse_dir_t* dir; | ||||
| 		qse_dir_errnum_t direrr; | ||||
| 		qse_dir_ent_t dirent; | ||||
| 		qse_char_t* src_path, * dst_path; | ||||
| 		cpfile_t sub_cpfile; | ||||
| 		int x; | ||||
|  | ||||
| 	copy_dir: | ||||
| 		if (cpfile->flags  & CPFILE_DST_ATTR) | ||||
| 		if (cpfile->flags & CPFILE_DST_ATTR) | ||||
| 		{ | ||||
| 			if (!cpfile->dst_attr.isdir) | ||||
| 			{ | ||||
| @ -361,12 +359,20 @@ static int copy_file (qse_fs_t* fs, cpfile_t* cpfile) | ||||
|  | ||||
| 		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; | ||||
| 			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) | ||||
| 		{ | ||||
| 			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 */ | ||||
|  | ||||
|  | ||||
| 			src_path = qse_mergepathdup (cpfile->src_path, dirent.name, fs->mmgr); | ||||
| 			dst_path = qse_mergepathdup (cpfile->dst_path, dirent.name, fs->mmgr); | ||||
| 			if (!src_path  || !dst_path) | ||||
| 			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) | ||||
| 			{ | ||||
| 				if (dst_path) QSE_MMGR_FREE (fs->mmgr, dst_path); | ||||
| 				if (src_path) QSE_MMGR_FREE (fs->mmgr, src_path); | ||||
| 				clear_cpfile (fs, &sub_cpfile); | ||||
| 				qse_dir_close (dir); | ||||
| 				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) | ||||
| 			{ | ||||
| 				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.src_fspath = (qse_fs_char_t*)qse_fs_makefspathformbs (fs, srcpath); | ||||
| 	cpfile.dst_fspath = (qse_fs_char_t*)qse_fs_makefspathformbs (fs, dstpath); | ||||
| 	cpfile.src_path = (qse_char_t*)make_str_with_mbs (fs, srcpath); | ||||
| 	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; | ||||
| 	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); | ||||
|  | ||||
| 	free_str_with_mbs (fs, dstpath, cpfile.dst_path); | ||||
| 	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); | ||||
| 	clear_cpfile (fs, &cpfile); | ||||
| 	return ret; | ||||
|  | ||||
| oops: | ||||
| 	if (cpfile.dst_path) free_str_with_mbs (fs, dstpath, cpfile.dst_path); | ||||
| 	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); | ||||
| 	clear_cpfile (fs, &cpfile); | ||||
| 	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.src_fspath = (qse_fs_char_t*)qse_fs_makefspathforwcs (fs, srcpath); | ||||
| 	cpfile.dst_fspath = (qse_fs_char_t*)qse_fs_makefspathforwcs (fs, dstpath); | ||||
| 	cpfile.src_path = (qse_char_t*)make_str_with_wcs (fs, srcpath); | ||||
| 	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; | ||||
| 	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); | ||||
|  | ||||
| 	free_str_with_wcs (fs, dstpath, cpfile.dst_path); | ||||
| 	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); | ||||
| 	clear_cpfile (fs, &cpfile); | ||||
| 	return ret; | ||||
|  | ||||
| oops: | ||||
| 	if (cpfile.dst_path) free_str_with_wcs (fs, dstpath, cpfile.dst_path);  | ||||
| 	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); | ||||
| 	clear_cpfile (fs, &cpfile); | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -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 | ||||
| } | ||||
|  | ||||
| @ -143,11 +143,16 @@ void qse_fs_freefspathforwcs ( | ||||
| #	define qse_fs_freefspath(fs,path,fspath) qse_fs_freefspathforwcs(fs,path,fspath); | ||||
| #endif | ||||
|  | ||||
|  | ||||
| int qse_fs_getattr ( | ||||
| int qse_fs_sysgetattr ( | ||||
| 	qse_fs_t*            fs, | ||||
| 	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 ( | ||||
|  | ||||
		Reference in New Issue
	
	Block a user