Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56850e12 authored by David Anderson's avatar David Anderson Committed by Gerrit Code Review
Browse files

Merge "libsnapshot: Add an open /dev/null mode for CowWriter."

parents f2609b2b 1b9ab3f5
Loading
Loading
Loading
Loading
+30 −8
Original line number Diff line number Diff line
@@ -110,15 +110,28 @@ bool CowWriter::ParseOptions() {
    return true;
}

bool CowWriter::SetFd(android::base::borrowed_fd fd) {
    if (fd.get() < 0) {
        owned_fd_.reset(open("/dev/null", O_RDWR | O_CLOEXEC));
        if (owned_fd_ < 0) {
            PLOG(ERROR) << "open /dev/null failed";
            return false;
        }
        fd_ = owned_fd_;
        is_dev_null_ = true;
    } else {
        fd_ = fd;
    }
    return true;
}

bool CowWriter::Initialize(unique_fd&& fd, OpenMode mode) {
    owned_fd_ = std::move(fd);
    return Initialize(borrowed_fd{owned_fd_}, mode);
}

bool CowWriter::Initialize(borrowed_fd fd, OpenMode mode) {
    fd_ = fd;

    if (!ParseOptions()) {
    if (!SetFd(fd) || !ParseOptions()) {
        return false;
    }

@@ -139,9 +152,7 @@ bool CowWriter::InitializeAppend(android::base::unique_fd&& fd, uint64_t label)
}

bool CowWriter::InitializeAppend(android::base::borrowed_fd fd, uint64_t label) {
    fd_ = fd;

    if (!ParseOptions()) {
    if (!SetFd(fd) || !ParseOptions()) {
        return false;
    }

@@ -304,7 +315,7 @@ bool CowWriter::EmitLabel(uint64_t label) {
    CowOperation op = {};
    op.type = kCowLabelOp;
    op.source = label;
    return WriteOperation(op) && !fsync(fd_.get());
    return WriteOperation(op) && Sync();
}

std::basic_string<uint8_t> CowWriter::Compress(const void* data, size_t length) {
@@ -383,7 +394,7 @@ bool CowWriter::Finalize() {
        PLOG(ERROR) << "lseek ops failed";
        return false;
    }
    return !fsync(fd_.get());
    return Sync();
}

uint64_t CowWriter::GetCowSize() {
@@ -424,5 +435,16 @@ bool CowWriter::WriteRawData(const void* data, size_t size) {
    return true;
}

bool CowWriter::Sync() {
    if (is_dev_null_) {
        return true;
    }
    if (fsync(fd_.get()) < 0) {
        PLOG(ERROR) << "fsync failed";
        return false;
    }
    return true;
}

}  // namespace snapshot
}  // namespace android
+7 −0
Original line number Diff line number Diff line
@@ -90,6 +90,9 @@ class CowWriter : public ICowWriter {
    // If opening for write, the file starts from the beginning.
    // If opening for append, if the file has a footer, we start appending to the last op.
    // If the footer isn't found, the last label is considered corrupt, and dropped.
    //
    // If fd is < 0, the CowWriter will be opened against /dev/null. This is for
    // computing COW sizes without using storage space.
    bool Initialize(android::base::unique_fd&& fd, OpenMode mode = OpenMode::WRITE);
    bool Initialize(android::base::borrowed_fd fd, OpenMode mode = OpenMode::WRITE);
    // Set up a writer, assuming that the given label is the last valid label.
@@ -119,6 +122,9 @@ class CowWriter : public ICowWriter {
    void AddOperation(const CowOperation& op);
    std::basic_string<uint8_t> Compress(const void* data, size_t length);

    bool SetFd(android::base::borrowed_fd fd);
    bool Sync();

  private:
    android::base::unique_fd owned_fd_;
    android::base::borrowed_fd fd_;
@@ -126,6 +132,7 @@ class CowWriter : public ICowWriter {
    CowFooter footer_{};
    int compression_ = 0;
    uint64_t next_op_pos_ = 0;
    bool is_dev_null_ = false;

    // :TODO: this is not efficient, but stringstream ubsan aborts because some
    // bytes overflow a signed char.