Lukacs Berki | 2573376 | 2016-02-16 12:20:45 +0000 | [diff] [blame] | 1 | // Copyright 2015 The Bazel Authors. All rights reserved. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | #include <errno.h> |
| 16 | #include <fcntl.h> |
| 17 | #include <stdio.h> |
| 18 | #include <unistd.h> |
| 19 | #include <sys/mman.h> |
| 20 | |
| 21 | #include <algorithm> |
| 22 | |
| 23 | #include "third_party/ijar/mapped_file.h" |
| 24 | |
| 25 | #define MAX_ERROR 2048 |
| 26 | |
| 27 | namespace devtools_ijar { |
| 28 | |
| 29 | static char errmsg[MAX_ERROR]; |
| 30 | |
| 31 | struct MappedInputFileImpl { |
| 32 | size_t discarded_; |
| 33 | int fd_; |
| 34 | }; |
| 35 | |
| 36 | MappedInputFile::MappedInputFile(const char* name) { |
| 37 | impl_ = NULL; |
| 38 | opened_ = false; |
| 39 | |
| 40 | int fd = open(name, O_RDONLY); |
| 41 | if (fd < 0) { |
| 42 | snprintf(errmsg, MAX_ERROR, "open(): %s", strerror(errno)); |
| 43 | errmsg_ = errmsg; |
| 44 | return; |
| 45 | } |
| 46 | |
| 47 | off_t length = lseek(fd, 0, SEEK_END); |
| 48 | if (length < 0) { |
| 49 | snprintf(errmsg, MAX_ERROR, "lseek(): %s", strerror(errno)); |
| 50 | errmsg_ = errmsg; |
| 51 | return; |
| 52 | } |
| 53 | |
| 54 | void* buffer = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0); |
| 55 | if (buffer == MAP_FAILED) { |
| 56 | snprintf(errmsg, MAX_ERROR, "mmap(): %s", strerror(errno)); |
| 57 | errmsg_ = errmsg; |
| 58 | return; |
| 59 | } |
| 60 | |
| 61 | impl_ = new MappedInputFileImpl(); |
| 62 | impl_->fd_ = fd; |
| 63 | impl_->discarded_ = 0; |
| 64 | buffer_ = reinterpret_cast<u1*>(buffer); |
| 65 | length_ = length; |
| 66 | opened_ = true; |
| 67 | } |
| 68 | |
| 69 | MappedInputFile::~MappedInputFile() { |
| 70 | delete impl_; |
| 71 | } |
| 72 | |
| 73 | void MappedInputFile::Discard(size_t bytes) { |
| 74 | munmap(buffer_ + impl_->discarded_, bytes); |
| 75 | impl_->discarded_ += bytes; |
| 76 | } |
| 77 | |
| 78 | int MappedInputFile::Close() { |
| 79 | if (close(impl_->fd_) < 0) { |
| 80 | snprintf(errmsg, MAX_ERROR, "close(): %s", strerror(errno)); |
| 81 | errmsg_ = errmsg; |
| 82 | return -1; |
| 83 | } |
| 84 | |
| 85 | return 0; |
| 86 | } |
| 87 | |
| 88 | struct MappedOutputFileImpl { |
| 89 | int fd_; |
Reker | b51a8cb | 2016-11-24 15:12:30 +0000 | [diff] [blame] | 90 | int mmap_length_; |
Lukacs Berki | 2573376 | 2016-02-16 12:20:45 +0000 | [diff] [blame] | 91 | }; |
| 92 | |
cushon | a29da01 | 2018-03-29 13:31:46 -0700 | [diff] [blame] | 93 | MappedOutputFile::MappedOutputFile(const char* name, size_t estimated_size) |
cushon | f572845 | 2018-03-21 20:30:12 -0700 | [diff] [blame] | 94 | : estimated_size_(estimated_size) { |
Lukacs Berki | 2573376 | 2016-02-16 12:20:45 +0000 | [diff] [blame] | 95 | impl_ = NULL; |
| 96 | opened_ = false; |
| 97 | int fd = open(name, O_CREAT|O_RDWR|O_TRUNC, 0644); |
| 98 | if (fd < 0) { |
| 99 | snprintf(errmsg, MAX_ERROR, "open(): %s", strerror(errno)); |
| 100 | errmsg_ = errmsg; |
| 101 | return; |
| 102 | } |
| 103 | |
| 104 | // Create mmap-able sparse file |
| 105 | if (ftruncate(fd, estimated_size) < 0) { |
| 106 | snprintf(errmsg, MAX_ERROR, "ftruncate(): %s", strerror(errno)); |
| 107 | errmsg_ = errmsg; |
| 108 | return; |
| 109 | } |
| 110 | |
| 111 | // Ensure that any buffer overflow in JarStripper will result in |
| 112 | // SIGSEGV or SIGBUS by over-allocating beyond the end of the file. |
Googler | fa59fbf | 2018-05-29 09:12:27 -0700 | [diff] [blame] | 113 | size_t mmap_length = |
| 114 | std::min(static_cast<size_t>(estimated_size + sysconf(_SC_PAGESIZE)), |
| 115 | std::numeric_limits<size_t>::max()); |
Yihong Wang | 5370e40 | 2020-02-14 11:38:22 -0800 | [diff] [blame] | 116 | void* mapped = |
| 117 | mmap(NULL, mmap_length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); |
Lukacs Berki | 2573376 | 2016-02-16 12:20:45 +0000 | [diff] [blame] | 118 | if (mapped == MAP_FAILED) { |
| 119 | snprintf(errmsg, MAX_ERROR, "mmap(): %s", strerror(errno)); |
| 120 | errmsg_ = errmsg; |
| 121 | return; |
| 122 | } |
| 123 | |
| 124 | impl_ = new MappedOutputFileImpl(); |
| 125 | impl_->fd_ = fd; |
Reker | b51a8cb | 2016-11-24 15:12:30 +0000 | [diff] [blame] | 126 | impl_->mmap_length_ = mmap_length; |
Lukacs Berki | 2573376 | 2016-02-16 12:20:45 +0000 | [diff] [blame] | 127 | buffer_ = reinterpret_cast<u1*>(mapped); |
| 128 | opened_ = true; |
| 129 | } |
| 130 | |
| 131 | |
| 132 | MappedOutputFile::~MappedOutputFile() { |
| 133 | delete impl_; |
| 134 | } |
| 135 | |
cushon | a29da01 | 2018-03-29 13:31:46 -0700 | [diff] [blame] | 136 | int MappedOutputFile::Close(size_t size) { |
cushon | f572845 | 2018-03-21 20:30:12 -0700 | [diff] [blame] | 137 | if (size > estimated_size_) { |
cushon | a29da01 | 2018-03-29 13:31:46 -0700 | [diff] [blame] | 138 | snprintf(errmsg, MAX_ERROR, "size %zu > estimated size %zu", size, |
cushon | f572845 | 2018-03-21 20:30:12 -0700 | [diff] [blame] | 139 | estimated_size_); |
| 140 | errmsg_ = errmsg; |
| 141 | return -1; |
| 142 | } |
Reker | b51a8cb | 2016-11-24 15:12:30 +0000 | [diff] [blame] | 143 | munmap(buffer_, impl_->mmap_length_); |
Lukacs Berki | 2573376 | 2016-02-16 12:20:45 +0000 | [diff] [blame] | 144 | if (ftruncate(impl_->fd_, size) < 0) { |
| 145 | snprintf(errmsg, MAX_ERROR, "ftruncate(): %s", strerror(errno)); |
| 146 | errmsg_ = errmsg; |
| 147 | return -1; |
| 148 | } |
| 149 | |
| 150 | if (close(impl_->fd_) < 0) { |
| 151 | snprintf(errmsg, MAX_ERROR, "close(): %s", strerror(errno)); |
| 152 | errmsg_ = errmsg; |
| 153 | return -1; |
| 154 | } |
| 155 | |
| 156 | return 0; |
| 157 | } |
| 158 | |
| 159 | } // namespace devtools_ijar |