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

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 する。
1.1.1.5 ! root       50: // ファイルがなければ作成して、あれば data で初期化する。これは SRAM とか用。
1.1       root       51: // 成功すれば mmap した領域のポインタを返す。
                     52: // 失敗すればエラーメッセージを表示して NULL を返す。
                     53: uint8 *
1.1.1.5 ! root       54: MappedFile::OpenCreate(off_t memlen_, const uint8 *data, uint datalen)
1.1       root       55: {
1.1.1.5 ! root       56:        void *m;
        !            57: 
1.1       root       58:        memlen = memlen_;
                     59: 
                     60:        fd = open(filename.c_str(), O_RDWR);
                     61:        if (fd < 0) {
                     62:                if (errno != ENOENT) {
                     63:                        warn("%s open failed", dispname.c_str());
                     64:                        return NULL;
                     65:                } else {
                     66:                        // オープンできない理由が ENOENT ならファイルを作ってみる
                     67:                        fd = open(filename.c_str(), O_RDWR | O_CREAT, 0644);
                     68:                        if (fd < 0) {
                     69:                                warn("%s create failed", dispname.c_str());
                     70:                                return NULL;
                     71:                        }
                     72: 
1.1.1.5 ! root       73:                        uint written = 0;
        !            74: 
        !            75:                        // data, datalen が指定されていれば先頭から書き込む。
        !            76:                        if (data != NULL && datalen > 0) {
        !            77:                                if (write(fd, data, datalen) < 0) {
        !            78:                                        warn("%s write failed", dispname.c_str());
        !            79:                                        goto abort;
        !            80:                                }
        !            81:                                written = datalen;
        !            82:                        }
        !            83: 
        !            84:                        // (残りを)ゼロで埋める。
        !            85:                        std::vector<char> zerobuf(memlen - written);
        !            86:                        if (write(fd, zerobuf.data(), zerobuf.size()) < 0) {
        !            87:                                warn("%s clear failed", dispname.c_str());
        !            88:                                goto abort;
1.1       root       89:                        }
                     90: 
                     91:                        warnx("%s created", dispname.c_str());
                     92:                        // FALLTHROUGH
                     93:                }
                     94:        }
                     95: 
                     96:        if (CheckFilesize() == false) {
1.1.1.5 ! root       97:                goto abort;
1.1       root       98:        }
                     99: 
                    100:        // mmap する。
1.1.1.5 ! root      101:        m = mmap(NULL, memlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1.1       root      102:        if (m == MAP_FAILED) {
                    103:                warn("%s mmap failed", dispname.c_str());
1.1.1.5 ! root      104:                goto abort;
1.1       root      105:        }
                    106:        mem = (uint8 *)m;
                    107: 
                    108:        return mem;
1.1.1.5 ! root      109: 
        !           110:  abort:
        !           111:        Close();
        !           112:        return NULL;
1.1       root      113: }
                    114: 
                    115: // ファイルサイズが memlen と同じかどうか調べる。
                    116: // ファイルサイズが memlen より短ければエラーメッセージを表示し false を返す。
                    117: // ファイルサイズが memlen より長ければワーニングを表示し true を返す。
                    118: // ファイルサイズが memlen と同じなら true を返す。
                    119: bool
                    120: MappedFile::CheckFilesize() const
                    121: {
                    122:        struct stat st;
                    123: 
                    124:        // ファイルサイズをチェック。
                    125:        // ファイルが短くても mmap は黙って成功してしまうようなので。
                    126:        if (fstat(fd, &st) < 0) {
                    127:                warn("%s fstat failed", dispname.c_str());
                    128:                return false;
                    129:        }
                    130: 
                    131:        if (st.st_size < memlen) {
                    132:                warnx("%s is too short (filesize is expected %jd but %jd)",
                    133:                        dispname.c_str(), (intmax_t)memlen, (intmax_t)st.st_size);
                    134:                return false;
                    135:        }
                    136:        if (st.st_size > memlen) {
                    137:                // 大きすぎるほうはワーニングだけでいいか
                    138:                warnx("%s is too large (ignore %jd bytes)",
                    139:                        dispname.c_str(), (intmax_t)(st.st_size - memlen));
                    140:        }
                    141:        return true;
                    142: }
                    143: 
                    144: // ファイルをクローズする。
                    145: // 呼び出しに副作用はない。
                    146: void
                    147: MappedFile::Close()
                    148: {
                    149:        if (mem != NULL) {
                    150:                munmap(mem, memlen);
                    151:                mem = NULL;
                    152:                memlen = 0;
                    153:        }
1.1.1.2   root      154:        fd.Close();
1.1       root      155: 
                    156:        filename.clear();
                    157:        dispname.clear();
                    158: }

unix.superglobalmegacorp.com

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