diff --git a/qse/include/qse/cmn/fs.h b/qse/include/qse/cmn/fs.h index cbd7cc62..8149e2b6 100644 --- a/qse/include/qse/cmn/fs.h +++ b/qse/include/qse/cmn/fs.h @@ -117,6 +117,20 @@ struct qse_fs_ent_t typedef struct qse_fs_ent_t qse_fs_ent_t; +struct qse_fs_attr_t +{ + unsigned int isdir: 1; + unsigned int islnk: 1; + unsigned int isreg: 1; + unsigned int isblk: 1; + unsigned int ischr: 1; + qse_uintmax_t size; + qse_uintmax_t ino; + qse_uintmax_t dev; +}; + +typedef struct qse_fs_attr_t qse_fs_attr_t; + typedef struct qse_fs_t qse_fs_t; enum qse_fs_trait_t @@ -129,6 +143,15 @@ enum qse_fs_trait_t }; typedef enum qse_fs_trait_t qse_fs_trait_t; + +/** + * \return -1 on failure, 0 to cancel, 1 to keep copying + */ +typedef int (*qse_fs_cbs_cp_t) ( + qse_fs_t* fs, + void* ctx +); + /** * \return -1 on failure, 0 to skip, 1 to delete */ @@ -155,6 +178,8 @@ struct qse_fs_t qse_fs_ent_t ent; qse_char_t* curdir; void* info; + + qse_uint8_t cpbuf[4096]; }; @@ -166,6 +191,16 @@ enum qse_fs_opt_t }; typedef enum qse_fs_opt_t qse_fs_opt_t; +enum qse_fs_cpfile_flag_t +{ + QSE_FS_CPFILE_PRESERVE = (1 << 0), + QSE_FS_CPFILE_REPLACE = (1 << 1), + QSE_FS_CPFILE_SYMLINK = (1 << 2), + + QSE_FS_CPFILE_ALL = (QSE_FS_CPFILE_PRESERVE | QSE_FS_CPFILE_REPLACE | QSE_FS_CPFILE_SYMLINK) +}; +typedef enum qse_fs_cpfile_flag_t qse_fs_cpfile_flag_t; + enum qse_fs_mkdir_flag_t { @@ -275,6 +310,26 @@ QSE_EXPORT int qse_fs_move ( ); +QSE_EXPORT int qse_fs_cpfilembs ( + qse_fs_t* fs, + const qse_mchar_t* srcpath, + const qse_mchar_t* dstpath, + int flags +); + +QSE_EXPORT int qse_fs_cpfilewcs ( + qse_fs_t* fs, + const qse_wchar_t* srcpath, + const qse_wchar_t* dstpath, + int flags +); + +#if defined(QSE_CHAR_IS_MCHAR) +# define qse_fs_cpfile(fs,srcpath,dstpath,flags) qse_fs_cpfilembs(fs,srcpath,dstpath,flags) +#else +# define qse_fs_cpfile(fs,srcpath,dstpath,flags) qse_fs_cpfilewcs(fs,srcpath,dstpath,flags) +#endif + QSE_EXPORT int qse_fs_mkdirmbs ( qse_fs_t* fs, const qse_mchar_t* path, diff --git a/qse/lib/cmn/fs-err.c b/qse/lib/cmn/fs-err.c index 037a90b2..c3054270 100644 --- a/qse/lib/cmn/fs-err.c +++ b/qse/lib/cmn/fs-err.c @@ -123,6 +123,9 @@ qse_fs_errnum_t qse_fs_syserrtoerrnum (qse_fs_t* fs, qse_fs_syserr_t e) case ENOTDIR: return QSE_FS_ENOTDIR; + case EXDEV: + return QSE_FS_EXDEV; + default: return QSE_FS_ESYSERR; } diff --git a/qse/lib/cmn/fs-make.c b/qse/lib/cmn/fs-make.c index 2221ebaa..13e75e87 100644 --- a/qse/lib/cmn/fs-make.c +++ b/qse/lib/cmn/fs-make.c @@ -112,7 +112,7 @@ static int make_directory_chain (qse_fs_t* fs, qse_fs_char_t* fspath) if (IS_FSPATHSEP(*p)) { #if defined(_WIN32) || defined(__DOS__) || defined(__OS2__) - /* exclude the separtor from the path name */ + /* exclude the separator from the path name */ c = *p; *p = QSE_FS_T('\0'); #else @@ -153,6 +153,8 @@ int qse_fs_mkdirmbs (qse_fs_t* fs, const qse_mchar_t* path, int flags) 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; @@ -184,6 +186,8 @@ int qse_fs_mkdirwcs (qse_fs_t* fs, const qse_wchar_t* path, int flags) 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; diff --git a/qse/lib/cmn/fs-move.c b/qse/lib/cmn/fs-move.c index 04d2ae5d..bce49f8f 100644 --- a/qse/lib/cmn/fs-move.c +++ b/qse/lib/cmn/fs-move.c @@ -51,25 +51,49 @@ struct fop_t #if defined(_WIN32) /* nothing yet */ #elif defined(__OS2__) - qse_mchar_t* old_path; - qse_mchar_t* new_path; + qse_fs_char_t* old_path; + qse_fs_char_t* new_path; #elif defined(__DOS__) - qse_mchar_t* old_path; - qse_mchar_t* new_path; + qse_fs_char_t* old_path; + qse_fs_char_t* new_path; #else - qse_mchar_t* old_path; - qse_mchar_t* new_path; - qse_mchar_t* new_path2; + 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) + +/* internal flags. it must not overlap with qse_fs_cpfile_flag_t enumerators */ +#define CPFILE_DST_ATTR (1 << 30) + +struct cpfile_t +{ + int flags; + + 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; + + +int qse_fs_move (qse_fs_t* fs, const qse_char_t* oldpath, const qse_char_t* newpath) { #if defined(_WIN32) @@ -208,7 +232,7 @@ int qse_fs_move ( 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); + 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; @@ -363,3 +387,369 @@ oops: #endif } +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 +} + + + + + + + + + + + + + +/* +#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 + */ + +static int copy_file_in_fs (qse_fs_t* fs, const cpfile_t* cpfile) +{ +#if defined(_WIN32) + /* ------------------------------------------------------ */ + DWORD copy_flags = 0; + + + if (flags & QSE_FS_CPFILE_SYMLINK) + copy_flags |= COPY_FILE_COPY_SYMLINK; + if (!(flags & QSE_FS_CPFILE_REPLACE)) + copy_flags |= COPY_FILE_FAIL_IF_EXISTS; + +/* + if (fs->cbs.cp) + { + Specify callback??? + } +*/ + + if (CopyFileEx (oldpath, newpath, QSE_NULL, QSE_NULL, QSE_NULL, copy_flags) == FALSE) + { + fs->errnum = qse_fs_syserrtoerrnum (fs, e); + return -1; + } + + return 0; + /* ------------------------------------------------------ */ + +#elif defined(__OS2__) + /* ------------------------------------------------------ */ + + APIRET rc; + USHORT opmode = 0; + + if (flags & QSE_FS_CPFILE_REPLACE) opmode |= 1; /* set bit 0 */ + + rc = DosCopy (oldpath, newpath, opmode, 0); + 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 ((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); + out = QSE_OPEN (cpfile->dst_fspath, O_CREAT | O_WRONLY | O_TRUNC, 0777); /* TODO: proper mode */ + + if (in <= -1 || 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; + } + } + + 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 copy_file (qse_fs_t* fs, cpfile_t* cpfile) +{ + + if (cpfile->src_attr.isdir) + { + fs->errnum = QSE_FS_ENOIMPL; /* TODO: copy a directory into a directory */ + return -1; + } + else + { + /* TODO: check if it's itself */ + + 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 */ + return -1; + } + + if (cpfile->dst_attr.isdir) + { + /* copy it to directory */ + fs->errnum = QSE_FS_ENOIMPL; /* TODO: copy a file into a directory */ + return -1; + } + + if (!(cpfile->flags & QSE_FS_CPFILE_REPLACE)) + { + fs->errnum = QSE_FS_EEXIST; + return -1; + } + } + + if (!cpfile->src_attr.isdir) + { + /* source is not a directory. */ + return copy_file_in_fs (fs, cpfile); + } + + fs->errnum = QSE_FS_ENOIMPL; /* TODO: copy a file into a directory */ + 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; /* 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); + if (!cpfile.src_fspath || !cpfile.dst_fspath) goto oops; + + 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); + + qse_fs_freefspathformbs (fs, dstpath, cpfile.dst_fspath); + qse_fs_freefspathformbs (fs, srcpath, cpfile.src_fspath); + return ret; + +oops: + 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; +} + +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; /* 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); + if (!cpfile.src_fspath || !cpfile.dst_fspath) goto oops; + + 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); + + qse_fs_freefspathforwcs (fs, dstpath, cpfile.dst_fspath); + qse_fs_freefspathforwcs (fs, srcpath, cpfile.src_fspath); + return ret; + +oops: + 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; +} diff --git a/qse/lib/cmn/fs.c b/qse/lib/cmn/fs.c index c2278f6f..af600a2a 100644 --- a/qse/lib/cmn/fs.c +++ b/qse/lib/cmn/fs.c @@ -813,3 +813,49 @@ void qse_fs_freefspathforwcs (qse_fs_t* fs, const qse_wchar_t* path, qse_fs_char { if (path != (const qse_wchar_t*)fspath) QSE_MMGR_FREE (fs->mmgr, fspath); } + + +int qse_fs_getattr (qse_fs_t* fs, const qse_fs_char_t* fspath, qse_fs_attr_t* attr) +{ +#if defined(_WIN32) +#error TODO +#elif defined(__OS2__) +#error TODO +#elif defined(__DOS__) +#error TODO +#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; + return 0; +#endif +} diff --git a/qse/lib/cmn/fs.h b/qse/lib/cmn/fs.h index d67f99cc..4a23b89e 100644 --- a/qse/lib/cmn/fs.h +++ b/qse/lib/cmn/fs.h @@ -139,6 +139,13 @@ void qse_fs_freefspathforwcs ( # define qse_fs_freefspath(fs,path,fspath) qse_fs_freefspathforwcs(fs,path,fspath); #endif + +int qse_fs_getattr ( + qse_fs_t* fs, + const qse_fs_char_t* fspath, + qse_fs_attr_t* attr +); + #if defined(__cplusplus) } #endif diff --git a/qse/lib/cmn/syscall.h b/qse/lib/cmn/syscall.h index bfb97f81..0199e674 100644 --- a/qse/lib/cmn/syscall.h +++ b/qse/lib/cmn/syscall.h @@ -368,6 +368,12 @@ # define QSE_SYMLINK(oldpath,newpath) symlink(oldpath,newpath) #endif +#if defined(SYS_readlink) && defined(QSE_USE_SYSCALL) +# define QSE_READLINK(path,buf,size) syscall(SYS_readlink,path,buf,size) +#else +# define QSE_READLINK(path,buf,size) readlink(path,buf,size) +#endif + #if defined(SYS_unlink) && defined(QSE_USE_SYSCALL) # define QSE_UNLINK(path) syscall(SYS_unlink,path) #else diff --git a/qse/samples/cmn/Makefile.am b/qse/samples/cmn/Makefile.am index ab34eb9f..1b41d829 100644 --- a/qse/samples/cmn/Makefile.am +++ b/qse/samples/cmn/Makefile.am @@ -18,6 +18,7 @@ bin_PROGRAMS = \ fmt02 \ fs01 \ fs02 \ + fs03 \ htb \ glob01 \ ipad01 \ diff --git a/qse/samples/cmn/Makefile.in b/qse/samples/cmn/Makefile.in index 10cd4d55..7cbb6ab3 100644 --- a/qse/samples/cmn/Makefile.in +++ b/qse/samples/cmn/Makefile.in @@ -54,8 +54,8 @@ host_triplet = @host@ bin_PROGRAMS = chr01$(EXEEXT) dir01$(EXEEXT) dll$(EXEEXT) \ env01$(EXEEXT) fio01$(EXEEXT) fio02$(EXEEXT) fma$(EXEEXT) \ fmt01$(EXEEXT) fmt02$(EXEEXT) fs01$(EXEEXT) fs02$(EXEEXT) \ - htb$(EXEEXT) glob01$(EXEEXT) ipad01$(EXEEXT) lda$(EXEEXT) \ - main01$(EXEEXT) main02$(EXEEXT) mbwc01$(EXEEXT) \ + fs03$(EXEEXT) htb$(EXEEXT) glob01$(EXEEXT) ipad01$(EXEEXT) \ + lda$(EXEEXT) main01$(EXEEXT) main02$(EXEEXT) mbwc01$(EXEEXT) \ mbwc02$(EXEEXT) nwad01$(EXEEXT) nwif01$(EXEEXT) \ nwif02$(EXEEXT) oht$(EXEEXT) path01$(EXEEXT) pio$(EXEEXT) \ pma$(EXEEXT) rex01$(EXEEXT) rbt$(EXEEXT) sio01$(EXEEXT) \ @@ -131,6 +131,10 @@ fs02_SOURCES = fs02.c fs02_OBJECTS = fs02.$(OBJEXT) fs02_LDADD = $(LDADD) fs02_DEPENDENCIES = $(am__DEPENDENCIES_2) +fs03_SOURCES = fs03.c +fs03_OBJECTS = fs03.$(OBJEXT) +fs03_LDADD = $(LDADD) +fs03_DEPENDENCIES = $(am__DEPENDENCIES_2) am_glob01_OBJECTS = glob01.$(OBJEXT) glob01_OBJECTS = $(am_glob01_OBJECTS) glob01_LDADD = $(LDADD) @@ -272,7 +276,7 @@ am__v_GEN_0 = @echo " GEN " $@; SOURCES = $(chr01_SOURCES) dir01.c $(dll_SOURCES) $(env01_SOURCES) \ $(fio01_SOURCES) $(fio02_SOURCES) $(fma_SOURCES) \ $(fmt01_SOURCES) $(fmt02_SOURCES) $(fs01_SOURCES) fs02.c \ - $(glob01_SOURCES) $(htb_SOURCES) $(ipad01_SOURCES) \ + fs03.c $(glob01_SOURCES) $(htb_SOURCES) $(ipad01_SOURCES) \ $(lda_SOURCES) $(main01_SOURCES) $(main02_SOURCES) \ $(mbwc01_SOURCES) $(mbwc02_SOURCES) $(nwad01_SOURCES) nwif01.c \ nwif02.c $(oht_SOURCES) $(path01_SOURCES) $(pio_SOURCES) \ @@ -283,7 +287,7 @@ SOURCES = $(chr01_SOURCES) dir01.c $(dll_SOURCES) $(env01_SOURCES) \ DIST_SOURCES = $(chr01_SOURCES) dir01.c $(dll_SOURCES) \ $(env01_SOURCES) $(fio01_SOURCES) $(fio02_SOURCES) \ $(fma_SOURCES) $(fmt01_SOURCES) $(fmt02_SOURCES) \ - $(fs01_SOURCES) fs02.c $(glob01_SOURCES) $(htb_SOURCES) \ + $(fs01_SOURCES) fs02.c fs03.c $(glob01_SOURCES) $(htb_SOURCES) \ $(ipad01_SOURCES) $(lda_SOURCES) $(main01_SOURCES) \ $(main02_SOURCES) $(mbwc01_SOURCES) $(mbwc02_SOURCES) \ $(nwad01_SOURCES) nwif01.c nwif02.c $(oht_SOURCES) \ @@ -628,6 +632,9 @@ fs01$(EXEEXT): $(fs01_OBJECTS) $(fs01_DEPENDENCIES) $(EXTRA_fs01_DEPENDENCIES) fs02$(EXEEXT): $(fs02_OBJECTS) $(fs02_DEPENDENCIES) $(EXTRA_fs02_DEPENDENCIES) @rm -f fs02$(EXEEXT) $(AM_V_CCLD)$(LINK) $(fs02_OBJECTS) $(fs02_LDADD) $(LIBS) +fs03$(EXEEXT): $(fs03_OBJECTS) $(fs03_DEPENDENCIES) $(EXTRA_fs03_DEPENDENCIES) + @rm -f fs03$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(fs03_OBJECTS) $(fs03_LDADD) $(LIBS) glob01$(EXEEXT): $(glob01_OBJECTS) $(glob01_DEPENDENCIES) $(EXTRA_glob01_DEPENDENCIES) @rm -f glob01$(EXEEXT) $(AM_V_CCLD)$(LINK) $(glob01_OBJECTS) $(glob01_LDADD) $(LIBS) @@ -730,6 +737,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmt02.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs01.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs02.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fs03.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glob01.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipad01.Po@am__quote@ diff --git a/qse/samples/cmn/fs03.c b/qse/samples/cmn/fs03.c new file mode 100644 index 00000000..0557af51 --- /dev/null +++ b/qse/samples/cmn/fs03.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include +#include +#include + + +static void print_usage (const qse_char_t* argv0) +{ + qse_fprintf (QSE_STDERR, QSE_T("Usage: %s command filename filename\n"), qse_basename(argv0)); + qse_fprintf (QSE_STDERR, QSE_T("Command is one of cpfile | cpfile-s\n")); + qse_fprintf (QSE_STDERR, QSE_T("Filename is a pattern for delXXX\n")); +} + +static int fs_main (int argc, qse_char_t* argv[]) +{ + qse_fs_t* fs; + qse_fs_cbs_t cbs; + int ret = 0; + + if (argc != 4) + { + print_usage (argv[0]); + return -1; + } + fs = qse_fs_open (QSE_MMGR_GETDFL(), 0); + +/* + qse_memset (&cbs, 0, QSE_SIZEOF(cbs)); + cbs.del = fs_del; + qse_fs_setopt (fs, QSE_FS_CBS, &cbs); +*/ + + if (qse_strcmp(argv[1], QSE_T("cpfile")) == 0) + { + if (qse_fs_cpfile (fs, argv[2], argv[3], 0) <= -1) + { + qse_fprintf (QSE_STDERR, QSE_T("cannot copy file - %d\n"), qse_fs_geterrnum(fs)); + ret = -1; + } + } + else if (qse_strcmp(argv[1], QSE_T("cpfile-s")) == 0) + { + if (qse_fs_cpfile (fs, argv[2], argv[3], QSE_FS_CPFILE_SYMLINK) <= -1) + { + qse_fprintf (QSE_STDERR, QSE_T("cannot copy file - %d\n"), qse_fs_geterrnum(fs)); + ret = -1; + } + } + else + { + print_usage (argv[0]); + ret = -1; + } + + qse_fs_close (fs); + return ret; +} + +int main (int argc, qse_achar_t* argv[]) +{ + int x; +#if defined(_WIN32) + char locale[100]; + UINT codepage = GetConsoleOutputCP(); + if (codepage == CP_UTF8) + { + /*SetConsoleOUtputCP (CP_UTF8);*/ + qse_setdflcmgrbyid (QSE_CMGR_UTF8); + } + else + { + sprintf (locale, ".%u", (unsigned int)codepage); + setlocale (LC_ALL, locale); + qse_setdflcmgrbyid (QSE_CMGR_SLMB); + } +#else + setlocale (LC_ALL, ""); + qse_setdflcmgrbyid (QSE_CMGR_SLMB); +#endif + + qse_openstdsios (); + + x = qse_runmain (argc, argv, fs_main); + + qse_closestdsios (); + + return x; +} +