]> gerrit.simantics Code Review - simantics/fmil.git/blobdiff - org.simantics.fmil.core/native/FMILibrary/src/Util/src/JM/jm_portability.c
Add FMILibrary-2.0.3 to org.simantics.fmil.core\native.
[simantics/fmil.git] / org.simantics.fmil.core / native / FMILibrary / src / Util / src / JM / jm_portability.c
diff --git a/org.simantics.fmil.core/native/FMILibrary/src/Util/src/JM/jm_portability.c b/org.simantics.fmil.core/native/FMILibrary/src/Util/src/JM/jm_portability.c
new file mode 100644 (file)
index 0000000..8268b02
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+    Copyright (C) 2012 Modelon AB
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the BSD style license.
+
+     This program 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.  See the
+    FMILIB_License.txt file for more details.
+
+    You should have received a copy of the FMILIB_License.txt file
+    along with this program. If not, contact Modelon AB <http://www.modelon.com>.
+*/\r
+\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <locale.h>\r
+#include <string.h>\r
+
+#include <fmilib_config.h>
+\r
+#include <JM/jm_types.h>\r
+#include <JM/jm_portability.h>\r
+\r
+static const char * module = "JMPRT";\r
+\r
+#ifdef WIN32\r
+#include <shlwapi.h>\r
+#include <direct.h>\r
+#define get_current_working_directory _getcwd\r
+#define set_current_working_directory _chdir   \r
+#else\r
+#include <unistd.h>\r
+#define get_current_working_directory getcwd\r
+#define set_current_working_directory chdir\r
+#endif\r
+\r
+#define JM_PORTABILITY_DLL_ERROR_MESSAGE_SIZE 1000\r
+\r
+DLL_HANDLE jm_portability_load_dll_handle(const char* dll_file_path)\r
+{\r
+#ifdef WIN32\r
+       /* printf("Will try to load %s\n", dll_file_path); */\r
+       return LoadLibrary(dll_file_path);\r
+#else  \r
+       return dlopen(dll_file_path, RTLD_NOW|RTLD_LOCAL);\r
+#endif\r
+}\r
+\r
+jm_status_enu_t jm_portability_free_dll_handle(DLL_HANDLE dll_handle)\r
+{      \r
+#ifdef WIN32           \r
+       if (FreeLibrary(dll_handle)==0) {\r
+               return jm_status_error;\r
+       } else {\r
+               return jm_status_success;\r
+       }\r
+#else          \r
+       if (dlclose(dll_handle)==0) {\r
+               return jm_status_success;                       \r
+       } else {\r
+               return jm_status_error;\r
+       }\r
+#endif\r
+}\r
+\r
+jm_status_enu_t jm_portability_load_dll_function(DLL_HANDLE dll_handle, char* dll_function_name, jm_dll_function_ptr* dll_function_ptrptr)\r
+{\r
+#ifdef WIN32\r
+       *dll_function_ptrptr = (jm_dll_function_ptr)GetProcAddress(dll_handle, dll_function_name);\r
+#else\r
+       *dll_function_ptrptr = dlsym(dll_handle, dll_function_name);\r
+#endif\r
+\r
+       if (*dll_function_ptrptr == NULL) {\r
+               return jm_status_error;\r
+       } else {\r
+               return jm_status_success;\r
+       }\r
+}\r
+\r
+char* jm_portability_get_last_dll_error(void)\r
+{\r
+       static char err_str[JM_PORTABILITY_DLL_ERROR_MESSAGE_SIZE]; \r
+\r
+#ifdef WIN32\r
+       LPVOID lpMsgBuf;\r
+       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);\r
+       jm_snprintf(err_str, JM_PORTABILITY_DLL_ERROR_MESSAGE_SIZE, "%s", lpMsgBuf);\r
+#else\r
+       jm_snprintf(err_str, JM_PORTABILITY_DLL_ERROR_MESSAGE_SIZE, "%s", dlerror());\r
+#endif \r
+       return err_str;\r
+}\r
+\r
+\r
+jm_status_enu_t jm_portability_get_current_working_directory(char* buffer, size_t len)\r
+{\r
+       int ilen = (int)len;\r
+       if(ilen != len) ilen = FILENAME_MAX + 2;\r
+       setlocale(LC_CTYPE, "en_US.UTF-8"); /* just in case, does not seem to have an effect */\r
+       if (get_current_working_directory(buffer, ilen) == NULL) {\r
+               return jm_status_error;\r
+       } else {\r
+               return jm_status_success;\r
+       }\r
+}\r
+\r
+jm_status_enu_t jm_portability_set_current_working_directory(const char* cwd)\r
+{\r
+       if (set_current_working_directory(cwd) == 0) {\r
+               return jm_status_success;\r
+       } else {\r
+               return jm_status_error;\r
+       }\r
+}\r
+\r
+#ifdef WIN32\r
+#define MAX_TEMP_DIR_NAME_LENGTH 262\r
+TCHAR jm_temp_dir_buffer[MAX_TEMP_DIR_NAME_LENGTH];\r
+#endif\r
+\r
+const char* jm_get_system_temp_dir() {\r
+#ifdef WIN32\r
+       if(!GetTempPath(MAX_TEMP_DIR_NAME_LENGTH, jm_temp_dir_buffer)) return 0;\r
+       return jm_temp_dir_buffer;\r
+#else\r
+       return "/tmp/";\r
+#endif\r
+}\r
+\r
+#ifdef WIN32\r
+#include <io.h>\r
+#else\r
+#include <stdlib.h>
+#endif\r
+char *jm_mkdtemp(jm_callbacks *cb, char *tmplt)
+{
+#ifdef WIN32
+    /* Windows does not have mkdtemp, use mktemp + mkdir */
+
+    if(!_mktemp(tmplt)) {
+        jm_log_fatal(cb, module, "Could not create a unique temporary directory name");
+        return NULL;
+    }
+    if(jm_mkdir(cb, tmplt) != jm_status_success) {
+        return NULL;
+    }
+    return tmplt;
+
+#else
+    return mkdtemp(tmplt);
+#endif
+}\r
+\r
+#ifdef WIN32\r
+#include <direct.h>\r
+#define MKDIR(dir) _mkdir(dir)\r
+#else\r
+#include <errno.h>\r
+#include <sys/stat.h>\r
+#define MKDIR(dir) mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)\r
+#endif\r
+\r
+jm_status_enu_t jm_mkdir(jm_callbacks* cb, const char* dir) {\r
+       if(!cb) {
+               cb = jm_get_default_callbacks();
+       }
+       if(MKDIR(dir)) {\r
+               jm_log_fatal(cb,module,"Could not create directory %s", dir);\r
+               return jm_status_error;\r
+       }\r
+       else\r
+               return jm_status_success;\r
+}\r
+\r
+\r
+jm_status_enu_t jm_rmdir(jm_callbacks* cb, const char* dir) {\r
+#ifdef WIN32
+       const char* fmt_cmd = "rmdir /s /q %s";
+#else
+    const char* fmt_cmd = "rm -rf %s";
+#endif
+    char * buf = (char*)cb->calloc(sizeof(char), strlen(dir)+strlen(fmt_cmd)+1);
+       if(!cb) {
+               cb = jm_get_default_callbacks();
+       }
+       if(!buf) {
+           jm_log_error(cb,module,"Could not allocate memory");
+               return jm_status_error;
+       }
+    sprintf(buf, fmt_cmd, dir);/*safe*/
+#ifdef WIN32
+       {
+               char* ch = buf+strlen(fmt_cmd) - 2;
+               while(*ch) {
+                       if(*ch == '/') *ch = '\\';
+                       ch++;
+               }
+       }
+#endif
+    jm_log_verbose(cb,module,"Removing %s", dir);
+    if(system(buf)) {
+           jm_log_error(cb,module,"Error removing %s (%s)", dir, strerror(errno));
+               return jm_status_error;
+       }
+    cb->free(buf);
+       return jm_status_success;
+}
+
+char* jm_get_dir_abspath(jm_callbacks* cb, const char* dir, char* outPath, size_t len) {\r
+       char curDir[FILENAME_MAX + 2];\r
+\r
+       if(!cb) {
+               cb = jm_get_default_callbacks();
+       }
+       if( jm_portability_get_current_working_directory(curDir, FILENAME_MAX+1) != jm_status_success) {\r
+               jm_log_fatal(cb,module, "Could not get current working directory (%s)", strerror(errno));\r
+               return 0;\r
+       };\r
+\r
+       if(jm_portability_set_current_working_directory(dir) != jm_status_success) {\r
+               jm_log_fatal(cb,module, "Could not change to the directory %s", dir);\r
+               jm_portability_set_current_working_directory(curDir);\r
+               return 0;\r
+       };\r
+       if( jm_portability_get_current_working_directory(outPath, len) != jm_status_success) {\r
+               jm_log_fatal(cb,module, "Could not get absolute path for the directory (%s)", strerror(errno));\r
+               jm_portability_set_current_working_directory(curDir);\r
+               return 0;\r
+       };\r
+       jm_portability_set_current_working_directory(curDir);\r
+       return outPath;\r
+}\r
+
+
+char* jm_mk_temp_dir(jm_callbacks* cb, const char* systemTempDir, const char* tempPrefix)
+{\r
+       size_t len;\r
+\r
+       char tmpDir[FILENAME_MAX + 2];\r
+       char* tmpPath;\r
+\r
+       if(!cb) {
+               cb = jm_get_default_callbacks();
+       }
+       if(!systemTempDir) {\r
+               systemTempDir = jm_get_system_temp_dir();\r
+               if(!systemTempDir) systemTempDir = "./";\r
+       }\r
+       if(!tempPrefix) {\r
+               tempPrefix = "jm";\r
+       }\r
+       len = strlen(systemTempDir);\r
+\r
+       if(!jm_get_dir_abspath(cb, systemTempDir, tmpDir, FILENAME_MAX + 2)) {\r
+               return 0;\r
+       }\r
+\r
+       len = strlen(tmpDir);\r
+       if(tmpDir[len-1] != FMI_FILE_SEP[0]) {\r
+               tmpDir[len] = FMI_FILE_SEP[0]; \r
+               tmpDir[len+1] = 0;\r
+               len++;\r
+       }\r
+       len += strlen(tempPrefix) + 6;\r
+       if(len + 16 > FILENAME_MAX) {\r
+               jm_log_fatal(cb,module, "Canonical name for the temporary files directory is too long (system limit for path length is %d)", FILENAME_MAX);\r
+               return 0;\r
+       }\r
+       tmpPath = (char*)cb->malloc(len + 7);\r
+       if(!tmpPath) {\r
+               jm_log_fatal(cb, module,"Could not allocate memory");\r
+               return 0;\r
+       }\r
+       sprintf(tmpPath,"%s%sXXXXXX",tmpDir,tempPrefix);/*safe*/\r
+\r
+    if (jm_mkdtemp(cb, tmpPath) == NULL) {
+        jm_log_fatal(cb, module,"Could not create a unique temporary directory");
+    }
+
+       return tmpPath;\r
+}\r
+\r
+char* jm_create_URL_from_abs_path(jm_callbacks* cb, const char* path) {\r
+       /* worst case: all symbols are 4-byte UTF-8 and need to be %-encoded */\r
+#define MAX_URL_LENGTH  (FILENAME_MAX * 4 * 3 + 7)\r
+       char buffer[MAX_URL_LENGTH];\r
+       char* url;\r
+       size_t urllen;\r
+       if(!cb) {
+               cb = jm_get_default_callbacks();
+       }
+\r
+#if defined(_WIN32) || defined(WIN32)\r
+       {\r
+               DWORD pathLen = MAX_URL_LENGTH;\r
+               HRESULT code = UrlCreateFromPathA(\r
+                       path,\r
+                       buffer,\r
+                       &pathLen,\r
+                       0);\r
+               if( (code != S_FALSE) && (code != S_OK)) {\r
+                       jm_log_fatal(cb, module,"Could not constuct file URL from path %s", path);\r
+                       return 0;\r
+               }\r
+               urllen = pathLen;\r
+       }\r
+#else\r
+       {\r
+               size_t i, len = strlen(path);\r
+               char *curBuf = buffer + 7;\r
+               unsigned char ch;\r
+               strcpy(buffer, "file://");\r
+               for( i = 0; i < len; i++) {\r
+                       ch = (unsigned char)path[i];\r
+                       if( (ch == '/') || ((ch >= 'A') && (ch <= 'Z')) \r
+                               || ((ch >= 'a') && (ch <= 'z'))\r
+                               || ((ch >= '0') && (ch <= '9'))\r
+                               || (ch == '-') || (ch == '_') || (ch == '.') ||(ch == '~')) {\r
+                                       *curBuf = ch;\r
+                                       curBuf++;\r
+                                       continue;\r
+                       }\r
+                       sprintf(curBuf, "%%%2X", (int)ch);/*safe*/\r
+                       curBuf+=3;\r
+               }\r
+               *curBuf = 0;\r
+               urllen = curBuf - buffer;\r
+       }\r
+#endif\r
+       url = (char*)cb->malloc(urllen+1);\r
+       if(!url) {\r
+               jm_log_fatal(cb, module,"Could not allocate memory");\r
+               return 0;\r
+       }\r
+       strcpy(url, buffer);\r
+       return url;\r
+}\r
+
+#ifndef HAVE_VSNPRINTF
+int jm_rpl_vsnprintf(char *, size_t, const char *, va_list);
+#endif
+
+int jm_vsnprintf(char * str, size_t size, const char * fmt, va_list al) {
+    return jm_rpl_vsnprintf(str, size, fmt, al);
+}
+
+int jm_snprintf(char * str, size_t size, const char * fmt, ...) {
+    va_list args;
+    int ret;
+    va_start (args, fmt);
+    ret = jm_vsnprintf(str, size, fmt, args);
+    va_end (args);
+    return ret;
+}