Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "cod.h"
00025 #include "cod-internal.h"
00026 #include "error.h"
00027 #include "endian.h"
00028 #include <config.h>
00029 #include <sys/types.h>
00030 #include <sys/stat.h>
00031 #include <unistd.h>
00032 #include <string>
00033 #include <string.h>
00034
00035 #ifdef HAVE_ZLIB
00036 #include <zlib.h>
00037 #endif
00038
00039 using namespace std;
00040
00041 namespace Barry {
00042
00043
00044 size_t SeekNextCod(std::istream &input)
00045 {
00046 unsigned char codtype_simple[] = CODFILE_TYPE_SIMPLE;
00047 char codtype_pkzip[] = CODFILE_TYPE_PKZIP;
00048 char local_file_sig[] = PKZIP_LOCAL_FILE_SIG;
00049 char directory_sig[] = PKZIP_DIRECTORY_SIG;
00050
00051 char signature[4];
00052
00053
00054 input.peek();
00055 if( input.eof() ) {
00056 return 0;
00057 }
00058
00059 if( input.read(signature, sizeof(signature)).eof() ) {
00060 throw Error("SeekNextCod: EOF while reading file signature");
00061 }
00062
00063 if( memcmp(signature, codtype_pkzip, sizeof(codtype_pkzip)) == 0 ) {
00064
00065 if( memcmp(signature, local_file_sig, sizeof(signature)) == 0 ) {
00066 pkzip_local_header_t header;
00067
00068 if( input.read((char *)&header, sizeof(pkzip_local_header_t)).eof() ) {
00069 throw Error("SeekNextCod: EOF while reading PKZIP header");
00070 }
00071
00072
00073 size_t skip_len = header.file_name_length + header.extra_field_length;
00074 if( input.ignore(skip_len).eof() ) {
00075 throw Error("SeekNextCod: EOF while skipping unused fields");
00076 }
00077
00078 return btohl(header.compressed_size);
00079 }
00080 else if( memcmp(signature, directory_sig, sizeof(signature)) == 0 ) {
00081
00082 return 0;
00083 }
00084 }
00085 else if( memcmp(signature, codtype_simple, sizeof(codtype_simple)) == 0 ) {
00086
00087 if( input.seekg(0, ios::end).fail() ) {
00088 throw Error("SeekNextCod: seek to end failed");
00089 }
00090
00091 uint32_t size = input.tellg();
00092
00093 if( input.seekg(0, ios::beg).fail() ) {
00094 throw Error("SeekNextCod: seek to start failed");
00095 }
00096
00097 return size;
00098 }
00099 else {
00100 throw Error("SeekNextCod: unknown COD file signature");
00101 }
00102
00103 return 0;
00104 }
00105
00106
00107 CodFileBuilder::CodFileBuilder(const std::string &module_name, size_t module_count)
00108 : m_module_name(module_name)
00109 , m_module_count(module_count)
00110 , m_current_module(0)
00111 {
00112 }
00113
00114 CodFileBuilder::~CodFileBuilder()
00115 {
00116 }
00117
00118 void CodFileBuilder::WriteNextHeader(std::ostream &output, const uint8_t* module_buffer, uint32_t module_size)
00119 {
00120
00121 if( m_module_count == 1 ) {
00122 return;
00123 }
00124
00125
00126
00127 uint32_t crc = 0;
00128
00129 #ifdef HAVE_ZLIB
00130 crc = crc32(0, NULL, module_size);
00131 crc = crc32(crc, module_buffer, module_size);
00132 #endif
00133
00134
00135 std::ostringstream file_name(m_module_name, ios::app);
00136 if( m_current_module == 0 )
00137 file_name << ".cod";
00138 else
00139 file_name << "-" << m_current_module << ".cod";
00140
00141
00142 uint32_t entry_offset = output.tellp();
00143
00144
00145 pkzip_local_header_t header;
00146 pkzip_directory_t entry;
00147
00148
00149 memset(&header, 0, sizeof(pkzip_local_header_t));
00150 memset(&entry, 0, sizeof(pkzip_directory_t));
00151
00152 char header_sig[] = PKZIP_LOCAL_FILE_SIG;
00153 output.write(header_sig, sizeof(header_sig));
00154
00155
00156 header.version_needed = htobs(10);
00157
00158
00159
00160
00161
00162
00163 header.crc_32 = htobl(crc);
00164 header.compressed_size = htobl(module_size);
00165 header.uncompressed_size = htobl(module_size);
00166 header.file_name_length = htobs(file_name.str().length());
00167
00168
00169
00170
00171
00172
00173 output.write((char *)&header, sizeof(pkzip_local_header_t));
00174 output << file_name.str();
00175
00176 char footer_sig[] = PKZIP_DIRECTORY_SIG;
00177
00178
00179 entry.version_madeby = htobs(10);
00180 entry.version_needed = htobs(10);
00181
00182 entry.crc_32 = htobl(crc);
00183 entry.compressed_size = htobl(module_size);
00184 entry.uncompressed_size = htobl(module_size);
00185 entry.file_name_length = htobs(file_name.str().length());
00186 entry.relative_offset = htobl(entry_offset);
00187
00188 m_directory.write(footer_sig, sizeof(footer_sig));
00189 m_directory.write((char*)&entry, sizeof(pkzip_directory_t));
00190 m_directory << file_name.str();
00191
00192 m_current_module ++;
00193 }
00194
00195 void CodFileBuilder::WriteFooter(std::ostream &output)
00196 {
00197
00198 if( m_module_count == 1 ) {
00199 return;
00200 }
00201
00202 pkzip_end_directory_t end;
00203 memset(&end, 0, sizeof(pkzip_end_directory_t));
00204
00205 end.this_disk_entry_count = htobs(m_current_module);
00206 end.total_entry_count = htobs(m_current_module);
00207 end.directory_length = htobl(m_directory.str().length());
00208
00209
00210 end.directory_offset = output.tellp();
00211
00212 char sig[] = PKZIP_END_DIRECTORY_SIG;
00213
00214 output.write(m_directory.str().data(), m_directory.str().length());
00215 output.write(sig, sizeof(sig));
00216 output.write((char *)&end, sizeof(pkzip_end_directory_t));
00217 }
00218
00219
00220 }
00221