X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f2e582dda83281f8b9422fc2fcd9b6ec5fd82352..2e14066008229145e2da7b9f05a478ce38631f83:/src/common/tarstrm.cpp?ds=sidebyside diff --git a/src/common/tarstrm.cpp b/src/common/tarstrm.cpp index 38020b7d25..9a6d851a0e 100644 --- a/src/common/tarstrm.cpp +++ b/src/common/tarstrm.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: tarstrm.cpp +// Name: src/common/tarstrm.cpp // Purpose: Streams for Tar files // Author: Mike Wetherell // RCS-ID: $Id$ @@ -26,7 +26,7 @@ #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" @@ -104,9 +104,9 @@ wxTarClassFactory::wxTarClassFactory() 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) { @@ -161,23 +161,23 @@ wxDEFINE_SCOPED_PTR_TYPE(wxTarHeaderBlock) // 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 } }; @@ -230,7 +230,7 @@ wxUint32 wxTarHeaderBlock::SumField(int id) } bool wxTarHeaderBlock::Read(wxInputStream& in) -{ +{ bool ok = true; for (int id = 0; id < TAR_NUMFIELDS && ok; id++) @@ -268,7 +268,7 @@ wxTarNumber wxTarHeaderBlock::GetOctal(int 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) { @@ -314,7 +314,7 @@ bool wxTarHeaderBlock::SetPath(const wxString& name, wxMBConv& conv) for (;;) { fits = i < maxprefix && len - i <= maxname; - + if (!fits) { const char *p = strchr(mbName + i, '/'); if (p) @@ -336,7 +336,7 @@ bool wxTarHeaderBlock::SetPath(const wxString& name, wxMBConv& conv) return fits && !badconv; } - + ///////////////////////////////////////////////////////////////////////////// // Some helpers @@ -362,7 +362,8 @@ static wxString wxTarUserName(int uid) 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) @@ -384,7 +385,8 @@ static wxString wxTarGroupName(int gid) 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) @@ -537,15 +539,15 @@ wxString wxTarEntry::GetName(wxPathFormat format /*=wxPATH_NATIVE*/) const 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: ; @@ -592,9 +594,9 @@ wxString wxTarEntry::GetInternalName(const wxString& name, 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; @@ -627,7 +629,7 @@ int wxTarEntry::GetMode() const return m_Mode; else return m_Mode | 0111; - + } void wxTarEntry::SetMode(int mode) @@ -693,9 +695,9 @@ wxTarEntry *wxTarInputStream::GetNextEntry() 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(); @@ -791,7 +793,9 @@ wxStreamError wxTarInputStream::ReadHeaders() 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; @@ -864,7 +868,7 @@ wxString wxTarInputStream::GetHeaderPath() const { wxString path; - if ((path = GetExtendedHeader(_T("path"))) != wxEmptyString) + if ((path = GetExtendedHeader(wxT("path"))) != wxEmptyString) return path; path = wxString(m_hdr->Get(TAR_NAME), GetConv()); @@ -872,7 +876,7 @@ wxString wxTarInputStream::GetHeaderPath() const 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 @@ -886,7 +890,7 @@ 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(); @@ -943,13 +947,13 @@ bool wxTarInputStream::ReadExtendedHeader(wxTarHeaderRecords*& recs) 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 @@ -983,7 +987,7 @@ bool wxTarInputStream::ReadExtendedHeader(wxTarHeaderRecords*& recs) if (value.empty()) recs->erase(key); else - (*recs)[key] = value; + (*recs)[key] = value; } if (!ok || recPos < len || size != lastread) { @@ -1032,13 +1036,15 @@ size_t wxTarInputStream::OnSysRead(void *buffer, size_t size) 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; } @@ -1083,12 +1089,12 @@ void wxTarOutputStream::Init(wxTarFormat format) m_extendedHdr = NULL; m_extendedSize = 0; m_lasterror = m_parent_o_stream->GetLastError(); + m_endrecWritten = false; } wxTarOutputStream::~wxTarOutputStream() { - if (m_tarsize) - Close(); + Close(); delete m_hdr; delete m_hdr2; delete [] m_extendedHdr; @@ -1207,7 +1213,7 @@ bool wxTarOutputStream::CloseEntry() bool wxTarOutputStream::Close() { - if (!CloseEntry()) + if (!CloseEntry() || (m_tarsize == 0 && m_endrecWritten)) return false; memset(m_hdr, 0, sizeof(*m_hdr)); @@ -1219,6 +1225,7 @@ bool wxTarOutputStream::Close() m_tarsize = 0; m_tarstart = wxInvalidOffset; m_lasterror = m_parent_o_stream->GetLastError(); + m_endrecWritten = true; return IsOk(); } @@ -1236,16 +1243,16 @@ bool wxTarOutputStream::WriteHeaders(wxTarEntry& entry) 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()); @@ -1254,7 +1261,7 @@ bool wxTarOutputStream::WriteHeaders(wxTarEntry& entry) 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); @@ -1275,7 +1282,7 @@ bool wxTarOutputStream::WriteHeaders(wxTarEntry& entry) // 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)); @@ -1285,7 +1292,7 @@ bool wxTarOutputStream::WriteHeaders(wxTarEntry& entry) 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)); @@ -1300,6 +1307,11 @@ bool wxTarOutputStream::WriteHeaders(wxTarEntry& entry) 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 @@ -1309,7 +1321,7 @@ bool wxTarOutputStream::WriteHeaders(wxTarEntry& entry) 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(); @@ -1320,12 +1332,12 @@ bool wxTarOutputStream::WriteHeaders(wxTarEntry& entry) 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); @@ -1341,7 +1353,7 @@ wxString wxTarOutputStream::PaxHeaderPath(const wxString& format, 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; } @@ -1386,7 +1398,7 @@ bool wxTarOutputStream::ModifyHeader() 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) @@ -1412,13 +1424,13 @@ void wxTarOutputStream::SetHeaderDate(const wxString& key, 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, '.'); @@ -1480,7 +1492,7 @@ void wxTarOutputStream::SetExtendedHeader(const wxString& key, 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; } }