wrote a file copy function partially
This commit is contained in:
parent
44129510dc
commit
e01c1f8644
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -18,6 +18,7 @@ bin_PROGRAMS = \
|
||||
fmt02 \
|
||||
fs01 \
|
||||
fs02 \
|
||||
fs03 \
|
||||
htb \
|
||||
glob01 \
|
||||
ipad01 \
|
||||
|
@ -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@
|
||||
|
93
qse/samples/cmn/fs03.c
Normal file
93
qse/samples/cmn/fs03.c
Normal file
@ -0,0 +1,93 @@
|
||||
#include <qse/cmn/fs.h>
|
||||
#include <qse/cmn/mem.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/sio.h>
|
||||
#include <qse/cmn/path.h>
|
||||
#include <qse/cmn/main.h>
|
||||
#include <qse/cmn/mbwc.h>
|
||||
#include <locale.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user