]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/utilsunx.cpp
wxMac removed debugging code
[wxWidgets.git] / src / unix / utilsunx.cpp
index 9ff30199ca6138fa76e439e253d7f10942ebae4c..70d467e744b424e795899c4ed0339f1b8f90a555 100644 (file)
@@ -26,7 +26,7 @@
 #include "wx/process.h"
 #include "wx/thread.h"
 
-#include "wx/stream.h"
+#include "wx/wfstream.h"
 
 #ifdef HAVE_STATFS
 #  ifdef __BSD__
 #  endif
 #endif // HAVE_STATFS
 
+// not only the statfs syscall is called differently depending on platform, but
+// we also can't use "struct statvfs" under Solaris because it breaks down if
+// HAVE_LARGEFILE_SUPPORT == 1 and we must use statvfs_t instead
 #ifdef HAVE_STATVFS
     #include <sys/statvfs.h>
 
     #define statfs statvfs
-#endif // HAVE_STATVFS
+    #define wxStatFs statvfs_t
+#elif HAVE_STATFS
+    #define wxStatFs struct statfs
+#endif // HAVE_STAT[V]FS
 
 #if wxUSE_GUI
     #include "wx/unix/execute.h"
@@ -155,7 +161,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *rc)
     int err = kill((pid_t)pid, (int)sig);
     if ( rc )
     {
-        switch ( err )
+        switch ( errno )
         {
             case 0:
                 *rc = wxKILL_OK;
@@ -187,7 +193,7 @@ int wxKill(long pid, wxSignal sig, wxKillError *rc)
 
 #define WXEXECUTE_NARGS   127
 
-long wxExecute( const wxString& command, bool sync, wxProcess *process )
+long wxExecute( const wxString& command, int flags, wxProcess *process )
 {
     wxCHECK_MSG( !command.IsEmpty(), 0, wxT("can't exec empty command") );
 
@@ -247,7 +253,11 @@ long wxExecute( const wxString& command, bool sync, wxProcess *process )
     argv[argc] = NULL;
 
     // do execute the command
-    long lRc = wxExecute(argv, sync, process);
+#if wxUSE_UNICODE
+    long lRc = -1;
+#else
+    long lRc = wxExecute(argv, flags, process);
+#endif
 
     // clean up
     argc = 0;
@@ -280,7 +290,7 @@ static wxString wxMakeShellCommand(const wxString& command)
 
 bool wxShell(const wxString& command)
 {
-    return wxExecute(wxMakeShellCommand(command), TRUE /* sync */) == 0;
+    return wxExecute(wxMakeShellCommand(command), wxEXEC_SYNC) == 0;
 }
 
 bool wxShell(const wxString& command, wxArrayString& output)
@@ -290,6 +300,29 @@ bool wxShell(const wxString& command, wxArrayString& output)
     return wxExecute(wxMakeShellCommand(command), output);
 }
 
+// Shutdown or reboot the PC
+bool wxShutdown(wxShutdownFlags wFlags)
+{
+    wxChar level;
+    switch ( wFlags )
+    {
+        case wxSHUTDOWN_POWEROFF:
+            level = _T('0');
+            break;
+
+        case wxSHUTDOWN_REBOOT:
+            level = _T('6');
+            break;
+
+        default:
+            wxFAIL_MSG( _T("unknown wxShutdown() flag") );
+            return FALSE;
+    }
+
+    return system(wxString::Format(_T("init %c"), level).mb_str()) == 0;
+}
+
+
 #if wxUSE_GUI
 
 void wxHandleProcessTermination(wxEndProcessData *proc_data)
@@ -320,35 +353,20 @@ void wxHandleProcessTermination(wxEndProcessData *proc_data)
 
 #if wxUSE_STREAMS
 
-class wxProcessFileInputStream : public wxInputStream
-{
-public:
-    wxProcessFileInputStream(int fd) { m_fd = fd; }
-    ~wxProcessFileInputStream() { close(m_fd); }
-
-    virtual bool Eof() const;
-
-protected:
-    size_t OnSysRead(void *buffer, size_t bufsize);
-
-protected:
-    int m_fd;
-};
+// ----------------------------------------------------------------------------
+// wxProcessFileInputStream: stream for reading from a pipe
+// ----------------------------------------------------------------------------
 
-class wxProcessFileOutputStream : public wxOutputStream
+class wxProcessFileInputStream : public wxFileInputStream
 {
 public:
-    wxProcessFileOutputStream(int fd) { m_fd = fd; }
-    ~wxProcessFileOutputStream() { close(m_fd); }
+    wxProcessFileInputStream(int fd) : wxFileInputStream(fd) { }
 
-protected:
-    size_t OnSysWrite(const void *buffer, size_t bufsize);
-
-protected:
-    int m_fd;
+    // return TRUE if we have anything to read, don't block
+    bool IsAvailable() const;
 };
 
-bool wxProcessFileInputStream::Eof() const
+bool wxProcessFileInputStream::IsAvailable() const
 {
     if ( m_lasterror == wxSTREAM_EOF )
         return TRUE;
@@ -358,10 +376,12 @@ bool wxProcessFileInputStream::Eof() const
     tv.tv_sec = 0;
     tv.tv_usec = 0;
 
+    const int fd = m_file->fd();
+
     fd_set readfds;
     FD_ZERO(&readfds);
-    FD_SET(m_fd, &readfds);
-    switch ( select(m_fd + 1, &readfds, NULL, NULL, &tv) )
+    FD_SET(fd, &readfds);
+    switch ( select(fd + 1, &readfds, NULL, NULL, &tv) )
     {
         case -1:
             wxLogSysError(_("Impossible to get child process input"));
@@ -375,49 +395,13 @@ bool wxProcessFileInputStream::Eof() const
             // still fall through
 
         case 1:
-            // input available: check if there is any
-            return wxInputStream::Eof();
-    }
-}
-
-size_t wxProcessFileInputStream::OnSysRead(void *buffer, size_t bufsize)
-{
-    int ret = read(m_fd, buffer, bufsize);
-    if ( ret == 0 )
-    {
-        m_lasterror = wxSTREAM_EOF;
-    }
-    else if ( ret == -1 )
-    {
-        m_lasterror = wxSTREAM_READ_ERROR;
-        ret = 0;
-    }
-    else
-    {
-        m_lasterror = wxSTREAM_NOERROR;
-    }
-
-    return ret;
-}
-
-size_t wxProcessFileOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
-{
-    int ret = write(m_fd, buffer, bufsize);
-    if ( ret == -1 )
-    {
-        m_lasterror = wxSTREAM_WRITE_ERROR;
-        ret = 0;
-    }
-    else
-    {
-        m_lasterror = wxSTREAM_NOERROR;
+            // input available
+            return TRUE;
     }
-
-    return ret;
 }
 
 // ----------------------------------------------------------------------------
-// wxStreamTempBuffer
+// wxStreamTempInputBuffer
 // ----------------------------------------------------------------------------
 
 /*
@@ -436,34 +420,38 @@ size_t wxProcessFileOutputStream::OnSysWrite(const void *buffer, size_t bufsize)
     command we set up a pipe with a valid file descriptor on the reading side
     when the output is redirected. So the subprocess happily writes to it ...
     until the pipe buffer (which is usually quite big on Unix, I think the
-    default is 4Mb) is full. Then the writing process stops and waits until we
+    default is 4Kb) is full. Then the writing process stops and waits until we
     read some data from the pipe to be able to continue writing to it but we
     never do it because we wait until it terminates to start reading and so we
     have a classical deadlock.
 
    Here is the fix: we now read the output as soon as it appears into a temp
-   buffer (wxStreamTempBuffer object) and later just stuff it back into the
+   buffer (wxStreamTempInputBuffer object) and later just stuff it back into the
    stream when the process terminates. See supporting code in wxExecute()
-   itself as well.   
+   itself as well.
+
+   Note that this is horribly inefficient for large amounts of output (count
+   the number of times we copy the data around) and so a better API is badly
+   needed!
 */
 
-class wxStreamTempBuffer
+class wxStreamTempInputBuffer
 {
 public:
-    wxStreamTempBuffer();
+    wxStreamTempInputBuffer();
 
     // call to associate a stream with this buffer, otherwise nothing happens
     // at all
-    void Init(wxInputStream *stream);
+    void Init(wxProcessFileInputStream *stream);
 
     // check for input on our stream and cache it in our buffer if any
     void Update();
 
-    ~wxStreamTempBuffer();
+    ~wxStreamTempInputBuffer();
 
 private:
     // the stream we're buffering, if NULL we don't do anything at all
-    wxInputStream *m_stream;
+    wxProcessFileInputStream *m_stream;
 
     // the buffer of size m_size (NULL if m_size == 0)
     void *m_buffer;
@@ -472,25 +460,25 @@ private:
     size_t m_size;
 };
 
-wxStreamTempBuffer::wxStreamTempBuffer()
+wxStreamTempInputBuffer::wxStreamTempInputBuffer()
 {
-    m_stream = NULL; 
+    m_stream = NULL;
     m_buffer = NULL;
     m_size = 0;
 }
 
-void wxStreamTempBuffer::Init(wxInputStream *stream)
+void wxStreamTempInputBuffer::Init(wxProcessFileInputStream *stream)
 {
     m_stream = stream;
 }
 
-void wxStreamTempBuffer::Update()
+void wxStreamTempInputBuffer::Update()
 {
-    if ( m_stream && !m_stream->Eof() )
+    if ( m_stream && m_stream->IsAvailable() )
     {
-        // realloc in blocks of 1Kb - surely not the best strategy but which
-        // one is?
-        static const size_t incSize = 1024;
+        // realloc in blocks of 4Kb: this is the default (and minimal) buffer
+        // size of the Unix pipes so it should be the optimal step
+        static const size_t incSize = 4096;
 
         void *buf = realloc(m_buffer, m_size + incSize);
         if ( !buf )
@@ -502,12 +490,12 @@ void wxStreamTempBuffer::Update()
         {
             m_buffer = buf;
             m_stream->Read((char *)m_buffer + m_size, incSize);
-            m_size += incSize;
+            m_size += m_stream->LastRead();
         }
     }
 }
 
-wxStreamTempBuffer::~wxStreamTempBuffer()
+wxStreamTempInputBuffer::~wxStreamTempInputBuffer()
 {
     if ( m_buffer )
     {
@@ -518,8 +506,92 @@ wxStreamTempBuffer::~wxStreamTempBuffer()
 
 #endif // wxUSE_STREAMS
 
+// ----------------------------------------------------------------------------
+// wxPipe: this encapsulates pipe() system call
+// ----------------------------------------------------------------------------
+
+class wxPipe
+{
+public:
+    // the symbolic names for the pipe ends
+    enum Direction
+    {
+        Read,
+        Write
+    };
+
+    enum
+    {
+        INVALID_FD = -1
+    };
+
+    // default ctor doesn't do anything
+    wxPipe() { m_fds[Read] = m_fds[Write] = INVALID_FD; }
+
+    // create the pipe, return TRUE if ok, FALSE on error
+    bool Create()
+    {
+        if ( pipe(m_fds) == -1 )
+        {
+            wxLogSysError(_("Pipe creation failed"));
+
+            return FALSE;
+        }
+
+        return TRUE;
+    }
+
+    // return TRUE if we were created successfully
+    bool IsOk() const { return m_fds[Read] != INVALID_FD; }
+
+    // return the descriptor for one of the pipe ends
+    int operator[](Direction which) const
+    {
+        wxASSERT_MSG( which >= 0 && (size_t)which < WXSIZEOF(m_fds),
+                      _T("invalid pipe index") );
+
+        return m_fds[which];
+    }
+
+    // detach a descriptor, meaning that the pipe dtor won't close it, and
+    // return it
+    int Detach(Direction which)
+    {
+        wxASSERT_MSG( which >= 0 && (size_t)which < WXSIZEOF(m_fds),
+                      _T("invalid pipe index") );
+
+        int fd = m_fds[which];
+        m_fds[which] = INVALID_FD;
+
+        return fd;
+    }
+
+    // close the pipe descriptors
+    void Close()
+    {
+        for ( size_t n = 0; n < WXSIZEOF(m_fds); n++ )
+        {
+            if ( m_fds[n] != INVALID_FD )
+                close(m_fds[n]);
+        }
+    }
+
+    // dtor closes the pipe descriptors
+    ~wxPipe() { Close(); }
+
+private:
+    int m_fds[2];
+};
+
+// ----------------------------------------------------------------------------
+// wxExecute: the real worker function
+// ----------------------------------------------------------------------------
+#ifdef __VMS
+#pragma message disable codeunreachable
+#endif
+
 long wxExecute(wxChar **argv,
-               bool sync,
+               int flags,
                wxProcess *process)
 {
     // for the sync execution, we return -1 to indicate failure, but for async
@@ -527,7 +599,7 @@ long wxExecute(wxChar **argv,
     //
     // we define this as a macro, not a variable, to avoid compiler warnings
     // about "ERROR_RETURN_CODE value may be clobbered by fork()"
-    #define ERROR_RETURN_CODE ((sync) ? -1 : 0)
+    #define ERROR_RETURN_CODE ((flags & wxEXEC_SYNC) ? -1 : 0)
 
     wxCHECK_MSG( *argv, ERROR_RETURN_CODE, wxT("can't exec empty command") );
 
@@ -556,10 +628,9 @@ long wxExecute(wxChar **argv,
 
 #if wxUSE_GUI
     // create pipes
-    int end_proc_detect[2];
-    if ( pipe(end_proc_detect) == -1 )
+    wxPipe pipeEndProcDetect;
+    if ( !pipeEndProcDetect.Create() )
     {
-        wxLogSysError( _("Pipe creation failed") );
         wxLogError( _("Failed to execute '%s'\n"), *argv );
 
         ARGS_CLEANUP;
@@ -569,25 +640,14 @@ long wxExecute(wxChar **argv,
 #endif // wxUSE_GUI
 
     // pipes for inter process communication
-    int pipeIn[2],      // stdin
-        pipeOut[2],     // stdout
-        pipeErr[2];     // stderr
-
-    pipeIn[0] = pipeIn[1] =
-    pipeOut[0] = pipeOut[1] =
-    pipeErr[0] = pipeErr[1] = -1;
+    wxPipe pipeIn,      // stdin
+           pipeOut,     // stdout
+           pipeErr;     // stderr
 
     if ( process && process->IsRedirected() )
     {
-        if ( pipe(pipeIn) == -1 || pipe(pipeOut) == -1 || pipe(pipeErr) == -1 )
+        if ( !pipeIn.Create() || !pipeOut.Create() || !pipeErr.Create() )
         {
-#if wxUSE_GUI
-            // free previously allocated resources
-            close(end_proc_detect[0]);
-            close(end_proc_detect[1]);
-#endif // wxUSE_GUI
-
-            wxLogSysError( _("Pipe creation failed") );
             wxLogError( _("Failed to execute '%s'\n"), *argv );
 
             ARGS_CLEANUP;
@@ -605,17 +665,6 @@ long wxExecute(wxChar **argv,
 
     if ( pid == -1 )     // error?
     {
-#if wxUSE_GUI
-        close(end_proc_detect[0]);
-        close(end_proc_detect[1]);
-        close(pipeIn[0]);
-        close(pipeIn[1]);
-        close(pipeOut[0]);
-        close(pipeOut[1]);
-        close(pipeErr[0]);
-        close(pipeErr[1]);
-#endif // wxUSE_GUI
-
         wxLogSysError( _("Fork failed") );
 
         ARGS_CLEANUP;
@@ -624,21 +673,19 @@ long wxExecute(wxChar **argv,
     }
     else if ( pid == 0 )  // we're in child
     {
-#if wxUSE_GUI
-        close(end_proc_detect[0]); // close reading side
-#endif // wxUSE_GUI
-
         // These lines close the open file descriptors to to avoid any
         // input/output which might block the process or irritate the user. If
         // one wants proper IO for the subprocess, the right thing to do is to
         // start an xterm executing it.
-        if ( !sync )
+        if ( !(flags & wxEXEC_SYNC) )
         {
             for ( int fd = 0; fd < FD_SETSIZE; fd++ )
             {
-                if ( fd == pipeIn[0] || fd == pipeOut[1] || fd == pipeErr[1]
+                if ( fd == pipeIn[wxPipe::Read]
+                        || fd == pipeOut[wxPipe::Write]
+                        || fd == pipeErr[wxPipe::Write]
 #if wxUSE_GUI
-                     || fd == end_proc_detect[1]
+                        || fd == pipeEndProcDetect[wxPipe::Write]
 #endif // wxUSE_GUI
                    )
                 {
@@ -646,25 +693,41 @@ long wxExecute(wxChar **argv,
                     continue;
                 }
 
-                // leave stderr opened too, it won't do any hurm
+                // leave stderr opened too, it won't do any harm
                 if ( fd != STDERR_FILENO )
                     close(fd);
             }
         }
 
-        // redirect stdio, stdout and stderr
-        if ( pipeIn[0] != -1 )
+#ifndef __VMS
+        if ( flags & wxEXEC_MAKE_GROUP_LEADER )
         {
-            if ( dup2(pipeIn[0], STDIN_FILENO) == -1 ||
-                 dup2(pipeOut[1], STDOUT_FILENO) == -1 ||
-                 dup2(pipeErr[1], STDERR_FILENO) == -1 )
+            // Set process group to child process' pid.  Then killing -pid
+            // of the parent will kill the process and all of its children.
+            setsid();
+        }
+#endif // !__VMS
+
+#if wxUSE_GUI
+        // reading side can be safely closed but we should keep the write one
+        // opened
+        pipeEndProcDetect.Detach(wxPipe::Write);
+        pipeEndProcDetect.Close();
+#endif // wxUSE_GUI
+
+        // redirect stdin, stdout and stderr
+        if ( pipeIn.IsOk() )
+        {
+            if ( dup2(pipeIn[wxPipe::Read], STDIN_FILENO) == -1 ||
+                 dup2(pipeOut[wxPipe::Write], STDOUT_FILENO) == -1 ||
+                 dup2(pipeErr[wxPipe::Write], STDERR_FILENO) == -1 )
             {
                 wxLogSysError(_("Failed to redirect child process input/output"));
             }
 
-            close(pipeIn[0]);
-            close(pipeOut[1]);
-            close(pipeErr[1]);
+            pipeIn.Close();
+            pipeOut.Close();
+            pipeErr.Close();
         }
 
         execvp (*mb_argv, mb_argv);
@@ -675,6 +738,9 @@ long wxExecute(wxChar **argv,
         // some compilers complain about missing return - of course, they
         // should know that exit() doesn't return but what else can we do if
         // they don't?
+        //
+        // and, sure enough, other compilers complain about unreachable code
+        // after exit() call, so we can just always have return here...
 #if defined(__VMS) || defined(__INTEL_COMPILER)
         return 0;
 #endif
@@ -683,34 +749,53 @@ long wxExecute(wxChar **argv,
     {
         ARGS_CLEANUP;
 
-        // pipe initialization: construction of the wxStreams
+        // prepare for IO redirection
+
 #if wxUSE_STREAMS
-        wxStreamTempBuffer bufIn, bufErr;
+        // the input buffer bufOut is connected to stdout, this is why it is
+        // called bufOut and not bufIn
+        wxStreamTempInputBuffer bufOut,
+                                bufErr;
 #endif // wxUSE_STREAMS
 
         if ( process && process->IsRedirected() )
         {
 #if wxUSE_STREAMS
-            // in/out for subprocess correspond to our out/in
-            wxOutputStream *outStream = new wxProcessFileOutputStream(pipeIn[1]);
-            wxInputStream *inStream = new wxProcessFileInputStream(pipeOut[0]);
-            wxInputStream *errStream = new wxProcessFileInputStream(pipeErr[0]);
+            wxOutputStream *inStream =
+                new wxFileOutputStream(pipeIn.Detach(wxPipe::Write));
+
+            wxProcessFileInputStream *outStream =
+                new wxProcessFileInputStream(pipeOut.Detach(wxPipe::Read));
 
-            process->SetPipeStreams(inStream, outStream, errStream);
+            wxProcessFileInputStream *errStream =
+                new wxProcessFileInputStream(pipeErr.Detach(wxPipe::Read));
 
-            bufIn.Init(inStream);
-            bufErr.Init(inStream);
+            process->SetPipeStreams(outStream, inStream, errStream);
+
+            bufOut.Init(outStream);
+            bufErr.Init(errStream);
 #endif // wxUSE_STREAMS
+        }
 
-            close(pipeIn[0]); // close reading side
-            close(pipeOut[1]); // close writing side
-            close(pipeErr[1]); // close writing side
+        if ( pipeIn.IsOk() )
+        {
+            pipeIn.Close();
+            pipeOut.Close();
+            pipeErr.Close();
         }
 
 #if wxUSE_GUI && !defined(__WXMICROWIN__)
         wxEndProcessData *data = new wxEndProcessData;
 
-        if ( sync )
+        data->tag = wxAddProcessCallback
+                    (
+                        data,
+                        pipeEndProcDetect.Detach(wxPipe::Read)
+                    );
+
+        pipeEndProcDetect.Close();
+
+        if ( flags & wxEXEC_SYNC )
         {
             // we may have process for capturing the program output, but it's
             // not used in wxEndProcessData in the case of sync execution
@@ -718,9 +803,6 @@ long wxExecute(wxChar **argv,
 
             // sync execution: indicate it by negating the pid
             data->pid = -pid;
-            data->tag = wxAddProcessCallback(data, end_proc_detect[0]);
-
-            close(end_proc_detect[1]); // close writing side
 
             wxBusyCursor bc;
             wxWindowDisabler wd;
@@ -730,7 +812,7 @@ long wxExecute(wxChar **argv,
             while ( data->pid != 0 )
             {
 #if wxUSE_STREAMS
-                bufIn.Update();
+                bufOut.Update();
                 bufErr.Update();
 #endif // wxUSE_STREAMS
 
@@ -752,14 +834,13 @@ long wxExecute(wxChar **argv,
             // will be deleted in GTK_EndProcessDetector
             data->process  = process;
             data->pid      = pid;
-            data->tag      = wxAddProcessCallback(data, end_proc_detect[0]);
-
-            close(end_proc_detect[1]); // close writing side
 
             return pid;
         }
 #else // !wxUSE_GUI
-        wxASSERT_MSG( sync, wxT("async execution not supported yet") );
+
+        wxASSERT_MSG( flags & wxEXEC_SYNC,
+                      wxT("async execution not supported yet") );
 
         int exitcode = 0;
         if ( waitpid(pid, &exitcode, 0) == -1 || !WIFEXITED(exitcode) )
@@ -770,7 +851,12 @@ long wxExecute(wxChar **argv,
         return exitcode;
 #endif // wxUSE_GUI
     }
+
+    return ERROR_RETURN_CODE;
 }
+#ifdef __VMS
+#pragma message enable codeunreachable
+#endif
 
 #undef ERROR_RETURN_CODE
 #undef ARGS_CLEANUP
@@ -948,6 +1034,7 @@ bool wxGetUserName(wxChar *buf, int sz)
     return FALSE;
 }
 
+#ifndef __WXMAC__
 wxString wxGetOsDescription()
 {
 #ifndef WXWIN_OS_DESCRIPTION
@@ -956,6 +1043,7 @@ wxString wxGetOsDescription()
     return WXWIN_OS_DESCRIPTION;
 #endif
 }
+#endif
 
 // this function returns the GUI toolkit version in GUI programs, but OS
 // version in non-GUI ones
@@ -982,6 +1070,11 @@ int wxGetOsVersion(int *majorVsn, int *minorVsn)
 
 #endif // !wxUSE_GUI
 
+unsigned long wxGetProcessId()
+{
+    return (unsigned long)getpid();
+}
+
 long wxGetFreeMemory()
 {
 #if defined(__LINUX__)
@@ -1011,37 +1104,41 @@ long wxGetFreeMemory()
     return -1;
 }
 
-#ifndef __WXMAC__
 bool wxGetDiskSpace(const wxString& path, wxLongLong *pTotal, wxLongLong *pFree)
 {
 #if defined(HAVE_STATFS) || defined(HAVE_STATVFS)
-    struct statfs fs;
-    if ( statfs(path, &fs) != 0 )
+    // the case to "char *" is needed for AIX 4.3
+    wxStatFs fs;
+    if ( statfs((char *)(const char*)path.fn_str(), &fs) != 0 )
     {
-        wxLogSysError("Failed to get file system statistics");
+        wxLogSysError( wxT("Failed to get file system statistics") );
 
         return FALSE;
     }
 
-    // under Solaris we might have to use fs.f_frsize instead as I think it
-    // may be a multiple of the block size in general (TODO)
+    // under Solaris we also have to use f_frsize field instead of f_bsize
+    // which is in general a multiple of f_frsize
+#ifdef HAVE_STATVFS
+    wxLongLong blockSize = fs.f_frsize;
+#else // HAVE_STATFS
+    wxLongLong blockSize = fs.f_bsize;
+#endif // HAVE_STATVFS/HAVE_STATFS
 
     if ( pTotal )
     {
-        *pTotal = wxLongLong(fs.f_blocks) * fs.f_bsize;
+        *pTotal = wxLongLong(fs.f_blocks) * blockSize;
     }
 
     if ( pFree )
     {
-        *pFree = wxLongLong(fs.f_bavail) * fs.f_bsize;
+        *pFree = wxLongLong(fs.f_bavail) * blockSize;
     }
 
     return TRUE;
-#endif // HAVE_STATFS
-
+#else // !HAVE_STATFS && !HAVE_STATVFS
     return FALSE;
+#endif // HAVE_STATFS
 }
-#endif
 
 // ----------------------------------------------------------------------------
 // env vars
@@ -1065,8 +1162,10 @@ bool wxGetEnv(const wxString& var, wxString *value)
 bool wxSetEnv(const wxString& variable, const wxChar *value)
 {
 #if defined(HAVE_SETENV)
-    return setenv(variable.mb_str(), value ? wxString(value).mb_str().data()
-                                           : NULL, 1 /* overwrite */) == 0;
+    return setenv(variable.mb_str(),
+                  value ? (const char *)wxString(value).mb_str()
+                        : NULL,
+                  1 /* overwrite */) == 0;
 #elif defined(HAVE_PUTENV)
     wxString s = variable;
     if ( value )
@@ -1093,7 +1192,7 @@ bool wxSetEnv(const wxString& variable, const wxChar *value)
 
 #include <signal.h>
 
-static void wxFatalSignalHandler(wxTYPE_SA_HANDLER)
+extern "C" void wxFatalSignalHandler(wxTYPE_SA_HANDLER)
 {
     if ( wxTheApp )
     {
@@ -1162,6 +1261,8 @@ bool wxHandleFatalExceptions(bool doit)
 // error and debug output routines (deprecated, use wxLog)
 // ----------------------------------------------------------------------------
 
+#if WXWIN_COMPATIBILITY_2_2
+
 void wxDebugMsg( const char *format, ... )
 {
   va_list ap;
@@ -1188,3 +1289,5 @@ void wxFatalError( const wxString &msg, const wxString &title )
   exit(3); // the same exit code as for abort()
 }
 
+#endif // WXWIN_COMPATIBILITY_2_2
+