Line data Source code
1 : /* 2 : Zipios -- a small C++ library that provides easy access to .zip files. 3 : 4 : Copyright (C) 2000-2007 Thomas Sondergaard 5 : Copyright (c) 2015-2022 Made to Order Software Corp. All Rights Reserved 6 : 7 : This library is free software; you can redistribute it and/or 8 : modify it under the terms of the GNU Lesser General Public 9 : License as published by the Free Software Foundation; either 10 : version 2.1 of the License, or (at your option) any later version. 11 : 12 : This library is distributed in the hope that it will be useful, 13 : but WITHOUT ANY WARRANTY; without even the implied warranty of 14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 : Lesser General Public License for more details. 16 : 17 : You should have received a copy of the GNU Lesser General Public 18 : License along with this library; if not, write to the Free Software 19 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 : */ 21 : 22 : /** \file 23 : * \brief Implementation of zipios::DirectoryEntry. 24 : * 25 : * The declaration of a simple zipios::FileEntry used when reading 26 : * a directory from disk. 27 : */ 28 : 29 : #include "zipios/directoryentry.hpp" 30 : 31 : #include "zipios/zipiosexceptions.hpp" 32 : 33 : #include "zipios_common.hpp" 34 : 35 : #include <fstream> 36 : #include <zlib.h> 37 : 38 : 39 : namespace zipios 40 : { 41 : 42 : /** \class DirectoryEntry 43 : * \brief A file entry that does not use compression. 44 : * 45 : * DirectoryEntry is a FileEntry that is suitable as a base class for 46 : * basic entries, that do not support any form of compression and 47 : * in most cases represent a file in a directory. 48 : */ 49 : 50 : 51 : /** \brief Initialize a DirectoryEntry object. 52 : * 53 : * This constructor initializes a DirectoryEntry which represents a 54 : * file on disk. If the basepath + filename does not exist or is 55 : * neither a regular file or a directory, then this entry is created 56 : * but marked as invalid. 57 : * 58 : * \param[in] filename The filename of the entry. 59 : * \param[in] comment A comment for the entry. 60 : */ 61 75806 : DirectoryEntry::DirectoryEntry(FilePath const & filename, std::string const & comment) 62 75806 : : FileEntry(filename, comment) 63 : { 64 75806 : m_valid = m_filename.isRegular() || m_filename.isDirectory(); 65 75806 : if(m_valid) 66 : { 67 75678 : m_uncompressed_size = m_filename.isDirectory() ? 0 : m_filename.fileSize(); 68 75678 : m_unix_time = m_filename.lastModificationTime(); 69 : } 70 75806 : } 71 : 72 : 73 : /** \brief Create a copy of the DirectoryEntry. 74 : * 75 : * The clone function creates a copy of this DirectoryEntry object. 76 : * 77 : * In most cases, when a collection is copied, a clone of each 78 : * entry is created to avoid potential problems with sharing 79 : * the same object between various lists. 80 : * 81 : * \return A shared pointer of the new DirectoryEntry object. 82 : */ 83 89743 : DirectoryEntry::pointer_t DirectoryEntry::clone() const 84 : { 85 89743 : return std::make_shared<DirectoryEntry>(*this); 86 : } 87 : 88 : 89 : /** \brief Clean up a DirectoryEntry object. 90 : * 91 : * The destructor is defined as it has to be virtual. 92 : * 93 : * It will eventually clean up resources used by the DirectoryEntry class. 94 : */ 95 165549 : DirectoryEntry::~DirectoryEntry() 96 : { 97 165549 : } 98 : 99 : 100 : /** \brief Compare two file entries for equality. 101 : * 102 : * This function compares most of the fields between two file 103 : * entries to see whether they are equal or not. 104 : * 105 : * \note 106 : * This function calls the base class isEqual() and also verifies 107 : * that the object comments are equal. 108 : * 109 : * \param[in] file_entry The file entry to compare this against. 110 : * 111 : * \return true if both FileEntry objects are considered equal. 112 : */ 113 1197 : bool DirectoryEntry::isEqual(FileEntry const & file_entry) const 114 : { 115 1197 : DirectoryEntry const * const de(dynamic_cast<DirectoryEntry const * const>(&file_entry)); 116 1197 : if(de == nullptr) 117 : { 118 738 : return false; 119 : } 120 459 : return FileEntry::isEqual(file_entry); 121 : } 122 : 123 : 124 : /** \brief Compute the CRC32 of this file. 125 : * 126 : * This function computers the CRC32 of this file and returns it. 127 : * 128 : * This is only a helper function. The CRC32 for the zip file is computed 129 : * on the fly as data is being streamed. 130 : * 131 : * \warning 132 : * This function recomputes the CRC32 on each call. It doesn't get cached. 133 : * 134 : * \return The CRC32 of this file. 135 : */ 136 0 : uint32_t DirectoryEntry::computeCRC32() const 137 : { 138 0 : uint32_t result(crc32(0L, Z_NULL, 0)); 139 : 140 0 : if(!m_filename.isDirectory()) 141 : { 142 : // TODO: I tried to use std::basic_ifstream<Bytef> to avoid the 143 : // reinterpret_cast<>(), but somehow that doesn't work at all 144 : // 145 0 : std::ifstream in; 146 0 : in.open(m_filename); 147 0 : if(!in.is_open()) 148 : { 149 0 : throw IOException( 150 : "Can't open file \"" 151 0 : + m_filename.filename() 152 0 : + "\"."); 153 : } 154 : 155 : for(;;) 156 : { 157 : Bytef buf[64 * 1024]; 158 0 : in.read(reinterpret_cast<char *>(buf), sizeof(buf)); 159 0 : if(in.gcount() == 0) 160 : { 161 0 : break; 162 : } 163 0 : result = crc32(result, buf, in.gcount()); 164 0 : } 165 0 : } 166 : 167 0 : return result; 168 : } 169 : 170 : 171 : } // zipios namespace 172 : 173 : // Local Variables: 174 : // mode: cpp 175 : // indent-tabs-mode: nil 176 : // c-basic-offset: 4 177 : // tab-width: 4 178 : // End: 179 : 180 : // vim: ts=4 sw=4 et