]> git.saurik.com Git - cydia.git/blobdiff - Cytore.hpp
Attempt to isolate Cydia's priviledged code paths.
[cydia.git] / Cytore.hpp
index 62e956c0447cd16bdbcb5c6ca28136c5aab1ed60..168f2ef574127f4090fbc5a45a8c136e86656849 100644 (file)
@@ -52,9 +52,6 @@ struct Header {
     uint32_t reserved_;
 };
 
-struct Block {
-};
-
 template <typename Target_>
 class Offset {
   private:
@@ -85,6 +82,10 @@ class Offset {
     }
 };
 
+struct Block {
+    Cytore::Offset<void> reserved_;
+};
+
 template <typename Type_>
 static _finline Type_ Round(Type_ value, Type_ size) {
     Type_ mask(size - 1);
@@ -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,10 +164,16 @@ 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_;
     }
@@ -149,35 +181,45 @@ class File {
     void Open(const char *path) {
         _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);
+            _assert(Truncate_(core));
             Header_().magic_ = Magic;
             Size_() = core;
         } 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 +235,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);
     }
 };