00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <sys/types.h>
00022
00023 #include <cstdlib>
00024 #include <cstdio>
00025 #include <vector>
00026 #include <iostream>
00027
00028 #include "debug.h"
00029
00030 #include "ifdfilecontainer.h"
00031 #include "io/file.h"
00032
00033
00034 using namespace Debug;
00035
00036 namespace OpenRaw {
00037
00038 namespace Internals {
00039
00040 IFDFileContainer::IFDFileContainer(IO::Stream *file, off_t offset)
00041 : RawContainer(file, offset),
00042 m_error(0),
00043 m_current_dir(),
00044 m_dirs()
00045 {
00046 }
00047
00048 IFDFileContainer::~IFDFileContainer()
00049 {
00050 m_dirs.clear();
00051 }
00052
00053
00054 IFDFileContainer::EndianType
00055 IFDFileContainer::isMagicHeader(const char *p, int len)
00056 {
00057 if (len < 4){
00058
00059 return ENDIAN_NULL;
00060 }
00061 if ((p[0] == 0x49) && (p[1] == 0x49)
00062 && (p[2] == 0x2a) && (p[3] == 0x00)) {
00063 return ENDIAN_LITTLE;
00064 }
00065 else if ((p[0] == 0x4d) && (p[1] == 0x4d)
00066 && (p[2] == 0x00) && (p[3] == 0x2a)) {
00067 return ENDIAN_BIG;
00068 }
00069 return ENDIAN_NULL;
00070 }
00071
00072
00073 int IFDFileContainer::countDirectories(void)
00074 {
00075 if (m_dirs.size() == 0) {
00076
00077 bool ret = _locateDirs();
00078 if (!ret) {
00079 return -1;
00080 }
00081 }
00082 return m_dirs.size();
00083 }
00084
00085 std::vector<IFDDir::Ref> &
00086 IFDFileContainer::directories()
00087 {
00088 if (m_dirs.size() == 0) {
00089 countDirectories();
00090 }
00091 return m_dirs;
00092 }
00093
00094 IFDDir::Ref
00095 IFDFileContainer::setDirectory(int dir)
00096 {
00097 if (dir < 0) {
00098
00099 return IFDDir::Ref((IFDDir*)NULL);
00100 }
00101
00102 int n = countDirectories();
00103 if (n <= 0) {
00104
00105 return IFDDir::Ref((IFDDir*)NULL);
00106 }
00107
00108
00109 if (dir > (int)m_dirs.size()) {
00110
00111 return IFDDir::Ref((IFDDir*)NULL);
00112 }
00113 m_current_dir = m_dirs[dir];
00114 m_current_dir->load();
00115 return m_current_dir;
00116 }
00117
00118
00119 size_t
00120 IFDFileContainer::getDirectoryDataSize()
00121 {
00122
00123 Trace(DEBUG1) << "getDirectoryDataSize()" << "\n";
00124 off_t offset = m_current_dir->offset();
00125
00126 Trace(DEBUG1) << "offset = " << offset
00127 << " m_numTags = " << m_current_dir->numTags() << "\n";
00128 off_t begin = offset + 2 + (m_current_dir->numTags()*12);
00129
00130 Trace(DEBUG1) << "begin = " << begin << "\n";
00131
00132 m_file->seek(begin, SEEK_SET);
00133 begin += 2;
00134 int32_t nextIFD;
00135 readInt32(m_file, nextIFD);
00136 Trace(DEBUG1) << "nextIFD = " << nextIFD << "\n";
00137 if (nextIFD == 0) {
00138
00139 }
00140 return nextIFD - begin;
00141 }
00142
00143
00144 bool
00145 IFDFileContainer::_locateDirs(void)
00146 {
00147 Trace(DEBUG1) << "_locateDirs()\n";
00148 if (m_endian == ENDIAN_NULL) {
00149 char buf[4];
00150 m_file->read(buf, 4);
00151 m_endian = isMagicHeader(buf, 4);
00152 if (m_endian == ENDIAN_NULL) {
00153
00154 return false;
00155 }
00156 }
00157 m_file->seek(4, SEEK_SET);
00158 int32_t offset = 0;
00159 readInt32(m_file, offset);
00160 m_dirs.clear();
00161 do {
00162 if (offset != 0) {
00163
00164 Trace(DEBUG1) << "push offset =0x" << offset << "\n";
00165
00166 IFDDir::Ref dir(new IFDDir(offset,*this));
00167 m_dirs.push_back(dir);
00168
00169
00170
00171 offset = dir->nextIFD();
00172 }
00173 } while(offset != 0);
00174
00175 Trace(DEBUG1) << "# dir found = " << m_dirs.size() << "\n";
00176 return (m_dirs.size() != 0);
00177 }
00178
00179
00180 }
00181 }
00182