diff options
-rw-r--r-- | libbutl/fdstream.cxx | 67 | ||||
-rw-r--r-- | libbutl/fdstream.mxx | 12 | ||||
-rw-r--r-- | libbutl/filesystem.cxx | 7 | ||||
-rw-r--r-- | libbutl/filesystem.mxx | 2 | ||||
-rw-r--r-- | tests/lz4/driver.cxx | 6 |
5 files changed, 76 insertions, 18 deletions
diff --git a/libbutl/fdstream.cxx b/libbutl/fdstream.cxx index 4948052..308d76c 100644 --- a/libbutl/fdstream.cxx +++ b/libbutl/fdstream.cxx @@ -12,20 +12,27 @@ # include <unistd.h> // close(), read(), write(), lseek(), dup(), pipe(), // ftruncate(), isatty(), ssize_t, STD*_FILENO # include <sys/uio.h> // writev(), iovec -# include <sys/stat.h> // stat(), S_I* +# include <sys/stat.h> // stat(), fstat(), S_I* # include <sys/time.h> // timeval # include <sys/types.h> // stat, off_t # include <sys/select.h> #else # include <libbutl/win32-utility.hxx> -# include <io.h> // _close(), _read(), _write(), _setmode(), _sopen(), - // _lseek(), _dup(), _pipe(), _chsize_s, - // _get_osfhandle() -# include <share.h> // _SH_DENYNO -# include <stdio.h> // _fileno(), stdin, stdout, stderr, SEEK_* -# include <fcntl.h> // _O_* -# include <sys/stat.h> // S_I* +# include <io.h> // _close(), _read(), _write(), _setmode(), _sopen(), + // _lseek(), _dup(), _pipe(), _chsize_s, + // _get_osfhandle() +# include <share.h> // _SH_DENYNO +# include <stdio.h> // _fileno(), stdin, stdout, stderr, SEEK_* +# include <fcntl.h> // _O_* +# include <sys/types.h> // _stat +# include <sys/stat.h> // fstat(), S_I* + +# ifdef _MSC_VER // Unlikely to be fixed in newer versions. +# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) +# endif # include <wchar.h> // wcsncmp(), wcsstr() @@ -1372,6 +1379,28 @@ namespace butl throw_generic_ios_failure (errno); } + entry_stat + fdstat (int fd) + { + struct stat s; + if (fstat (fd, &s) != 0) + throw_generic_error (errno); + + auto m (s.st_mode); + entry_type t (entry_type::unknown); + + // Note: cannot be a symlink. + // + if (S_ISREG (m)) + t = entry_type::regular; + else if (S_ISDIR (m)) + t = entry_type::directory; + else if (S_ISBLK (m) || S_ISCHR (m) || S_ISFIFO (m) || S_ISSOCK (m)) + t = entry_type::other; + + return entry_stat {t, static_cast<uint64_t> (s.st_size)}; + } + bool fdterm (int fd) { @@ -1779,6 +1808,28 @@ namespace butl throw_generic_ios_failure (e); } + entry_stat + fdstat (int fd) + { + // Since symlinks have been taken care of, we can just _fstat(). + // + struct __stat64 s; + if (_fstat64 (fd, &s) != 0) + throw_generic_error (errno); + + auto m (s.st_mode); + entry_type t (entry_type::unknown); + + if (S_ISREG (m)) + t = entry_type::regular; + else if (S_ISDIR (m)) + t = entry_type::directory; + else if (S_ISCHR (m)) + t = entry_type::other; + + return entry_stat {t, static_cast<uint64_t> (s.st_size)}; + } + bool fdterm (int fd) { diff --git a/libbutl/fdstream.mxx b/libbutl/fdstream.mxx index c863d2c..9818732 100644 --- a/libbutl/fdstream.mxx +++ b/libbutl/fdstream.mxx @@ -30,7 +30,7 @@ import std.core; import std.io; #endif import butl.path; -import butl.filesystem; // permissions +import butl.filesystem; // permissions, entry_stat import butl.small_vector; #else #include <libbutl/path.mxx> @@ -862,9 +862,17 @@ LIBBUTL_MODEXPORT namespace butl LIBBUTL_SYMEXPORT void fdtruncate (int, std::uint64_t); - // Test whether a file descriptor refers to a terminal. Throw ios::failure on + // Return filesystem entry stat from file descriptor. Throw ios::failure on // the underlying OS error. // + // See also path_entry() in filesystem. + // + LIBBUTL_SYMEXPORT entry_stat + fdstat (int); + + // Test whether a file descriptor refers to a terminal. Throw ios::failure + // on the underlying OS error. + // LIBBUTL_SYMEXPORT bool fdterm (int); diff --git a/libbutl/filesystem.cxx b/libbutl/filesystem.cxx index 2147c6f..787747d 100644 --- a/libbutl/filesystem.cxx +++ b/libbutl/filesystem.cxx @@ -24,13 +24,14 @@ # include <sys/types.h> // _stat # include <sys/stat.h> // _stat(), S_I* -# include <cwchar> // mbsrtowcs(), wcsrtombs(), mbstate_t -# include <cstring> // strncmp() - # ifdef _MSC_VER // Unlikely to be fixed in newer versions. # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) # endif + +# include <cwchar> // mbsrtowcs(), wcsrtombs(), mbstate_t +# include <cstring> // strncmp() #endif #include <cassert> diff --git a/libbutl/filesystem.mxx b/libbutl/filesystem.mxx index 7506439..eb03ab2 100644 --- a/libbutl/filesystem.mxx +++ b/libbutl/filesystem.mxx @@ -125,6 +125,8 @@ LIBBUTL_MODEXPORT namespace butl // std::system_error, unless ignore_error is true (in which case erroneous // entries are treated as non-existent). // + // See also fdstat() in fdstream. + // LIBBUTL_SYMEXPORT std::pair<bool, entry_stat> path_entry (const char*, bool follow_symlinks = false, diff --git a/tests/lz4/driver.cxx b/tests/lz4/driver.cxx index e3da5e6..e2fd537 100644 --- a/tests/lz4/driver.cxx +++ b/tests/lz4/driver.cxx @@ -24,14 +24,10 @@ try if (argv[1][1] == 'c') { - // @@ TODO: would be nice to get it from fd. - // - entry_stat st (path_entry (argv[2], true /* follow_symlinks */).second); - lz4::compress (ofs, ifs, 1 /* compression_level */, 4 /* block_size_id (64KB) */, - st.size); + fdstat (ifs.fd ()).size); } else { |