aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbutl/fdstream.cxx67
-rw-r--r--libbutl/fdstream.mxx12
-rw-r--r--libbutl/filesystem.cxx7
-rw-r--r--libbutl/filesystem.mxx2
-rw-r--r--tests/lz4/driver.cxx6
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
{