#include "wx/buffer.h"
#include "wx/datetime.h"
-#include "wx/ptr_scpd.h"
+#include "wx/scopedptr.h"
#include "wx/filename.h"
#include "wx/thread.h"
const wxChar * const *
wxTarClassFactory::GetProtocols(wxStreamProtocolType type) const
{
- static const wxChar *protocols[] = { _T("tar"), NULL };
- static const wxChar *mimetypes[] = { _T("application/x-tar"), NULL };
- static const wxChar *fileexts[] = { _T(".tar"), NULL };
+ static const wxChar *protocols[] = { wxT("tar"), NULL };
+ static const wxChar *mimetypes[] = { wxT("application/x-tar"), NULL };
+ static const wxChar *fileexts[] = { wxT(".tar"), NULL };
static const wxChar *empty[] = { NULL };
switch (type) {
// A table giving the field names and offsets in a tar header block
const wxTarField wxTarHeaderBlock::fields[] =
{
- { _T("name"), 0 }, // 100
- { _T("mode"), 100 }, // 8
- { _T("uid"), 108 }, // 8
- { _T("gid"), 116 }, // 8
- { _T("size"), 124 }, // 12
- { _T("mtime"), 136 }, // 12
- { _T("chksum"), 148 }, // 8
- { _T("typeflag"), 156 }, // 1
- { _T("linkname"), 157 }, // 100
- { _T("magic"), 257 }, // 6
- { _T("version"), 263 }, // 2
- { _T("uname"), 265 }, // 32
- { _T("gname"), 297 }, // 32
- { _T("devmajor"), 329 }, // 8
- { _T("devminor"), 337 }, // 8
- { _T("prefix"), 345 }, // 155
- { _T("unused"), 500 }, // 12
+ { wxT("name"), 0 }, // 100
+ { wxT("mode"), 100 }, // 8
+ { wxT("uid"), 108 }, // 8
+ { wxT("gid"), 116 }, // 8
+ { wxT("size"), 124 }, // 12
+ { wxT("mtime"), 136 }, // 12
+ { wxT("chksum"), 148 }, // 8
+ { wxT("typeflag"), 156 }, // 1
+ { wxT("linkname"), 157 }, // 100
+ { wxT("magic"), 257 }, // 6
+ { wxT("version"), 263 }, // 2
+ { wxT("uname"), 265 }, // 32
+ { wxT("gname"), 297 }, // 32
+ { wxT("devmajor"), 329 }, // 8
+ { wxT("devminor"), 337 }, // 8
+ { wxT("prefix"), 345 }, // 155
+ { wxT("unused"), 500 }, // 12
{ NULL, TAR_BLOCKSIZE }
};
}
bool wxTarHeaderBlock::Read(wxInputStream& in)
-{
+{
bool ok = true;
for (int id = 0; id < TAR_NUMFIELDS && ok; id++)
bool wxTarHeaderBlock::SetOctal(int id, wxTarNumber n)
{
// set an octal field, return true if the number fits
- char *field = Get(id);
+ char *field = Get(id);
char *p = field + Len(id);
*--p = 0;
while (p > field) {
for (;;) {
fits = i < maxprefix && len - i <= maxname;
-
+
if (!fits) {
const char *p = strchr(mbName + i, '/');
if (p)
return fits && !badconv;
}
-
+
/////////////////////////////////////////////////////////////////////////////
// Some helpers
wxCharBuffer buf(bufsize);
struct passwd pw;
- if (getpwuid_r(uid, &pw, buf.data(), bufsize, &ppw) == 0)
+ memset(&pw, 0, sizeof(pw));
+ if (getpwuid_r(uid, &pw, buf.data(), bufsize, &ppw) == 0 && pw.pw_name)
return wxString(pw.pw_name, wxConvLibc);
#else
if ((ppw = getpwuid(uid)) != NULL)
wxCharBuffer buf(bufsize);
struct group gr;
- if (getgrgid_r(gid, &gr, buf.data(), bufsize, &pgr) == 0)
+ memset(&gr, 0, sizeof(gr));
+ if (getgrgid_r(gid, &gr, buf.data(), bufsize, &pgr) == 0 && gr.gr_name)
return wxString(gr.gr_name, wxConvLibc);
#else
if ((pgr = getgrgid(gid)) != NULL)
switch (wxFileName::GetFormat(format)) {
case wxPATH_DOS:
{
- wxString name(isDir ? m_Name + _T("\\") : m_Name);
+ wxString name(isDir ? m_Name + wxT("\\") : m_Name);
for (size_t i = 0; i < name.length(); i++)
- if (name[i] == _T('/'))
- name[i] = _T('\\');
+ if (name[i] == wxT('/'))
+ name[i] = wxT('\\');
return name;
}
case wxPATH_UNIX:
- return isDir ? m_Name + _T("/") : m_Name;
+ return isDir ? m_Name + wxT("/") : m_Name;
default:
;
while (!internal.empty() && *internal.begin() == '/')
internal.erase(0, 1);
- while (!internal.empty() && internal.compare(0, 2, _T("./")) == 0)
+ while (!internal.empty() && internal.compare(0, 2, wxT("./")) == 0)
internal.erase(0, 2);
- if (internal == _T(".") || internal == _T(".."))
+ if (internal == wxT(".") || internal == wxT(".."))
internal = wxEmptyString;
return internal;
return m_Mode;
else
return m_Mode | 0111;
-
+
}
void wxTarEntry::SetMode(int mode)
entry->SetOffset(m_offset);
- entry->SetDateTime(GetHeaderDate(_T("mtime")));
- entry->SetAccessTime(GetHeaderDate(_T("atime")));
- entry->SetCreateTime(GetHeaderDate(_T("ctime")));
+ entry->SetDateTime(GetHeaderDate(wxT("mtime")));
+ entry->SetAccessTime(GetHeaderDate(wxT("atime")));
+ entry->SetCreateTime(GetHeaderDate(wxT("ctime")));
entry->SetTypeFlag(*m_hdr->Get(TAR_TYPEFLAG));
bool isDir = entry->IsDir();
while (!done) {
m_hdr->Read(*m_parent_i_stream);
if (m_parent_i_stream->Eof())
+ {
wxLogError(_("incomplete header block in tar"));
+ }
if (!*m_parent_i_stream)
return wxSTREAM_READ_ERROR;
m_offset += TAR_BLOCKSIZE;
{
wxString path;
- if ((path = GetExtendedHeader(_T("path"))) != wxEmptyString)
+ if ((path = GetExtendedHeader(wxT("path"))) != wxEmptyString)
return path;
path = wxString(m_hdr->Get(TAR_NAME), GetConv());
return path;
const char *prefix = m_hdr->Get(TAR_PREFIX);
- return *prefix ? wxString(prefix, GetConv()) + _T("/") + path : path;
+ return *prefix ? wxString(prefix, GetConv()) + wxT("/") + path : path;
}
wxDateTime wxTarInputStream::GetHeaderDate(const wxString& key) const
return ll;
}
- if (key == _T("mtime"))
+ if (key == wxT("mtime"))
return wxLongLong(m_hdr->GetOctal(TAR_MTIME)) * 1000L;
return wxDateTime();
size_t recPos, recSize;
bool ok = true;
- for (recPos = 0; recPos < len; recPos += recSize) {
+ for (recPos = 0; recPos < len && ok; recPos += recSize) {
char *pRec = buf.data() + recPos;
char *p = pRec;
// read the record size (byte count in ascii decimal)
recSize = 0;
- while (isdigit(*p))
+ while (isdigit((unsigned char) *p))
recSize = recSize * 10 + *p++ - '0';
// validity checks
if (value.empty())
recs->erase(key);
else
- (*recs)[key] = value;
+ (*recs)[key] = value;
}
if (!ok || recPos < len || size != lastread) {
size_t lastread = m_parent_i_stream->Read(buffer, size).LastRead();
m_pos += lastread;
-
+
if (m_pos >= m_size) {
m_lasterror = wxSTREAM_EOF;
} else if (!m_parent_i_stream->IsOk()) {
// any other error will have been reported by the underlying stream
if (m_parent_i_stream->Eof())
+ {
wxLogError(_("unexpected end of file"));
+ }
m_lasterror = wxSTREAM_READ_ERROR;
}
{
if (!CloseEntry() || (m_tarsize == 0 && m_endrecWritten))
return false;
-
+
memset(m_hdr, 0, sizeof(*m_hdr));
int count = (RoundUpSize(m_tarsize + 2 * TAR_BLOCKSIZE, m_BlockingFactor)
- m_tarsize) / TAR_BLOCKSIZE;
entry.SetSize(0);
m_large = !SetHeaderNumber(TAR_SIZE, entry.GetSize());
- SetHeaderDate(_T("mtime"), entry.GetDateTime());
+ SetHeaderDate(wxT("mtime"), entry.GetDateTime());
if (entry.GetAccessTime().IsValid())
- SetHeaderDate(_T("atime"), entry.GetAccessTime());
+ SetHeaderDate(wxT("atime"), entry.GetAccessTime());
if (entry.GetCreateTime().IsValid())
- SetHeaderDate(_T("ctime"), entry.GetCreateTime());
+ SetHeaderDate(wxT("ctime"), entry.GetCreateTime());
*m_hdr->Get(TAR_TYPEFLAG) = char(entry.GetTypeFlag());
strcpy(m_hdr->Get(TAR_MAGIC), USTAR_MAGIC);
- strcpy(m_hdr->Get(TAR_VERSION), USTAR_VERSION);
+ strcpy(m_hdr->Get(TAR_VERSION), USTAR_VERSION);
SetHeaderString(TAR_LINKNAME, entry.GetLinkName());
SetHeaderString(TAR_UNAME, entry.GetUserName());
if (~entry.GetDevMajor())
SetHeaderNumber(TAR_DEVMAJOR, entry.GetDevMajor());
if (~entry.GetDevMinor())
- SetHeaderNumber(TAR_DEVMINOR, entry.GetDevMinor());
+ SetHeaderNumber(TAR_DEVMINOR, entry.GetDevMinor());
m_chksum = m_hdr->Sum();
m_hdr->SetOctal(TAR_CHKSUM, m_chksum);
// an old tar that doesn't understand extended headers will
// extract it as a file, so give these fields reasonable values
// so that the user will have access to read and remove it.
- m_hdr2->SetPath(PaxHeaderPath(_T("%d/PaxHeaders.%p/%f"),
+ m_hdr2->SetPath(PaxHeaderPath(wxT("%d/PaxHeaders.%p/%f"),
entry.GetName(wxPATH_UNIX)), GetConv());
m_hdr2->SetOctal(TAR_MODE, 0600);
strcpy(m_hdr2->Get(TAR_UID), m_hdr->Get(TAR_UID));
strcpy(m_hdr2->Get(TAR_MTIME), m_hdr->Get(TAR_MTIME));
*m_hdr2->Get(TAR_TYPEFLAG) = 'x';
strcpy(m_hdr2->Get(TAR_MAGIC), USTAR_MAGIC);
- strcpy(m_hdr2->Get(TAR_VERSION), USTAR_VERSION);
+ strcpy(m_hdr2->Get(TAR_VERSION), USTAR_VERSION);
strcpy(m_hdr2->Get(TAR_UNAME), m_hdr->Get(TAR_UNAME));
strcpy(m_hdr2->Get(TAR_GNAME), m_hdr->Get(TAR_GNAME));
m_tarsize += rounded;
*m_extendedHdr = 0;
+
+ // update m_headpos which is used to seek back to fix up the file
+ // length if it is not known in advance
+ if (m_tarstart != wxInvalidOffset)
+ m_headpos = m_tarstart + m_tarsize;
}
// if don't have extended headers just report error
m_badfit.c_str(), entry.GetName().c_str());
m_badfit.clear();
}
-
+
m_hdr->Write(*m_parent_o_stream);
m_tarsize += TAR_BLOCKSIZE;
m_lasterror = m_parent_o_stream->GetLastError();
wxString wxTarOutputStream::PaxHeaderPath(const wxString& format,
const wxString& path)
{
- wxString d = path.BeforeLast(_T('/'));
- wxString f = path.AfterLast(_T('/'));
+ wxString d = path.BeforeLast(wxT('/'));
+ wxString f = path.AfterLast(wxT('/'));
wxString ret;
-
+
if (d.empty())
- d = _T(".");
+ d = wxT(".");
ret.reserve(format.length() + path.length() + 16);
case 'd': ret << d; break;
case 'f': ret << f; break;
case 'p': ret << wxGetProcessId(); break;
- case '%': ret << _T("%"); break;
+ case '%': ret << wxT("%"); break;
}
begin = end + 2;
}
void wxTarOutputStream::SetHeaderPath(const wxString& name)
{
if (!m_hdr->SetPath(name, GetConv()) || (m_pax && !name.IsAscii()))
- SetExtendedHeader(_T("path"), name);
+ SetExtendedHeader(wxT("path"), name);
}
bool wxTarOutputStream::SetHeaderNumber(int id, wxTarNumber n)
wxLongLong ll = datetime.IsValid() ? datetime.GetValue() : wxLongLong(0);
wxLongLong secs = ll / 1000L;
- if (key != _T("mtime")
+ if (key != wxT("mtime")
|| !m_hdr->SetOctal(TAR_MTIME, wxTarNumber(secs.GetValue()))
|| secs <= 0 || secs >= 0x7fffffff)
{
wxString str;
if (ll >= LONG_MIN && ll <= LONG_MAX) {
- str.Printf(_T("%g"), ll.ToLong() / 1000.0);
+ str.Printf(wxT("%g"), ll.ToLong() / 1000.0);
} else {
str = ll.ToString();
str.insert(str.end() - 3, '.');
else {
// if not pax then make a list of fields to report as errors
if (!m_badfit.empty())
- m_badfit += _T(", ");
+ m_badfit += wxT(", ");
m_badfit += key;
}
}