]> git.tdb.fi Git - libs/core.git/blobdiff - source/fs/unix/utils.cpp
Move most platform-specific code into overlay directories
[libs/core.git] / source / fs / unix / utils.cpp
diff --git a/source/fs/unix/utils.cpp b/source/fs/unix/utils.cpp
new file mode 100644 (file)
index 0000000..c832343
--- /dev/null
@@ -0,0 +1,65 @@
+#include <cstdio>
+#include <unistd.h>
+#include <msp/core/systemerror.h>
+#include "dir.h"
+#include "stat.h"
+#include "utils.h"
+
+using namespace std;
+
+namespace Msp {
+namespace FS {
+
+Path readlink(const Path &link)
+{
+       char buf[4096];
+       int len = ::readlink(link.c_str(), buf, sizeof(buf));
+       if(len==-1)
+               throw system_error("readlink");
+       return string(buf, len);
+}
+
+Path realpath(const Path &path)
+{
+       list<string> queue(path.begin(), path.end());
+       if(!path.is_absolute())
+       {
+               Path cwd = getcwd();
+               queue.insert(queue.begin(), cwd.begin(), cwd.end());
+       }
+
+       Path real;
+       unsigned n_links = 0;
+       while(!queue.empty())
+       {
+               Path next = real/queue.front();
+               queue.pop_front();
+
+               if(is_link(next))
+               {
+                       if(++n_links>64)
+                               throw runtime_error("too many symbolic links");
+                       Path link = readlink(next);
+                       queue.insert(queue.begin(), link.begin(), link.end());
+               }
+               else
+                       real = next;
+       }
+
+       return real;
+}
+
+void rename(const Path &from, const Path &to)
+{
+       if(::rename(from.c_str(), to.c_str())==-1)
+               throw system_error("rename");
+}
+
+void unlink(const Path &path)
+{
+       if(::unlink(path.c_str())==-1)
+               throw system_error("unlink");
+}
+
+} // namespace FS
+} // namespace Msp