Annotation of nono/lib/mappedfile.cpp, revision 1.1.1.4

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
1.1.1.4 ! root        7: //
1.1       root        8: // ファイルを mmap して提供するクラス
1.1.1.4 ! root        9: //
1.1       root       10: 
                     11: #include "mappedfile.h"
                     12: #include "mystring.h"
                     13: #include <vector>
                     14: #include <fcntl.h>
                     15: #include <sys/stat.h>
                     16: #include <sys/mman.h>
                     17: 
                     18: // コンストラクタ
                     19: MappedFile::MappedFile()
                     20: {
                     21: }
                     22: 
                     23: // デストラクタ
                     24: MappedFile::~MappedFile()
                     25: {
                     26:        Close();
                     27: }
                     28: 
                     29: // ファイル名を指定する。
                     30: // filename_ が空でないことは呼び出し側で保証すること。
                     31: void
                     32: MappedFile::SetFilename(const std::string& filename_)
                     33: {
                     34:        filename = filename_;
                     35:        assert(!filename.empty());
                     36: 
                     37:        // 表示名を更新
                     38:        SetDispname(string_format("\"%s\"", filename.c_str()));
                     39: }
                     40: 
                     41: // 表示名を設定する。
                     42: // デフォルトのから変えたい時にどうぞ。
                     43: void
                     44: MappedFile::SetDispname(const std::string& name)
                     45: {
                     46:        dispname = name;
                     47: }
                     48: 
                     49: // サイズが len で確定しているファイルを読み書き両用でオープンして mmap する。
                     50: // ファイルがなければ作成する。これは SRAM とか用。
                     51: // 成功すれば mmap した領域のポインタを返す。
                     52: // 失敗すればエラーメッセージを表示して NULL を返す。
                     53: uint8 *
                     54: MappedFile::OpenCreate(off_t memlen_)
                     55: {
                     56:        memlen = memlen_;
                     57: 
                     58:        fd = open(filename.c_str(), O_RDWR);
                     59:        if (fd < 0) {
                     60:                if (errno != ENOENT) {
                     61:                        warn("%s open failed", dispname.c_str());
                     62:                        return NULL;
                     63:                } else {
                     64:                        // オープンできない理由が ENOENT ならファイルを作ってみる
                     65:                        fd = open(filename.c_str(), O_RDWR | O_CREAT, 0644);
                     66:                        if (fd < 0) {
                     67:                                warn("%s create failed", dispname.c_str());
                     68:                                return NULL;
                     69:                        }
                     70: 
                     71:                        // ゼロで埋める
                     72:                        std::vector<char> zerobuf(memlen);
                     73:                        if (write(fd, &zerobuf[0], zerobuf.size()) < 0) {
                     74:                                warn("%s write failed", dispname.c_str());
                     75:                                Close();
                     76:                                return NULL;
                     77:                        }
                     78: 
                     79:                        warnx("%s created", dispname.c_str());
                     80:                        // FALLTHROUGH
                     81:                }
                     82:        }
                     83: 
                     84:        if (CheckFilesize() == false) {
                     85:                Close();
                     86:                return NULL;
                     87:        }
                     88: 
                     89:        // mmap する。
                     90:        void *m = mmap(NULL, memlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
                     91:        if (m == MAP_FAILED) {
                     92:                warn("%s mmap failed", dispname.c_str());
                     93:                Close();
                     94:                return NULL;
                     95:        }
                     96:        mem = (uint8 *)m;
                     97: 
                     98:        return mem;
                     99: }
                    100: 
                    101: // ファイルサイズが memlen と同じかどうか調べる。
                    102: // ファイルサイズが memlen より短ければエラーメッセージを表示し false を返す。
                    103: // ファイルサイズが memlen より長ければワーニングを表示し true を返す。
                    104: // ファイルサイズが memlen と同じなら true を返す。
                    105: bool
                    106: MappedFile::CheckFilesize() const
                    107: {
                    108:        struct stat st;
                    109: 
                    110:        // ファイルサイズをチェック。
                    111:        // ファイルが短くても mmap は黙って成功してしまうようなので。
                    112:        if (fstat(fd, &st) < 0) {
                    113:                warn("%s fstat failed", dispname.c_str());
                    114:                return false;
                    115:        }
                    116: 
                    117:        if (st.st_size < memlen) {
                    118:                warnx("%s is too short (filesize is expected %jd but %jd)",
                    119:                        dispname.c_str(), (intmax_t)memlen, (intmax_t)st.st_size);
                    120:                return false;
                    121:        }
                    122:        if (st.st_size > memlen) {
                    123:                // 大きすぎるほうはワーニングだけでいいか
                    124:                warnx("%s is too large (ignore %jd bytes)",
                    125:                        dispname.c_str(), (intmax_t)(st.st_size - memlen));
                    126:        }
                    127:        return true;
                    128: }
                    129: 
                    130: // ファイルをクローズする。
                    131: // 呼び出しに副作用はない。
                    132: void
                    133: MappedFile::Close()
                    134: {
                    135:        if (mem != NULL) {
                    136:                munmap(mem, memlen);
                    137:                mem = NULL;
                    138:                memlen = 0;
                    139:        }
1.1.1.2   root      140:        fd.Close();
1.1       root      141: 
                    142:        filename.clear();
                    143:        dispname.clear();
                    144: }

unix.superglobalmegacorp.com

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