|  | // Copyright 2016 The Bazel Authors. All rights reserved. | 
|  | // | 
|  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | // you may not use this file except in compliance with the License. | 
|  | // You may obtain a copy of the License at | 
|  | // | 
|  | //    http://www.apache.org/licenses/LICENSE-2.0 | 
|  | // | 
|  | // Unless required by applicable law or agreed to in writing, software | 
|  | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | // See the License for the specific language governing permissions and | 
|  | // limitations under the License. | 
|  |  | 
|  | #ifndef BAZEL_SRC_TOOLS_SINGLEJAR_INPUT_JAR_H_ | 
|  | #define BAZEL_SRC_TOOLS_SINGLEJAR_INPUT_JAR_H_ 1 | 
|  |  | 
|  | #ifndef __STDC_FORMAT_MACROS | 
|  | #define __STDC_FORMAT_MACROS 1 | 
|  | #endif | 
|  |  | 
|  | #include <inttypes.h> | 
|  | #include <stdlib.h> | 
|  |  | 
|  | #include <string> | 
|  |  | 
|  | #include "src/tools/singlejar/diag.h" | 
|  | #include "src/tools/singlejar/mapped_file.h" | 
|  | #include "src/tools/singlejar/zip_headers.h" | 
|  |  | 
|  | /* | 
|  | * An input jar. The usage pattern is: | 
|  | *   InputJar input_jar; | 
|  | *   if (!input_jar.Open("path/to/file")) { fail...} | 
|  | *   CDH *dir_entry; | 
|  | *   LH *local_header; | 
|  | *   while (dir_entry = input_jar.NextEntry(&local_header)) { | 
|  | *     // process entry. | 
|  | *   } | 
|  | *   input_jar.Close(); // actually, called by destructor, too. | 
|  | */ | 
|  | class InputJar { | 
|  | public: | 
|  | InputJar() {} | 
|  |  | 
|  | ~InputJar() { Close(); } | 
|  |  | 
|  | #ifndef _WIN32 | 
|  | // Not used on Windows, only in Google's own code. Don't add more usage of it. | 
|  | int fd() const { return mapped_file_.fd(); } | 
|  | #endif | 
|  |  | 
|  | // Opens the file, memory maps it and locates Central Directory. | 
|  | bool Open(const std::string& path); | 
|  |  | 
|  | // Returns the next Central Directory Header or nullptr. | 
|  | const CDH *NextEntry(const LH **local_header_ptr) { | 
|  | if (path_.empty()) { | 
|  | diag_errx(1, "%s:%d: call Open() first!", __FILE__, __LINE__); | 
|  | } | 
|  | if (!cdh_->is()) { | 
|  | return nullptr; | 
|  | } | 
|  | const CDH *current_cdh = cdh_; | 
|  | const uint8_t *new_cdr = ziph::byte_ptr(cdh_) + cdh_->size(); | 
|  | if (!mapped_file_.mapped(new_cdr)) { | 
|  | diag_errx( | 
|  | 1, | 
|  | "Bad directory record at offset 0x%" PRIx64 " of %s\n" | 
|  | "file name length = %u, extra_field length = %u, comment length = %u", | 
|  | CentralDirectoryRecordOffset(cdh_), path_.c_str(), | 
|  | cdh_->file_name_length(), cdh_->extra_fields_length(), | 
|  | cdh_->comment_length()); | 
|  | } | 
|  | cdh_ = reinterpret_cast<const CDH *>(new_cdr); | 
|  | *local_header_ptr = LocalHeader(current_cdh); | 
|  | return current_cdh; | 
|  | } | 
|  |  | 
|  | // Closes the file. | 
|  | bool Close(); | 
|  |  | 
|  | uint64_t CentralDirectoryRecordOffset(const void *cdr) const { | 
|  | return mapped_file_.offset(cdr); | 
|  | } | 
|  |  | 
|  | const LH *LocalHeader(const CDH *cdh) const { | 
|  | return reinterpret_cast<const LH *>( | 
|  | mapped_file_.address(cdh->local_header_offset() + preamble_size_)); | 
|  | } | 
|  |  | 
|  | uint64_t LocalHeaderOffset(const LH *lh) const { | 
|  | return mapped_file_.offset(lh); | 
|  | } | 
|  |  | 
|  | const uint8_t *mapped_start() const { | 
|  | return mapped_file_.address(0); | 
|  | } | 
|  |  | 
|  | private: | 
|  | std::string path_; | 
|  | MappedFile mapped_file_; | 
|  | const CDH *cdh_;  // current directory entry | 
|  | uint64_t preamble_size_;  // Bytes before the Zip proper. | 
|  | }; | 
|  |  | 
|  | #endif  //  BAZEL_SRC_TOOLS_SINGLEJAR_INPUT_JAR_H_ |