1 #include "archivefile.h"
2
ArchiveFile(QString fileName,bool sequential,bool deflate,QObject * parent)3 ArchiveFile::ArchiveFile(QString fileName, bool sequential, bool deflate, QObject *parent) :
4 QObject(parent),
5 m_archive(0),
6 m_entry(0),
7 m_fileName(fileName),
8 m_sequential(sequential),
9 m_deflate(deflate),
10 m_openMode(QIODevice::ReadOnly)
11 {
12 }
13
~ArchiveFile()14 ArchiveFile::~ArchiveFile()
15 {
16 if ( isOpen() )
17 close();
18 }
19
open(QIODevice::OpenMode openMode,QString fileName)20 bool ArchiveFile::open(QIODevice::OpenMode openMode, QString fileName)
21 {
22 if ( isOpen() )
23 close();
24 if ( !fileName.isEmpty() )
25 m_fileName = fileName;
26 m_openMode = openMode;
27 m_entry = 0;
28 int result = 0;
29 switch ( m_openMode ) {
30 case QIODevice::WriteOnly:
31 m_archive = archive_write_new();
32 archive_write_set_format_zip(m_archive);
33 if ( m_deflate )
34 archive_write_set_options(m_archive, "compression=deflate");
35 else
36 archive_write_set_options(m_archive, "compression=store");
37 result = archive_write_open_filename(m_archive, m_fileName.toUtf8().constData());
38 if ( result != ARCHIVE_OK) {
39 archive_write_free(m_archive);
40 m_archive = 0;
41 return false;
42 } else
43 return true;
44 case QIODevice::ReadOnly:
45 default:
46 m_archive = archive_read_new();
47 archive_read_support_filter_all(m_archive);
48 archive_read_support_format_all(m_archive);
49 result = archive_read_open_filename(m_archive, m_fileName.toUtf8().constData(), QMC2_ARCHIVE_BLOCK_SIZE);
50 if ( result != ARCHIVE_OK) {
51 archive_read_free(m_archive);
52 m_archive = 0;
53 return false;
54 } else {
55 if ( !m_sequential )
56 createEntryList();
57 return true;
58 }
59 }
60 }
61
close()62 void ArchiveFile::close()
63 {
64 entryList().clear();
65 m_nameToIndexCache.clear();
66 if ( isOpen() ) {
67 switch ( m_openMode ) {
68 case QIODevice::WriteOnly:
69 archive_write_close(m_archive);
70 archive_write_free(m_archive);
71 break;
72 case QIODevice::ReadOnly:
73 default:
74 archive_read_close(m_archive);
75 archive_read_free(m_archive);
76 break;
77 }
78 m_archive = 0;
79 m_entry = 0;
80 }
81 }
82
reopen()83 void ArchiveFile::reopen()
84 {
85 archive_read_free(m_archive);
86 m_archive = archive_read_new();
87 archive_read_support_filter_all(m_archive);
88 archive_read_support_format_all(m_archive);
89 archive_read_open_filename(m_archive, m_fileName.toUtf8().constData(), QMC2_ARCHIVE_BLOCK_SIZE);
90 }
91
writeEntryDataBig(const BigByteArray & buffer)92 qint64 ArchiveFile::writeEntryDataBig(const BigByteArray &buffer)
93 {
94 qint64 len = 0;
95 for (int i = 0; i < buffer.chunks(); i++)
96 len += writeEntryData(buffer.chunk(i));
97 return len;
98 }
99
seekNextEntry(ArchiveEntryMetaData * metaData,bool * reset)100 bool ArchiveFile::seekNextEntry(ArchiveEntryMetaData *metaData, bool *reset)
101 {
102 if ( !isOpen() )
103 return false;
104 if ( !m_sequential ) {
105 if ( reset != 0 && *reset ) {
106 reopen();
107 *reset = false;
108 }
109 }
110 if ( archive_read_next_header(m_archive, &m_entry) == ARCHIVE_OK ) {
111 *metaData = ArchiveEntryMetaData(archive_entry_pathname(m_entry), archive_entry_size(m_entry), QDateTime::fromTime_t(archive_entry_mtime(m_entry)));
112 return true;
113 } else
114 return false;
115 }
116
seekEntry(uint index)117 bool ArchiveFile::seekEntry(uint index)
118 {
119 if ( !isOpen() )
120 return false;
121 ArchiveEntryMetaData metadata = entryList()[index];
122 archive_read_free(m_archive);
123 m_archive = archive_read_new();
124 archive_read_support_filter_all(m_archive);
125 archive_read_support_format_all(m_archive);
126 archive_read_open_filename(m_archive, m_fileName.toUtf8().constData(), QMC2_ARCHIVE_BLOCK_SIZE);
127 while ( archive_read_next_header(m_archive, &m_entry) == ARCHIVE_OK )
128 if ( metadata.name().compare(archive_entry_pathname(m_entry), Qt::CaseSensitive) == 0 )
129 return true;
130 return false;
131 }
132
readEntry(QByteArray & buffer)133 qint64 ArchiveFile::readEntry(QByteArray &buffer)
134 {
135 if ( !isOpen() || writeMode() )
136 return 0;
137 #if defined(QMC2_OS_WIN)
138 __int64 size = archive_entry_size(m_entry);
139 #else
140 int64_t size = archive_entry_size(m_entry);
141 #endif
142 if ( size > 0 ) {
143 char *data = new char[size];
144 #if defined(QMC2_OS_WIN) && defined(_MSC_VER)
145 SSIZE_T len = archive_read_data(m_archive, data, size);
146 #else
147 ssize_t len = archive_read_data(m_archive, data, size);
148 #endif
149 if ( len > 0 ) {
150 buffer = QByteArray(data, len);
151 delete [] data;
152 return len;
153 }
154 delete [] data;
155 }
156 return 0;
157 }
158
createEntry(QString name,size_t size)159 bool ArchiveFile::createEntry(QString name, size_t size)
160 {
161 m_entry = archive_entry_new();
162 archive_entry_set_pathname(m_entry, name.toUtf8().constData());
163 archive_entry_set_size(m_entry, size);
164 archive_entry_set_filetype(m_entry, AE_IFREG);
165 archive_entry_set_perm(m_entry, 0644);
166 archive_entry_set_mtime(m_entry, QDateTime::currentDateTime().toTime_t(), 0);
167 archive_write_header(m_archive, m_entry);
168 return !hasError();
169 }
170
closeEntry()171 void ArchiveFile::closeEntry()
172 {
173 archive_write_finish_entry(m_archive);
174 archive_entry_free(m_entry);
175 }
176
createEntryList()177 void ArchiveFile::createEntryList()
178 {
179 entryList().clear();
180 m_nameToIndexCache.clear();
181 if ( !isOpen() )
182 return;
183 struct archive_entry *entry;
184 int counter = 0;
185 while ( archive_read_next_header(m_archive, &entry) == ARCHIVE_OK ) {
186 QString entryName(archive_entry_pathname(entry));
187 entryList() << ArchiveEntryMetaData(entryName, archive_entry_size(entry), QDateTime::fromTime_t(archive_entry_mtime(entry)));
188 m_nameToIndexCache.insert(entryName, counter++);
189 archive_read_data_skip(m_archive);
190 }
191 }
192