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

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

unix.superglobalmegacorp.com

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