blob: 6e3a908718440aa22d25907493537f84cea035d0 [file] [log] [blame]
Lukacs Berki25733762016-02-16 12:20:45 +00001// 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
27namespace devtools_ijar {
28
29static char errmsg[MAX_ERROR];
30
31struct MappedInputFileImpl {
32 size_t discarded_;
33 int fd_;
34};
35
36MappedInputFile::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
69MappedInputFile::~MappedInputFile() {
70 delete impl_;
71}
72
73void MappedInputFile::Discard(size_t bytes) {
74 munmap(buffer_ + impl_->discarded_, bytes);
75 impl_->discarded_ += bytes;
76}
77
78int 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
88struct MappedOutputFileImpl {
89 int fd_;
Rekerb51a8cb2016-11-24 15:12:30 +000090 int mmap_length_;
Lukacs Berki25733762016-02-16 12:20:45 +000091};
92
cushona29da012018-03-29 13:31:46 -070093MappedOutputFile::MappedOutputFile(const char* name, size_t estimated_size)
cushonf5728452018-03-21 20:30:12 -070094 : estimated_size_(estimated_size) {
Lukacs Berki25733762016-02-16 12:20:45 +000095 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.
Googlerfa59fbf2018-05-29 09:12:27 -0700113 size_t mmap_length =
114 std::min(static_cast<size_t>(estimated_size + sysconf(_SC_PAGESIZE)),
115 std::numeric_limits<size_t>::max());
Yihong Wang5370e402020-02-14 11:38:22 -0800116 void* mapped =
117 mmap(NULL, mmap_length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
Lukacs Berki25733762016-02-16 12:20:45 +0000118 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;
Rekerb51a8cb2016-11-24 15:12:30 +0000126 impl_->mmap_length_ = mmap_length;
Lukacs Berki25733762016-02-16 12:20:45 +0000127 buffer_ = reinterpret_cast<u1*>(mapped);
128 opened_ = true;
129}
130
131
132MappedOutputFile::~MappedOutputFile() {
133 delete impl_;
134}
135
cushona29da012018-03-29 13:31:46 -0700136int MappedOutputFile::Close(size_t size) {
cushonf5728452018-03-21 20:30:12 -0700137 if (size > estimated_size_) {
cushona29da012018-03-29 13:31:46 -0700138 snprintf(errmsg, MAX_ERROR, "size %zu > estimated size %zu", size,
cushonf5728452018-03-21 20:30:12 -0700139 estimated_size_);
140 errmsg_ = errmsg;
141 return -1;
142 }
Rekerb51a8cb2016-11-24 15:12:30 +0000143 munmap(buffer_, impl_->mmap_length_);
Lukacs Berki25733762016-02-16 12:20:45 +0000144 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