diff --git a/src/lol/base/string.h b/src/lol/base/string.h
index a9d953f8..8872f070 100644
--- a/src/lol/base/string.h
+++ b/src/lol/base/string.h
@@ -95,6 +95,13 @@ public:
         return ((Super const &)*this).Count() - 1;
     }
 
+    /* Return a C string */
+    inline char const *C() const
+    {
+        return &(*this)[0];
+    }
+
+    /* Does not initialise the newly allocated characters */
     void Resize(int count)
     {
         ASSERT(count >= 0);
diff --git a/src/lol/sys/atomic.h b/src/lol/sys/atomic.h
index 8412b57c..26306e1b 100644
--- a/src/lol/sys/atomic.h
+++ b/src/lol/sys/atomic.h
@@ -20,6 +20,7 @@ namespace lol
 template<typename T> class Atomic
 {
 public:
+    inline Atomic() : m_value(0) {}
     inline Atomic(T const &value) : m_value(value) {}
 
     operator T() const
@@ -42,7 +43,7 @@ public:
         return ret;
     }
 
-    inline T& operator++()
+    inline T operator++()
     {
         m_mutex.Lock();
         T ret = ++m_value;
@@ -58,7 +59,7 @@ public:
         return ret;
     }
 
-    inline T& operator--()
+    inline T operator--()
     {
         m_mutex.Lock();
         T ret = --m_value;
diff --git a/src/lol/sys/file.h b/src/lol/sys/file.h
index d572beb0..4f7363c1 100644
--- a/src/lol/sys/file.h
+++ b/src/lol/sys/file.h
@@ -37,11 +37,13 @@ struct FileAccess
 class File
 {
 public:
-    inline File() : m_data(0) {}
-    inline ~File() {}
+    File();
+    File(File const &that);
+    File &operator =(File const &that);
+    ~File();
 
     void Open(String const &file, FileAccess mode);
-    String const &ReadString();
+    String ReadString();
     void Close();
 
 private:
diff --git a/src/sys/file.cpp b/src/sys/file.cpp
index 2fc0ffc7..c376bb2d 100644
--- a/src/sys/file.cpp
+++ b/src/sys/file.cpp
@@ -21,7 +21,100 @@ class FileData
 {
     friend class File;
 
+    void Open(String const &file, FileAccess mode)
+    {
+#if HAVE_STDIO_H
+        /* FIXME: no modes, no error checking, no nothing */
+        m_fd = fopen(file.C(), "r");
+#endif
+    }
+
+    String ReadString()
+    {
+        String ret;
+#if HAVE_STDIO_H
+        while (!feof(m_fd))
+        {
+            char buf[BUFSIZ];
+            size_t count = fread(buf, 1, BUFSIZ, m_fd);
+            if (count <= 0)
+                break;
+
+            int oldsize = ret.Count();
+            ret.Resize(oldsize + count);
+            memcpy(&ret[oldsize], buf, count);
+        }
+#endif
+        return ret;
+    }
+
+    void Close()
+    {
+#if HAVE_STDIO_H
+        fclose(m_fd);
+#endif
+    }
+
+#if HAVE_STDIO_H
+    FILE *m_fd;
+#endif
+    Atomic<int> m_refcount;
 };
 
+File::File()
+  : m_data(new FileData)
+{
+    ++m_data->m_refcount;
+}
+
+File::File(File const &that)
+  : m_data(that.m_data)
+{
+    ++m_data->m_refcount;
+}
+
+File &File::operator =(File const &that)
+{
+    if (this == &that)
+        return *this;
+
+    int refcount = --m_data->m_refcount;
+    if (refcount == 0)
+    {
+        m_data->Close();
+        delete m_data;
+    }
+
+    m_data = that.m_data;
+    ++m_data->m_refcount;
+
+    return *this;
+}
+
+File::~File()
+{
+    int refcount = --m_data->m_refcount;
+    if (refcount == 0)
+    {
+        m_data->Close();
+        delete m_data;
+    }
+}
+
+void File::Open(String const &file, FileAccess mode)
+{
+    return m_data->Open(file, mode);
+}
+
+String File::ReadString()
+{
+    return m_data->ReadString();
+}
+
+void File::Close()
+{
+    m_data->Close();
+}
+
 } /* namespace lol */