diff --git a/qse/include/qse/cmn/str.h b/qse/include/qse/cmn/str.h index 5627b55b..7135d6d5 100644 --- a/qse/include/qse/cmn/str.h +++ b/qse/include/qse/cmn/str.h @@ -1152,6 +1152,29 @@ QSE_EXPORT qse_size_t qse_mbsxjoinv ( va_list ap ); +QSE_EXPORT qse_size_t qse_mbscajoin ( + qse_mchar_t* buf, + ... +); + +QSE_EXPORT qse_size_t qse_mbsxcajoin ( + qse_mchar_t* buf, + qse_size_t size, + ... +); + +QSE_EXPORT qse_size_t qse_mbscajoinv ( + qse_mchar_t* buf, + va_list ap +); + +QSE_EXPORT qse_size_t qse_mbsxcajoinv ( + qse_mchar_t* buf, + qse_size_t size, + va_list ap +); + + /** * The qse_wcsjoin() function joins a list of wide-charcter strings into @@ -1195,16 +1218,46 @@ QSE_EXPORT qse_size_t qse_wcsxjoinv ( va_list ap ); +QSE_EXPORT qse_size_t qse_wcscajoin ( + qse_wchar_t* buf, + ... +); + +QSE_EXPORT qse_size_t qse_wcsxcajoin ( + qse_wchar_t* buf, + qse_size_t size, + ... +); + +QSE_EXPORT qse_size_t qse_wcscajoinv ( + qse_wchar_t* buf, + va_list ap +); + +QSE_EXPORT qse_size_t qse_wcsxcajoinv ( + qse_wchar_t* buf, + qse_size_t size, + va_list ap +); + #if defined(QSE_CHAR_IS_MCHAR) # define qse_strjoin qse_mbsjoin # define qse_strxjoin qse_mbsxjoin # define qse_strjoinv qse_mbsjoinv # define qse_strxjoinv qse_mbsxjoinv +# define qse_strcajoin qse_mbscajoin +# define qse_strxcajoin qse_mbsxcajoin +# define qse_strcajoinv qse_mbscajoinv +# define qse_strxcajoinv qse_mbsxcajoinv #else # define qse_strjoin qse_wcsjoin # define qse_strxjoin qse_wcsxjoin # define qse_strjoinv qse_wcsjoinv # define qse_strxjoinv qse_wcsxjoinv +# define qse_strcajoin qse_wcscajoin +# define qse_strxcajoin qse_wcsxcajoin +# define qse_strcajoinv qse_wcscajoinv +# define qse_strxcajoinv qse_wcsxcajoinv #endif /* ---------------------------------------------------- */ diff --git a/qse/include/qse/si/Makefile.am b/qse/include/qse/si/Makefile.am index 66263de2..8a60a8ea 100644 --- a/qse/include/qse/si/Makefile.am +++ b/qse/include/qse/si/Makefile.am @@ -30,6 +30,7 @@ pkginclude_HEADERS += \ App.hpp \ Condition.hpp \ Mutex.hpp \ + Path.hpp \ SocketAddress.hpp \ Socket.hpp \ SpinLock.hpp \ diff --git a/qse/include/qse/si/Makefile.in b/qse/include/qse/si/Makefile.in index 37a81d3b..563b76b4 100644 --- a/qse/include/qse/si/Makefile.in +++ b/qse/include/qse/si/Makefile.in @@ -91,6 +91,7 @@ host_triplet = @host@ @ENABLE_CXX_TRUE@ App.hpp \ @ENABLE_CXX_TRUE@ Condition.hpp \ @ENABLE_CXX_TRUE@ Mutex.hpp \ +@ENABLE_CXX_TRUE@ Path.hpp \ @ENABLE_CXX_TRUE@ SocketAddress.hpp \ @ENABLE_CXX_TRUE@ Socket.hpp \ @ENABLE_CXX_TRUE@ SpinLock.hpp \ @@ -136,7 +137,7 @@ am__can_run_installinfo = \ am__pkginclude_HEADERS_DIST = cnd.h dir.h fio.h fs.h glob.h intr.h \ log.h mtx.h mux.h netlink.h nwad.h nwif.h nwio.h os.h pio.h \ rwl.h sck.h sinfo.h sio.h spl.h task.h thr.h tio.h App.hpp \ - Condition.hpp Mutex.hpp SocketAddress.hpp Socket.hpp \ + Condition.hpp Mutex.hpp Path.hpp SocketAddress.hpp Socket.hpp \ SpinLock.hpp TcpServer.hpp Thread.hpp am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ diff --git a/qse/include/qse/si/Path.hpp b/qse/include/qse/si/Path.hpp index 91238cba..67fba22f 100644 --- a/qse/include/qse/si/Path.hpp +++ b/qse/include/qse/si/Path.hpp @@ -27,11 +27,12 @@ #ifndef _QSE_SI_PATH_CLASS_ #define _QSE_SI_PATH_CLASS_ -#include -#include +#include +#include QSE_BEGIN_NAMESPACE(QSE) -class Path + +class Path: public Mmged { public: enum @@ -39,74 +40,65 @@ public: MAX_LEN = QSE_PATH_MAX }; - Path (); - Path (const qse_char_t* n); - Path (const Path& fn); - Path& operator= (const Path& fn); + Path (Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT; + Path (const qse_char_t* n, Mmgr* mmgr = QSE_NULL) QSE_CPP_NOEXCEPT; + Path (const Path& path) QSE_CPP_NOEXCEPT; + Path& operator= (const Path& path) QSE_CPP_NOEXCEPT; - const qse_char_t* name () const - { - return full_path; - } + // NOTE: the current implementation doesn't have much to benefit from C++11 Move + // semantics and the rvalue reference. - void setName (const qse_char_t* n) - { - if (n == QSE_NULL || n[0] == QSE_CHAR('\0')) set_to_root(); - else { - qse_strxcpy (full_path, qse_countof(full_path), n); - this->set_base_name (); - } - } + void setName (const qse_char_t* n) QSE_CPP_NOEXCEPT; - const qse_char_t* baseName () const - { - return base_name; - } - const qse_char_t* baseDir () const - { - return base_dir; - } + const qse_char_t* getName () const QSE_CPP_NOEXCEPT { return this->full_path; } + const qse_char_t* getBaseName () const QSE_CPP_NOEXCEPT { return this->base_name; } + const qse_char_t* getBaseDir () const QSE_CPP_NOEXCEPT { return this->base_dir; } - bool exists () - { - return exists (full_path); - } - static bool exists (const qse_char_t* path); +#if 0 + bool exists () const QSE_CPP_NOEXCEPT { return this->exists(this->full_path); } + static bool exists (const qse_mchar_t* path) QSE_CPP_NOEXCEPT; + static bool exists (const qse_wchar_t* path) QSE_CPP_NOEXCEPT; - int getSize (qse_off_t* sz); - bool isWritable (); - bool isReadable (); - bool isReadWritable (); -#ifndef _WIN32 - bool isExecutable (); + int getSize (qse_foff_t* sz) const QSE_CPP_NOEXCEPT { return this->getSize(this->full_path, sz); } + static int getSize (const qse_mchar_t* path, qse_foff_t* sz) QSE_CPP_NOEXCEPT; + static int getSize (const qse_wchar_t* path, qse_foff_t* sz) QSE_CPP_NOEXCEPT; + + bool isWritable () const QSE_CPP_NOEXCEPT; + bool isReadable () const QSE_CPP_NOEXCEPT; + bool isReadWritable () const QSE_CPP_NOEXCEPT; + bool isExecutable () const QSE_CPP_NOEXCEPT; + + bool isDir () const QSE_CPP_NOEXCEPT { return this->isDir(this->full_path); } + static bool isDir (const qse_char_t* path) QSE_CPP_NOEXCEPT; + + bool isRegular () const QSE_CPP_NOEXCEPT { return this->isRegular(this->full_path); } + static bool isRegular (const qse_char_t* path) QSE_CPP_NOEXCEPT; #endif - bool isDirectory () const { return this->isDirectory (full_path); } - static bool isDirectory (const qse_char_t* path); + int chmod (qse_fmode_t mode) QSE_CPP_NOEXCEPT { return this->chmod(this->full_path, mode); } + static int chmod (const qse_mchar_t* path, qse_fmode_t mode) QSE_CPP_NOEXCEPT; + static int chmod (const qse_wchar_t* path, qse_fmode_t mode) QSE_CPP_NOEXCEPT; - bool isRegular () const { return this->isRegular (full_path); } - static bool isRegular (const qse_char_t* path); + int unlink () QSE_CPP_NOEXCEPT { return this->unlink(this->full_path); } + static int unlink (const qse_mchar_t* path) QSE_CPP_NOEXCEPT; + static int unlink (const qse_wchar_t* path) QSE_CPP_NOEXCEPT; - int chmod (qse_mode_t mode); - static int chmod (const qse_char_t* path, qse_mode_t mode); + int mkdir (qse_fmode_t mode) QSE_CPP_NOEXCEPT { return this->mkdir(this->full_path, mode); } + static int mkdir (const qse_mchar_t* path, qse_fmode_t mode) QSE_CPP_NOEXCEPT; + static int mkdir (const qse_wchar_t* path, qse_fmode_t mode) QSE_CPP_NOEXCEPT; - int unlink (); - static int unlink (const qse_char_t* path); - - int mkdir (qse_mode_t mode); - static int mkdir (const qse_char_t* path, qse_mode_t mode); - - int setToSelf (const qse_char_t* argv0 = QSE_NULL); + int setToSelf (const qse_mchar_t* argv0 = QSE_NULL) QSE_CPP_NOEXCEPT; + int setToSelf (const qse_wchar_t* argv0 = QSE_NULL) QSE_CPP_NOEXCEPT; protected: qse_char_t full_path[QSE_PATH_MAX + 1]; qse_char_t base_name[QSE_PATH_MAX + 1]; qse_char_t base_dir [QSE_PATH_MAX + 1]; - void set_base_name (); - void set_to_root (); + void set_base_name () QSE_CPP_NOEXCEPT; + void set_to_root () QSE_CPP_NOEXCEPT; }; QSE_END_NAMESPACE(QSE) - + #endif diff --git a/qse/include/qse/si/fs.h b/qse/include/qse/si/fs.h index 2bdd4ff3..8ba2250f 100644 --- a/qse/include/qse/si/fs.h +++ b/qse/include/qse/si/fs.h @@ -46,33 +46,7 @@ # define QSE_SIZEOF_FS_CHAR_T QSE_SIZEOF_MCHAR_T #endif -#if (QSE_SIZEOF_MODE_T == QSE_SIZEOF_LONG) -# if defined(QSE_MODE_T_IS_SIGNED) - typedef long int qse_fs_mode_t; -# else - typedef unsigned long int qse_fs_mode_t; -# endif -#elif (QSE_SIZEOF_MODE_T == QSE_SIZEOF_INT) -# if defined(QSE_MODE_T_IS_SIGNED) - typedef int qse_fs_mode_t; -# else - typedef unsigned int qse_fs_mode_t; -# endif -#elif (QSE_SIZEOF_MODE_T == QSE_SIZEOF_SHORT) -# if defined(QSE_MODE_T_IS_SIGNED) - typedef short int qse_fs_mode_t; -# else - typedef unsigned short int qse_fs_mode_t; -# endif -#elif (QSE_SIZEOF_MODE_T == QSE_SIZEOF_CHAR) -# if defined(QSE_MODE_T_IS_SIGNED) - typedef signed char qse_fs_mode_t; -# else - typedef unsigned char qse_fs_mode_t; -# endif -#else - typedef unsigned int qse_fs_mode_t; -#endif +typedef qse_fmode_t qse_fs_mode_t; enum qse_fs_errnum_t { @@ -519,6 +493,34 @@ QSE_EXPORT int qse_fs_rmdirwcs ( #endif +/* ========================================================================= + * GLOBAL UTILITIES NOT USING THE FS OBJECT + * ========================================================================= */ + +QSE_EXPORT qse_mchar_t* qse_get_current_mbsdir ( + qse_mchar_t* buf, + qse_size_t size, + qse_mmgr_t* mmgr +); + +QSE_EXPORT qse_wchar_t* qse_get_current_wcsdir ( + qse_wchar_t* buf, + qse_size_t size, + qse_mmgr_t* mmgr +); + +#if defined(QSE_CHAR_IS_MCHAR) +# define qse_get_current_dir(buf,size,mmgr) qse_get_current_mbsdir(buf,size,mmgr) +#else +# define qse_get_current_dir(buf,size,mmgr) qse_get_current_wcsdir(buf,size,mmgr) +#endif + +QSE_EXPORT int qse_get_prog_path ( + const qse_char_t* argv0, + qse_char_t* buf, + qse_size_t size, + qse_mmgr_t* mmgr +); #if defined(__cplusplus) } diff --git a/qse/include/qse/types.h b/qse/include/qse/types.h index 9ad7b138..7a762ff1 100644 --- a/qse/include/qse/types.h +++ b/qse/include/qse/types.h @@ -914,9 +914,53 @@ typedef struct qse_tmgr_t qse_tmgr_t; #elif defined(QSE_HAVE_INT16_T) && (QSE_SIZEOF_OFF_T==2) typedef qse_int16_t qse_foff_t; # define QSE_SIZEOF_FOFF_T QSE_SIZEOF_INT16_T +#elif defined(QSE_HAVE_INT8_T) && (QSE_SIZEOF_OFF_T==1) + typedef qse_int8_t qse_foff_t; +# define QSE_SIZEOF_FOFF_T QSE_SIZEOF_INT16_T #else typedef qse_int32_t qse_foff_t; /* this line is for doxygen */ -# error Unsupported platform +# error Unsupported platform +#endif + +/** + * The #qse_fmode_t type defines an integer that can represent a file offset. + * Depending on your system, it's defined to one of #qse_int64_t, #qse_int32_t, + * and #qse_int16_t. + */ +#if defined(QSE_MODE_T_IS_SIGNED) +# if defined(QSE_HAVE_INT64_T) && (QSE_SIZEOF_MODE_T==8) + typedef qse_int64_t qse_fmode_t; +# define QSE_SIZEOF_FMODE_T QSE_SIZEOF_INT64_T +# elif defined(QSE_HAVE_INT32_T) && (QSE_SIZEOF_MODE_T==4) + typedef qse_int32_t qse_fmode_t; +# define QSE_SIZEOF_FMODE_T QSE_SIZEOF_INT32_T +# elif defined(QSE_HAVE_INT16_T) && (QSE_SIZEOF_MODE_T==2) + typedef qse_int16_t qse_fmode_t; +# define QSE_SIZEOF_FMODE_T QSE_SIZEOF_INT16_T +# elif defined(QSE_HAVE_INT8_T) && (QSE_SIZEOF_MODE_T==1) + typedef qse_int8_t qse_fmode_t; +# define QSE_SIZEOF_FMODE_T QSE_SIZEOF_INT8_T +# else + typedef qse_int32_t qse_fmode_t; /* this line is for doxygen */ +# error Unsupported platform +# endif +#else +# if defined(QSE_HAVE_INT64_T) && (QSE_SIZEOF_MODE_T==8) + typedef qse_uint64_t qse_fmode_t; +# define QSE_SIZEOF_FMODE_T QSE_SIZEOF_INT64_T +# elif defined(QSE_HAVE_INT32_T) && (QSE_SIZEOF_MODE_T==4) + typedef qse_uint32_t qse_fmode_t; +# define QSE_SIZEOF_FMODE_T QSE_SIZEOF_INT32_T +# elif defined(QSE_HAVE_INT16_T) && (QSE_SIZEOF_MODE_T==2) + typedef qse_uint16_t qse_fmode_t; +# define QSE_SIZEOF_FMODE_T QSE_SIZEOF_INT16_T +# elif defined(QSE_HAVE_INT8_T) && (QSE_SIZEOF_MODE_T==1) + typedef qse_uint8_t qse_fmode_t; +# define QSE_SIZEOF_FMODE_T QSE_SIZEOF_INT8_T +# else + typedef qse_uint32_t qse_fmode_t; /* this line is for doxygen */ +# error Unsupported platform +# endif #endif /* diff --git a/qse/lib/cmn/str-join.c b/qse/lib/cmn/str-join.c index ddbb7650..29afb424 100644 --- a/qse/lib/cmn/str-join.c +++ b/qse/lib/cmn/str-join.c @@ -33,6 +33,10 @@ #undef strjoinv #undef strxjoin #undef strxjoinv +#undef strcajoin +#undef strcajoinv +#undef strxcajoin +#undef strxcajoinv #undef strcpy #undef strxcpy @@ -41,6 +45,10 @@ #define strjoinv qse_mbsjoinv #define strxjoin qse_mbsxjoin #define strxjoinv qse_mbsxjoinv +#define strcajoin qse_mbscajoin +#define strcajoinv qse_mbscajoinv +#define strxcajoin qse_mbsxcajoin +#define strxcajoinv qse_mbsxcajoinv #define strcpy qse_mbscpy #define strxcpy qse_mbsxcpy #include "str-join.h" @@ -52,6 +60,10 @@ #undef strjoinv #undef strxjoin #undef strxjoinv +#undef strcajoin +#undef strcajoinv +#undef strxcajoin +#undef strxcajoinv #undef strcpy #undef strxcpy @@ -60,6 +72,10 @@ #define strjoinv qse_wcsjoinv #define strxjoin qse_wcsxjoin #define strxjoinv qse_wcsxjoinv +#define strcajoin qse_wcscajoin +#define strcajoinv qse_wcscajoinv +#define strxcajoin qse_wcsxcajoin +#define strxcajoinv qse_wcsxcajoinv #define strcpy qse_wcscpy #define strxcpy qse_wcsxcpy #include "str-join.h" diff --git a/qse/lib/cmn/str-join.h b/qse/lib/cmn/str-join.h index 54650f84..382803f2 100644 --- a/qse/lib/cmn/str-join.h +++ b/qse/lib/cmn/str-join.h @@ -89,3 +89,70 @@ qse_size_t strjoin (char_t* buf, ...) return n; } + +/* ------------------------------------------------------------------------- */ + +qse_size_t strxcajoinv (char_t* buf, qse_size_t size, va_list ap) +{ + const char_t* p; + char_t* ptr; + qse_size_t left, n; + + n = strlen(buf); + left = size - n; + ptr = buf + n; + + while (left > 0) + { + p = va_arg (ap, const char_t*); + if (p == QSE_NULL) break; + + n = strxcpy(ptr, left, p); + left -= n; ptr += n; + } + + return size - left; +} + +qse_size_t strxcajoin (char_t* buf, qse_size_t size, ...) +{ + va_list ap; + qse_size_t n; + + va_start (ap, size); + n = strxcajoinv(buf, size, ap); + va_end (ap); + + return n; +} + +qse_size_t strcajoinv (char_t* buf, va_list ap) +{ + const char_t* p; + char_t* ptr = buf + strlen(buf); + qse_size_t n; + + while (1) + { + p = va_arg(ap, const char_t*); + if (p == QSE_NULL) break; + + n = strcpy(ptr, p); + ptr += n; + } + + return ptr - buf; +} + + +qse_size_t strcajoin (char_t* buf, ...) +{ + va_list ap; + qse_size_t n; + + va_start (ap, buf); + n = strcajoinv(buf, ap); + va_end (ap); + + return n; +} diff --git a/qse/lib/cmn/syscall.h b/qse/lib/cmn/syscall.h index 369e50a9..30a5e6f1 100644 --- a/qse/lib/cmn/syscall.h +++ b/qse/lib/cmn/syscall.h @@ -505,6 +505,16 @@ # define QSE_UTIMENSAT(dirfd,path,times,flags) utimensat(dirfd,path,times,flags) #endif +/* +the library's getcwd() returns char* while the system call returns int. +so it's not practical to define QSE_GETCWD(). +#if defined(SYS_getcwd) && defined(QSE_USE_SYSCALL) +# define QSE_GETCWD(buf,size) syscall(SYS_getcwd,buf,size) +#else +# define QSE_GETCWD(buf,size) getcwd(buf,size) +#endif +*/ + /* ===== DIRECTORY - not really system calls ===== */ #define QSE_OPENDIR(name) opendir(name) #define QSE_CLOSEDIR(dir) closedir(dir) diff --git a/qse/lib/si/Makefile.am b/qse/lib/si/Makefile.am index 97d7ec84..71c3466f 100644 --- a/qse/lib/si/Makefile.am +++ b/qse/lib/si/Makefile.am @@ -20,6 +20,7 @@ libqsesi_la_SOURCES = \ fs-err.c \ fs-make.c \ fs-move.c \ + fs-util.c \ glob.c \ intr.c \ log.c \ @@ -50,6 +51,7 @@ if ENABLE_CXX lib_LTLIBRARIES += libqsesixx.la libqsesixx_la_SOURCES = \ App.cpp \ + Path.cpp \ SocketAddress.cpp \ Socket.cpp \ TcpServer.cpp \ diff --git a/qse/lib/si/Makefile.in b/qse/lib/si/Makefile.in index ca63c01a..514042a1 100644 --- a/qse/lib/si/Makefile.in +++ b/qse/lib/si/Makefile.in @@ -142,14 +142,15 @@ am_libqsesi_la_OBJECTS = libqsesi_la-cnd.lo libqsesi_la-dir.lo \ libqsesi_la-fio.lo libqsesi_la-fs.lo libqsesi_la-fs-attr.lo \ libqsesi_la-fs-copy.lo libqsesi_la-fs-delete.lo \ libqsesi_la-fs-err.lo libqsesi_la-fs-make.lo \ - libqsesi_la-fs-move.lo libqsesi_la-glob.lo libqsesi_la-intr.lo \ - libqsesi_la-log.lo libqsesi_la-mtx.lo libqsesi_la-mux.lo \ - libqsesi_la-netlink.lo libqsesi_la-nwad.lo \ - libqsesi_la-nwad-skad.lo libqsesi_la-nwif.lo \ - libqsesi_la-nwif-cfg.lo libqsesi_la-nwio.lo libqsesi_la-os.lo \ - libqsesi_la-pio.lo libqsesi_la-rwl.lo libqsesi_la-sck.lo \ - libqsesi_la-sinfo.lo libqsesi_la-sio.lo libqsesi_la-task.lo \ - libqsesi_la-thr.lo libqsesi_la-tio.lo + libqsesi_la-fs-move.lo libqsesi_la-fs-util.lo \ + libqsesi_la-glob.lo libqsesi_la-intr.lo libqsesi_la-log.lo \ + libqsesi_la-mtx.lo libqsesi_la-mux.lo libqsesi_la-netlink.lo \ + libqsesi_la-nwad.lo libqsesi_la-nwad-skad.lo \ + libqsesi_la-nwif.lo libqsesi_la-nwif-cfg.lo \ + libqsesi_la-nwio.lo libqsesi_la-os.lo libqsesi_la-pio.lo \ + libqsesi_la-rwl.lo libqsesi_la-sck.lo libqsesi_la-sinfo.lo \ + libqsesi_la-sio.lo libqsesi_la-task.lo libqsesi_la-thr.lo \ + libqsesi_la-tio.lo libqsesi_la_OBJECTS = $(am_libqsesi_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -159,10 +160,11 @@ libqsesi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libqsesi_la_CFLAGS) \ $(CFLAGS) $(libqsesi_la_LDFLAGS) $(LDFLAGS) -o $@ libqsesixx_la_DEPENDENCIES = -am__libqsesixx_la_SOURCES_DIST = App.cpp SocketAddress.cpp Socket.cpp \ - TcpServer.cpp Thread.cpp -@ENABLE_CXX_TRUE@am_libqsesixx_la_OBJECTS = App.lo SocketAddress.lo \ -@ENABLE_CXX_TRUE@ Socket.lo TcpServer.lo Thread.lo +am__libqsesixx_la_SOURCES_DIST = App.cpp Path.cpp SocketAddress.cpp \ + Socket.cpp TcpServer.cpp Thread.cpp +@ENABLE_CXX_TRUE@am_libqsesixx_la_OBJECTS = App.lo Path.lo \ +@ENABLE_CXX_TRUE@ SocketAddress.lo Socket.lo TcpServer.lo \ +@ENABLE_CXX_TRUE@ Thread.lo libqsesixx_la_OBJECTS = $(am_libqsesixx_la_OBJECTS) libqsesixx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ @@ -437,6 +439,7 @@ libqsesi_la_SOURCES = \ fs-err.c \ fs-make.c \ fs-move.c \ + fs-util.c \ glob.c \ intr.c \ log.c \ @@ -464,6 +467,7 @@ libqsesi_la_LDFLAGS = -L../cmn -version-info 1:0:0 -no-undefined libqsesi_la_LIBADD = -lqsecmn $(PTHREAD_LIBS) $(SSL_LIBS) @ENABLE_CXX_TRUE@libqsesixx_la_SOURCES = \ @ENABLE_CXX_TRUE@ App.cpp \ +@ENABLE_CXX_TRUE@ Path.cpp \ @ENABLE_CXX_TRUE@ SocketAddress.cpp \ @ENABLE_CXX_TRUE@ Socket.cpp \ @ENABLE_CXX_TRUE@ TcpServer.cpp \ @@ -553,6 +557,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/App.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Path.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Socket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketAddress.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TcpServer.Plo@am__quote@ @@ -566,6 +571,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-fs-err.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-fs-make.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-fs-move.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-fs-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-fs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-glob.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-intr.Plo@am__quote@ @@ -679,6 +685,13 @@ libqsesi_la-fs-move.lo: fs-move.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-fs-move.lo `test -f 'fs-move.c' || echo '$(srcdir)/'`fs-move.c +libqsesi_la-fs-util.lo: fs-util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-fs-util.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-fs-util.Tpo -c -o libqsesi_la-fs-util.lo `test -f 'fs-util.c' || echo '$(srcdir)/'`fs-util.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-fs-util.Tpo $(DEPDIR)/libqsesi_la-fs-util.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='fs-util.c' object='libqsesi_la-fs-util.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -c -o libqsesi_la-fs-util.lo `test -f 'fs-util.c' || echo '$(srcdir)/'`fs-util.c + libqsesi_la-glob.lo: glob.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libqsesi_la_CFLAGS) $(CFLAGS) -MT libqsesi_la-glob.lo -MD -MP -MF $(DEPDIR)/libqsesi_la-glob.Tpo -c -o libqsesi_la-glob.lo `test -f 'glob.c' || echo '$(srcdir)/'`glob.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libqsesi_la-glob.Tpo $(DEPDIR)/libqsesi_la-glob.Plo diff --git a/qse/lib/si/Path.cpp b/qse/lib/si/Path.cpp index d50fc606..c80ae6f5 100644 --- a/qse/lib/si/Path.cpp +++ b/qse/lib/si/Path.cpp @@ -25,69 +25,109 @@ */ #include +#include +#include +#include +#include +#include "../cmn/syscall.h" + + QSE_BEGIN_NAMESPACE(QSE) -Path::Path () +Path::Path (Mmgr* mmgr) QSE_CPP_NOEXCEPT: Mmged(mmgr) { this->set_to_root (); } -Path::Path (const qse_char_t* n) +Path::Path (const qse_char_t* n, Mmgr* mmgr) QSE_CPP_NOEXCEPT: Mmged(mmgr) { this->setName (n); } -Path::Path (const Path& fn) +Path::Path (const Path& path) QSE_CPP_NOEXCEPT: Mmged(path) { - qse_strxcpy (this->full_path, QSE_COUNTOF(this->full_path), fn.this->full_path); + qse_strxcpy (this->full_path, QSE_COUNTOF(this->full_path), path.full_path); this->set_base_name (); } -Path& Path::operator= (const Path& fn) +Path& Path::operator= (const Path& path) QSE_CPP_NOEXCEPT { - qse_strxcpy (this->full_path, QSE_COUNTOF(this->full_path), fn.this->full_path); - this->set_base_name (); + if (this != &path) + { + this->setMmgr (path.getMmgr()); + qse_strxcpy (this->full_path, QSE_COUNTOF(this->full_path), path.full_path); + this->set_base_name (); + } return *this; } -bool Path::exists (const qse_char_t* path) +void Path::setName (const qse_char_t* n) QSE_CPP_NOEXCEPT { - return ::qse_access (path, QSE_ACCESS_EXIST) == 0; + if (n == QSE_NULL || n[0] == QSE_T('\0')) this->set_to_root(); + else + { + qse_strxcpy (this->full_path, QSE_COUNTOF(this->full_path), n); + this->set_base_name (); + } } -int Path::getSize (qse_off_t* sz) +#if 0 +bool Path::exists (const qse_mchar_t* path) QSE_CPP_NOEXCEPT { - qse_stat_t buf; - if (::qse_stat (this->full_path, &buf) == -1) return -1; - *sz = buf.st_size; +#if defined(QSE_ACCESS) && defined(F_OK) + return QSE_ACCESS(path, F_OK) == 0; +#else +# error UNSUPPORTED PLATFORM +#endif +} + +bool Path::exists (const qse_wchar_t* path) QSE_CPP_NOEXCEPT +{ + return true; +} + +int Path::getSize (const qse_mchar_t* path, qse_foff_t* sz) QSE_CPP_NOEXCEPT +{ +#if defined(QSE_STAT) + /* use stat() instead of lstat() to get the information about the actual file whe the path is a symbolic link */ + qse_stat_t st; + if (QSE_STAT(path, &st) == -1) return -1; + *sz = st.st_size; return 0; +#else +# error UNSUPPORTED PLATFORM +#endif } -bool Path::isWritable () +int Path::getSize (const qse_wchar_t* path, qse_foff_t* sz) QSE_CPP_NOEXCEPT +{ + return -1; +} + +bool Path::isWritable () const QSE_CPP_NOEXCEPT { return ::qse_access (this->full_path, QSE_ACCESS_WRITE) == 0; } -bool Path::isReadable () +bool Path::isReadable () const QSE_CPP_NOEXCEPT { return ::qse_access (this->full_path, QSE_ACCESS_READ) == 0; } -bool Path::isReadWritable () +bool Path::isReadWritable () QSE_CPP_NOEXCEPT { - return ::qse_access (this->full_path, - QSE_ACCESS_READ | QSE_ACCESS_WRITE) == 0; + return ::qse_access (this->full_path, QSE_ACCESS_READ | QSE_ACCESS_WRITE) == 0; } #if !defined(_WIN32) -bool Path::isExecutable () +bool Path::isExecutable () QSE_CPP_NOEXCEPT { return ::qse_access (this->full_path, QSE_ACCESS_EXECUTE) == 0; } #endif -bool Path::isDirectory (const qse_char_t* path) +bool Path::isDir (const qse_char_t* path) QSE_CPP_NOEXCEPT { int n; qse_stat_t st; @@ -101,7 +141,7 @@ bool Path::isDirectory (const qse_char_t* path) #endif } -bool Path::isRegular (const qse_char_t* path) +bool Path::isRegular (const qse_char_t* path) QSE_CPP_NOEXCEPT { int n; qse_stat_t st; @@ -114,38 +154,77 @@ bool Path::isRegular (const qse_char_t* path) return S_ISREG(st.st_mode); #endif } +#endif -int Path::chmod (qse_mode_t mode) + +int Path::chmod (const qse_mchar_t* path, qse_fmode_t mode) QSE_CPP_NOEXCEPT { - return qse_chmod (this->full_path, mode); +#if defined(QSE_CHMOD) + return QSE_CHMOD(path, mode); +#else +# error UNSUPPORTED PLATFORM +#endif } -int Path::chmod (const qse_char_t* path, qse_mode_t mode) +int Path::chmod (const qse_wchar_t* path, qse_fmode_t mode) QSE_CPP_NOEXCEPT { - return qse_chmod (path, mode); +#if defined(QSE_CHMOD) + qse_mchar_t* xpath = qse_wcstombsdup(path, QSE_NULL, QSE_MMGR_GETDFL()); + if (!xpath) return -1; + return QSE_CHMOD(xpath, mode); +#else +# error UNSUPPORTED PLATFORM +#endif } -int Path::unlink () +int Path::unlink (const qse_mchar_t* path) QSE_CPP_NOEXCEPT { - return ::qse_unlink (this->full_path); +#if defined(QSE_UNLINK) + return QSE_UNLINK(path); +#else +# error UNSUPPORTED PLATFORM +#endif } -int Path::mkdir (qse_mode_t mode) +int Path::unlink (const qse_wchar_t* path) QSE_CPP_NOEXCEPT { - return ::qse_mkdir(this->full_path, mode); +#if defined(QSE_UNLINK) + qse_mchar_t* xpath = qse_wcstombsdup(path, QSE_NULL, QSE_MMGR_GETDFL()); + if (!xpath) return -1; + return QSE_UNLINK(xpath); +#else +# error UNSUPPORTED PLATFORM +#endif } -int Path::mkdir (const qse_char_t* path, qse_mode_t mode) +int Path::mkdir (const qse_mchar_t* path, qse_fmode_t mode) QSE_CPP_NOEXCEPT { - return ::qse_mkdir(path, mode); +#if defined(QSE_MKDIR) + return QSE_MKDIR(path, mode); +#else +# error UNSUPPORTED PLATFORM +#endif } -void Path::set_base_name () +int Path::mkdir (const qse_wchar_t* path, qse_fmode_t mode) QSE_CPP_NOEXCEPT +{ +#if defined(QSE_MKDIR) + qse_mchar_t* xpath = qse_wcstombsdup(path, QSE_NULL, QSE_MMGR_GETDFL()); + if (!xpath) return -1; + return QSE_MKDIR(xpath, mode); +#else +# error UNSUPPORTED PLATFORM +#endif +} + + +void Path::set_base_name () QSE_CPP_NOEXCEPT { qse_size_t len = qse_strlen(this->full_path); QSE_ASSERT (len > 0); - for (qse_size_t i = len; i > 0; i--) { + for (qse_size_t i = len; i > 0; i--) + { #if defined(_WIN32) if ((this->full_path[i - 1] == QSE_T('/') || this->full_path[i - 1] == QSE_T('\\')) && i != len) { @@ -196,7 +275,7 @@ void Path::set_base_name () qse_strcpy (this->base_dir, QSE_T("")); } -void Path::set_to_root () +void Path::set_to_root () QSE_CPP_NOEXCEPT { qse_strcpy (this->full_path, QSE_T("/")); //this->set_base_name (); @@ -204,10 +283,15 @@ void Path::set_to_root () qse_strcpy (this->base_dir, QSE_T("/")); } -int Path::setToSelf (const qse_char_t* argv0) +int Path::setToSelf (const qse_mchar_t* argv0) QSE_CPP_NOEXCEPT +{ + return 0; +} + +int Path::setToSelf (const qse_wchar_t* argv0) QSE_CPP_NOEXCEPT { qse_char_t p[MAX_LEN + 1]; - if (qse_getpnm(argv0, p, QSE_COUNTOF(p)) == -1) return -1; + if (qse_get_prog_path(argv0, p, QSE_COUNTOF(p), this->getMmgr()) == -1) return -1; this->setName (p); return 0; } diff --git a/qse/lib/si/fs-util.c b/qse/lib/si/fs-util.c new file mode 100644 index 00000000..9106179c --- /dev/null +++ b/qse/lib/si/fs-util.c @@ -0,0 +1,204 @@ +/* + * $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 +#include +#include +#include +#include +#include "../cmn/syscall.h" +#include + +qse_mchar_t* qse_get_current_mbsdir (qse_mchar_t* buf, qse_size_t size, qse_mmgr_t* mmgr) +{ + qse_mchar_t* tmp; + + if (buf) + { + if (!getcwd(buf, size)) return QSE_NULL; + return buf; + } + + if (!mmgr) return QSE_NULL; + + size = QSE_PATH_MAX; + +again: + tmp = QSE_MMGR_REALLOC(mmgr, buf, size * QSE_SIZEOF(*buf)); + if (!tmp) return QSE_NULL; + buf = tmp; + + if (!getcwd(buf, size)) + { +/* TODO: handle ENAMETOOLONG + * or read /proc/self/cwd if available? */ + if (errno == ERANGE) + { + /* grow buffer and continue */ + size <<= 1; + goto again; + } + + QSE_MMGR_FREE (mmgr, buf); + return QSE_NULL; + } + + return buf; +} + +qse_wchar_t* qse_get_current_wcsdir (qse_wchar_t* buf, qse_size_t size, qse_mmgr_t* mmgr) +{ + qse_mchar_t* mbsdir; + qse_wchar_t* wcsdir; + qse_size_t wcslen; + + mbsdir = qse_get_current_mbsdir(QSE_NULL, 0, mmgr); + if (!mbsdir) return QSE_NULL; + + wcsdir = qse_mbstowcsdup(mbsdir, &wcslen, mmgr); + QSE_MMGR_FREE (mmgr, mbsdir); + + if (!wcsdir) return QSE_NULL; + + if (buf) + { + if (wcslen >= size) + { + /* cannot copy the path in full */ + QSE_MMGR_FREE (mmgr, wcsdir); + return QSE_NULL; + } + qse_wcscpy (buf, wcsdir); + return buf; + } + + return wcsdir; +} + +/* +int qse_get_mbsfile_stat (const qse_mchar_t* file, qse_fstat_t* stat) +{ + return -1; +} + +int qse_get_wcsfile_stat (const qse_wchar_t* file, qse_fstat_t* stat) +{ + return -1 +}*/ + +int qse_get_prog_path (const qse_char_t* argv0, qse_char_t* buf, qse_size_t size, qse_mmgr_t* mmgr) +{ +#if defined(_WIN32) + if (GetModuleFileName(QSE_NULL, buf, size) == 0) return -1; +#else + if (argv0 == QSE_NULL) return -1; + + if (argv0[0] == QSE_T('/')) + { + /*qse_strxcpy (buf, size, argv0);*/ + qse_canonpath(argv0, buf, size); + } + else if (qse_strchr(argv0, QSE_T('/'))) + { + if (!qse_get_current_dir(buf, size, mmgr)) return -1; + qse_strxcajoin (buf, size, QSE_T("/"), argv0, QSE_NULL); + qse_canonpath (buf, buf, size); + } + else + { + qse_char_t *p, *q, * px = QSE_NULL; + qse_stat_t st; + qse_char_t dir[QSE_PATH_MAX + 1]; + qse_char_t pbuf[QSE_PATH_MAX + 1]; + int first = 1; + +#if defined(QSE_CHAR_IS_MCHAR) + p = getenv("PATH"); + if (!p) p = (qse_char_t*)QSE_T("/bin:/usr/bin"); +#else + qse_mchar_t* mp = getenv ("PATH"); + + if (!mp) p = (qse_char_t*)QSE_T("/bin:/usr/bin"); + else + { + px = qse_mbstowcsdup(mp, QSE_NULL, mmgr); + if (!px) return -1; + p = px; + } +#endif + + for (;;) + { + while (*p == QSE_T(':')) p++; + if (*p == QSE_T('\0')) + { + if (first) + { + p = (qse_char_t*)QSE_T("./"); + first = 0; + } + else + { + if (px) QSE_MMGR_FREE (mmgr, px); + return -1; + } + } + + q = p; + while (*p != QSE_T(':') && *p != QSE_T('\0')) p++; + + if (p - q >= QSE_COUNTOF(dir) - 1) + { + if (px) QSE_MMGR_FREE (mmgr, px); + return -1; + } + + qse_strxncpy (dir, QSE_COUNTOF(dir), q, p - q); + qse_canonpath (dir, dir, QSE_COUNTOF(dir)); + + qse_strxjoin (pbuf, QSE_COUNTOF(pbuf), dir, QSE_T("/"), argv0, QSE_NULL); + + if (qse_access(pbuf, QSE_ACCESS_EXECUTE) == 0 && + qse_stat(pbuf, &st) == 0 && S_ISREG(st.st_mode)) + { + break; + } + } + + if (px) QSE_MMGR_FREE (mmgr, px); + + if (pbuf[0] == QSE_T('/')) qse_strxcpy (buf, size, pbuf); + else + { + if (!qse_get_current_dir(buf, size, mmgr)) return -1; + qse_strxcajoin (buf, size, QSE_T("/"), pbuf, QSE_NULL); + qse_canonpath (buf, buf, size); + } + } +#endif + + return 0; +} diff --git a/qse/lib/si/fs.c b/qse/lib/si/fs.c index 32141a3c..bffb0bb5 100644 --- a/qse/lib/si/fs.c +++ b/qse/lib/si/fs.c @@ -614,7 +614,7 @@ qse_fs_ent_t* qse_fs_read (qse_fs_t* fs, int flags) (flags & QSE_FS_ENT_TIME); if (stat_needed) { - qse_mchar_t* tmp_name[4]; + const qse_mchar_t* tmp_name[4]; qse_mchar_t* mfname; /* TODO: use a buffer in info... instead of allocating an deallocating every time */ @@ -622,7 +622,7 @@ qse_fs_ent_t* qse_fs_read (qse_fs_t* fs, int flags) tmp_name[1] = QSE_MT("/"); tmp_name[2] = ent->d_name; tmp_name[3] = QSE_NULL; - mfname = qse_mbsadup (tmp_name, QSE_NULL, fs->mmgr); + mfname = qse_mbsadup(tmp_name, QSE_NULL, fs->mmgr); if (mfname == QSE_NULL) { fs->errnum = QSE_FS_ENOMEM;