~efargaspro/+junk/codeblocks-16.01-release

« back to all changes in this revision

Viewing changes to src/plugins/contrib/devpak_plugin/mytar.cpp

  • Committer: damienlmoore at gmail
  • Date: 2016-02-02 02:43:22 UTC
  • Revision ID: damienlmoore@gmail.com-20160202024322-yql5qmtbwdyamdwd
Code::BlocksĀ 16.01

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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
 
4
 *
 
5
 * $Revision: 7109 $
 
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 $
 
8
 */
 
9
 
 
10
#include "mytar.h"
 
11
#include <io.h>
 
12
#include <globals.h>
 
13
#include <wx/intl.h>
 
14
#include <wx/arrimpl.cpp>
 
15
WX_DEFINE_OBJARRAY(ReplacersArray);
 
16
 
 
17
TAR::TAR(const wxString& filename)
 
18
    : m_pFile(0),
 
19
    m_SkipBytes(0),
 
20
    m_Size(0)
 
21
{
 
22
    if (!filename.IsEmpty())
 
23
        Open(filename);
 
24
}
 
25
 
 
26
TAR::~TAR()
 
27
{
 
28
    Close();
 
29
}
 
30
 
 
31
bool TAR::Open(const wxString& filename)
 
32
{
 
33
    if (filename.IsEmpty())
 
34
        return false;
 
35
    Close();
 
36
 
 
37
    m_pFile = fopen(filename.mb_str(), "rb");
 
38
    if (!m_pFile)
 
39
        return false;
 
40
 
 
41
    fseek(m_pFile, 0, SEEK_END);
 
42
    m_Size = ftell(m_pFile);
 
43
    fseek(m_pFile, 0, SEEK_SET);
 
44
 
 
45
    return true;
 
46
}
 
47
 
 
48
void TAR::Close()
 
49
{
 
50
    if (m_pFile)
 
51
        fclose(m_pFile);
 
52
    m_pFile = 0;
 
53
    Reset();
 
54
    m_Size = 0;
 
55
}
 
56
 
 
57
void TAR::Reset()
 
58
{
 
59
    if (m_pFile)
 
60
        fseek(m_pFile, 0, SEEK_SET);
 
61
    m_SkipBytes = 0;
 
62
}
 
63
 
 
64
int TAR::OctToInt(const char* oct)
 
65
{
 
66
        int i = 0;
 
67
        if (sscanf(oct, "%o", &i) != 1)
 
68
        i = 0;
 
69
//        return 1;
 
70
    return i;
 
71
}
 
72
 
 
73
size_t TAR::OffsetRecords(size_t bytes)
 
74
{
 
75
    size_t i = bytes / sizeof(TAR::Header);
 
76
    if (bytes % sizeof(TAR::Header) > 0)
 
77
        ++i;
 
78
    return i;
 
79
}
 
80
 
 
81
bool TAR::Next(TAR::Record* rec)
 
82
{
 
83
    if (!rec)
 
84
        return false;
 
85
    rec->name.Clear();
 
86
    rec->size = 0;
 
87
    rec->pos = 0;
 
88
    if (m_SkipBytes > 0)
 
89
        fseek(m_pFile, OffsetRecords(m_SkipBytes) * sizeof(TAR::Header), SEEK_CUR);
 
90
    TAR::Header buffer;
 
91
    memset(&buffer, 0, sizeof(TAR::Header));
 
92
 
 
93
    // reached end of file?
 
94
    size_t pos = ftell(m_pFile);
 
95
    if (pos + sizeof(buffer) > m_Size)
 
96
        return false; // yes
 
97
    if (fread(&buffer, sizeof(buffer), 1, m_pFile) != 1)
 
98
        return false;
 
99
 
 
100
    rec->pos = pos;
 
101
    rec->name = cbC2U(buffer.name);
 
102
    rec->size = OctToInt(buffer.size);
 
103
 
 
104
#if 1
 
105
    // many DevPaks, end with a single null record...
 
106
    if (buffer.name[0] == 0)
 
107
        return false;
 
108
#else // 0
 
109
    // 2 consecutive nulls means EOT
 
110
    static bool previousWasNull = false;
 
111
    if (rec->name.IsEmpty())
 
112
    {
 
113
        rec->name.Clear();
 
114
        if (previousWasNull)
 
115
            return false; // EOT
 
116
        else
 
117
        {
 
118
            previousWasNull = true;
 
119
            m_SkipBytes = rec->size;
 
120
            return true;
 
121
        }
 
122
    }
 
123
    else
 
124
        previousWasNull = false; // reset flag
 
125
#endif // 0
 
126
 
 
127
    switch (buffer.typeflag)
 
128
    {
 
129
        case 0:
 
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;
 
143
        default: break;
 
144
    }
 
145
 
 
146
    switch (rec->ft)
 
147
    {
 
148
        case ftLink:
 
149
        case ftSymbolicLink:
 
150
        case ftDirectory:
 
151
        case ftFifo:
 
152
        case ftVolumeHeader:
 
153
            m_SkipBytes = 0;
 
154
            break;
 
155
        default:
 
156
            m_SkipBytes = rec->size;
 
157
            break;
 
158
    }
 
159
    return true;
 
160
}
 
161
 
 
162
bool TAR::ExtractAll(const wxString& dirname, wxString& status, wxArrayString* files)
 
163
{
 
164
    Reset();
 
165
    status.Clear();
 
166
    if (files)
 
167
        files->Clear();
 
168
    TAR::Record r;
 
169
    while (Next(&r))
 
170
    {
 
171
        wxString convertedFile;
 
172
        if (!ExtractFile(&r, dirname, status, &convertedFile))
 
173
        {
 
174
            status << _("Failed extracting") << _T(" \"") << r.name << _T("\"\n");
 
175
            return false;
 
176
        }
 
177
        if (files && !convertedFile.IsEmpty())
 
178
            files->Add(convertedFile);
 
179
    }
 
180
    return true;
 
181
}
 
182
 
 
183
void TAR::ClearReplacers()
 
184
{
 
185
    m_Replacers.Clear();
 
186
}
 
187
 
 
188
void TAR::AddReplacer(const wxString& from, const wxString& to)
 
189
{
 
190
    Replacers r;
 
191
    r.from = from;
 
192
    if (r.from.Last() != _T('/'))
 
193
        r.from << _T('/');
 
194
    r.to = to;
 
195
    r.to.Replace(_T("<app>"), _T(""));
 
196
 
 
197
    // avoid duplicates
 
198
    for (unsigned int i = 0; i < m_Replacers.GetCount(); ++i)
 
199
    {
 
200
        if (m_Replacers[i].from == r.from)
 
201
            return;
 
202
    }
 
203
 
 
204
    m_Replacers.Add(r);
 
205
}
 
206
 
 
207
void TAR::ReplaceThings(wxString& path)
 
208
{
 
209
    while (path.Replace(_T("\\"), _T("/")))
 
210
        ;
 
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("/")))
 
214
        ;
 
215
    while (path.Replace(_T("//"), _T("/")))
 
216
        ;
 
217
}
 
218
 
 
219
bool TAR::ExtractFile(Record* rec, const wxString& dirname, wxString& status, wxString* convertedFile)
 
220
{
 
221
    if (!rec)
 
222
        return false;
 
223
 
 
224
    if (convertedFile)
 
225
        convertedFile->Clear();
 
226
    wxString path;
 
227
    if (rec->name.IsEmpty())
 
228
        return true;
 
229
    if (!dirname.IsEmpty())
 
230
    {
 
231
        path << dirname << _T("/");
 
232
    }
 
233
    path << rec->name;
 
234
    ReplaceThings(path);
 
235
 
 
236
    switch (rec->ft)
 
237
    {
 
238
        case ftNormal:
 
239
        {
 
240
            CreateDirRecursively(path);
 
241
            status << _("Unpacking ") << path << _T('\n');
 
242
            if (convertedFile)
 
243
                *convertedFile = path;
 
244
 
 
245
            FILE* out = fopen(path.mb_str(), "wb");
 
246
            if (!out)
 
247
            {
 
248
                status << wxString(_("Can't open file ")) << path << _T("\n");
 
249
                return false;
 
250
            }
 
251
            if (rec->size > 0)
 
252
            {
 
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)
 
257
                {
 
258
                    delete[] buffer;
 
259
                    fclose(out);
 
260
                    fseek(m_pFile, oldpos, SEEK_SET);
 
261
                    status << _("Failure reading file ") << path << _T("\n");
 
262
                    return false;
 
263
                }
 
264
                fwrite(buffer, rec->size, 1, out);
 
265
                delete[] buffer;
 
266
                fseek(m_pFile, oldpos, SEEK_SET);
 
267
            }
 
268
            fclose(out);
 
269
            break;
 
270
        }
 
271
 
 
272
        default: break;
 
273
    }
 
274
 
 
275
    return true;
 
276
}
 
277
 
 
278
TAR::Record* TAR::FindFile(const wxString& filename)
 
279
{
 
280
    if (filename.IsEmpty())
 
281
        return 0;
 
282
    Reset();
 
283
    static TAR::Record r;
 
284
    while (Next(&r))
 
285
    {
 
286
        if (r.name.CmpNoCase(filename) == 0 ||
 
287
            r.name.Matches(filename)) // support wildcards
 
288
        {
 
289
            return &r;
 
290
        }
 
291
    }
 
292
    return 0;
 
293
}