12fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/*
22fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * Copyright (C) 2013, The Android Open Source Project
32fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa *
42fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * Licensed under the Apache License, Version 2.0 (the "License");
52fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * you may not use this file except in compliance with the License.
62fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * You may obtain a copy of the License at
72fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa *
82fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa *     http://www.apache.org/licenses/LICENSE-2.0
92fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa *
102fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * Unless required by applicable law or agreed to in writing, software
112fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * distributed under the License is distributed on an "AS IS" BASIS,
122fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * See the License for the specific language governing permissions and
142fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa * limitations under the License.
152fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa */
162fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
172fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include "suggest/policyimpl/dictionary/utils/mmapped_buffer.h"
182fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
192fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include <cerrno>
202fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include <climits>
212fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include <cstdio>
222fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include <fcntl.h>
232fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include <sys/mman.h>
242fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include <unistd.h>
252fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
262fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa#include "suggest/policyimpl/dictionary/utils/file_utils.h"
272fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
282fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasanamespace latinime {
292fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
302fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
312fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        const char *const path, const int bufferOffset, const int bufferSize,
322fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        const bool isUpdatable) {
332fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    const int mmapFd = open(path, O_RDONLY);
342fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    if (mmapFd < 0) {
352fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        AKLOGE("DICT: Can't open the source. path=%s errno=%d", path, errno);
362dc8e36f8eaa598371a67dc58757a096a75374a3Keisuke Kuroyanagi        return nullptr;
372fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    }
382fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    const int pagesize = sysconf(_SC_PAGESIZE);
392fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    const int offset = bufferOffset % pagesize;
402fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    int alignedOffset = bufferOffset - offset;
412fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    int alignedSize = bufferSize + offset;
422fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    const int protMode = isUpdatable ? PROT_READ | PROT_WRITE : PROT_READ;
432fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    void *const mmappedBuffer = mmap(0, alignedSize, protMode, MAP_PRIVATE, mmapFd,
442fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            alignedOffset);
452fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    if (mmappedBuffer == MAP_FAILED) {
462fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        AKLOGE("DICT: Can't mmap dictionary. errno=%d", errno);
472fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        close(mmapFd);
482dc8e36f8eaa598371a67dc58757a096a75374a3Keisuke Kuroyanagi        return nullptr;
492fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    }
502fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    uint8_t *const buffer = static_cast<uint8_t *>(mmappedBuffer) + offset;
512fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    if (!buffer) {
522fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        AKLOGE("DICT: buffer is null");
532fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        close(mmapFd);
542dc8e36f8eaa598371a67dc58757a096a75374a3Keisuke Kuroyanagi        return nullptr;
552fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    }
562fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    return MmappedBufferPtr(new MmappedBuffer(buffer, bufferSize, mmappedBuffer, alignedSize,
572fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            mmapFd, isUpdatable));
582fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa}
592fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
602fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
612fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        const char *const path, const bool isUpdatable) {
622fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    const int fileSize = FileUtils::getFileSize(path);
632fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    if (fileSize == -1) {
642dc8e36f8eaa598371a67dc58757a096a75374a3Keisuke Kuroyanagi        return nullptr;
652fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    } else if (fileSize == 0) {
662fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        return MmappedBufferPtr(new MmappedBuffer(isUpdatable));
672fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    } else {
682fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        return openBuffer(path, 0 /* bufferOffset */, fileSize, isUpdatable);
692fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    }
702fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa}
712fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
722fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa/* static */ MmappedBuffer::MmappedBufferPtr MmappedBuffer::openBuffer(
732fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        const char *const dirPath, const char *const fileName, const bool isUpdatable) {
742fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    const int filePathBufferSize = PATH_MAX + 1 /* terminator */;
752fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    char filePath[filePathBufferSize];
762fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    const int filePathLength = snprintf(filePath, filePathBufferSize, "%s%s", dirPath,
772fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa            fileName);
782fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    if (filePathLength >= filePathBufferSize) {
792dc8e36f8eaa598371a67dc58757a096a75374a3Keisuke Kuroyanagi        return nullptr;
802fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    }
812fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    return openBuffer(filePath, isUpdatable);
822fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa}
832fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
842fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen WakasaMmappedBuffer::~MmappedBuffer() {
852fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    if (mAlignedSize == 0) {
862fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        return;
872fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    }
882fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    int ret = munmap(mMmappedBuffer, mAlignedSize);
892fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    if (ret != 0) {
902fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        AKLOGE("DICT: Failure in munmap. ret=%d errno=%d", ret, errno);
912fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    }
922fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    ret = close(mMmapFd);
932fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    if (ret != 0) {
942fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa        AKLOGE("DICT: Failure in close. ret=%d errno=%d", ret, errno);
952fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa    }
962fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa}
972fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa
982fa3693c264a4c150ac307d9bb7f6f8f18cc4ffcKen Wakasa} // namespace latinime
99