|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2021 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: // ! 8: // ディスクイメージ (生イメージ形式) ! 9: // ! 10: ! 11: #include "diskimage_raw.h" ! 12: #include <fcntl.h> ! 13: #include <sys/stat.h> ! 14: #include <sys/mman.h> ! 15: ! 16: // コンストラクタ ! 17: DiskImageRaw::DiskImageRaw(const std::string& pathname_) ! 18: : inherited(DiskImage::Type::Raw) ! 19: { ! 20: pathname = pathname_; ! 21: memlen = (off_t)-1; ! 22: } ! 23: ! 24: // デストラクタ ! 25: DiskImageRaw::~DiskImageRaw() ! 26: { ! 27: Close(); ! 28: } ! 29: ! 30: // このディスクイメージのサイズと書き込み可能かどうかを返す。 ! 31: // Open() 前でも動作する。 ! 32: int ! 33: DiskImageRaw::GetInfo(off_t *sizep, bool *w_ok) ! 34: { ! 35: // ファイルサイズは未取得なら取得 ! 36: if (memlen == (off_t)-1) { ! 37: struct stat st; ! 38: ! 39: if (stat(pathname.c_str(), &st) < 0) { ! 40: warn("%s: stat failed", pathname.c_str()); ! 41: return -1; ! 42: } ! 43: memlen = st.st_size; ! 44: } ! 45: *sizep = memlen; ! 46: ! 47: // ファイルのパーミッション ! 48: int r = access(pathname.c_str(), W_OK); ! 49: if (r == 0) { ! 50: *w_ok = true; ! 51: } else if (errno == EACCES) { ! 52: *w_ok = false; ! 53: } else { ! 54: warn("%s: access failed", pathname.c_str()); ! 55: return -1; ! 56: } ! 57: ! 58: return 0; ! 59: } ! 60: ! 61: // オープン ! 62: bool ! 63: DiskImageRaw::Open(bool read_only) ! 64: { ! 65: int openmode; ! 66: int prot; ! 67: ! 68: assert(pathname.empty() == false); ! 69: ! 70: if (read_only) { ! 71: openmode = O_RDONLY; ! 72: prot = PROT_READ; ! 73: } else { ! 74: openmode = O_RDWR; ! 75: prot = PROT_READ | PROT_WRITE; ! 76: } ! 77: ! 78: fd = open(pathname.c_str(), openmode); ! 79: if (fd < 0) { ! 80: warn("%s", pathname.c_str()); ! 81: return false; ! 82: } ! 83: ! 84: // ファイルサイズは未取得なら取得 ! 85: if (memlen == (off_t)-1) { ! 86: struct stat st; ! 87: ! 88: if (fstat(fd, &st) < 0) { ! 89: warn("%s: stat failed", pathname.c_str()); ! 90: fd.Close(); ! 91: return false; ! 92: } ! 93: memlen = st.st_size; ! 94: } ! 95: ! 96: // mmap ! 97: void *m = mmap(NULL, (size_t)memlen, prot, MAP_SHARED, fd, 0); ! 98: if (m == MAP_FAILED) { ! 99: warn("%s: mmap failed", pathname.c_str()); ! 100: fd.Close(); ! 101: return false; ! 102: } ! 103: mem = (uint8 *)m; ! 104: ! 105: return true; ! 106: } ! 107: ! 108: bool ! 109: DiskImageRaw::Read(void *buf, off_t offset, size_t size) ! 110: { ! 111: if (__predict_false(fd < 0)) { ! 112: return false; ! 113: } ! 114: ! 115: memcpy(buf, &mem[offset], size); ! 116: return true; ! 117: } ! 118: ! 119: bool ! 120: DiskImageRaw::Write(const void *buf, off_t offset, size_t size) ! 121: { ! 122: if (__predict_false(fd < 0)) { ! 123: return false; ! 124: } ! 125: ! 126: memcpy(&mem[offset], buf, size); ! 127: return true; ! 128: } ! 129: ! 130: void ! 131: DiskImageRaw::Close() ! 132: { ! 133: if (fd >= 0) { ! 134: munmap(mem, (size_t)memlen); ! 135: fd.Close(); ! 136: } ! 137: } ! 138: ! 139: off_t ! 140: DiskImageRaw::GetSize() const ! 141: { ! 142: return memlen; ! 143: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.