]> git.tdb.fi Git - libs/core.git/blobdiff - source/fs/unix/stat.cpp
Move most platform-specific code into overlay directories
[libs/core.git] / source / fs / unix / stat.cpp
diff --git a/source/fs/unix/stat.cpp b/source/fs/unix/stat.cpp
new file mode 100644 (file)
index 0000000..1404fed
--- /dev/null
@@ -0,0 +1,102 @@
+#define _FILE_OFFSET_BITS 64
+#include <cerrno>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <grp.h>
+#include <pwd.h>
+#include <msp/core/systemerror.h>
+#include <msp/strings/format.h>
+#include "stat.h"
+#include "stat_private.h"
+
+namespace Msp {
+namespace FS {
+
+Stat::Private::Private(const Private &other):
+       owner_id(other.owner_id),
+       group_id(other.group_id)
+{ }
+
+Stat::Private::~Private()
+{ }
+
+Stat Stat::Private::from_struct_stat(const struct stat &st)
+{
+       Stat result;
+       result.exists = true;
+       if(S_ISREG(st.st_mode))
+               result.type = REGULAR;
+       else if(S_ISDIR(st.st_mode))
+               result.type = DIRECTORY;
+       else if(S_ISLNK(st.st_mode))
+               result.type = SYMLINK;
+       else
+               result.type = UNKNOWN;
+       result.size = st.st_size;
+       result.alloc_size = st.st_blocks*512;
+       result.mtime = Time::TimeStamp::from_unixtime(st.st_mtime);
+
+       result.priv = new Private;
+       result.priv->owner_id = st.st_uid;
+       result.priv->group_id = st.st_gid;
+
+       return result;
+}
+
+void Stat::Private::fill_owner_info(Stat::OwnerInfo &result)
+{
+       char buf[1024];
+
+       struct passwd pw;
+       struct passwd *owner;
+       if(!getpwuid_r(owner_id, &pw, buf, sizeof(buf), &owner) && owner)
+               result.owner = owner->pw_name;
+       else
+               result.owner = format("%d", owner_id);
+
+       struct group gr;
+       struct group *group;
+       if(!getgrgid_r(group_id, &gr, buf, sizeof(buf), &group) && group)
+               result.group = group->gr_name;
+       else
+               result.group = format("%d", group_id);
+}
+
+
+Stat Stat::stat(const Path &path)
+{
+       struct stat st;
+       int ret = ::stat(path.str().c_str(), &st);
+       if(ret==-1)
+       {
+               if(errno==ENOENT)
+                       return Stat();
+               else
+                       throw system_error("stat");
+       }
+
+       return Private::from_struct_stat(st);
+}
+
+Stat Stat::lstat(const Path &path)
+{
+       struct stat st;
+       int ret = ::lstat(path.str().c_str(), &st);
+       if(ret==-1)
+       {
+               if(errno==ENOENT)
+                       return Stat();
+               else
+                       throw system_error("lstat");
+       }
+
+       return Private::from_struct_stat(st);
+}
+
+bool exists(const Path &path)
+{
+       return access(path.str().c_str(), F_OK)==0;
+}
+
+} // namespace FS
+} // namespace Msp