2
* This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3
* http://www.gnu.org/licenses/gpl-3.0.html
6
* $Id: mytar.cpp 7109 2011-04-15 11:53:16Z mortenmacfly $
7
* $HeadURL: http://svn.code.sf.net/p/codeblocks/code/branches/release-16.xx/src/plugins/contrib/devpak_plugin/mytar.cpp $
14
#include <wx/arrimpl.cpp>
15
WX_DEFINE_OBJARRAY(ReplacersArray);
17
TAR::TAR(const wxString& filename)
22
if (!filename.IsEmpty())
31
bool TAR::Open(const wxString& filename)
33
if (filename.IsEmpty())
37
m_pFile = fopen(filename.mb_str(), "rb");
41
fseek(m_pFile, 0, SEEK_END);
42
m_Size = ftell(m_pFile);
43
fseek(m_pFile, 0, SEEK_SET);
60
fseek(m_pFile, 0, SEEK_SET);
64
int TAR::OctToInt(const char* oct)
67
if (sscanf(oct, "%o", &i) != 1)
73
size_t TAR::OffsetRecords(size_t bytes)
75
size_t i = bytes / sizeof(TAR::Header);
76
if (bytes % sizeof(TAR::Header) > 0)
81
bool TAR::Next(TAR::Record* rec)
89
fseek(m_pFile, OffsetRecords(m_SkipBytes) * sizeof(TAR::Header), SEEK_CUR);
91
memset(&buffer, 0, sizeof(TAR::Header));
93
// reached end of file?
94
size_t pos = ftell(m_pFile);
95
if (pos + sizeof(buffer) > m_Size)
97
if (fread(&buffer, sizeof(buffer), 1, m_pFile) != 1)
101
rec->name = cbC2U(buffer.name);
102
rec->size = OctToInt(buffer.size);
105
// many DevPaks, end with a single null record...
106
if (buffer.name[0] == 0)
109
// 2 consecutive nulls means EOT
110
static bool previousWasNull = false;
111
if (rec->name.IsEmpty())
118
previousWasNull = true;
119
m_SkipBytes = rec->size;
124
previousWasNull = false; // reset flag
127
switch (buffer.typeflag)
130
case _T('0'): rec->ft = ftNormal; break;
131
case _T('1'): rec->ft = ftLink; break;
132
case _T('2'): rec->ft = ftSymbolicLink; break;
133
case _T('3'): rec->ft = ftCharacter; break;
134
case _T('4'): rec->ft = ftBlock; break;
135
case _T('5'): rec->ft = ftDirectory; break;
136
case _T('6'): rec->ft = ftFifo; break;
137
case _T('7'): rec->ft = ftContiguous; break;
138
case _T('D'): rec->ft = ftDumpDir; break;
139
case _T('M'): rec->ft = ftMultiVolume; break;
140
case _T('V'): rec->ft = ftVolumeHeader; break;
141
// case _T('L'): rec.ft = ftLongName; break;
142
// case _T('K'): rec.ft = ftLongLink; break;
156
m_SkipBytes = rec->size;
162
bool TAR::ExtractAll(const wxString& dirname, wxString& status, wxArrayString* files)
171
wxString convertedFile;
172
if (!ExtractFile(&r, dirname, status, &convertedFile))
174
status << _("Failed extracting") << _T(" \"") << r.name << _T("\"\n");
177
if (files && !convertedFile.IsEmpty())
178
files->Add(convertedFile);
183
void TAR::ClearReplacers()
188
void TAR::AddReplacer(const wxString& from, const wxString& to)
192
if (r.from.Last() != _T('/'))
195
r.to.Replace(_T("<app>"), _T(""));
198
for (unsigned int i = 0; i < m_Replacers.GetCount(); ++i)
200
if (m_Replacers[i].from == r.from)
207
void TAR::ReplaceThings(wxString& path)
209
while (path.Replace(_T("\\"), _T("/")))
211
for (unsigned int i = 0; i < m_Replacers.GetCount(); ++i)
212
path.Replace(m_Replacers[i].from, m_Replacers[i].to);
213
while (path.Replace(_T("\\"), _T("/")))
215
while (path.Replace(_T("//"), _T("/")))
219
bool TAR::ExtractFile(Record* rec, const wxString& dirname, wxString& status, wxString* convertedFile)
225
convertedFile->Clear();
227
if (rec->name.IsEmpty())
229
if (!dirname.IsEmpty())
231
path << dirname << _T("/");
240
CreateDirRecursively(path);
241
status << _("Unpacking ") << path << _T('\n');
243
*convertedFile = path;
245
FILE* out = fopen(path.mb_str(), "wb");
248
status << wxString(_("Can't open file ")) << path << _T("\n");
253
size_t oldpos = ftell(m_pFile);
254
char* buffer = new char[rec->size];
255
memset(buffer, 0, rec->size);
256
if (fread(buffer, rec->size, 1, m_pFile) != 1)
260
fseek(m_pFile, oldpos, SEEK_SET);
261
status << _("Failure reading file ") << path << _T("\n");
264
fwrite(buffer, rec->size, 1, out);
266
fseek(m_pFile, oldpos, SEEK_SET);
278
TAR::Record* TAR::FindFile(const wxString& filename)
280
if (filename.IsEmpty())
283
static TAR::Record r;
286
if (r.name.CmpNoCase(filename) == 0 ||
287
r.name.Matches(filename)) // support wildcards