Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/art/art/libartbase/base/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 10 kB image not shown  

Quelle  zip_archive.cc

  Sprache: C
 

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * 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.
 */


#include "zip_archive.h"

#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <vector>

#include "android-base/stringprintf.h"
#include "ziparchive/zip_archive.h"
#include "ziparchive/zip_error.h"

#include "base/mman.h"
#include "bit_utils.h"
#include "unix_file/fd_file.h"

namespace art {

// Log file contents and mmap info when mapping entries directly.
static constexpr const bool kDebugZipMapDirectly = false;

using android::base::StringPrintf;

uint32_t ZipEntry::GetUncompressedLength() const { return zip_entry_->uncompressed_length; }

uint32_t ZipEntry::GetCrc32() const { return zip_entry_->crc32; }

bool ZipEntry::IsUncompressed() const { return zip_entry_->method == kCompressStored; }

bool ZipEntry::IsAlignedTo(size_t alignment) const {
  DCHECK(IsPowerOfTwo(alignment)) << alignment;
  return IsAlignedParam(zip_entry_->offset, static_cast<int>(alignment));
}

off_t ZipEntry::GetOffset() const { return zip_entry_->offset; }

ZipEntry::~ZipEntry() {
  delete zip_entry_;
}

bool ZipEntry::ExtractToFile(File& file, std::string* error_msg) {
  const int32_t error = ExtractEntryToFile(handle_, zip_entry_, file.Fd());
  if (error != 0) {
    *error_msg = "Failed to extract '" + entry_name_ + "': " + ErrorCodeString(error);
    return false;
  }

  return true;
}

MemMap ZipEntry::ExtractToMemMap(const char* zip_filename,
                                 const char* entry_filename,
                                 std::string* error_msg) {
  std::string name(entry_filename);
  name += " extracted in memory from ";
  name += zip_filename;
  MemMap map = MemMap::MapAnonymous(name.c_str(),
                                    GetUncompressedLength(),
                                    PROT_READ | PROT_WRITE,
                                    /*low_4gb=*/ false,
                                    error_msg);
  if (!map.IsValid()) {
    DCHECK(!error_msg->empty());
    return MemMap::Invalid();
  }

  DCHECK_EQ(map.Size(), GetUncompressedLength());
  if (!ExtractToMemory(map.Begin(), error_msg)) {
    return MemMap::Invalid();
  }

  return map;
}

bool ZipEntry::ExtractToMemory(/*out*/uint8_t* buffer, /*out*/std::string* error_msg) {
  const int32_t error = ::ExtractToMemory(handle_, zip_entry_, buffer, GetUncompressedLength());
  if (error != 0) {
    *error_msg = "Failed to extract '" + entry_name_ + "': " + ErrorCodeString(error);
    return false;
  }
  return true;
}

MemMap ZipEntry::MapDirectlyFromFile(const char* zip_filename, std::string* error_msg) {
  const int zip_fd = GetFileDescriptor(handle_);
  const char* entry_filename = entry_name_.c_str();

  // Should not happen since we don't have a memory ZipArchive constructor.
  // However the underlying ZipArchive isn't required to have an FD,
  // so check to be sure.
  CHECK_GE(zip_fd, 0) <<
      StringPrintf("Cannot map '%s' (in zip '%s') directly because the zip archive "
                   "is not file backed.",
                   entry_filename,
                   zip_filename);

  if (!IsUncompressed()) {
    *error_msg = StringPrintf("Cannot map '%s' (in zip '%s') directly because it is compressed.",
                              entry_filename,
                              zip_filename);
    return MemMap::Invalid();
  } else if (zip_entry_->uncompressed_length != zip_entry_->compressed_length) {
    *error_msg = StringPrintf("Cannot map '%s' (in zip '%s') directly because "
                              "entry has bad size (%u != %u).",
                              entry_filename,
                              zip_filename,
                              zip_entry_->uncompressed_length,
                              zip_entry_->compressed_length);
    return MemMap::Invalid();
  }

  std::string name(entry_filename);
  name += " mapped directly in memory from ";
  name += zip_filename;

  const off_t offset = zip_entry_->offset;

  if (kDebugZipMapDirectly) {
    LOG(INFO) << "zip_archive: " << "make mmap of " << name << " @ offset = " << offset;
  }

  MemMap map =
      MemMap::MapFile(GetUncompressedLength(),  // Byte count
                      PROT_READ | PROT_WRITE,
                      MAP_PRIVATE,
                      zip_fd,
                      offset,
                      /*low_4gb=*/ false,
                      name.c_str(),
                      error_msg);

  if (!map.IsValid()) {
    DCHECK(!error_msg->empty());
  }

  if (kDebugZipMapDirectly) {
    // Dump contents of file, same format as using this shell command:
    // $> od -j <offset> -t x1 <zip_filename>
    static constexpr const int kMaxDumpChars = 15;
    lseek(zip_fd, 0, SEEK_SET);

    int count = offset + kMaxDumpChars;

    std::string tmp;
    char buf;

    // Dump file contents.
    int i = 0;
    while (read(zip_fd, &buf, 1) > 0 && i < count) {
      tmp += StringPrintf("%3d ", (unsigned int)buf);
      ++i;
    }

    LOG(INFO) << "map_fd raw bytes starting at 0";
    LOG(INFO) << "" << tmp;
    LOG(INFO) << "---------------------------";

    // Dump map contents.
    if (map.IsValid()) {
      tmp = "";

      count = kMaxDumpChars;

      uint8_t* begin = map.Begin();
      for (i = 0; i < count; ++i) {
        tmp += StringPrintf("%3d ", (unsigned int)begin[i]);
      }

      LOG(INFO) << "map address " << StringPrintf("%p", begin);
      LOG(INFO) << "map first " << kMaxDumpChars << " chars:";
      LOG(INFO) << tmp;
    }
  }

  return map;
}

MemMap ZipEntry::MapDirectlyOrExtract(const char* zip_filename,
                                      const char* entry_filename,
                                      std::string* error_msg,
                                      size_t alignment) {
  if (IsUncompressed() && IsAlignedTo(alignment) && GetFileDescriptor(handle_) >= 0) {
    std::string local_error_msg;
    MemMap ret = MapDirectlyFromFile(zip_filename, &local_error_msg);
    if (ret.IsValid()) {
      return ret;
    }
    // Fall back to extraction for the failure case.
  }
  return ExtractToMemMap(zip_filename, entry_filename, error_msg);
}

static void SetCloseOnExec(int fd) {
#ifdef _WIN32
  // Exec is not supported on Windows.
  UNUSED(fd);
  PLOG(ERROR) << "SetCloseOnExec is not supported on Windows.";
#else
  // This dance is more portable than Linux's O_CLOEXEC open(2) flag.
  int flags = fcntl(fd, F_GETFD);
  if (flags == -1) {
    PLOG(WARNING) << "fcntl(" << fd << ", F_GETFD) failed";
    return;
  }
  int rc = fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
  if (rc == -1) {
    PLOG(WARNING) << "fcntl(" << fd << ", F_SETFD, " << flags << ") failed";
    return;
  }
#endif
}

ZipArchive* ZipArchive::Open(const char* filename, std::string* error_msg) {
  DCHECK(filename != nullptr);

  // Don't call into `OpenArchive` on file absence. `OpenArchive` prints a warning even if the file
  // absence is expected.
  if (!OS::FileExists(filename)) {
    *error_msg = StringPrintf("Failed to open '%s': File not found", filename);
    return nullptr;
  }

  ZipArchiveHandle handle;
  const int32_t error = OpenArchive(filename, &handle);
  if (error != 0) {
    *error_msg = StringPrintf("Failed to open '%s': %s", filename, ErrorCodeString(error));
    CloseArchive(handle);
    return nullptr;
  }

  SetCloseOnExec(GetFileDescriptor(handle));
  return new ZipArchive(handle);
}

ZipArchive* ZipArchive::OpenFromFd(int fd, const char* filename, std::string* error_msg) {
  return OpenFromFdInternal(fd, /*assume_ownership=*/true, filename, error_msg);
}

ZipArchive* ZipArchive::OpenFromOwnedFd(int fd, const char* filename, std::string* error_msg) {
  return OpenFromFdInternal(fd, /*assume_ownership=*/false, filename, error_msg);
}

ZipArchive* ZipArchive::OpenFromMemory(const uint8_t* data,
                                       size_t size,
                                       const char* filename,
                                       std::string* error_msg) {
  DCHECK(filename != nullptr);
  DCHECK(data != nullptr);

  ZipArchiveHandle handle;
  const int32_t error = OpenArchiveFromMemory(data, size, filename, &handle);
  if (error != 0) {
    *error_msg =
        StringPrintf("Failed to open '%s' from memory: %s", filename, ErrorCodeString(error));
    CloseArchive(handle);
    return nullptr;
  }

  return new ZipArchive(handle);
}

ZipArchive* ZipArchive::OpenFromFdInternal(int fd,
                                           bool assume_ownership,
                                           const char* filename,
                                           std::string* error_msg) {
  DCHECK(filename != nullptr);
  DCHECK_GT(fd, 0);

  ZipArchiveHandle handle;
  const int32_t error = OpenArchiveFd(fd, filename, &handle, assume_ownership);
  if (error != 0) {
    *error_msg = StringPrintf("Failed to open '%s' from fd: %s", filename, ErrorCodeString(error));
    CloseArchive(handle);
    return nullptr;
  }

  SetCloseOnExec(GetFileDescriptor(handle));
  return new ZipArchive(handle);
}

ZipEntry* ZipArchive::Find(const char* name, std::string* error_msg) const {
  return FindImpl(name, /*allow_entry_not_found=*/false, error_msg);
}

ZipEntry* ZipArchive::FindOrNull(const char* name, std::string* error_msg) const {
  return FindImpl(name, /*allow_entry_not_found=*/true, error_msg);
}

ZipEntry* ZipArchive::FindImpl(const char* name,
                               bool allow_entry_not_found,
                               std::string* error_msg) const {
  DCHECK(name != nullptr);

  auto zip_entry = std::make_unique<::ZipEntry>();
  const int32_t error = FindEntry(handle_, name, zip_entry.get());
  if (error != 0) {
    if (!allow_entry_not_found || error != ZipError::kEntryNotFound) {
      *error_msg = StringPrintf("Failed to find entry '%s': %s", name, ErrorCodeString(error));
    }
    return nullptr;
  }

  return new ZipEntry(handle_, zip_entry.release(), name);
}

ZipArchive::~ZipArchive() {
  CloseArchive(handle_);
}

}  // namespace art

Messung V0.5 in Prozent
C=92 H=95 G=93

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.