* @version 1.0
* @brief This file is the implementation file of zip input
*/
+#include <stddef.h>
+#include <iomanip>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <errno.h>
#include <dpl/zip_input.h>
-#include <dpl/file_input_mapping.h>
+#include <dpl/scoped_close.h>
#include <dpl/binary_queue.h>
#include <dpl/scoped_free.h>
-#include <dpl/scoped_ptr.h>
+#include <memory>
#include <dpl/scoped_array.h>
#include <dpl/foreach.h>
#include <dpl/log/log.h>
class Device
{
private:
- DPL::ScopedPtr<FileInputMapping> m_fileMapping;
+ int m_handle;
+ off64_t m_size; // file mapping size
+ unsigned char *m_address; // mapping base address
struct File
{
public:
Device(const std::string &fileName)
{
- Try
+ LogPedantic("Creating file mapping");
+ // Open device and map it to user space
+ int file = TEMP_FAILURE_RETRY(open(fileName.c_str(), O_RDONLY));
+
+ if (file == -1)
+ {
+ int error = errno;
+ ThrowMsg(ZipInput::Exception::OpenFailed,
+ "Failed to open file. errno = " << error);
+ }
+
+ // Scoped close on file
+ ScopedClose scopedClose(file);
+
+ // Calculate file size
+ off64_t size = lseek64(file, 0, SEEK_END);
+
+ if (size == static_cast<off64_t>(-1))
{
- LogPedantic("Creating file mapping");
- m_fileMapping.Reset(new FileInputMapping(fileName));
+ int error = errno;
+ ThrowMsg(ZipInput::Exception::OpenFailed,
+ "Failed to seek file. errno = " << error);
}
- Catch (FileInputMapping::Exception::Base)
+
+ // Map file to usespace
+ void *address = mmap(0, static_cast<size_t>(size),
+ PROT_READ, MAP_SHARED, file, 0);
+
+ if (address == MAP_FAILED)
{
- LogPedantic("Failed to create file mapping");
+ int error = errno;
+ ThrowMsg(ZipInput::Exception::OpenFailed,
+ "Failed to map file. errno = " << error);
+ }
+
+ // Release scoped close
+ m_handle = scopedClose.Release();
+
+ // Save mapped up address
+ m_size = size;
+ m_address = static_cast<unsigned char *>(address);
+
+ LogPedantic("Created file mapping: " << fileName <<
+ " of size: " << m_size <<
+ " at address: " << std::hex << static_cast<void *>(m_address));
+ }
- ReThrowMsg(ZipInput::Exception::OpenFailed,
- "Failed to open zip file mapping");
+ ~Device()
+ {
+ // Close mapping
+ if (munmap(m_address, static_cast<size_t>(m_size)) == -1)
+ {
+ int error = errno;
+ LogPedantic("Failed to munmap file. errno = " << error);
}
- LogPedantic("File mapping created");
+ // Close file descriptor
+ if (close(m_handle) == -1)
+ {
+ int error = errno;
+ LogPedantic("Failed to close file. errno = " << error);
+ }
}
// zlib_filefunc64_def interface: files
static voidpf ZCALLBACK open64_file(voidpf opaque,
- const void* filename,
- int mode)
+ const void* /*filename*/,
+ int /*mode*/)
{
- (void)filename;
- (void)mode;
-
Device *device = static_cast<Device *>(opaque);
// Open file for master device
File *deviceFile = static_cast<File *>(pstream);
// Check if offset is out of bounds
- if (deviceFile->offset >= device->m_fileMapping->GetSize())
+ if (deviceFile->offset >= device->m_size)
{
LogPedantic("Device: read offset out of bounds");
return -1;
}
- off64_t bytesLeft = device->m_fileMapping->GetSize() -
+ off64_t bytesLeft = device->m_size -
deviceFile->offset;
off64_t bytesToRead;
// Do copy
memcpy(buf,
- device->m_fileMapping->GetAddress() + deviceFile->offset,
+ device->m_address + deviceFile->offset,
static_cast<size_t>(bytesToRead));
// Increment file offset
return static_cast<uLong>(bytesToRead);
}
- static uLong ZCALLBACK write_file(voidpf opaque,
- voidpf stream,
- const void* buf,
- uLong size)
+ static uLong ZCALLBACK write_file(voidpf /*opaque*/,
+ voidpf /*stream*/,
+ const void* /*buf*/,
+ uLong /*size*/)
{
- (void)opaque;
- (void)stream;
- (void)buf;
- (void)size;
-
// Not supported by device
LogPedantic("Unsupported function called!");
return -1;
}
- static int ZCALLBACK close_file(voidpf opaque,
- voidpf stream)
+ static int ZCALLBACK close_file(voidpf /*opaque*/, voidpf stream)
{
- (void)opaque;
File *deviceFile = static_cast<File *>(stream);
// Delete file
return 0;
}
- static int ZCALLBACK testerror_file(voidpf opaque,
- voidpf stream)
+ static int ZCALLBACK testerror_file(voidpf /*opaque*/, voidpf /*stream*/)
{
- (void)opaque;
- (void)stream;
-
// No errors
return 0;
}
- static ZPOS64_T ZCALLBACK tell64_file(voidpf opaque,
- voidpf stream)
+ static ZPOS64_T ZCALLBACK tell64_file(voidpf /*opaque*/, voidpf stream)
{
- (void)opaque;
File *deviceFile = static_cast<File *>(stream);
return static_cast<ZPOS64_T>(deviceFile->offset);
case ZLIB_FILEFUNC_SEEK_END:
deviceFile->offset =
- device->m_fileMapping->GetSize() -
+ device->m_size -
static_cast<off64_t>(offset);
break;
// Create master device
LogPedantic("Creating master device");
- ScopedPtr<Device> device(new Device(fileName));
+ std::unique_ptr<Device> device(new Device(fileName));
// Open master file
zlib_filefunc64_def interface;
interface.zseek64_file = &Device::seek64_file;
interface.zclose_file = &Device::close_file;
interface.zerror_file = &Device::testerror_file;
- interface.opaque = device.Get();
+ interface.opaque = device.get();
LogPedantic("Opening zip file");
unzFile file = unzOpen2_64(NULL, &interface);
// Release scoped unz close
m_masterFile = scopedUnzClose.Release();
- m_device = device.Release();
+ m_device = device.release();
LogPedantic("Zip file opened");
}
),
std::string(fileName.Get()),
std::string(fileComment.Get()),
- static_cast<unsigned long>(fileInfo.version),
- static_cast<unsigned long>(fileInfo.version_needed),
- static_cast<unsigned long>(fileInfo.flag),
- static_cast<unsigned long>(fileInfo.compression_method),
- static_cast<unsigned long>(fileInfo.dosDate),
- static_cast<unsigned long>(fileInfo.crc),
static_cast<off64_t>(fileInfo.compressed_size),
- static_cast<off64_t>(fileInfo.uncompressed_size),
- static_cast<unsigned long>(fileInfo.disk_num_start),
- static_cast<unsigned long>(fileInfo.internal_fa),
- static_cast<unsigned long>(fileInfo.external_fa),
- FileDateTime(
- fileInfo.tmu_date.tm_sec,
- fileInfo.tmu_date.tm_min,
- fileInfo.tmu_date.tm_hour,
- fileInfo.tmu_date.tm_mday,
- fileInfo.tmu_date.tm_mon,
- fileInfo.tmu_date.tm_year
- )
+ static_cast<off64_t>(fileInfo.uncompressed_size)
)
);
return m_fileInfos.size();
}
-ZipInput::File *ZipInput::OpenFile(FileHandle handle)
-{
- return new File(m_device, handle);
-}
-
ZipInput::File *ZipInput::OpenFile(const std::string &fileName)
{
FOREACH(iterator, m_fileInfos)