strigi/src/streams
cpioinputstream.cpp
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 #include "cpioinputstream.h"
00021 #include <strigi/strigiconfig.h>
00022 #include "subinputstream.h"
00023
00024 #include <list>
00025 #include <cstring>
00026
00027 using namespace std;
00028 using namespace Strigi;
00029
00030 const char unsigned* CpioInputStream::magic = (const char unsigned *)"070701";
00031
00032 bool
00033 CpioInputStream::checkHeader(const char* data, int32_t datasize) {
00034 if (datasize < 6) return false;
00035
00036 bool ok = memcmp(data, magic, 6) == 0;
00037 return ok;
00038 }
00039 CpioInputStream::CpioInputStream(InputStream* input)
00040 : SubStreamProvider(input) {
00041 m_entryinfo.type = EntryInfo::File;
00042 }
00043 CpioInputStream::~CpioInputStream() {
00044 }
00045 InputStream*
00046 CpioInputStream::nextEntry() {
00047 if (m_status) return 0;
00048 if (m_entrystream) {
00049 while (m_entrystream->status() == Ok) {
00050 m_entrystream->skip(m_entrystream->size());
00051 }
00052 delete m_entrystream;
00053 m_entrystream = 0;
00054 if (padding) {
00055 m_input->skip(padding);
00056 }
00057 }
00058 readHeader();
00059 m_entrystream = new SubInputStream(m_input, m_entryinfo.size);
00060 return (m_status) ?0 :m_entrystream;
00061 }
00062 void
00063 CpioInputStream::readHeader() {
00064
00065 const char* b;
00066 int32_t toread;
00067 int32_t nread;
00068
00069
00070 toread = 110;
00071 nread = m_input->read(b, toread, toread);
00072 if (nread != toread) {
00073 m_status = m_input->status();
00074 if (m_status == Eof) {
00075 return;
00076 }
00077 m_error = "Error reading cpio entry: ";
00078 if (nread == -1) {
00079 m_error += m_input->error();
00080 } else {
00081 m_error += " premature end of file.";
00082 }
00083 return;
00084 }
00085
00086 if (memcmp(b, magic, 6) != 0) {
00087 m_status = Error;
00088 m_error = "CPIO Entry signature is unknown: ";
00089 m_error.append(b, 6);
00090 return;
00091 }
00092 m_entryinfo.size = readHexField(b+54);
00093 m_entryinfo.mtime = readHexField(b+46);
00094 int32_t filenamesize = readHexField(b+94);
00095 if (m_status) {
00096 m_error = "Error parsing entry field.";
00097 return;
00098 }
00099 char namepadding = (filenamesize+2) % 4;
00100 if (namepadding) namepadding = 4 - namepadding;
00101 padding = m_entryinfo.size % 4;
00102 if (padding) padding = 4 - padding;
00103
00104
00105 toread = filenamesize + namepadding;
00106 nread = m_input->read(b, toread, toread);
00107 if (nread != toread) {
00108 m_error = "Error reading cpio entry name.";
00109 m_status = Error;
00110 return;
00111 }
00112 int32_t len = filenamesize - 1;
00113 if (len > 2 && b[0] == '.' && b[1] == '/') {
00114 b += 2;
00115 }
00116
00117 len = 0;
00118 while (len < filenamesize && b[len] != '\0') len++;
00119 m_entryinfo.filename = std::string((const char*)b, len);
00120
00121
00122 if ("TRAILER!!!" == m_entryinfo.filename) {
00123 m_status = Eof;
00124 }
00125 }
00126 int32_t
00127 CpioInputStream::readHexField(const char *b) {
00128 int32_t val = 0;
00129 char c;
00130 for (unsigned char i=0; i<8; ++i) {
00131 val <<= 4;
00132 c = b[i];
00133 if (c > 'F') {
00134 val += c - 87;
00135 } else if (c > '9') {
00136 val += c - 55;
00137 } else {
00138 val += c - 48;
00139 }
00140 }
00141 return val;
00142 }