]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/tarstrm.cpp
made wxApp::argv an object convertible to either char** or wchar_t** for better compa...
[wxWidgets.git] / src / common / tarstrm.cpp
index f3a1cec17a55214ce8ab5768d844c0c69d811f43..38020b7d25f132f7b7c85c8213a9bfa87eeedbad 100644 (file)
@@ -19,7 +19,6 @@
 #include "wx/tarstrm.h"
 
 #ifndef WX_PRECOMP
-    #include "wx/hashmap.h"
     #include "wx/intl.h"
     #include "wx/log.h"
     #include "wx/utils.h"
 #include "wx/datetime.h"
 #include "wx/ptr_scpd.h"
 #include "wx/filename.h"
+#include "wx/thread.h"
 
 #include <ctype.h>
 
 #ifdef __UNIX__
+#include <pwd.h>
 #include <grp.h>
 #endif
 
@@ -62,7 +63,7 @@ enum {
 };
 
 enum {
-    TAR_BLOCKSIZE = 512,
+    TAR_BLOCKSIZE = 512
 };
 
 // checksum type
@@ -109,10 +110,10 @@ wxTarClassFactory::GetProtocols(wxStreamProtocolType type) const
     static const wxChar *empty[]     = { NULL };
 
     switch (type) {
-        case wxSTREAM_PROTOCOL:         return protocols;
-        case wxSTREAM_MIMETYPE:         return mimetypes;
-        case wxSTREAM_FILEEXTENSION:    return fileexts;
-        default:                        return empty;
+        case wxSTREAM_PROTOCOL: return protocols;
+        case wxSTREAM_MIMETYPE: return mimetypes;
+        case wxSTREAM_FILEEXT:  return fileexts;
+        default:                return empty;
     }
 }
 
@@ -155,7 +156,7 @@ private:
     static void check();
 };
 
-wxDEFINE_SCOPED_PTR_TYPE(wxTarHeaderBlock);
+wxDEFINE_SCOPED_PTR_TYPE(wxTarHeaderBlock)
 
 // A table giving the field names and offsets in a tar header block
 const wxTarField wxTarHeaderBlock::fields[] =
@@ -182,10 +183,12 @@ const wxTarField wxTarHeaderBlock::fields[] =
 
 void wxTarHeaderBlock::check()
 {
+#if 0
     wxCOMPILE_TIME_ASSERT(
         WXSIZEOF(fields) == TAR_NUMFIELDS + 1,
         Wrong_number_of_elements_in_fields_table
     );
+#endif
 }
 
 bool wxTarHeaderBlock::IsAllZeros() const
@@ -246,7 +249,7 @@ bool wxTarHeaderBlock::Write(wxOutputStream& out)
     return ok;
 }
 
-bool wxTarHeaderBlock::WriteField(wxOutputStream& out, int id)
+inline bool wxTarHeaderBlock::WriteField(wxOutputStream& out, int id)
 {
     return out.Write(Get(id), Len(id)).LastWrite() == Len(id);
 }
@@ -269,7 +272,7 @@ bool wxTarHeaderBlock::SetOctal(int id, wxTarNumber n)
     char *p = field + Len(id);
     *--p = 0;
     while (p > field) {
-        *--p = '0' + (n & 7);
+        *--p = char('0' + (n & 7));
         n >>= 3;
     }
     return n == 0;
@@ -288,7 +291,10 @@ bool wxTarHeaderBlock::SetPath(const wxString& name, wxMBConv& conv)
         size_t len = name.length();
         wxCharBuffer approx(len);
         for (size_t i = 0; i < len; i++)
-            approx.data()[i] = name[i] & ~0x7F ? '_' : name[i];
+        {
+            wxChar c = name[i];
+            approx.data()[i] = c & ~0x7F ? '_' : c;
+        }
         nameBuf = approx;
     }
 
@@ -340,32 +346,99 @@ static wxFileOffset RoundUpSize(wxFileOffset size, int factor = 1)
     return ((size + chunk - 1) / chunk) * chunk;
 }
 
-static wxString GroupName()
-{
 #ifdef __UNIX__
-    group *gr;
-    if ((gr = getgrgid(getgid())) != NULL)
-        return wxString(gr->gr_name, wxConvLibc);
+
+static wxString wxTarUserName(int uid)
+{
+    struct passwd *ppw;
+
+#ifdef HAVE_GETPWUID_R
+#if defined HAVE_SYSCONF && defined _SC_GETPW_R_SIZE_MAX
+    long pwsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+    size_t bufsize(wxMin(wxMax(1024l, pwsize), 32768l));
+#else
+    size_t bufsize = 1024;
+#endif
+    wxCharBuffer buf(bufsize);
+    struct passwd pw;
+
+    if (getpwuid_r(uid, &pw, buf.data(), bufsize, &ppw) == 0)
+        return wxString(pw.pw_name, wxConvLibc);
+#else
+    if ((ppw = getpwuid(uid)) != NULL)
+        return wxString(ppw->pw_name, wxConvLibc);
 #endif
     return _("unknown");
 }
 
-static inline int UserId()
+static wxString wxTarGroupName(int gid)
 {
-#ifdef __UNIX__
-    return getuid();
+    struct group *pgr;
+#ifdef HAVE_GETGRGID_R
+#if defined HAVE_SYSCONF && defined _SC_GETGR_R_SIZE_MAX
+    long grsize = sysconf(_SC_GETGR_R_SIZE_MAX);
+    size_t bufsize(wxMin(wxMax(1024l, grsize), 32768l));
+#else
+    size_t bufsize = 1024;
+#endif
+    wxCharBuffer buf(bufsize);
+    struct group gr;
+
+    if (getgrgid_r(gid, &gr, buf.data(), bufsize, &pgr) == 0)
+        return wxString(gr.gr_name, wxConvLibc);
 #else
-    return 0;
+    if ((pgr = getgrgid(gid)) != NULL)
+        return wxString(pgr->gr_name, wxConvLibc);
 #endif
+    return _("unknown");
 }
 
-static inline int GroupId()
+#endif  // __UNIX__
+
+// Cache the user and group names since getting them can be expensive,
+// get both names and ids at the same time.
+//
+struct wxTarUser
+{
+    wxTarUser();
+    ~wxTarUser() { delete [] uname; delete [] gname; }
+
+    int uid;
+    int gid;
+
+    wxChar *uname;
+    wxChar *gname;
+};
+
+wxTarUser::wxTarUser()
 {
 #ifdef __UNIX__
-    return getgid();
+    uid = getuid();
+    gid = getgid();
+    wxString usr = wxTarUserName(uid);
+    wxString grp = wxTarGroupName(gid);
 #else
-    return 0;
+    uid = 0;
+    gid = 0;
+    wxString usr = wxGetUserId();
+    wxString grp = _("unknown");
+#endif
+
+    uname = new wxChar[usr.length() + 1];
+    wxStrcpy(uname, usr.c_str());
+
+    gname = new wxChar[grp.length() + 1];
+    wxStrcpy(gname, grp.c_str());
+}
+
+static const wxTarUser& wxGetTarUser()
+{
+#if wxUSE_THREADS
+    static wxCriticalSection cs;
+    wxCriticalSectionLocker lock(cs);
 #endif
+    static wxTarUser tu;
+    return tu;
 }
 
 // ignore the size field for entry types 3, 4, 5 and 6
@@ -380,7 +453,7 @@ static inline wxFileOffset GetDataSize(const wxTarEntry& entry)
             return 0;
         default:
             return entry.GetSize();
-    };
+    }
 }
 
 
@@ -393,14 +466,14 @@ wxTarEntry::wxTarEntry(const wxString& name /*=wxEmptyString*/,
                        wxFileOffset size    /*=0*/)
   : m_Mode(0644),
     m_IsModeSet(false),
-    m_UserId(UserId()),
-    m_GroupId(GroupId()),
+    m_UserId(wxGetTarUser().uid),
+    m_GroupId(wxGetTarUser().gid),
     m_Size(size),
     m_Offset(wxInvalidOffset),
     m_ModifyTime(dt),
     m_TypeFlag(wxTAR_REGTYPE),
-    m_UserName(wxGetUserId()),
-    m_GroupName(GroupName()),
+    m_UserName(wxGetTarUser().uname),
+    m_GroupName(wxGetTarUser().gname),
     m_DevMajor(~0),
     m_DevMinor(~0)
 {
@@ -413,7 +486,8 @@ wxTarEntry::~wxTarEntry()
 }
 
 wxTarEntry::wxTarEntry(const wxTarEntry& e)
-  : m_Name(e.m_Name),
+  : wxArchiveEntry(),
+    m_Name(e.m_Name),
     m_Mode(e.m_Mode),
     m_IsModeSet(e.m_IsModeSet),
     m_UserId(e.m_UserId),
@@ -528,14 +602,14 @@ wxString wxTarEntry::GetInternalName(const wxString& name,
 
 bool wxTarEntry::IsDir() const
 {
-    return m_TypeFlag - wxTAR_DIRTYPE == 0;
+    return m_TypeFlag == wxTAR_DIRTYPE;
 }
 
 void wxTarEntry::SetIsDir(bool isDir)
 {
     if (isDir)
         m_TypeFlag = wxTAR_DIRTYPE;
-    else if (m_TypeFlag - wxTAR_DIRTYPE == 0)
+    else if (m_TypeFlag == wxTAR_DIRTYPE)
         m_TypeFlag = wxTAR_REGTYPE;
 }
 
@@ -569,8 +643,6 @@ void wxTarEntry::SetMode(int mode)
 wxDECLARE_SCOPED_PTR(wxTarEntry, wxTarEntryPtr_)
 wxDEFINE_SCOPED_PTR (wxTarEntry, wxTarEntryPtr_)
 
-WX_DECLARE_STRING_HASH_MAP(wxString, wxTarHeaderRecords);
-
 wxTarInputStream::wxTarInputStream(wxInputStream& stream,
                                    wxMBConv& conv /*=wxConvLocal*/)
  :  wxArchiveInputStream(stream, conv)
@@ -826,8 +898,8 @@ wxTarNumber wxTarInputStream::GetHeaderNumber(int id) const
 
     if ((value = GetExtendedHeader(m_hdr->Name(id))) != wxEmptyString) {
         wxTarNumber n = 0;
-        const wxChar *p = value;
-        while (*p == ' ')
+        wxString::const_iterator p = value.begin();
+        while (*p == ' ' && p != value.end())
             p++;
         while (isdigit(*p))
             n = n * 10 + (*p++ - '0');
@@ -1049,10 +1121,10 @@ bool wxTarOutputStream::PutNextEntry(wxTarEntry *entry)
             wxTAR_LNKTYPE, wxTAR_SYMTYPE, wxTAR_CHRTYPE, wxTAR_BLKTYPE,
             wxTAR_DIRTYPE, wxTAR_FIFOTYPE, 0
         };
-        char typeflag = e->GetTypeFlag();
+        int typeflag = e->GetTypeFlag();
 
         // pax does now allow data for wxTAR_LNKTYPE
-        if (!m_pax || typeflag - wxTAR_LNKTYPE != 0)
+        if (!m_pax || typeflag != wxTAR_LNKTYPE)
             if (strchr(nodata, typeflag) != NULL)
                 CloseEntry();
     }
@@ -1162,7 +1234,7 @@ bool wxTarOutputStream::WriteHeaders(wxTarEntry& entry)
 
     if (entry.GetSize() == wxInvalidOffset)
         entry.SetSize(0);
-    m_large = SetHeaderNumber(TAR_SIZE, entry.GetSize());
+    m_large = !SetHeaderNumber(TAR_SIZE, entry.GetSize());
 
     SetHeaderDate(_T("mtime"), entry.GetDateTime());
     if (entry.GetAccessTime().IsValid())
@@ -1170,7 +1242,7 @@ bool wxTarOutputStream::WriteHeaders(wxTarEntry& entry)
     if (entry.GetCreateTime().IsValid())
         SetHeaderDate(_T("ctime"), entry.GetCreateTime());
 
-    *m_hdr->Get(TAR_TYPEFLAG) = entry.GetTypeFlag();
+    *m_hdr->Get(TAR_TYPEFLAG) = char(entry.GetTypeFlag());
 
     strcpy(m_hdr->Get(TAR_MAGIC), USTAR_MAGIC);
     strcpy(m_hdr->Get(TAR_VERSION), USTAR_VERSION); 
@@ -1265,7 +1337,7 @@ wxString wxTarOutputStream::PaxHeaderPath(const wxString& format,
         if (end == wxString::npos || end + 1 >= format.length())
             break;
         ret << format.substr(begin, end - begin);
-        switch (format[end + 1]) {
+        switch ( format[end + 1].GetValue() ) {
             case 'd': ret << d; break;
             case 'f': ret << f; break;
             case 'p': ret << wxGetProcessId(); break;
@@ -1340,7 +1412,8 @@ void wxTarOutputStream::SetHeaderDate(const wxString& key,
     wxLongLong ll = datetime.IsValid() ? datetime.GetValue() : wxLongLong(0);
     wxLongLong secs = ll / 1000L;
 
-    if (key != _T("mtime") || !m_hdr->SetOctal(TAR_MTIME, secs.GetValue())
+    if (key != _T("mtime")
+        || !m_hdr->SetOctal(TAR_MTIME, wxTarNumber(secs.GetValue()))
         || secs <= 0 || secs >= 0x7fffffff)
     {
         wxString str;
@@ -1358,11 +1431,16 @@ void wxTarOutputStream::SetExtendedHeader(const wxString& key,
                                           const wxString& value)
 {
     if (m_pax) {
+#if wxUSE_UNICODE
+        const wxCharBuffer utf_key = key.utf8_str();
+        const wxCharBuffer utf_value = value.utf8_str();
+#else
         const wxWX2WCbuf wide_key = key.wc_str(GetConv());
         const wxCharBuffer utf_key = wxConvUTF8.cWC2MB(wide_key);
 
         const wxWX2WCbuf wide_value = value.wc_str(GetConv());
         const wxCharBuffer utf_value = wxConvUTF8.cWC2MB(wide_value);
+#endif // wxUSE_UNICODE/!wxUSE_UNICODE
 
         // a small buffer to format the length field in
         char buf[32];