|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2020 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: // UFS ! 8: ! 9: #include "ufs.h" ! 10: #include "ffs_dir.h" ! 11: #include "scsidev.h" ! 12: ! 13: // ! 14: // ファイルシステムハンドルっぽいもの ! 15: // ! 16: ! 17: // コンストラクタ ! 18: Filesys::Filesys(Device *parent_) ! 19: { ! 20: parent = parent_; ! 21: fs = &fs0; ! 22: } ! 23: ! 24: // デストラクタ ! 25: Filesys::~Filesys() ! 26: { ! 27: } ! 28: ! 29: // パーティションを FFS としてオープンする(マウントのようなイメージ)。 ! 30: // start, size はこのパーティションの開始セクタとセクタ数。 ! 31: // 成功すれば true を返す。 ! 32: // 失敗すれば errstr にエラーメッセージをセットして false を返す。 ! 33: bool ! 34: Filesys::Mount(SCSIHD *hd_, uint32 start, uint32 size) ! 35: { ! 36: hd = hd_; ! 37: part_start = start; ! 38: part_size = size; ! 39: ! 40: // FFS の先頭にはブートブロックがあり、続けてスーパーブロックがある。 ! 41: // ブートブロックはブートローダのための領域で、ここもファイルシステムの ! 42: // 内側という認識のようだ。 ! 43: // ! 44: // ブートブロックの大きさはおそらくファイルシステムごとに固定で、 ! 45: // FFSv1(?) なら 8KB のようだ。ここは LUNA-I の ROM が解釈できるのと ! 46: // 同じファイルシステムだけ扱えればよいので、8KB 固定とする。 ! 47: // 続いてスーパーブロックがある。ここにこのファイルシステムのパラメータ ! 48: // が書いてある。 ! 49: // ! 50: // +-------------+ 0 <- part_start (パーティション先頭) ! 51: // | BootBlock | ! 52: // +-------------+ 8KB ! 53: // | SuperBlock | ! 54: // | fs_iblkno ---+ ! 55: // +-------------+ | ! 56: // : : | ! 57: // | ! 58: // : : | ! 59: // +-------------+ <-+ ! 60: // | InodeBlock? | ! 61: // ! 62: // スーパーブロックの構造は <ufs/ffs/fs.h> の struct fs 参照。 ! 63: ! 64: // スーパーブロックを読む (ここはまだ PeekBlock() は使えない) ! 65: hd->PeekImage(&fs0, part_start * 512 + 8192, sizeof(fs0)); ! 66: // 読み込んだスーパーブロックはゲストエンディアン(BE) なので ! 67: // 使う前に (もう面倒なのでほぼ全部) ホストエンディアンにしておく。 ! 68: // ヘッダに定義してあるマクロをそのまま使いたいからだけど、正気かなこれ。 ! 69: fs->fs_firstfield = be32toh(fs->fs_firstfield); ! 70: fs->fs_sblkno = be32toh(fs->fs_sblkno); ! 71: fs->fs_cblkno = be32toh(fs->fs_cblkno); ! 72: fs->fs_iblkno = be32toh(fs->fs_iblkno); ! 73: fs->fs_dblkno = be32toh(fs->fs_dblkno); ! 74: fs->fs_old_cgoffset = be32toh(fs->fs_old_cgoffset); ! 75: fs->fs_old_cgmask = be32toh(fs->fs_old_cgmask); ! 76: fs->fs_old_time = be32toh(fs->fs_old_time); ! 77: fs->fs_old_size = be32toh(fs->fs_old_size); ! 78: fs->fs_old_dsize = be32toh(fs->fs_old_dsize); ! 79: fs->fs_ncg = be32toh(fs->fs_ncg); ! 80: fs->fs_bsize = be32toh(fs->fs_bsize); ! 81: fs->fs_fsize = be32toh(fs->fs_fsize); ! 82: fs->fs_frag = be32toh(fs->fs_frag); ! 83: fs->fs_minfree = be32toh(fs->fs_minfree); ! 84: fs->fs_old_rotdelay = be32toh(fs->fs_old_rotdelay); ! 85: fs->fs_old_rps = be32toh(fs->fs_old_rps); ! 86: fs->fs_bmask = be32toh(fs->fs_bmask); ! 87: fs->fs_fmask = be32toh(fs->fs_fmask); ! 88: fs->fs_bshift = be32toh(fs->fs_bshift); ! 89: fs->fs_fshift = be32toh(fs->fs_fshift); ! 90: fs->fs_maxcontig = be32toh(fs->fs_maxcontig); ! 91: fs->fs_maxbpg = be32toh(fs->fs_maxbpg); ! 92: fs->fs_fragshift = be32toh(fs->fs_fragshift); ! 93: fs->fs_fsbtodb = be32toh(fs->fs_fsbtodb); ! 94: fs->fs_sbsize = be32toh(fs->fs_sbsize); ! 95: //fs->fs_spare1[2] ! 96: fs->fs_nindir = be32toh(fs->fs_nindir); ! 97: fs->fs_inopb = be32toh(fs->fs_inopb); ! 98: fs->fs_old_nspf = be32toh(fs->fs_old_nspf); ! 99: fs->fs_optim = be32toh(fs->fs_optim); ! 100: fs->fs_old_npsect = be32toh(fs->fs_old_npsect); ! 101: fs->fs_old_interleave = be32toh(fs->fs_old_interleave); ! 102: fs->fs_old_trackskew = be32toh(fs->fs_old_trackskew); ! 103: fs->fs_id[0] = be32toh(fs->fs_id[0]); ! 104: fs->fs_id[1] = be32toh(fs->fs_id[1]); ! 105: fs->fs_old_csaddr = be32toh(fs->fs_old_csaddr); ! 106: fs->fs_cssize = be32toh(fs->fs_cssize); ! 107: fs->fs_cgsize = be32toh(fs->fs_cgsize); ! 108: fs->fs_spare2 = be32toh(fs->fs_spare2); ! 109: fs->fs_old_nsect = be32toh(fs->fs_old_nsect); ! 110: fs->fs_old_spc = be32toh(fs->fs_old_spc); ! 111: fs->fs_old_ncyl = be32toh(fs->fs_old_ncyl); ! 112: fs->fs_old_cpg = be32toh(fs->fs_old_cpg); ! 113: fs->fs_ipg = be32toh(fs->fs_ipg); ! 114: fs->fs_fpg = be32toh(fs->fs_fpg); ! 115: //struct csum fs_old_cstotal ! 116: //u_char fs_fsmnt[MAXMNTLEN] ! 117: //u_char fs_volname[MAXVOLLEN] ! 118: fs->fs_swuid = be64toh(fs->fs_swuid); ! 119: fs->fs_pad = be32toh(fs->fs_pad); ! 120: fs->fs_cgrotor = be32toh(fs->fs_cgrotor); ! 121: //void *fs_ocsp[NOCSPTRS] ! 122: //struct csum *fs_csp ! 123: //uint32_t *fs_maxcluster ! 124: //u_char *fs_active ! 125: fs->fs_old_cpc = be32toh(fs->fs_old_cpc); ! 126: fs->fs_maxbsize = be32toh(fs->fs_maxbsize); ! 127: fs->fs_journal_flags = be32toh(fs->fs_journal_flags); ! 128: //uint64_t fs->fs_journallocs[4] ! 129: fs->fs_quota_magic = be32toh(fs->fs_quota_magic); ! 130: //uint64_t fs->fs_quotafile[2] ! 131: //uint64_t fs->fs_sparecon64[9] ! 132: fs->fs_sblockloc = be64toh(fs->fs_sblockloc); ! 133: //struct csum_total fs_cstotal ! 134: fs->fs_time = be64toh(fs->fs_time); ! 135: fs->fs_size = be64toh(fs->fs_size); ! 136: fs->fs_dsize = be64toh(fs->fs_dsize); ! 137: fs->fs_csaddr = be64toh(fs->fs_csaddr); ! 138: fs->fs_pendingblocks = be64toh(fs->fs_pendingblocks); ! 139: fs->fs_pendinginodes = be32toh(fs->fs_pendinginodes); ! 140: // uint32_t fs->fs_snapinum[FSMAXSNAP] ! 141: fs->fs_avgfilesize = be32toh(fs->fs_avgfilesize); ! 142: fs->fs_avgfpdir = be32toh(fs->fs_avgfpdir); ! 143: fs->fs_save_cgsize = be32toh(fs->fs_save_cgsize); ! 144: // uint32_t fs->fs_sparecon32[26] ! 145: fs->fs_flags = be32toh(fs->fs_flags); ! 146: fs->fs_contigsumsize = be32toh(fs->fs_contigsumsize); ! 147: fs->fs_maxsymlinklen = be32toh(fs->fs_maxsymlinklen); ! 148: fs->fs_old_inodefmt = be32toh(fs->fs_old_inodefmt); ! 149: fs->fs_maxfilesize = be64toh(fs->fs_maxfilesize); ! 150: fs->fs_qbmask = be64toh(fs->fs_qbmask); ! 151: fs->fs_qfmask = be64toh(fs->fs_qfmask); ! 152: fs->fs_state = be32toh(fs->fs_state); ! 153: fs->fs_old_postblformat = be32toh(fs->fs_old_postblformat); ! 154: fs->fs_old_nrpos = be32toh(fs->fs_old_nrpos); ! 155: // uint32_t fs->fs_spare5[2] ! 156: fs->fs_magic = be32toh(fs->fs_magic); ! 157: ! 158: // マジック ! 159: if (fs->fs_magic != FS_UFS1_MAGIC) { ! 160: errstr = string_format("Bad superblock magic 0x%08x (!= 0x%08x)", ! 161: fs->fs_magic, FS_UFS1_MAGIC); ! 162: return false; ! 163: } ! 164: ! 165: // なんとなく主要なパラメータを表示してみるか ! 166: if (parent->loglevel >= 2) { ! 167: uint32 sblkno = fs->fs_sblkno; // super block in filesys ! 168: uint32 cblkno = fs->fs_cblkno; // cylinder group block in filesys ! 169: uint32 iblkno = fs->fs_iblkno; // inode block in filesys ! 170: uint32 dblkno = fs->fs_dblkno; // data block in filesys ! 171: uint32 bsize = fs->fs_bsize; // size of basic blocks ! 172: uint32 ipg = fs->fs_ipg; // inodes per group ! 173: uint32 fpg = fs->fs_fpg; // blocks per group x fs_frag ! 174: uint32 old_cgoffset = fs->fs_old_cgoffset; // cg. offset in cyl. ! 175: uint32 fsbtodb= fs->fs_fsbtodb; // shift constant ! 176: ! 177: parent->putmsgn("%s fs.fs_sblkno=0x%x (0x%x)", ! 178: __func__, sblkno, sblkno * 512); ! 179: parent->putmsgn("%s fs.fs_cblkno=0x%x (0x%x)", ! 180: __func__, cblkno, cblkno * 512); ! 181: parent->putmsgn("%s fs.fs_dblkno=0x%x (0x%x)", ! 182: __func__, dblkno, dblkno * 512); ! 183: parent->putmsgn("%s fs.fs_iblkno=0x%x (0x%x)", ! 184: __func__, iblkno, iblkno * 512); ! 185: parent->putmsgn("%s fs.fs_bsize=0x%x", __func__, bsize); ! 186: parent->putmsgn("%s fs.fs_ipg=0x%x", __func__, ipg); ! 187: parent->putmsgn("%s fs.fs_fpg=0x%x", __func__, fpg); ! 188: parent->putmsgn("%s fs.fs_old_cgoffset=0x%x", __func__, old_cgoffset); ! 189: parent->putmsgn("%s fs.fs_fsbtodb=%d", __func__, fsbtodb); ! 190: } ! 191: ! 192: return true; ! 193: } ! 194: ! 195: // ファイル名からファイルをオープンする。 ! 196: // オープンできれば file を埋めて true を返す。 ! 197: // オープンできなければ errstr にエラーメッセージをセットして false を返す。 ! 198: bool ! 199: Filesys::OpenFile(inodefile& file, const std::string& filename_) ! 200: { ! 201: std::string filename(filename_); ! 202: std::vector<std::string> path; ! 203: int idx = 0; ! 204: inodefile dir(parent); ! 205: ! 206: enum { ! 207: STATE_REG, // 通常ファイル (終了条件) ! 208: STATE_PATH, // パス解析 ! 209: STATE_DIR, // ディレクトリ読み込み ! 210: STATE_FIND, // ディレクトリからファイルを検索 ! 211: STATE_LINK, // シンボリックリンク ! 212: } state; ! 213: ! 214: // DKFILE の先頭に '/' がなければここで足しておく。 ! 215: // ファイル名を分解する際にルートディレクトリマークが必要なので。 ! 216: if (filename[0] != '/') { ! 217: filename.insert(0, 1, '/'); ! 218: } ! 219: state = STATE_PATH; ! 220: ! 221: while (state != STATE_REG) { ! 222: switch (state) { ! 223: case STATE_PATH: ! 224: // ファイル名をパスに分解 ! 225: // filename にパス名をセットしてからここに来ること。 ! 226: parent->putmsgf(1, lstr("%s Path filename=|%s|", ! 227: lam_func, filename.c_str())); ! 228: if (filename.empty()) { ! 229: errstr = "Filename empty?"; ! 230: return false; ! 231: } ! 232: path.clear(); ! 233: for (int s = 0; s < filename.size(); ) { ! 234: int p = filename.find('/', s); ! 235: if (p == std::string::npos) { ! 236: p = filename.size(); ! 237: } ! 238: // '/' が連続していなければパスコンポーネント ! 239: if (p != s) { ! 240: path.push_back(filename.substr(s, p - s)); ! 241: } ! 242: s = p + 1; ! 243: } ! 244: idx = 0; ! 245: if (parent->loglevel >= 1) { ! 246: for (int i = 0; i < path.size(); i++) { ! 247: parent->putmsgn("%s path[%d]=|%s|", ! 248: __func__, i, path[i].c_str()); ! 249: } ! 250: } ! 251: // パスが '/' から始まっていればルートディレクトリの読み込みから。 ! 252: // そうでなければ現在のディレクトリでファイルの検索から。 ! 253: if (filename[0] == '/') { ! 254: // ルートディレクトリの inode 番号は伝統的に #2 と ! 255: // いうことになっている。 ! 256: dir.ino = 2; ! 257: state = STATE_DIR; ! 258: } else { ! 259: state = STATE_FIND; ! 260: } ! 261: break; ! 262: ! 263: case STATE_DIR: ! 264: // inode 番号からディレクトリエントリを取得。 ! 265: // dir.ino をセットしてからここに来ること。 ! 266: parent->putmsgf(1, lstr("%s Readdir ino=%d", lam_func, dir.ino)); ! 267: Readi(dir); ! 268: // 中身(ディレクトリエントリ) を取得 ! 269: ReadData(dir); ! 270: state = STATE_FIND; ! 271: break; ! 272: ! 273: case STATE_FIND: ! 274: // ディレクトリエントリ dir.data から ! 275: // ファイル名 path[idx] を探す。 ! 276: parent->putmsgf(1, lstr("%s FindFile %s", ! 277: lam_func, path[idx].c_str())); ! 278: file.ino = dir.FindFile(path[idx]); ! 279: if (file.ino == 0) { ! 280: errstr = string_format("file not found"); ! 281: return false; ! 282: } ! 283: // ファイルの inode 情報を取得。 ! 284: Readi(file); ! 285: switch (be16toh(file.di.di_mode) & IFMT) { ! 286: case IFREG: // 通常ファイル ! 287: state = STATE_REG; ! 288: break; ! 289: ! 290: case IFLNK: // シンボリックリンク ! 291: state = STATE_LINK; ! 292: break; ! 293: ! 294: case IFDIR: // ディレクトリ ! 295: dir.ino = file.ino; ! 296: idx++; ! 297: // パスの最後のコンポーネントがまだディレクトリならエラー ! 298: if (idx >= path.size()) { ! 299: errstr = "is a directory"; ! 300: return false; ! 301: } ! 302: state = STATE_DIR; ! 303: break; ! 304: ! 305: default: // それ以外は対応してないし来ないはず ! 306: errstr = string_format("invalid filemode %06o", ! 307: be16toh(file.di.di_mode)); ! 308: return false; ! 309: } ! 310: break; ! 311: ! 312: case STATE_LINK: ! 313: // リンク先ファイル名を取り出す ! 314: parent->putmsgf(1, lstr("%s Readlink", lam_func)); ! 315: ReadData(file); ! 316: filename = std::string((const char *)file.data.data(), ! 317: file.data.size()); ! 318: // パス解析へ ! 319: state = STATE_PATH; ! 320: break; ! 321: ! 322: default: ! 323: __unreachable(); ! 324: } ! 325: } ! 326: // 通常ファイルに到達 ! 327: ! 328: if (idx != path.size() - 1) { ! 329: // パスの最後のコンポーネントじゃなければエラー ! 330: errstr = "path not found"; ! 331: return false; ! 332: } ! 333: ! 334: return true; ! 335: } ! 336: ! 337: // inode(.di) で指定されたファイル(またはディレクトリ)の本文を ! 338: // inode.data に返す。 ! 339: // 今の所エラーは起きない。 ! 340: void ! 341: Filesys::ReadData(inodefile& inode) ! 342: { ! 343: // di (ufs1_dinode) にはこの inode (ファイルまたはディレクトリ)の ! 344: // データの格納ブロックが記録されている。ディレクトリとは中身が ! 345: // ディレクトリエントリであるファイルと同じ構造のもの。 ! 346: // di_db[] (直接ブロック) ! 347: // di_ib[] (間接ブロック) ! 348: // di_blocks (実際に使用しているブロック数) ! 349: // ! 350: // 直接ブロック di_db[] は12要素の配列で、データブロックの位置が ! 351: // 記録されている (未使用なら 0 のようだ)。 ! 352: // データブロックは fs->fs_bsize でたぶん基本 4KB のやつ。 ! 353: // これもパーティション先頭からのセクタ番号で表記される。なので ! 354: // ディスク上で連続しているファイルなら di_db[N] と di_db[N + 1] は ! 355: // 8 ずつ増えてるのが見えるはず。 ! 356: // 例えば以下のサンプル断片は、直接ブロック2つでセクタ 100 から ! 357: // セクタ 115 までの連続する 16KB を所有している様子を示している。 ! 358: // ! 359: // #100 #101 #102 #107 ! 360: // +------+------+------+- .. -+------+ ! 361: // di_db[0] = 100 ---> | Data | Data | Data | | Data | ! 362: // +------+------+------+- .. -+------+ ! 363: // ! 364: // #108 #115 ! 365: // +------+------+------+- .. -+------+ ! 366: // di_db[1] = 108 ---> | Data | Data | Data | | Data | ! 367: // +------+------+------+- .. -+------+ ! 368: // ! 369: // 間接ブロック di_ib[0], [1], [2] はそれぞれ一次、二次、三次の ! 370: // 間接記録になっている。一次間接だとこういう感じ。 ! 371: // ! 372: // #120 ! 373: // +--------+ +------+- .. ! 374: // di_ib[0] = 120 ---> | #200 ------> #200 | Data | ! 375: // | | +------+- .. ! 376: // | #208 ------> #208 | Data | ! 377: // +--------+ +------+- .. ! 378: // ! 379: ! 380: uint32 ino = inode.ino; ! 381: struct ufs1_dinode *di = &inode.di; ! 382: std::vector<uint8>& data = inode.data; ! 383: uint64 bsize64 = (uint64)fs->fs_bsize; ! 384: ! 385: uint64 di_size = be64toh(di->di_size); ! 386: uint32 di_blocks = be32toh(di->di_blocks); ! 387: // di->di_db[] にファイル(またはディレクトリ)の内容の位置が並んでいる ! 388: if (parent->loglevel >= 2) { ! 389: parent->putmsgn("%s di[%d].di_blocks=%u", __func__, ino, di_blocks); ! 390: ! 391: std::string dbstr; ! 392: for (int i = 0; i < UFS_NDADDR; i++) { ! 393: dbstr += string_format(" %u", be32toh(di->di_db[i])); ! 394: } ! 395: parent->putmsgn("%s di[%d].di_db[]=%s, di_ib[]=%u %u %u", ! 396: __func__, ino, dbstr.c_str() + 1, ! 397: be32toh(di->di_ib[0]), ! 398: be32toh(di->di_ib[1]), ! 399: be32toh(di->di_ib[2])); ! 400: } ! 401: ! 402: uint64 offset = 0; // 次に読み込む位置 (ここまでに読み込んだバイト数) ! 403: ! 404: // サイズが分かっているのであらかじめ確保しておく ! 405: data.resize(di_size); ! 406: ! 407: // 直接ブロック ! 408: for (int i = 0; i < countof(di->di_db); i++) { ! 409: uint64 remain = di_size - offset; // 残りバイト数 ! 410: uint32 nbytes = std::min(remain, bsize64); // 今回読み込み分 ! 411: PeekBlock(&data[offset], be32toh(di->di_db[i]), nbytes); ! 412: offset += nbytes; ! 413: if (offset >= di_size) { ! 414: return; ! 415: } ! 416: } ! 417: // 一次間接ブロック ! 418: std::vector<uint32> ib0buf(fs->fs_bsize / sizeof(uint32)); ! 419: PeekBlock(&ib0buf[0], be32toh(di->di_ib[0]), fs->fs_bsize); ! 420: if (parent->loglevel >= 2) { ! 421: std::string distr; ! 422: for (const auto& x : ib0buf) { ! 423: if (x == 0) ! 424: break; ! 425: distr += string_format(" %u", be32toh(x)); ! 426: } ! 427: parent->putmsgn("%s di[%d].di_ib[0]=%s", ! 428: __func__, ino, distr.c_str() + 1); ! 429: } ! 430: for (const auto& x : ib0buf) { ! 431: uint64 remain = di_size - offset; // 残りバイト数 ! 432: uint32 nbytes = std::min(remain, bsize64); // 今回読み込み分 ! 433: PeekBlock(&data[offset], be32toh(x), nbytes); ! 434: offset += nbytes; ! 435: if (offset >= di_size) { ! 436: return; ! 437: } ! 438: } ! 439: ! 440: // 二次、三次ブロックは未対応 ! 441: if (offset < di_size) { ! 442: PANIC("di_ib[1] not supported"); ! 443: } ! 444: } ! 445: ! 446: // inode.ino で指定された disk inode 情報を inode.di に返す。 ! 447: // 今の所エラーは起きない。 ! 448: void ! 449: Filesys::Readi(inodefile& inode) ! 450: { ! 451: // di は inode のディスク上の記録構造で 128 バイト長。 ! 452: // 詳細は <ufs/ufs/dinode.h> の ufs1_dinode 参照。 ! 453: // 基本的には inode ブロックにこの dinode が配列のように並んでいるが ! 454: // シリンダグループを越えるためには謎のマクロを使う。 ! 455: // sys/lib/libsa/ufs.c 参照。 ! 456: // ! 457: // dinode のうち、ここで関係するかも知れないのは ! 458: // di_mode (のうちファイルモード) ! 459: // di_size (ファイルサイズ) ! 460: // di_db[] (直接ブロック) ! 461: // di_ib[] (間接ブロック) ! 462: // di_blocks (ブロック数) ! 463: // くらいか。 ! 464: ! 465: uint32 ino = inode.ino; ! 466: ! 467: // ino が含まれるブロックを読み込む。 ! 468: // ino_to_fsba(fs, ino) が指定の ino が含まれるブロックを返す。 ! 469: // ino_to_fsbo(fs, ino) はそのブロック内での ino のオフセットを返す。 ! 470: // 例えば inode=2 の fsba が 0x18、fsbo が 2 なら、0x18ブロック目の ! 471: // [2] からつまり256バイト目からとなる。 ! 472: std::vector<char> buf(fs->fs_bsize); ! 473: uint64 fsba = ino_to_fsba(fs, ino); ! 474: uint32 fsbo = ino_to_fsbo(fs, ino); ! 475: PeekBlock(&buf[0], fsba, buf.size()); ! 476: ! 477: // ino で示される inode のディスク上構造を ! 478: // (ゲストエンディアンのまま) di にコピーして持っておく。 ! 479: struct ufs1_dinode *di = &inode.di; ! 480: memcpy(di, &((ufs1_dinode *)(&buf[0]))[fsbo], sizeof(*di)); ! 481: uint16 di_mode = be16toh(di->di_mode); ! 482: uint16 di_nlink = be16toh(di->di_nlink); ! 483: uint64 di_size = be64toh(di->di_size); ! 484: parent->putmsgf(2, ! 485: lstr("%s di[%d].di_mode=%05o di_nlink=%d di_size=%" PRIu64, ! 486: lam_func, ino, di_mode, di_nlink, di_size)); ! 487: } ! 488: ! 489: // ディスクの指定ブロック b の先頭から len バイト読み出して buf に返す。 ! 490: // buf は少なくとも len バイト確保してあること。 ! 491: void ! 492: Filesys::PeekBlock(void *buf, uint32 b, uint32 len) const ! 493: { ! 494: // FFS_FSBTODB(fs, b) がブロック番号 b をセクタ番号に変換する。 ! 495: uint32 sector = part_start + FFS_FSBTODB(fs, b); ! 496: hd->PeekImage(buf, sector * 512, len); ! 497: } ! 498: ! 499: ! 500: // ! 501: // inode 情報クラス ! 502: // ! 503: ! 504: // コンストラクタ ! 505: inodefile::inodefile(Device *parent_) ! 506: { ! 507: parent = parent_; ! 508: } ! 509: ! 510: // デストラクタ ! 511: inodefile::~inodefile() ! 512: { ! 513: } ! 514: ! 515: // ディレクトリエントリ dirbuf から name で指定されるファイル名に対応する ! 516: // inode 番号を返す。見付からなければ 0 を返す。 ! 517: uint32 ! 518: inodefile::FindFile(const std::string& name) ! 519: { ! 520: // ディレクトリエントリは struct direct が可変長で並んでいる。 ! 521: // ../host/ffs_dir.h (元は NetBSD の <ufs/ufs/dir.h>) 参照。 ! 522: // d->d_reclen がこの1つ分のエントリの長さなので、次のエントリ位置は ! 523: // このエントリの頭から d->d_reclen を足したところになる。 ! 524: // 最終エントリの d_reclen を足すとバッファ末尾になるようになっている ! 525: // ようだ。 ! 526: const char *dp = (const char *)(data.data()); ! 527: const char *dend = dp + data.size(); ! 528: uint32 file_ino; ! 529: uint16 reclen; ! 530: ! 531: for (; dp < dend; dp += reclen) { ! 532: const struct direct *d = (const struct direct *)dp; ! 533: file_ino = be32toh(d->d_fileno); ! 534: reclen = be16toh(d->d_reclen); ! 535: ! 536: std::string str = string_format("ino=%u reclen=%u name=|%s|", ! 537: file_ino, reclen, d->d_name); ! 538: if (d->d_reclen == 0) { ! 539: parent->putmsgf(1, lstr("%s reclen=0 !", lam_func)); ! 540: break; ! 541: } ! 542: ! 543: if (strcmp(name.c_str(), d->d_name) == 0) { ! 544: parent->putmsgf(2, lstr("%s %s found", lam_func, str.c_str())); ! 545: return file_ino; ! 546: } else { ! 547: parent->putmsgf(2, lstr("%s %s skip", lam_func, str.c_str())); ! 548: } ! 549: } ! 550: parent->putmsgf(2, lstr("%s %s not found", lam_func, name.c_str())); ! 551: return 0; ! 552: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.