X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fporting.cpp;h=023f0cca7d431d20377ee65564eec7a4d661c528;hb=bb9fe6eb2b32548e66d62b64e949b058ec7856fc;hp=584d2e2a2924c54a10ca67310395b53a84c42525;hpb=976d0b2caa3f69c0b7c40e98517073e08e87774d;p=dragonfireclient.git diff --git a/src/porting.cpp b/src/porting.cpp index 584d2e2a2..023f0cca7 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -29,18 +29,22 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #elif defined(_WIN32) + #include + #include #include #endif #if !defined(_WIN32) #include #include #endif - +#if defined(__hpux) + #define _PSTAT64 + #include +#endif #if !defined(_WIN32) && !defined(__APPLE__) && \ !defined(__ANDROID__) && !defined(SERVER) #define XORG_USED #endif - #ifdef XORG_USED #include #include @@ -51,7 +55,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include "log.h" #include "util/string.h" -#include "main.h" #include "settings.h" #include @@ -72,196 +75,68 @@ bool * signal_handler_killstatus(void) #if !defined(_WIN32) // POSIX #include -void sigint_handler(int sig) +void signal_handler(int sig) { - if(g_killed == false) - { - dstream< - BOOL WINAPI event_handler(DWORD sig) - { - switch(sig) - { - case CTRL_C_EVENT: - case CTRL_CLOSE_EVENT: - case CTRL_LOGOFF_EVENT: - case CTRL_SHUTDOWN_EVENT: - - if(g_killed == false) - { - dstream<= 702106)) \ - || defined(__linux) || defined(linux) - - cpu_set_t cpuset; - - CPU_ZERO(&cpuset); - CPU_SET(pnumber, &cpuset); - return pthread_setaffinity_np(tid, sizeof(cpuset), &cpuset) == 0; - -#elif defined(__sun) || defined(sun) - - return processor_bind(P_LWPID, MAKE_LWPID_PTHREAD(tid), - pnumber, NULL) == 0; - -#elif defined(_AIX) - - return bindprocessor(BINDTHREAD, (tid_t)tid, pnumber) == 0; - -#elif defined(__hpux) || defined(hpux) - - pthread_spu_t answer; - - return pthread_processor_bind_np(PTHREAD_BIND_ADVISORY_NP, - &answer, pnumber, tid) == 0; - -#elif defined(__APPLE__) - - struct thread_affinity_policy tapol; - - thread_port_t threadport = pthread_mach_thread_np(tid); - tapol.affinity_tag = pnumber + 1; - return thread_policy_set(threadport, THREAD_AFFINITY_POLICY, - (thread_policy_t)&tapol, THREAD_AFFINITY_POLICY_COUNT) == KERN_SUCCESS; - -#else - - return false; - -#endif -} -#endif - -bool threadSetPriority(threadid_t tid, int prio) { -#if defined(_WIN32) - - HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, 0, tid); - if (!hThread) - return false; - - bool success = SetThreadPriority(hThread, prio) != 0; - - CloseHandle(hThread); - return success; - -#else - - struct sched_param sparam; - int policy; - - if (pthread_getschedparam(tid, &policy, &sparam) != 0) - return false; - - int min = sched_get_priority_min(policy); - int max = sched_get_priority_max(policy); - - sparam.sched_priority = min + prio * (max - min) / THREAD_PRIORITY_HIGHEST; - return pthread_setschedparam(tid, policy, &sparam) == 0; - -#endif -} - - /* Path mangler */ @@ -269,6 +144,9 @@ bool threadSetPriority(threadid_t tid, int prio) { // Default to RUN_IN_PLACE style relative paths std::string path_share = ".."; std::string path_user = ".."; +std::string path_locale = path_share + DIR_DELIM + "locale"; +std::string path_cache = path_user + DIR_DELIM + "cache"; + std::string getDataPath(const char *subpath) { @@ -287,10 +165,16 @@ void pathRemoveFile(char *path, char delim) path[i] = 0; } -bool detectMSVCBuildDir(char *c_path) +bool detectMSVCBuildDir(const std::string &path) { - std::string path(c_path); - const char *ends[] = {"bin\\Release", "bin\\Build", NULL}; + const char *ends[] = { + "bin\\Release", + "bin\\MinSizeRel", + "bin\\RelWithDebInfo", + "bin\\Debug", + "bin\\Build", + NULL + }; return (removeStringEnd(path, ends) != ""); } @@ -308,14 +192,14 @@ std::string get_sysinfo() oss << "Windows/" << osvi.dwMajorVersion << "." << osvi.dwMinorVersion; - if(osvi.szCSDVersion[0]) + if (osvi.szCSDVersion[0]) oss << "-" << tmp; oss << " "; #ifdef _WIN64 oss << "x86_64"; #else BOOL is64 = FALSE; - if(IsWow64Process(GetCurrentProcess(), &is64) && is64) + if (IsWow64Process(GetCurrentProcess(), &is64) && is64) oss << "x86_64"; // 32-bit app on 64-bit OS else oss << "x86"; @@ -330,232 +214,386 @@ std::string get_sysinfo() #endif } -void initializePaths() + +bool getCurrentWorkingDir(char *buf, size_t len) { -#if RUN_IN_PLACE - /* - Use relative paths if RUN_IN_PLACE - */ +#ifdef _WIN32 + DWORD ret = GetCurrentDirectory(len, buf); + return (ret != 0) && (ret <= len); +#else + return getcwd(buf, len); +#endif +} - infostream<<"Using relative paths (RUN_IN_PLACE)"<= len) + return false; - /* scriptapi no longer allows paths that start with "..", so assuming that - the current working directory is bin/, strip off the last component. */ - char *cwd = getcwd(NULL, 0); - pathRemoveFile(cwd, '/'); - path_share = std::string(cwd); - path_user = std::string(cwd); + return true; +} - #endif -#else // RUN_IN_PLACE +// HP-UX +#elif defined(__hpux) + +bool getCurrentExecPath(char *buf, size_t len) +{ + struct pst_status psts; + + if (pstat_getproc(&psts, sizeof(psts), 0, getpid()) == -1) + return false; + + if (pstat_getpathname(buf, len, &psts.pst_fid_text) == -1) + return false; + + return true; +} + + +#else - /* - Use platform-specific paths otherwise - */ +bool getCurrentExecPath(char *buf, size_t len) +{ + return false; +} + +#endif - infostream<<"Using system-wide paths (NOT RUN_IN_PLACE)"<" - len = GetEnvironmentVariable("APPDATA", buf, buflen); - assert(len < buflen); + DWORD len = GetEnvironmentVariable("APPDATA", buf, sizeof(buf)); + FATAL_ERROR_IF(len == 0 || len > sizeof(buf), "Failed to get APPDATA"); + path_user = std::string(buf) + DIR_DELIM + PROJECT_NAME; + return true; +} - /* - Linux - */ - #elif defined(linux) - // Get path to executable - std::string bindir = ""; - { - char buf[BUFSIZ]; - memset(buf, 0, BUFSIZ); - if (readlink("/proc/self/exe", buf, BUFSIZ-1) == -1) { - errorstream << "Unable to read bindir "<< std::endl; -#ifndef __ANDROID__ - assert("Unable to read bindir" == 0); +//// Linux +#elif defined(__linux__) + +bool setSystemPaths() +{ + char buf[BUFSIZ]; + + if (!getCurrentExecPath(buf, sizeof(buf))) { +#ifdef __ANDROID__ + errorstream << "Unable to read bindir "<< std::endl; +#else + FATAL_ERROR("Unable to read bindir"); #endif - } else { - pathRemoveFile(buf, '/'); - bindir = buf; - } + return false; } + pathRemoveFile(buf, '/'); + std::string bindir(buf); + // Find share directory from these. // It is identified by containing the subdirectory "builtin". std::list trylist; std::string static_sharedir = STATIC_SHAREDIR; - if(static_sharedir != "" && static_sharedir != ".") + if (static_sharedir != "" && static_sharedir != ".") trylist.push_back(static_sharedir); - trylist.push_back( - bindir + DIR_DELIM + ".." + DIR_DELIM + "share" + DIR_DELIM + PROJECT_NAME); - trylist.push_back(bindir + DIR_DELIM + ".."); + + trylist.push_back(bindir + DIR_DELIM ".." DIR_DELIM "share" + DIR_DELIM + PROJECT_NAME); + trylist.push_back(bindir + DIR_DELIM ".."); + #ifdef __ANDROID__ trylist.push_back(path_user); #endif - for(std::list::const_iterator i = trylist.begin(); - i != trylist.end(); i++) - { + for (std::list::const_iterator + i = trylist.begin(); i != trylist.end(); i++) { const std::string &trypath = *i; - if(!fs::PathExists(trypath) || !fs::PathExists(trypath + DIR_DELIM + "builtin")){ - dstream<<"WARNING: system-wide share not found at \"" - <= 1 && buf[cwdlen - 1] == DIR_DELIM_CHAR) { + cwdlen--; + buf[cwdlen] = '\0'; + } + + if (cwdlen >= 4 && !strcmp(buf + cwdlen - 4, DIR_DELIM "bin")) + pathRemoveFile(buf, DIR_DELIM_CHAR); + + std::string execpath(buf); + + path_share = execpath; + path_user = execpath; + } + path_cache = path_user + DIR_DELIM + "cache"; +#else + infostream << "Using system-wide paths (NOT RUN_IN_PLACE)" << std::endl; + + if (!setSystemPaths()) + errorstream << "Failed to get one or more system-wide path" << std::endl; + + // Initialize path_cache + // First try $XDG_CACHE_HOME/PROJECT_NAME + const char *cache_dir = getenv("XDG_CACHE_HOME"); + const char *home_dir = getenv("HOME"); + if (cache_dir) { + path_cache = std::string(cache_dir) + DIR_DELIM + PROJECT_NAME; + } else if (home_dir) { + // Then try $HOME/.cache/PROJECT_NAME + path_cache = std::string(home_dir) + DIR_DELIM + ".cache" + + DIR_DELIM + PROJECT_NAME; + } else { + // If neither works, use $PATH_USER/cache + path_cache = path_user + DIR_DELIM + "cache"; + } + // Migrate cache folder to new location if possible + migrateCachePath(); +#endif + + infostream << "Detected share path: " << path_share << std::endl; + infostream << "Detected user path: " << path_user << std::endl; + infostream << "Detected cache path: " << path_cache << std::endl; + +#ifdef USE_GETTEXT + bool found_localedir = false; +# ifdef STATIC_LOCALEDIR + if (STATIC_LOCALEDIR[0] && fs::PathExists(STATIC_LOCALEDIR)) { + found_localedir = true; + path_locale = STATIC_LOCALEDIR; + infostream << "Using locale directory " << STATIC_LOCALEDIR << std::endl; + } else { + path_locale = getDataPath("locale"); + if (fs::PathExists(path_locale)) { + found_localedir = true; + infostream << "Using in-place locale directory " << path_locale + << " even though a static one was provided " + << "(RUN_IN_PLACE or CUSTOM_LOCALEDIR)." << std::endl; + } + } +# else + path_locale = getDataPath("locale"); + if (fs::PathExists(path_locale)) { + found_localedir = true; + } +# endif + if (!found_localedir) { + warningstream << "Couldn't find a locale directory!" << std::endl; + } +#endif // USE_GETTEXT } + + void setXorgClassHint(const video::SExposedVideoData &video_data, const std::string &name) { @@ -573,17 +611,142 @@ void setXorgClassHint(const video::SExposedVideoData &video_data, #endif } +bool setXorgWindowIcon(IrrlichtDevice *device) +{ +#ifdef XORG_USED +# if RUN_IN_PLACE + return setXorgWindowIconFromPath(device, + path_share + "/misc/" PROJECT_NAME "-xorg-icon-128.png"); +# else + // We have semi-support for reading in-place data if we are + // compiled with RUN_IN_PLACE. Don't break with this and + // also try the path_share location. + return + setXorgWindowIconFromPath(device, + ICON_DIR "/hicolor/128x128/apps/" PROJECT_NAME ".png") || + setXorgWindowIconFromPath(device, + path_share + "/misc/" PROJECT_NAME "-xorg-icon-128.png"); +# endif +#else + return false; +#endif +} + +bool setXorgWindowIconFromPath(IrrlichtDevice *device, + const std::string &icon_file) +{ +#ifdef XORG_USED + + video::IVideoDriver *v_driver = device->getVideoDriver(); + + video::IImageLoader *image_loader = NULL; + u32 cnt = v_driver->getImageLoaderCount(); + for (u32 i = 0; i < cnt; i++) { + if (v_driver->getImageLoader(i)->isALoadableFileExtension(icon_file.c_str())) { + image_loader = v_driver->getImageLoader(i); + break; + } + } + + if (!image_loader) { + warningstream << "Could not find image loader for file '" + << icon_file << "'" << std::endl; + return false; + } + + io::IReadFile *icon_f = device->getFileSystem()->createAndOpenFile(icon_file.c_str()); + + if (!icon_f) { + warningstream << "Could not load icon file '" + << icon_file << "'" << std::endl; + return false; + } + + video::IImage *img = image_loader->loadImage(icon_f); + + if (!img) { + warningstream << "Could not load icon file '" + << icon_file << "'" << std::endl; + icon_f->drop(); + return false; + } + + u32 height = img->getDimension().Height; + u32 width = img->getDimension().Width; + + size_t icon_buffer_len = 2 + height * width; + long *icon_buffer = new long[icon_buffer_len]; + + icon_buffer[0] = width; + icon_buffer[1] = height; + + for (u32 x = 0; x < width; x++) { + for (u32 y = 0; y < height; y++) { + video::SColor col = img->getPixel(x, y); + long pixel_val = 0; + pixel_val |= (u8)col.getAlpha() << 24; + pixel_val |= (u8)col.getRed() << 16; + pixel_val |= (u8)col.getGreen() << 8; + pixel_val |= (u8)col.getBlue(); + icon_buffer[2 + x + y * width] = pixel_val; + } + } + + img->drop(); + icon_f->drop(); + + const video::SExposedVideoData &video_data = v_driver->getExposedVideoData(); + + Display *x11_dpl = (Display *)video_data.OpenGLLinux.X11Display; + + if (x11_dpl == NULL) { + warningstream << "Could not find x11 display for setting its icon." + << std::endl; + delete [] icon_buffer; + return false; + } + + Window x11_win = (Window)video_data.OpenGLLinux.X11Window; + + Atom net_wm_icon = XInternAtom(x11_dpl, "_NET_WM_ICON", False); + Atom cardinal = XInternAtom(x11_dpl, "CARDINAL", False); + XChangeProperty(x11_dpl, x11_win, + net_wm_icon, cardinal, 32, + PropModeReplace, (const unsigned char *)icon_buffer, + icon_buffer_len); + + delete [] icon_buffer; + +#endif + return true; +} + +//// +//// Video/Display Information (Client-only) +//// + #ifndef SERVER + +static irr::IrrlichtDevice *device; + +void initIrrlicht(irr::IrrlichtDevice *device_) +{ + device = device_; +} + v2u32 getWindowSize() { return device->getVideoDriver()->getScreenSize(); } -std::vector > getVideoModes() +std::vector > getSupportedVideoModes() { + IrrlichtDevice *nulldevice = createDevice(video::EDT_NULL); + sanity_check(nulldevice != NULL); + std::vector > mlist; - video::IVideoModeList *modelist = device->getVideoModeList(); + video::IVideoModeList *modelist = nulldevice->getVideoModeList(); u32 num_modes = modelist->getVideoModeCount(); for (u32 i = 0; i != num_modes; i++) { @@ -592,6 +755,8 @@ std::vector > getVideoModes() mlist.push_back(core::vector3d(mode_res.Width, mode_res.Height, mode_depth)); } + nulldevice->drop(); + return mlist; } @@ -640,41 +805,47 @@ const char *getVideoDriverFriendlyName(irr::video::E_DRIVER_TYPE type) return driver_names[type]; } +# ifndef __ANDROID__ +# ifdef XORG_USED -#ifndef __ANDROID__ -#ifdef XORG_USED -float getDisplayDensity() +static float calcDisplayDensity() { - const char* current_display = getenv("DISPLAY"); + const char *current_display = getenv("DISPLAY"); if (current_display != NULL) { - Display * x11display = XOpenDisplay(current_display); + Display *x11display = XOpenDisplay(current_display); - if (x11display != NULL) { - /* try x direct */ - float dpi_height = - floor(DisplayHeight(x11display, 0) / - (DisplayHeightMM(x11display, 0) * 0.039370) + 0.5); - float dpi_width = - floor(DisplayWidth(x11display, 0) / - (DisplayWidthMM(x11display, 0) * 0.039370) +0.5); + if (x11display != NULL) { + /* try x direct */ + float dpi_height = floor(DisplayHeight(x11display, 0) / + (DisplayHeightMM(x11display, 0) * 0.039370) + 0.5); + float dpi_width = floor(DisplayWidth(x11display, 0) / + (DisplayWidthMM(x11display, 0) * 0.039370) + 0.5); - XCloseDisplay(x11display); + XCloseDisplay(x11display); - return (std::max(dpi_height,dpi_width) / 96.0); - } + return std::max(dpi_height,dpi_width) / 96.0; } + } /* return manually specified dpi */ return g_settings->getFloat("screen_dpi")/96.0; } -#else + +float getDisplayDensity() +{ + static float cached_display_density = calcDisplayDensity(); + return cached_display_density; +} + + +# else // XORG_USED float getDisplayDensity() { return g_settings->getFloat("screen_dpi")/96.0; } -#endif +# endif // XORG_USED v2u32 getDisplaySize() { @@ -685,8 +856,47 @@ v2u32 getDisplaySize() return deskres; } -#endif +# endif // __ANDROID__ +#endif // SERVER + + +//// +//// OS-specific Secure Random +//// + +#ifdef WIN32 + +bool secure_rand_fill_buf(void *buf, size_t len) +{ + HCRYPTPROV wctx; + + if (!CryptAcquireContext(&wctx, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) + return false; + + CryptGenRandom(wctx, len, (BYTE *)buf); + CryptReleaseContext(wctx, 0); + return true; +} + +#else + +bool secure_rand_fill_buf(void *buf, size_t len) +{ + // N.B. This function checks *only* for /dev/urandom, because on most + // common OSes it is non-blocking, whereas /dev/random is blocking, and it + // is exceptionally uncommon for there to be a situation where /dev/random + // exists but /dev/urandom does not. This guesswork is necessary since + // random devices are not covered by any POSIX standard... + FILE *fp = fopen("/dev/urandom", "rb"); + if (!fp) + return false; + + bool success = fread(buf, len, 1, fp) == 1; + + fclose(fp); + return success; +} + #endif } //namespace porting -