changed qse_fs_cpfile() to copy a directory that has been copied already
This commit is contained in:
		| @ -176,29 +176,33 @@ enum qse_fs_trait_t | |||||||
| typedef enum qse_fs_trait_t qse_fs_trait_t; | typedef enum qse_fs_trait_t qse_fs_trait_t; | ||||||
|  |  | ||||||
|  |  | ||||||
| /** | enum qse_fs_action_t | ||||||
|  * \return -1 on failure, 0 to cancel, 1 to keep copying | { | ||||||
|  */ | 	QSE_FS_CPFILE, | ||||||
| typedef int (*qse_fs_cbs_cp_t) ( | 	QSE_FS_RMFILE, | ||||||
| 	qse_fs_t*          fs, | 	QSE_FS_MKDIR, | ||||||
| 	const qse_char_t*  srcpath, | 	QSE_FS_RMDIR, | ||||||
| 	const qse_char_t*  dstpath, | 	QSE_FS_RENFILE, | ||||||
| 	qse_uintmax_t      bytes_totoal, | 	QSE_FS_SYMLINK | ||||||
| 	qse_uintmax_t      bytes_copied | }; | ||||||
| ); | typedef enum qse_fs_action_t qse_fs_action_t; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * \return -1 on failure, 0 to skip, 1 to delete |  * \return -1 on failure, 0 on success | ||||||
|  */ |  */ | ||||||
| typedef int (*qse_fs_cbs_rm_t) ( | typedef int (*qse_fs_actcb_t) ( | ||||||
| 	qse_fs_t*          fs, | 	qse_fs_t*          fs, | ||||||
| 	const qse_char_t* path | 	qse_fs_action_t    action, | ||||||
|  | 	const qse_char_t*  srcpath, | ||||||
|  | 	const qse_char_t*  dstpath, | ||||||
|  | 	qse_uintmax_t      bytes_total, | ||||||
|  | 	qse_uintmax_t      bytes_copied | ||||||
| ); | ); | ||||||
|  |  | ||||||
| struct qse_fs_cbs_t | struct qse_fs_cbs_t | ||||||
| { | { | ||||||
| 	qse_fs_cbs_rm_t rm; | 	qse_fs_actcb_t actcb; | ||||||
| 	qse_fs_cbs_cp_t cp; | 	/*qse_fs_querycb_t querycb;*/ | ||||||
| }; | }; | ||||||
| typedef struct qse_fs_cbs_t qse_fs_cbs_t; | typedef struct qse_fs_cbs_t qse_fs_cbs_t; | ||||||
|  |  | ||||||
| @ -217,6 +221,12 @@ struct qse_fs_t | |||||||
|  |  | ||||||
| 	qse_uint8_t     cpbuf[4096]; | 	qse_uint8_t     cpbuf[4096]; | ||||||
| 	void*           cfs; /* stack for recursive file copying */ | 	void*           cfs; /* stack for recursive file copying */ | ||||||
|  | 	struct | ||||||
|  | 	{ | ||||||
|  | 		void* ptr; | ||||||
|  | 		qse_size_t len; | ||||||
|  | 		qse_size_t capa; | ||||||
|  | 	} ddr; /* destination directores remembers while copying */ | ||||||
| }; | }; | ||||||
|  |  | ||||||
| enum qse_fs_opt_t | enum qse_fs_opt_t | ||||||
| @ -343,12 +353,6 @@ QSE_EXPORT int qse_fs_pop ( | |||||||
| ); | ); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| QSE_EXPORT int qse_fs_getattronfd ( | QSE_EXPORT int qse_fs_getattronfd ( | ||||||
| 	qse_fs_t*            fs, | 	qse_fs_t*            fs, | ||||||
| 	qse_fs_handle_t      fd, | 	qse_fs_handle_t      fd, | ||||||
|  | |||||||
| @ -35,6 +35,13 @@ | |||||||
| #define CPFILE_DST_ATTR (1 << 29) | #define CPFILE_DST_ATTR (1 << 29) | ||||||
| #define CPFILE_DST_FSPATH_MERGED (1 << 30) | #define CPFILE_DST_FSPATH_MERGED (1 << 30) | ||||||
|  |  | ||||||
|  | struct devino_t | ||||||
|  | { | ||||||
|  | 	qse_uintmax_t dev; | ||||||
|  | 	qse_uintmax_t ino; | ||||||
|  | }; | ||||||
|  | typedef struct devino_t devino_t; | ||||||
|  |  | ||||||
| struct cpfile_t | struct cpfile_t | ||||||
| { | { | ||||||
| 	int flags; | 	int flags; | ||||||
| @ -42,9 +49,63 @@ struct cpfile_t | |||||||
| 	qse_fs_char_t* dst_fspath; | 	qse_fs_char_t* dst_fspath; | ||||||
| 	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 is_dir_remembered (qse_fs_t* fs, qse_fs_attr_t* attr) | ||||||
|  | { | ||||||
|  | 	qse_size_t i; | ||||||
|  | 	devino_t* di; | ||||||
|  |  | ||||||
|  | 	di = (devino_t*)fs->ddr.ptr; | ||||||
|  | 	for (i = 0; i < fs->ddr.len; i++) | ||||||
|  | 	{ | ||||||
|  | 		if (attr->dev == di->dev && attr->ino == di->ino) return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int remember_dir_to_history (qse_fs_t* fs, qse_fs_attr_t* attr) | ||||||
|  | { | ||||||
|  | 	qse_size_t i; | ||||||
|  | 	devino_t* di; | ||||||
|  |  | ||||||
|  | 	di = (devino_t*)fs->ddr.ptr; | ||||||
|  | 	for (i = 0; i < fs->ddr.len; i++) | ||||||
|  | 	{ | ||||||
|  | 		if (attr->dev == di->dev  && attr->ino == di->ino)  | ||||||
|  | 		{ | ||||||
|  | 			fs->errnum = QSE_FS_EEXIST; | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | /* TODO: table baded lookup instead of sequential search? */ | ||||||
|  | 	if (fs->ddr.len >= fs->ddr.capa) | ||||||
|  | 	{ | ||||||
|  | 		qse_size_t newcapa; | ||||||
|  |  | ||||||
|  | 		newcapa = QSE_ALIGNTO(fs->ddr.capa + 1, 256); | ||||||
|  | 		di = (devino_t*)QSE_MMGR_REALLOC (fs->mmgr, di, newcapa * QSE_SIZEOF(*di)); | ||||||
|  |  | ||||||
|  | 		if (!di)  | ||||||
|  | 		{ | ||||||
|  | 			fs->errnum = QSE_FS_ENOMEM; | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		fs->ddr.ptr = di; | ||||||
|  | 		fs->ddr.capa = newcapa; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	di[fs->ddr.len].dev = attr->dev; | ||||||
|  | 	di[fs->ddr.len].ino = attr->ino; | ||||||
|  | 	fs->ddr.len++; | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| static int merge_dstdir_and_srcbase (qse_fs_t* fs, cpfile_t* cpfile) | static int merge_dstdir_and_srcbase (qse_fs_t* fs, cpfile_t* cpfile) | ||||||
| { | { | ||||||
| @ -169,7 +230,6 @@ static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile) | |||||||
|  |  | ||||||
| #else | #else | ||||||
|  |  | ||||||
|  |  | ||||||
| 	if ((cpfile->flags & QSE_FS_CPFILE_SYMLINK) && cpfile->src_attr.islnk) | 	if ((cpfile->flags & QSE_FS_CPFILE_SYMLINK) && cpfile->src_attr.islnk) | ||||||
| 	{ | 	{ | ||||||
| 		/* the source file is a symbolic link and the SYMLINK option is on.*/ | 		/* the source file is a symbolic link and the SYMLINK option is on.*/ | ||||||
| @ -196,8 +256,9 @@ static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile) | |||||||
| 		{ | 		{ | ||||||
| 			if (cpfile->flags & QSE_FS_CPFILE_FORCE) | 			if (cpfile->flags & QSE_FS_CPFILE_FORCE) | ||||||
| 			{ | 			{ | ||||||
| /* TODO: call cbs.rm callback??? */ |  | ||||||
| 				QSE_UNLINK (cpfile->dst_fspath); | 				QSE_UNLINK (cpfile->dst_fspath); | ||||||
|  | 				if (fs->cbs.actcb && qse_fs_invokecb (fs, QSE_FS_RMFILE, cpfile->dst_fspath, QSE_NULL, 0, 0) <= -1) goto oops_1; | ||||||
|  |  | ||||||
| 				if (QSE_SYMLINK (tmpbuf, cpfile->dst_fspath) <= -1) | 				if (QSE_SYMLINK (tmpbuf, cpfile->dst_fspath) <= -1) | ||||||
| 				{ | 				{ | ||||||
| 					fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | 					fs->errnum = qse_fs_syserrtoerrnum (fs, errno); | ||||||
| @ -205,25 +266,7 @@ static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile) | |||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 		if (fs->cbs.actcb && qse_fs_invokecb (fs, QSE_FS_SYMLINK, tmpbuf, cpfile->dst_fspath, 0, 0) <= -1) goto oops_1; | ||||||
| 		if (fs->cbs.cp) |  | ||||||
| 		{ |  | ||||||
| 			qse_char_t* srcpath = QSE_NULL, * dstpath = QSE_NULL; |  | ||||||
| 			int x = 1; |  | ||||||
|  |  | ||||||
| 			srcpath = (qse_char_t*)make_str_with_fspath (fs, cpfile->src_fspath); |  | ||||||
| 			dstpath = (qse_char_t*)make_str_with_fspath (fs, cpfile->dst_fspath); |  | ||||||
|  |  | ||||||
| 			if (srcpath && dstpath) |  | ||||||
| 			{ |  | ||||||
| 				x = fs->cbs.cp (fs, srcpath, dstpath, cpfile->src_attr.size, cpfile->src_attr.size); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			if (srcpath) free_str_with_fspath (fs, cpfile->src_fspath, srcpath); |  | ||||||
| 			if (dstpath) free_str_with_fspath (fs, cpfile->dst_fspath, dstpath); |  | ||||||
|  |  | ||||||
| 			if (x <= -1) goto oops_1; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		QSE_MMGR_FREE (fs->mmgr, tmpbuf); | 		QSE_MMGR_FREE (fs->mmgr, tmpbuf); | ||||||
| 		return 0; | 		return 0; | ||||||
| @ -262,7 +305,7 @@ static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile) | |||||||
| 			goto oops_2; | 			goto oops_2; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (fs->cbs.cp) | 		if (fs->cbs.actcb) | ||||||
| 		{ | 		{ | ||||||
| 			srcpath = (qse_char_t*)make_str_with_fspath (fs, cpfile->src_fspath); | 			srcpath = (qse_char_t*)make_str_with_fspath (fs, cpfile->src_fspath); | ||||||
| 			dstpath = (qse_char_t*)make_str_with_fspath (fs, cpfile->dst_fspath); | 			dstpath = (qse_char_t*)make_str_with_fspath (fs, cpfile->dst_fspath); | ||||||
| @ -276,7 +319,7 @@ static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile) | |||||||
| 			{ | 			{ | ||||||
| 				if (bytes_copied == 0 && srcpath && dstpath) | 				if (bytes_copied == 0 && srcpath && dstpath) | ||||||
| 				{ | 				{ | ||||||
| 					if (fs->cbs.cp (fs, srcpath, dstpath, cpfile->src_attr.size, bytes_copied) <= -1) goto oops_2; | 					if (fs->cbs.actcb (fs, QSE_FS_CPFILE, srcpath, dstpath, cpfile->src_attr.size, bytes_copied) <= -1) goto oops_2; | ||||||
| 				} | 				} | ||||||
| 				break; | 				break; | ||||||
| 			} | 			} | ||||||
| @ -293,7 +336,7 @@ static int copy_file_in_fs (qse_fs_t* fs, cpfile_t* cpfile) | |||||||
|  |  | ||||||
| 			if (srcpath && dstpath) | 			if (srcpath && dstpath) | ||||||
| 			{ | 			{ | ||||||
| 				if (fs->cbs.cp (fs, srcpath, dstpath, cpfile->src_attr.size, bytes_copied) <= -1) goto oops_2; | 				if (fs->cbs.actcb (fs, QSE_FS_CPFILE, srcpath, dstpath, cpfile->src_attr.size, bytes_copied) <= -1) goto oops_2; | ||||||
| /* TODO: skip, ignore, etc... */ | /* TODO: skip, ignore, etc... */ | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| @ -396,12 +439,6 @@ static void pop_cfs (qse_fs_t* fs, cpfile_t* cpfile, qse_dir_t** dir) | |||||||
| 	QSE_MMGR_FREE (fs->mmgr, cfs); | 	QSE_MMGR_FREE (fs->mmgr, cfs); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int can_copy_dir_into (qse_fs_t* fs, cpfile_t* cpfile) |  | ||||||
| { |  | ||||||
| /* TODO: */ |  | ||||||
| 	return 1; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int copy_file (qse_fs_t* fs, cpfile_t* cpfile) | static int copy_file (qse_fs_t* fs, cpfile_t* cpfile) | ||||||
| { | { | ||||||
| #if defined(NO_RECURSION) | #if defined(NO_RECURSION) | ||||||
| @ -454,6 +491,16 @@ start_over: | |||||||
| 			goto oops; | 			goto oops; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 		if (is_dir_remembered (fs, &cpfile->src_attr)) | ||||||
|  | 		{ | ||||||
|  | 			/* skip this source directory as it's one of the destination  | ||||||
|  | 			 * directores earlier. see the call to remember_dir_to_history() | ||||||
|  | 			 * below. */ | ||||||
|  | 			goto skip_dir; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		/* both the source and the destion is a directory */ | ||||||
| 		dir = qse_dir_open ( | 		dir = qse_dir_open ( | ||||||
| 			fs->mmgr, 0, (const qse_char_t*)cpfile->src_fspath, | 			fs->mmgr, 0, (const qse_char_t*)cpfile->src_fspath, | ||||||
| 		#if defined(QSE_FS_CHAR_IS_MCHAR) | 		#if defined(QSE_FS_CHAR_IS_MCHAR) | ||||||
| @ -469,17 +516,20 @@ start_over: | |||||||
| 			goto oops; | 			goto oops; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| /* TODO: check if the directory is beging copied into itself in advance...XXXXXXXXXXXXXXXXXXXXXX */ |  | ||||||
|  |  | ||||||
| 		if (qse_fs_mkdirsys (fs, cpfile->dst_fspath) <= -1)  | 		if (qse_fs_mkdirsys (fs, cpfile->dst_fspath) <= -1)  | ||||||
| 		{ | 		{ | ||||||
| 			/* it's ok if the destination directory already exists */ | 			/* it's ok if the destination directory already exists */ | ||||||
| 			if (fs->errnum != QSE_FS_EEXIST) goto oops; | 			if (fs->errnum != QSE_FS_EEXIST) goto oops; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (!can_copy_dir_into (fs, cpfile))  | 		/* (re)load the attribute. */ | ||||||
|  | 		if (qse_fs_getattrsys (fs, cpfile->dst_fspath, &cpfile->dst_attr, QSE_FS_GETATTR_SYMLINK) <= -1) goto oops; | ||||||
|  | 		cpfile->flags |= CPFILE_DST_ATTR; | ||||||
|  |  | ||||||
|  | 		if (remember_dir_to_history (fs, &cpfile->dst_attr) <= -1)  | ||||||
| 		{ | 		{ | ||||||
| 			fs->errnum = QSE_FS_EPERM; | 			/* if the directory has been copied once, fs->errnum should be QSE_FS_EEXIST */ | ||||||
|  | 			if (fs->errnum == QSE_FS_EEXIST) goto close_dir; | ||||||
| 			goto oops; | 			goto oops; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @ -532,8 +582,12 @@ start_over: | |||||||
| 		#endif | 		#endif | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 	close_dir: | ||||||
| 		qse_dir_close (dir); | 		qse_dir_close (dir); | ||||||
| 		dir = QSE_NULL; | 		dir = QSE_NULL; | ||||||
|  |  | ||||||
|  | 	skip_dir: | ||||||
|  | 		/* do nothing more */ ; | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| @ -570,6 +624,7 @@ start_over: | |||||||
| 		if (copy_file_in_fs (fs, cpfile) <= -1) goto oops; | 		if (copy_file_in_fs (fs, cpfile) <= -1) goto oops; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | skip: | ||||||
| #if defined(NO_RECURSION) | #if defined(NO_RECURSION) | ||||||
| 	if (fs->cfs) | 	if (fs->cfs) | ||||||
| 	{  | 	{  | ||||||
| @ -636,6 +691,7 @@ oops: | |||||||
| int qse_fs_cpfilembs (qse_fs_t* fs, const qse_mchar_t* srcpath, const qse_mchar_t* dstpath, int flags) | int qse_fs_cpfilembs (qse_fs_t* fs, const qse_mchar_t* srcpath, const qse_mchar_t* dstpath, int flags) | ||||||
| { | { | ||||||
| 	glob_ctx_t ctx; | 	glob_ctx_t ctx; | ||||||
|  | 	int ret = 0; | ||||||
|  |  | ||||||
| 	ctx.fs = fs; | 	ctx.fs = fs; | ||||||
| 	ctx.flags = flags; | 	ctx.flags = flags; | ||||||
| @ -648,10 +704,8 @@ int qse_fs_cpfilembs (qse_fs_t* fs, const qse_mchar_t* srcpath, const qse_mchar_ | |||||||
| 		if (qse_globmbs (srcpath, copy_file_for_glob, &ctx, DEFAULT_GLOB_FLAGS, fs->mmgr, fs->cmgr) <= -1) | 		if (qse_globmbs (srcpath, copy_file_for_glob, &ctx, DEFAULT_GLOB_FLAGS, fs->mmgr, fs->cmgr) <= -1) | ||||||
| 		{ | 		{ | ||||||
| 			if (fs->errnum == QSE_FS_ENOERR) fs->errnum = QSE_FS_EGLOB; | 			if (fs->errnum == QSE_FS_ENOERR) fs->errnum = QSE_FS_EGLOB; | ||||||
| 			return -1; | 			ret = -1; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		return 0; |  | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| @ -659,13 +713,23 @@ int qse_fs_cpfilembs (qse_fs_t* fs, const qse_mchar_t* srcpath, const qse_mchar_ | |||||||
| 		s.ptr = (qse_mchar_t*)srcpath; | 		s.ptr = (qse_mchar_t*)srcpath; | ||||||
| 		s.len = 0; /* not important */ | 		s.len = 0; /* not important */ | ||||||
| 		/* let me use the glob callback function for simplicity */ | 		/* let me use the glob callback function for simplicity */ | ||||||
| 		return copy_file_for_glob (&s, &ctx); | 		ret = copy_file_for_glob (&s, &ctx); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if (fs->ddr.ptr) | ||||||
|  | 	{ | ||||||
|  | 		QSE_MMGR_FREE (fs->mmgr, fs->ddr.ptr); | ||||||
|  | 		fs->ddr.ptr = QSE_NULL; | ||||||
|  | 		fs->ddr.len = 0; | ||||||
|  | 		fs->ddr.capa = 0; | ||||||
|  | 	} | ||||||
|  | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| int qse_fs_cpfilewcs (qse_fs_t* fs, const qse_wchar_t* srcpath, const qse_wchar_t* dstpath, int flags) | int qse_fs_cpfilewcs (qse_fs_t* fs, const qse_wchar_t* srcpath, const qse_wchar_t* dstpath, int flags) | ||||||
| { | { | ||||||
| 	glob_ctx_t ctx; | 	glob_ctx_t ctx; | ||||||
|  | 	int ret = 0; | ||||||
|  |  | ||||||
| 	ctx.fs = fs; | 	ctx.fs = fs; | ||||||
| 	ctx.flags = flags; | 	ctx.flags = flags; | ||||||
| @ -678,10 +742,8 @@ int qse_fs_cpfilewcs (qse_fs_t* fs, const qse_wchar_t* srcpath, const qse_wchar_ | |||||||
| 		if (qse_globwcs (srcpath, copy_file_for_glob, &ctx, DEFAULT_GLOB_FLAGS, fs->mmgr, fs->cmgr) <= -1) | 		if (qse_globwcs (srcpath, copy_file_for_glob, &ctx, DEFAULT_GLOB_FLAGS, fs->mmgr, fs->cmgr) <= -1) | ||||||
| 		{ | 		{ | ||||||
| 			if (fs->errnum == QSE_FS_ENOERR) fs->errnum = QSE_FS_EGLOB; | 			if (fs->errnum == QSE_FS_ENOERR) fs->errnum = QSE_FS_EGLOB; | ||||||
| 			return -1; | 			ret = -1; | ||||||
| 		}  | 		}  | ||||||
|  |  | ||||||
| 		return 0; |  | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| @ -689,6 +751,16 @@ int qse_fs_cpfilewcs (qse_fs_t* fs, const qse_wchar_t* srcpath, const qse_wchar_ | |||||||
| 		qse_wcstr_t s; | 		qse_wcstr_t s; | ||||||
| 		s.ptr = (qse_wchar_t*)srcpath; | 		s.ptr = (qse_wchar_t*)srcpath; | ||||||
| 		s.len = 0; /* not important */ | 		s.len = 0; /* not important */ | ||||||
| 		return copy_file_for_glob (&s, &ctx); | 		ret = copy_file_for_glob (&s, &ctx); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if (fs->ddr.ptr) | ||||||
|  | 	{ | ||||||
|  | 		QSE_MMGR_FREE (fs->mmgr, fs->ddr.ptr); | ||||||
|  | 		fs->ddr.ptr = QSE_NULL; | ||||||
|  | 		fs->ddr.len = 0; | ||||||
|  | 		fs->ddr.capa = 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return ret; | ||||||
| } | } | ||||||
|  | |||||||
| @ -127,10 +127,10 @@ static int delete_file (qse_fs_t* fs, const qse_char_t* path, int purge) | |||||||
| 	qse_fs_char_t* fspath; | 	qse_fs_char_t* fspath; | ||||||
| 	int ret; | 	int ret; | ||||||
|  |  | ||||||
| 	if (fs->cbs.rm)  | 	if (fs->cbs.actcb)  | ||||||
| 	{ | 	{ | ||||||
| 		int x; | 		int x; | ||||||
| 		x = fs->cbs.rm (fs, path); | 		x = fs->cbs.actcb (fs, QSE_FS_RMFILE, path, QSE_NULL, 0, 0); | ||||||
| 		if (x <= -1) return -1; | 		if (x <= -1) return -1; | ||||||
| 		if (x == 0) return 0; /* skipped */ | 		if (x == 0) return 0; /* skipped */ | ||||||
| 	} | 	} | ||||||
| @ -184,10 +184,10 @@ static int delete_directory_nocbs (qse_fs_t* fs, const qse_char_t* path) | |||||||
|  |  | ||||||
| static int delete_directory (qse_fs_t* fs, const qse_char_t* path) | static int delete_directory (qse_fs_t* fs, const qse_char_t* path) | ||||||
| { | { | ||||||
| 	if (fs->cbs.rm)  | 	if (fs->cbs.actcb)  | ||||||
| 	{ | 	{ | ||||||
| 		int x; | 		int x; | ||||||
| 		x = fs->cbs.rm (fs, path); | 		x = fs->cbs.actcb (fs, QSE_FS_RMDIR, path, QSE_NULL, 0, 0); | ||||||
| 		if (x <= -1) return -1; | 		if (x <= -1) return -1; | ||||||
| 		if (x == 0) return 0; /* skipped */ | 		if (x == 0) return 0; /* skipped */ | ||||||
| 	} | 	} | ||||||
| @ -276,70 +276,51 @@ static int purge_path (qse_fs_t* fs, const qse_char_t* path) | |||||||
| static int delete_from_fs_with_mbs (qse_fs_t* fs, const qse_mchar_t* path, int dir) | static int delete_from_fs_with_mbs (qse_fs_t* fs, const qse_mchar_t* path, int dir) | ||||||
| { | { | ||||||
| 	qse_fs_char_t* fspath; | 	qse_fs_char_t* fspath; | ||||||
| 	int ret; | 	int ret = 0; | ||||||
|  |  | ||||||
| 	fspath = qse_fs_makefspathformbs (fs, path); | 	fspath = qse_fs_makefspathformbs (fs, path); | ||||||
| 	if (!fspath) return -1; | 	if (!fspath) return -1; | ||||||
|  |  | ||||||
| 	if (fs->cbs.rm) | 	if (fs->cbs.actcb) | ||||||
| 	{ | 	{ | ||||||
| 		qse_char_t* xpath; |  | ||||||
| 		int x; | 		int x; | ||||||
|  |  | ||||||
| 		xpath = (qse_char_t*)make_str_with_mbs (fs, path); | 		x = qse_fs_invokecb (fs, (dir? QSE_FS_RMDIR: QSE_FS_RMFILE), fspath, QSE_NULL, 0, 0); | ||||||
| 		if (!xpath) |  | ||||||
| 		{ |  | ||||||
| 			fs->errnum = QSE_FS_ENOMEM; |  | ||||||
| 			return -1; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		x = fs->cbs.rm (fs, xpath); | 		if (x <= -1) { ret = -1; goto done; }  | ||||||
|  | 		if (x == 0) goto done; /* skipped */ | ||||||
| 		free_str_with_mbs (fs, path, xpath); |  | ||||||
|  |  | ||||||
| 		if (x <= -1) return -1; |  | ||||||
| 		if (x == 0) return 0; /* skipped */ |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	ret = dir? qse_fs_rmdirsys (fs, fspath):  | 	ret = dir? qse_fs_rmdirsys (fs, fspath):  | ||||||
| 	           qse_fs_rmfilesys (fs, fspath); | 	           qse_fs_rmfilesys (fs, fspath); | ||||||
|  |  | ||||||
|  | done: | ||||||
| 	qse_fs_freefspathformbs (fs, path, fspath); | 	qse_fs_freefspathformbs (fs, path, fspath); | ||||||
|  |  | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int delete_from_fs_with_wcs (qse_fs_t* fs, const qse_wchar_t* path, int dir) | static int delete_from_fs_with_wcs (qse_fs_t* fs, const qse_wchar_t* path, int dir) | ||||||
| { | { | ||||||
| 	qse_fs_char_t* fspath; | 	qse_fs_char_t* fspath; | ||||||
| 	int ret; | 	int ret = 0; | ||||||
|  |  | ||||||
| 	if (fs->cbs.rm) |  | ||||||
| 	{ |  | ||||||
| 		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.rm (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); | 	fspath = qse_fs_makefspathforwcs (fs, path); | ||||||
| 	if (!fspath) return -1; | 	if (!fspath) return -1; | ||||||
|  |  | ||||||
|  | 	if (fs->cbs.actcb) | ||||||
|  | 	{ | ||||||
|  | 		int x; | ||||||
|  |  | ||||||
|  | 		x = qse_fs_invokecb (fs, (dir? QSE_FS_RMDIR: QSE_FS_RMFILE), fspath, QSE_NULL, 0, 0); | ||||||
|  |  | ||||||
|  | 		if (x <= -1) { ret = -1; goto done; }  | ||||||
|  | 		if (x == 0) goto done; /* skipped */ | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	ret = dir? qse_fs_rmdirsys (fs, fspath):  | 	ret = dir? qse_fs_rmdirsys (fs, fspath):  | ||||||
| 	           qse_fs_rmfilesys (fs, fspath); | 	           qse_fs_rmfilesys (fs, fspath); | ||||||
|  |  | ||||||
|  | done: | ||||||
| 	qse_fs_freefspathforwcs (fs, path, fspath); | 	qse_fs_freefspathforwcs (fs, path, fspath); | ||||||
|  |  | ||||||
| 	return ret; | 	return ret; | ||||||
|  | |||||||
| @ -192,6 +192,16 @@ int qse_fs_rmdirsys ( | |||||||
| 	const qse_fs_char_t* fspath | 	const qse_fs_char_t* fspath | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int qse_fs_invokecb ( | ||||||
|  | 	qse_fs_t*       fs, | ||||||
|  | 	qse_fs_action_t action, | ||||||
|  | 	qse_fs_char_t*  src_fspath, | ||||||
|  | 	qse_fs_char_t*  dst_fspath, | ||||||
|  | 	qse_uintmax_t bytes_total, | ||||||
|  | 	qse_uintmax_t bytes_done | ||||||
|  | ); | ||||||
|  |  | ||||||
| #if defined(__cplusplus) | #if defined(__cplusplus) | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -823,3 +823,35 @@ void qse_fs_freefspathforwcs (qse_fs_t* fs, const qse_wchar_t* path, qse_fs_char | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | int qse_fs_invokecb (qse_fs_t* fs, qse_fs_action_t action, qse_fs_char_t* src_fspath, qse_fs_char_t* dst_fspath, qse_uintmax_t bytes_total, qse_uintmax_t bytes_done) | ||||||
|  | { | ||||||
|  | 	qse_char_t* srcpath = QSE_NULL, * dstpath = QSE_NULL; | ||||||
|  | 	int x = 1; | ||||||
|  |  | ||||||
|  | 	if (src_fspath)  | ||||||
|  | 	{ | ||||||
|  | 		srcpath = (qse_char_t*)make_str_with_fspath (fs, src_fspath); | ||||||
|  | 		if (!srcpath)  | ||||||
|  | 		{ | ||||||
|  | 			x = -1; | ||||||
|  | 			goto done; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (dst_fspath)  | ||||||
|  | 	{ | ||||||
|  | 		dstpath = (qse_char_t*)make_str_with_fspath (fs, dst_fspath); | ||||||
|  | 		if (!dstpath) | ||||||
|  | 		{ | ||||||
|  | 			x = -1; | ||||||
|  | 			goto done; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	x = fs->cbs.actcb (fs, action, srcpath, dstpath, bytes_total, bytes_done); | ||||||
|  |  | ||||||
|  | done: | ||||||
|  | 	if (srcpath) free_str_with_fspath (fs, cpfile->src_fspath, srcpath); | ||||||
|  | 	if (dstpath) free_str_with_fspath (fs, cpfile->dst_fspath, dstpath); | ||||||
|  |  | ||||||
|  | 	return x; | ||||||
|  | } | ||||||
|  | |||||||
| @ -12,13 +12,40 @@ | |||||||
| #	include <windows.h> | #	include <windows.h> | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| static int fs_rm (qse_fs_t* fs, const qse_char_t* path) | static int fs_actcb (qse_fs_t* fs, qse_fs_action_t act, const qse_char_t* srcpath, const qse_char_t* dstpath, qse_uintmax_t total, qse_uintmax_t done) | ||||||
| { | { | ||||||
| 	qse_printf (QSE_T("Deleting [%s]\n"), path); | 	switch (act) | ||||||
|  | 	{ | ||||||
|  | 		case QSE_FS_CPFILE: | ||||||
|  | 			if (total == done) qse_printf (QSE_T("Copied [%s] to [%s]\n"), srcpath, dstpath); | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 		case QSE_FS_RMFILE: | ||||||
|  | 			qse_printf (QSE_T("Removed file [%s]\n"), srcpath); | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 		case QSE_FS_SYMLINK: | ||||||
|  | 			qse_printf (QSE_T("Symlinked [%s] to [%s]\n"), srcpath, dstpath); | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 		case QSE_FS_MKDIR: | ||||||
|  | 			qse_printf (QSE_T("Made directory [%s]\n"), srcpath); | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 		case QSE_FS_RMDIR: | ||||||
|  | 			qse_printf (QSE_T("Removed directory [%s]\n"), srcpath); | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 		case QSE_FS_RENFILE: | ||||||
|  | 			qse_printf (QSE_T("renamed  [%s] to [%s]\n"), srcpath); | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| /*if (qse_strcmp(path, QSE_T("b/c")) == 0) return 0;*/ | /*if (qse_strcmp(path, QSE_T("b/c")) == 0) return 0;*/ | ||||||
|         return 1; |         return 1; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| static void print_usage (const qse_char_t* argv0) | static void print_usage (const qse_char_t* argv0) | ||||||
| { | { | ||||||
| 	qse_fprintf (QSE_STDERR, QSE_T("Usage: %s command filename\n"), qse_basename(argv0)); | 	qse_fprintf (QSE_STDERR, QSE_T("Usage: %s command filename\n"), qse_basename(argv0)); | ||||||
| @ -40,7 +67,7 @@ static int fs_main (int argc, qse_char_t* argv[]) | |||||||
| 	fs = qse_fs_open (QSE_MMGR_GETDFL(), 0); | 	fs = qse_fs_open (QSE_MMGR_GETDFL(), 0); | ||||||
|  |  | ||||||
| 	qse_memset (&cbs, 0, QSE_SIZEOF(cbs)); | 	qse_memset (&cbs, 0, QSE_SIZEOF(cbs)); | ||||||
| 	cbs.rm = fs_rm; | 	cbs.actcb = fs_actcb; | ||||||
| 	qse_fs_setopt (fs, QSE_FS_CBS, &cbs); | 	qse_fs_setopt (fs, QSE_FS_CBS, &cbs); | ||||||
|  |  | ||||||
| 	if (qse_strcmp(argv[1], QSE_T("rmfile")) == 0) | 	if (qse_strcmp(argv[1], QSE_T("rmfile")) == 0) | ||||||
|  | |||||||
| @ -25,9 +25,35 @@ static void print_usage (const qse_char_t* argv0) | |||||||
| 	qse_fprintf (QSE_STDERR, QSE_T("  -g            glob\n")); | 	qse_fprintf (QSE_STDERR, QSE_T("  -g            glob\n")); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int fs_cp (qse_fs_t* fs, const qse_char_t* srcpath, const qse_char_t* dstpath, qse_uintmax_t total, qse_uintmax_t copied) | static int fs_actcb (qse_fs_t* fs, qse_fs_action_t act, const qse_char_t* srcpath, const qse_char_t* dstpath, qse_uintmax_t total, qse_uintmax_t done) | ||||||
| { | { | ||||||
| 	if (total == copied) qse_printf (QSE_T("Copied [%s] to [%s]\n"), srcpath, dstpath); | 	switch (act) | ||||||
|  | 	{ | ||||||
|  | 		case QSE_FS_CPFILE: | ||||||
|  | 			if (total == done) qse_printf (QSE_T("Copied [%s] to [%s]\n"), srcpath, dstpath); | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 		case QSE_FS_RMFILE: | ||||||
|  | 			qse_printf (QSE_T("Removed file [%s]\n"), srcpath); | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 		case QSE_FS_SYMLINK: | ||||||
|  | 			qse_printf (QSE_T("Symlinked [%s] to [%s]\n"), srcpath, dstpath); | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 		case QSE_FS_MKDIR: | ||||||
|  | 			qse_printf (QSE_T("Made directory [%s]\n"), srcpath); | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 		case QSE_FS_RMDIR: | ||||||
|  | 			qse_printf (QSE_T("Removed directory [%s]\n"), srcpath); | ||||||
|  | 			break; | ||||||
|  |  | ||||||
|  | 		case QSE_FS_RENFILE: | ||||||
|  | 			qse_printf (QSE_T("renamed  [%s] to [%s]\n"), srcpath); | ||||||
|  | 			break; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| /*if (qse_strcmp(path, QSE_T("b/c")) == 0) return 0;*/ | /*if (qse_strcmp(path, QSE_T("b/c")) == 0) return 0;*/ | ||||||
|         return 1; |         return 1; | ||||||
| } | } | ||||||
| @ -93,7 +119,7 @@ static int fs_main (int argc, qse_char_t* argv[]) | |||||||
| 	fs = qse_fs_open (QSE_MMGR_GETDFL(), 0); | 	fs = qse_fs_open (QSE_MMGR_GETDFL(), 0); | ||||||
|  |  | ||||||
| 	qse_memset (&cbs, 0, QSE_SIZEOF(cbs)); | 	qse_memset (&cbs, 0, QSE_SIZEOF(cbs)); | ||||||
| 	cbs.cp = fs_cp; | 	cbs.actcb = fs_actcb; | ||||||
| 	qse_fs_setopt (fs, QSE_FS_CBS, &cbs); | 	qse_fs_setopt (fs, QSE_FS_CBS, &cbs); | ||||||
|  |  | ||||||
| 	if (qse_fs_cpfile (fs, argv[opt.ind], argv[opt.ind + 1], cpfile_flags) <= -1) | 	if (qse_fs_cpfile (fs, argv[opt.ind], argv[opt.ind + 1], cpfile_flags) <= -1) | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user