Annotation of nono/host/diskimage.cpp, revision 1.1.1.2

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2021 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
1.1.1.2 ! root        8: // ディスクイメージ
1.1       root        9: //
                     10: 
                     11: #include "diskimage.h"
                     12: #include "diskimage_raw.h"
1.1.1.2 ! root       13: #include "mainapp.h"
        !            14: #include <fcntl.h>
        !            15: 
        !            16: //
        !            17: // ディスクイメージクラス (外部向け)
        !            18: //
1.1       root       19: 
                     20: // コンストラクタ
1.1.1.2 ! root       21: DiskImage::DiskImage()
1.1       root       22: {
                     23: }
                     24: 
                     25: // デストラクタ
                     26: DiskImage::~DiskImage()
                     27: {
1.1.1.2 ! root       28:        Close();
1.1       root       29: }
                     30: 
1.1.1.2 ! root       31: // パス名を指定して、下位ドライバをオープン
        !            32: bool
        !            33: DiskImage::CreateHandler(const std::string& pathname_)
1.1       root       34: {
1.1.1.2 ! root       35:        pathname = pathname_;
        !            36:        cow_enable = false;
        !            37: 
1.1       root       38:        // 今の所 Raw しかない
1.1.1.2 ! root       39:        try {
        !            40:                driver.reset(new DiskImageRaw(pathname));
        !            41:                return true;
        !            42:        } catch (...) {
        !            43:        }
        !            44: 
        !            45:        return false;
        !            46: }
        !            47: 
        !            48: 
        !            49: // このディスクイメージのサイズと書き込み可能かどうかを返す。
        !            50: // Open() 前でも動作する。
        !            51: bool
        !            52: DiskImage::GetInfo(off_t *sizep, bool *w_ok)
        !            53: {
        !            54:        assert((bool)driver);
        !            55:        return driver->GetInfo(sizep, w_ok);
        !            56: }
        !            57: 
        !            58: // オープン
        !            59: //
        !            60: // ro          cow
        !            61: // false       false   : RW オープン、書き込み可
        !            62: // true                false   : RO オープン、読み込み専用
        !            63: // *           true    : RO オープン、CoW
        !            64: bool
        !            65: DiskImage::Open(bool read_only, bool cow_enable_)
        !            66: {
        !            67:        assert((bool)driver);
        !            68:        cow_enable = cow_enable_;
        !            69: 
        !            70:        // ベースファイルをオープン
        !            71:        if (cow_enable) {
        !            72:                read_only = true;
        !            73:        }
        !            74:        if (driver->Open(read_only) == false) {
        !            75:                return false;
        !            76:        }
        !            77: 
        !            78:        if (cow_enable) {
        !            79:                // CoW なら一時ファイルもオープン
        !            80: 
        !            81:                // VM ディレクトリに適当な名前の隠しファイルで作成
        !            82:                auto pos = pathname.rfind('/');
        !            83:                if (pos != std::string::npos) {
        !            84:                        // パス区切りがあればファイル名部分
        !            85:                        cowname = pathname.substr(pos + 1);
        !            86:                } else {
        !            87:                        // なければ全部
        !            88:                        cowname = pathname;
        !            89:                }
        !            90:                // 空になることはないはず
        !            91:                assert(cowname.empty() == false);
        !            92: 
        !            93:                cowname = gMainApp.GetVMDir() + "/." + cowname + ".cow";
        !            94:                cowfd = open(cowname.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0644);
        !            95:                if (cowfd < 0) {
        !            96:                        return false;
        !            97:                }
        !            98:        }
        !            99: 
        !           100:        return true;
        !           101: }
        !           102: 
        !           103: // クローズ
        !           104: void
        !           105: DiskImage::Close()
        !           106: {
        !           107:        if (cow_enable) {
        !           108:                if (cowfd.Valid()) {
        !           109:                        cowfd.Close();
        !           110:                        unlink(cowname.c_str());
        !           111:                }
        !           112:                cow_enable = false;
        !           113:        }
        !           114: 
        !           115:        if ((bool)driver) {
        !           116:                driver.reset();
        !           117:        }
        !           118: }
        !           119: 
        !           120: // このディスクイメージのサイズ(バイト数)を返す。
        !           121: // オープン後のみ使用可能。
        !           122: off_t
        !           123: DiskImage::GetSize() const
        !           124: {
        !           125:        assert((bool)driver);
        !           126:        return driver->GetSize();
        !           127: }
        !           128: 
        !           129: // 読み出し
        !           130: bool
        !           131: DiskImage::Read(void *buf, off_t offset, size_t size) const
        !           132: {
        !           133:        assert((bool)driver);
        !           134: 
        !           135:        if (__predict_false(offset + size >= GetSize())) {
        !           136:                return false;
        !           137:        }
        !           138: 
        !           139:        if (__predict_true(cow_enable == false)) {
        !           140:                // 通常モード
        !           141:                return driver->Read(buf, offset, size);
        !           142: 
        !           143:        } else {
        !           144:                // Copy-on-Write モード
        !           145:                while (size > 0) {
        !           146:                        off_t  blk_addr = offset / BLKSIZE;
        !           147:                        size_t blk_off  = offset % BLKSIZE;
        !           148:                        size_t blk_size = std::min(size, BLKSIZE - blk_off);
        !           149: 
        !           150:                        if (map_contains(blk_addr)) {
        !           151:                                // キャッシュにあればそこから読み出す。
        !           152:                                auto cow_offset = map.at(blk_addr);
        !           153:                                if (lseek(cowfd, cow_offset + blk_off, SEEK_SET) < 0) {
        !           154:                                        return false;
        !           155:                                }
        !           156:                                if (read(cowfd, buf, blk_size) < 0) {
        !           157:                                        return false;
        !           158:                                }
        !           159:                        } else {
        !           160:                                // キャッシュになければファイルから直接読む
        !           161:                                if (driver->Read(buf, offset, blk_size) == false) {
        !           162:                                        return false;
        !           163:                                }
        !           164:                        }
        !           165: 
        !           166:                        buf = (uint8 *)buf + blk_size;
        !           167:                        offset += blk_size;
        !           168:                        size -= blk_size;
        !           169:                }
        !           170:        }
        !           171: 
        !           172:        return true;
        !           173: }
        !           174: 
        !           175: // 書き込み
        !           176: bool
        !           177: DiskImage::Write(const void *buf, off_t offset, size_t size)
        !           178: {
        !           179:        assert((bool)driver);
        !           180: 
        !           181:        if (__predict_false(offset + size >= GetSize())) {
        !           182:                return false;
        !           183:        }
        !           184: 
        !           185:        if (__predict_true(cow_enable == false)) {
        !           186:                // 通常モード
        !           187:                return driver->Write(buf, offset, size);
        !           188: 
        !           189:        } else {
        !           190:                // Copy-on-Write モード
        !           191: 
        !           192:                off_t cow_offset;
        !           193:                while (size > 0) {
        !           194:                        off_t  blk_addr = offset / BLKSIZE;
        !           195:                        size_t blk_off  = offset % BLKSIZE;
        !           196:                        size_t blk_size = std::min(size, BLKSIZE - blk_off);
        !           197: 
        !           198:                        if (map_contains(blk_addr) == false) {
        !           199:                                // キャッシュになければファイルから読んで..
        !           200:                                SectBuf newbuf;
        !           201:                                off_t read_off = blk_addr * BLKSIZE;
        !           202:                                if (driver->Read(&newbuf[0], read_off, BLKSIZE) == false) {
        !           203:                                        return false;
        !           204:                                }
        !           205: 
        !           206:                                // それをキャッシュの末尾に追加
        !           207:                                cow_offset = lseek(cowfd, 0, SEEK_END);
        !           208:                                if (cow_offset == (off_t)-1) {
        !           209:                                        return false;
        !           210:                                }
        !           211:                                if (write(cowfd, &newbuf[0], BLKSIZE) < BLKSIZE) {
        !           212:                                        return false;
        !           213:                                }
        !           214:                                map.emplace(blk_addr, cow_offset);
        !           215:                        }
        !           216: 
        !           217:                        // キャッシュに書き込む
        !           218:                        cow_offset = map.at(blk_addr);
        !           219:                        if (lseek(cowfd, cow_offset + blk_off, SEEK_SET) < 0) {
        !           220:                                return false;
        !           221:                        }
        !           222:                        if (write(cowfd, buf, blk_size) < 0) {
        !           223:                                return false;
        !           224:                        }
        !           225: 
        !           226:                        buf = (const uint8 *)buf + blk_size;
        !           227:                        offset += blk_size;
        !           228:                        size -= blk_size;
        !           229:                }
        !           230:        }
        !           231: 
        !           232:        return true;
        !           233: }
        !           234: 
        !           235: 
        !           236: //
        !           237: // ディスクイメージドライバの基本クラス
        !           238: //
        !           239: 
        !           240: // コンストラクタ
        !           241: DiskImageDriver::DiskImageDriver(const std::string& pathname_)
        !           242:        : pathname(pathname_)
        !           243: {
        !           244: }
        !           245: 
        !           246: // デストラクタ
        !           247: DiskImageDriver::~DiskImageDriver()
        !           248: {
1.1       root      249: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.