]> git.saurik.com Git - cydia.git/blobdiff - Cytore.hpp
Objective-C seriously didn't notice my mistake :/.
[cydia.git] / Cytore.hpp
index 62e956c0447cd16bdbcb5c6ca28136c5aab1ed60..c0bad09b89178a24151a09621b2a172d9e666dc8 100644 (file)
@@ -50,10 +50,7 @@ struct Header {
     uint32_t version_;
     uint32_t size_;
     uint32_t reserved_;
-};
-
-struct Block {
-};
+} _packed;
 
 template <typename Target_>
 class Offset {
@@ -83,7 +80,11 @@ class Offset {
     bool IsNull() const {
         return offset_ == 0;
     }
-};
+} _packed;
+
+struct Block {
+    Cytore::Offset<void> reserved_;
+} _packed;
 
 template <typename Type_>
 static _finline Type_ Round(Type_ value, Type_ size) {
@@ -100,7 +101,23 @@ class File {
 
   private:
     int file_;
-    std::vector<uint8_t *> blocks_;
+
+    typedef std::vector<uint8_t *> BlockVector_;
+    BlockVector_ blocks_;
+
+    struct Mapping_ {
+        uint8_t *data_;
+        size_t size_;
+
+        Mapping_(uint8_t *data, size_t size) :
+            data_(data),
+            size_(size)
+        {
+        }
+    };
+
+    typedef std::vector<Mapping_> MappingVector_;
+    MappingVector_ maps_;
 
     Header &Header_() {
         return *reinterpret_cast<Header *>(blocks_[0]);
@@ -115,14 +132,23 @@ class File {
         size_t extend(size - before);
 
         void *data(mmap(NULL, extend, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, file_, before));
+        _assert(data != MAP_FAILED);
+        uint8_t *bytes(reinterpret_cast<uint8_t *>(data));
+
+        maps_.push_back(Mapping_(bytes, extend));
         for (size_t i(0); i != extend >> Shift_; ++i)
-            blocks_.push_back(reinterpret_cast<uint8_t *>(data) + Block_ * i);
+            blocks_.push_back(bytes + Block_ * i);
     }
 
-    void Truncate_(size_t capacity) {
+    bool Truncate_(size_t capacity) {
         capacity = Round(capacity, Block_);
-        ftruncate(file_, capacity);
+
+        int error(ftruncate(file_, capacity));
+        if (error != 0)
+            return false;
+
         Map_(capacity);
+        return true;
     }
 
   public:
@@ -138,46 +164,70 @@ class File {
     }
 
     ~File() {
-        // XXX: this object is never deconstructed. if it were, this should unmap the memory
+        for (typename MappingVector_::const_iterator map(maps_.begin()); map != maps_.end(); ++map)
+            munmap(map->data_, map->size_);
         close(file_);
     }
 
+    void Sync() {
+        for (typename MappingVector_::const_iterator map(maps_.begin()); map != maps_.end(); ++map)
+            msync(map->data_, map->size_, MS_SYNC);
+    }
+
     size_t Capacity() const {
         return blocks_.size() * Block_;
     }
 
-    void Open(const char *path) {
+    void Open(const char *path) { open:
         _assert(file_ == -1);
         file_ = open(path, O_RDWR | O_CREAT | O_EXLOCK, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+        _assert(file_ != -1);
 
         struct stat stat;
-        fstat(file_, &stat);
+        _assert(fstat(file_, &stat) == 0);
 
         size_t core(sizeof(Header) + sizeof(Base_));
 
         size_t size(stat.st_size);
         if (size == 0) {
-            Truncate_(core);
+            if (!Truncate_(core)) {
+                unlink(path);
+                _assert(false);
+            }
+
             Header_().magic_ = Magic;
             Size_() = core;
+        } else if (size < core) {
+            close(file_);
+            file_ = -1;
+            unlink(path);
+            goto open;
         } else {
-            _assert(size >= core);
-            Truncate_(size);
+            // XXX: this involves an unneccessary call to ftruncate()
+            _assert(Truncate_(size));
             _assert(Header_().magic_ == Magic);
             _assert(Header_().version_ == 0);
         }
     }
 
-    void Reserve(size_t capacity) {
+    bool Reserve(size_t capacity) {
         if (capacity <= Capacity())
-            return;
+            return true;
+
+        uint8_t *block(blocks_.back());
         blocks_.pop_back();
-        Truncate_(capacity);
+
+        if (Truncate_(capacity))
+            return true;
+        else {
+            blocks_.push_back(block);
+            return false;
+        }
     }
 
     template <typename Target_>
     Target_ &Get(uint32_t offset) {
-        return *reinterpret_cast<Target_ *>(blocks_[offset >> Shift_] + (offset & Mask_));
+        return *reinterpret_cast<Target_ *>(offset == 0 ? NULL : blocks_[offset >> Shift_] + (offset & Mask_));
     }
 
     template <typename Target_>
@@ -193,9 +243,15 @@ class File {
     Offset<Target_> New(size_t extra = 0) {
         size_t size(sizeof(Target_) + extra);
         size = Round(size, sizeof(uintptr_t));
-        Reserve(Size_() + size);
-        uint32_t offset(Size_());
-        Size_() += size;
+
+        uint32_t offset;
+        if (!Reserve(Size_() + size))
+            offset = 0;
+        else {
+            offset = Size_();
+            Size_() += size;
+        }
+
         return Offset<Target_>(offset);
     }
 };