strigi/src/streams
arinputstream.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 "arinputstream.h"
00021 #include <strigi/strigiconfig.h>
00022 #include "subinputstream.h"
00023
00024 #include <stdlib.h>
00025 #include <cstring>
00026
00027 using namespace Strigi;
00028
00029 bool
00030 ArInputStream::checkHeader(const char* data, int32_t datasize) {
00031 static const char magic[] = {0x21,0x3c,0x61,0x72,0x63,0x68,0x3e,0x0a};
00032 if (datasize < 8) return false;
00033 bool ok = std::memcmp(data, magic, 8) == 0;
00034 return ok;
00035 }
00036 ArInputStream::ArInputStream(InputStream* input)
00037 : SubStreamProvider(input) {
00038
00039 const char*b;
00040 if (input->read(b, 8, 8) != 8 || !checkHeader(b, 8)) {
00041 m_status = Error;
00042 }
00043 }
00044 ArInputStream::~ArInputStream() {
00045 }
00046 InputStream*
00047 ArInputStream::nextEntry() {
00048 if (m_status) return 0;
00049 if (m_entrystream) {
00050 m_entrystream->skip(m_entrystream->size());
00051 delete m_entrystream;
00052 m_entrystream = 0;
00053 }
00054 readHeader();
00055 if (m_status) return 0;
00056 m_entrystream = new SubInputStream(m_input, m_entryinfo.size);
00057 return m_entrystream;
00058 }
00059 void
00060 ArInputStream::readHeader() {
00061 const char *b;
00062 int32_t toread;
00063 int32_t nread;
00064
00065 int64_t pos = m_input->position();
00066 if (pos%2) {
00067 m_input->skip(1);
00068 }
00069
00070
00071 toread = 60;
00072 nread = m_input->read(b, toread, toread);
00073 if (m_input->status() == Error) {
00074 m_error = "Error reading ar header: ";
00075 m_error += m_input->error();
00076 m_status = Error;
00077 return;
00078 }
00079 if (nread <= 1) {
00080 m_status = Eof;
00081 return;
00082 }
00083 if (nread != toread) {
00084 m_error = "Error reading ar header: premature end of file.";
00085 m_status = Error;
00086 return;
00087 }
00088 int len;
00089 for (len=0; len<16; len++) {
00090 char c = b[len];
00091 if (c == ' ' || c == '/' || c == '\0') {
00092 break;
00093 }
00094 }
00095
00096
00097 char bc[61];
00098 std::memcpy(bc, b, 60);
00099 bc[60] = '\0';
00100 m_entryinfo.size = atoi(bc+48);
00101 if (m_entryinfo.size < 0) {
00102 m_error = "Error: negative file size.";
00103 m_status = Error;
00104 return;
00105 }
00106 m_entryinfo.mtime = atoi(bc+16);
00107 if (len == 0) {
00108 if (b[1] == '/') {
00109
00110 nread = m_input->read(b, (int32_t)m_entryinfo.size, (int32_t)m_entryinfo.size);
00111 if (nread != m_entryinfo.size) {
00112 m_error = "premature end of stream";
00113 m_status = Error;
00114 return;
00115 }
00116 gnufilenames.assign(b, (unsigned int)m_entryinfo.size);
00117 readHeader();
00118 } else if (b[1] == ' ') {
00119 m_input->skip(m_entryinfo.size);
00120 readHeader();
00121 } else {
00122 uint p = atoi(bc+1);
00123 if (gnufilenames.length() <= p) {
00124 m_error = "Invalid name field.";
00125 m_status = Error;
00126 return;
00127 }
00128 const char* c = gnufilenames.c_str() + p;
00129 const char* e = std::strchr(c, '/');
00130 if (e) {
00131 m_entryinfo.filename = std::string(c, e-c);
00132 } else {
00133 m_entryinfo.filename = c;
00134 }
00135 }
00136 } else {
00137 m_entryinfo.filename = std::string(b, len);
00138 }
00139 m_entryinfo.type = Strigi::EntryInfo::File;
00140 }