unix.cpp

Go to the documentation of this file.
00001 /* $Id: unix.cpp 19857 2010-05-18 21:44:47Z rubidium $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "../../stdafx.h"
00013 #include "../../textbuf_gui.h"
00014 #include "../../functions.h"
00015 #include "../../crashlog.h"
00016 #include "../../core/random_func.hpp"
00017 
00018 
00019 #include <dirent.h>
00020 #include <unistd.h>
00021 #include <sys/stat.h>
00022 #include <time.h>
00023 #include <signal.h>
00024 
00025 #ifdef __APPLE__
00026   #include <sys/mount.h>
00027 #elif (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) || defined(__GLIBC__)
00028   #define HAS_STATVFS
00029 #endif
00030 
00031 #ifdef HAS_STATVFS
00032 #include <sys/statvfs.h>
00033 #endif
00034 
00035 
00036 #ifdef __MORPHOS__
00037 #include <exec/types.h>
00038 ULONG __stack = (1024*1024)*2; // maybe not that much is needed actually ;)
00039 
00040 /* The system supplied definition of SIG_IGN does not match */
00041 #undef SIG_IGN
00042 #define SIG_IGN (void (*)(int))1
00043 #endif /* __MORPHOS__ */
00044 
00045 #ifdef __AMIGA__
00046 #warning add stack symbol to avoid that user needs to set stack manually (tokai)
00047 // ULONG __stack =
00048 #endif
00049 
00050 #if defined(__APPLE__)
00051   #if defined(WITH_SDL)
00052     /* the mac implementation needs this file included in the same file as main() */
00053     #include <SDL.h>
00054   #endif
00055 #endif
00056 
00057 bool FiosIsRoot(const char *path)
00058 {
00059 #if !defined(__MORPHOS__) && !defined(__AMIGAOS__)
00060   return path[1] == '\0';
00061 #else
00062   /* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */
00063   const char *s = strchr(path, ':');
00064   return s != NULL && s[1] == '\0';
00065 #endif
00066 }
00067 
00068 void FiosGetDrives()
00069 {
00070   return;
00071 }
00072 
00073 bool FiosGetDiskFreeSpace(const char *path, uint64 *tot)
00074 {
00075   uint64 free = 0;
00076 
00077 #ifdef __APPLE__
00078   struct statfs s;
00079 
00080   if (statfs(path, &s) != 0) return false;
00081   free = (uint64)s.f_bsize * s.f_bavail;
00082 #elif defined(HAS_STATVFS)
00083   struct statvfs s;
00084 
00085   if (statvfs(path, &s) != 0) return false;
00086   free = (uint64)s.f_frsize * s.f_bavail;
00087 #endif
00088   if (tot != NULL) *tot = free;
00089   return true;
00090 }
00091 
00092 bool FiosIsValidFile(const char *path, const struct dirent *ent, struct stat *sb)
00093 {
00094   char filename[MAX_PATH];
00095   int res;
00096 #if defined(__MORPHOS__) || defined(__AMIGAOS__)
00097   /* On MorphOS or AmigaOS paths look like: "Volume:directory/subdirectory" */
00098   if (FiosIsRoot(path)) {
00099     res = snprintf(filename, lengthof(filename), "%s:%s", path, ent->d_name);
00100   } else // XXX - only next line!
00101 #else
00102   assert(path[strlen(path) - 1] == PATHSEPCHAR);
00103   if (strlen(path) > 2) assert(path[strlen(path) - 2] != PATHSEPCHAR);
00104 #endif
00105   res = snprintf(filename, lengthof(filename), "%s%s", path, ent->d_name);
00106 
00107   /* Could we fully concatenate the path and filename? */
00108   if (res >= (int)lengthof(filename) || res < 0) return false;
00109 
00110   return stat(filename, sb) == 0;
00111 }
00112 
00113 bool FiosIsHiddenFile(const struct dirent *ent)
00114 {
00115   return ent->d_name[0] == '.';
00116 }
00117 
00118 #ifdef WITH_ICONV
00119 
00120 #include <iconv.h>
00121 #include <errno.h>
00122 #include "../../debug.h"
00123 #include "../../string_func.h"
00124 
00125 const char *GetCurrentLocale(const char *param);
00126 
00127 #define INTERNALCODE "UTF-8"
00128 
00132 static const char *GetLocalCode()
00133 {
00134 #if defined(__APPLE__)
00135   return "UTF-8-MAC";
00136 #else
00137   /* Strip locale (eg en_US.UTF-8) to only have UTF-8 */
00138   const char *locale = GetCurrentLocale("LC_CTYPE");
00139   if (locale != NULL) locale = strchr(locale, '.');
00140 
00141   return (locale == NULL) ? "" : locale + 1;
00142 #endif
00143 }
00144 
00149 static const char *convert_tofrom_fs(iconv_t convd, const char *name)
00150 {
00151   static char buf[1024];
00152   /* Work around buggy iconv implementation where inbuf is wrongly typed as
00153    * non-const. Correct implementation is at
00154    * http://www.opengroup.org/onlinepubs/007908799/xsh/iconv.html */
00155 #ifdef HAVE_BROKEN_ICONV
00156   char *inbuf = const_cast<char*>(name);
00157 #else
00158   const char *inbuf = name;
00159 #endif
00160 
00161   char *outbuf  = buf;
00162   size_t outlen = sizeof(buf) - 1;
00163   size_t inlen  = strlen(name);
00164 
00165   strecpy(outbuf, name, outbuf + outlen);
00166 
00167   iconv(convd, NULL, NULL, NULL, NULL);
00168   if (iconv(convd, &inbuf, &inlen, &outbuf, &outlen) == (size_t)(-1)) {
00169     DEBUG(misc, 0, "[iconv] error converting '%s'. Errno %d", name, errno);
00170   }
00171 
00172   *outbuf = '\0';
00173   /* FIX: invalid characters will abort conversion, but they shouldn't occur? */
00174   return buf;
00175 }
00176 
00180 const char *OTTD2FS(const char *name)
00181 {
00182   static iconv_t convd = (iconv_t)(-1);
00183 
00184   if (convd == (iconv_t)(-1)) {
00185     const char *env = GetLocalCode();
00186     convd = iconv_open(env, INTERNALCODE);
00187     if (convd == (iconv_t)(-1)) {
00188       DEBUG(misc, 0, "[iconv] conversion from codeset '%s' to '%s' unsupported", INTERNALCODE, env);
00189       return name;
00190     }
00191   }
00192 
00193   return convert_tofrom_fs(convd, name);
00194 }
00195 
00199 const char *FS2OTTD(const char *name)
00200 {
00201   static iconv_t convd = (iconv_t)(-1);
00202 
00203   if (convd == (iconv_t)(-1)) {
00204     const char *env = GetLocalCode();
00205     convd = iconv_open(INTERNALCODE, env);
00206     if (convd == (iconv_t)(-1)) {
00207       DEBUG(misc, 0, "[iconv] conversion from codeset '%s' to '%s' unsupported", env, INTERNALCODE);
00208       return name;
00209     }
00210   }
00211 
00212   return convert_tofrom_fs(convd, name);
00213 }
00214 
00215 #else
00216 const char *FS2OTTD(const char *name) {return name;}
00217 const char *OTTD2FS(const char *name) {return name;}
00218 #endif /* WITH_ICONV */
00219 
00220 void ShowInfo(const char *str)
00221 {
00222   fprintf(stderr, "%s\n", str);
00223 }
00224 
00225 #if !defined(__APPLE__)
00226 void ShowOSErrorBox(const char *buf, bool system)
00227 {
00228   /* All unix systems, except OSX. Only use escape codes on a TTY. */
00229   if (isatty(fileno(stderr))) {
00230     fprintf(stderr, "\033[1;31mError: %s\033[0;39m\n", buf);
00231   } else {
00232     fprintf(stderr, "Error: %s\n", buf);
00233   }
00234 }
00235 #endif
00236 
00237 #ifdef WITH_COCOA
00238 void cocoaSetupAutoreleasePool();
00239 void cocoaReleaseAutoreleasePool();
00240 #endif
00241 
00242 int CDECL main(int argc, char *argv[])
00243 {
00244   int ret;
00245 
00246 #ifdef WITH_COCOA
00247   cocoaSetupAutoreleasePool();
00248   /* This is passed if we are launched by double-clicking */
00249   if (argc >= 2 && strncmp(argv[1], "-psn", 4) == 0) {
00250     argv[1] = NULL;
00251     argc = 1;
00252   }
00253 #endif
00254   CrashLog::InitialiseCrashLog();
00255 
00256   SetRandomSeed(time(NULL));
00257 
00258   signal(SIGPIPE, SIG_IGN);
00259 
00260   ret = ttd_main(argc, argv);
00261 
00262 #ifdef WITH_COCOA
00263   cocoaReleaseAutoreleasePool();
00264 #endif
00265 
00266   return ret;
00267 }
00268 
00269 #ifndef WITH_COCOA
00270 bool GetClipboardContents(char *buffer, size_t buff_len)
00271 {
00272   return false;
00273 }
00274 #endif
00275 
00276 
00277 /* multi os compatible sleep function */
00278 
00279 #ifdef __AMIGA__
00280 /* usleep() implementation */
00281 # include <devices/timer.h>
00282 # include <dos/dos.h>
00283 
00284   extern struct Device      *TimerBase    = NULL;
00285   extern struct MsgPort     *TimerPort    = NULL;
00286   extern struct timerequest *TimerRequest = NULL;
00287 #endif /* __AMIGA__ */
00288 
00289 void CSleep(int milliseconds)
00290 {
00291   #if defined(PSP)
00292     sceKernelDelayThread(milliseconds * 1000);
00293   #elif defined(__BEOS__)
00294     snooze(milliseconds * 1000);
00295   #elif defined(__AMIGA__)
00296   {
00297     ULONG signals;
00298     ULONG TimerSigBit = 1 << TimerPort->mp_SigBit;
00299 
00300     /* send IORequest */
00301     TimerRequest->tr_node.io_Command = TR_ADDREQUEST;
00302     TimerRequest->tr_time.tv_secs    = (milliseconds * 1000) / 1000000;
00303     TimerRequest->tr_time.tv_micro   = (milliseconds * 1000) % 1000000;
00304     SendIO((struct IORequest *)TimerRequest);
00305 
00306     if (!((signals = Wait(TimerSigBit | SIGBREAKF_CTRL_C)) & TimerSigBit) ) {
00307       AbortIO((struct IORequest *)TimerRequest);
00308     }
00309     WaitIO((struct IORequest *)TimerRequest);
00310   }
00311   #else
00312     usleep(milliseconds * 1000);
00313   #endif
00314 }

Generated on Sat Jun 19 17:14:51 2010 for OpenTTD by  doxygen 1.6.1