2 Copyright (C) 2012 Modelon AB
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the BSD style license.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 FMILIB_License.txt file for more details.
12 You should have received a copy of the FMILIB_License.txt file
13 along with this program. If not, contact Modelon AB <http://www.modelon.com>.
21 #include <fmilib_config.h>
23 #include <JM/jm_types.h>
\r
24 #include <JM/jm_portability.h>
\r
26 static const char * module = "JMPRT";
\r
29 #include <shlwapi.h>
\r
31 #define get_current_working_directory _getcwd
\r
32 #define set_current_working_directory _chdir
\r
35 #define get_current_working_directory getcwd
\r
36 #define set_current_working_directory chdir
\r
39 #define JM_PORTABILITY_DLL_ERROR_MESSAGE_SIZE 1000
\r
41 DLL_HANDLE jm_portability_load_dll_handle(const char* dll_file_path)
\r
44 /* printf("Will try to load %s\n", dll_file_path); */
\r
45 return LoadLibrary(dll_file_path);
\r
47 return dlopen(dll_file_path, RTLD_NOW|RTLD_LOCAL);
\r
51 jm_status_enu_t jm_portability_free_dll_handle(DLL_HANDLE dll_handle)
\r
54 if (FreeLibrary(dll_handle)==0) {
\r
55 return jm_status_error;
\r
57 return jm_status_success;
\r
60 if (dlclose(dll_handle)==0) {
\r
61 return jm_status_success;
\r
63 return jm_status_error;
\r
68 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
71 *dll_function_ptrptr = (jm_dll_function_ptr)GetProcAddress(dll_handle, dll_function_name);
\r
73 *dll_function_ptrptr = dlsym(dll_handle, dll_function_name);
\r
76 if (*dll_function_ptrptr == NULL) {
\r
77 return jm_status_error;
\r
79 return jm_status_success;
\r
83 char* jm_portability_get_last_dll_error(void)
\r
85 static char err_str[JM_PORTABILITY_DLL_ERROR_MESSAGE_SIZE];
\r
89 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
90 jm_snprintf(err_str, JM_PORTABILITY_DLL_ERROR_MESSAGE_SIZE, "%s", lpMsgBuf);
\r
92 jm_snprintf(err_str, JM_PORTABILITY_DLL_ERROR_MESSAGE_SIZE, "%s", dlerror());
\r
98 jm_status_enu_t jm_portability_get_current_working_directory(char* buffer, size_t len)
\r
100 int ilen = (int)len;
\r
101 if(ilen != len) ilen = FILENAME_MAX + 2;
\r
102 setlocale(LC_CTYPE, "en_US.UTF-8"); /* just in case, does not seem to have an effect */
\r
103 if (get_current_working_directory(buffer, ilen) == NULL) {
\r
104 return jm_status_error;
\r
106 return jm_status_success;
\r
110 jm_status_enu_t jm_portability_set_current_working_directory(const char* cwd)
\r
112 if (set_current_working_directory(cwd) == 0) {
\r
113 return jm_status_success;
\r
115 return jm_status_error;
\r
120 #define MAX_TEMP_DIR_NAME_LENGTH 262
\r
121 TCHAR jm_temp_dir_buffer[MAX_TEMP_DIR_NAME_LENGTH];
\r
124 const char* jm_get_system_temp_dir() {
\r
126 if(!GetTempPath(MAX_TEMP_DIR_NAME_LENGTH, jm_temp_dir_buffer)) return 0;
\r
127 return jm_temp_dir_buffer;
\r
138 char *jm_mkdtemp(jm_callbacks *cb, char *tmplt)
141 /* Windows does not have mkdtemp, use mktemp + mkdir */
143 if(!_mktemp(tmplt)) {
144 jm_log_fatal(cb, module, "Could not create a unique temporary directory name");
147 if(jm_mkdir(cb, tmplt) != jm_status_success) {
153 return mkdtemp(tmplt);
158 #include <direct.h>
\r
159 #define MKDIR(dir) _mkdir(dir)
\r
162 #include <sys/stat.h>
\r
163 #define MKDIR(dir) mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)
\r
166 jm_status_enu_t jm_mkdir(jm_callbacks* cb, const char* dir) {
\r
168 cb = jm_get_default_callbacks();
171 jm_log_fatal(cb,module,"Could not create directory %s", dir);
\r
172 return jm_status_error;
\r
175 return jm_status_success;
\r
179 jm_status_enu_t jm_rmdir(jm_callbacks* cb, const char* dir) {
\r
181 const char* fmt_cmd = "rmdir /s /q %s";
183 const char* fmt_cmd = "rm -rf %s";
185 char * buf = (char*)cb->calloc(sizeof(char), strlen(dir)+strlen(fmt_cmd)+1);
187 cb = jm_get_default_callbacks();
190 jm_log_error(cb,module,"Could not allocate memory");
191 return jm_status_error;
193 sprintf(buf, fmt_cmd, dir);/*safe*/
196 char* ch = buf+strlen(fmt_cmd) - 2;
198 if(*ch == '/') *ch = '\\';
203 jm_log_verbose(cb,module,"Removing %s", dir);
205 jm_log_error(cb,module,"Error removing %s (%s)", dir, strerror(errno));
206 return jm_status_error;
209 return jm_status_success;
212 char* jm_get_dir_abspath(jm_callbacks* cb, const char* dir, char* outPath, size_t len) {
\r
213 char curDir[FILENAME_MAX + 2];
\r
216 cb = jm_get_default_callbacks();
218 if( jm_portability_get_current_working_directory(curDir, FILENAME_MAX+1) != jm_status_success) {
\r
219 jm_log_fatal(cb,module, "Could not get current working directory (%s)", strerror(errno));
\r
223 if(jm_portability_set_current_working_directory(dir) != jm_status_success) {
\r
224 jm_log_fatal(cb,module, "Could not change to the directory %s", dir);
\r
225 jm_portability_set_current_working_directory(curDir);
\r
228 if( jm_portability_get_current_working_directory(outPath, len) != jm_status_success) {
\r
229 jm_log_fatal(cb,module, "Could not get absolute path for the directory (%s)", strerror(errno));
\r
230 jm_portability_set_current_working_directory(curDir);
\r
233 jm_portability_set_current_working_directory(curDir);
\r
238 char* jm_mk_temp_dir(jm_callbacks* cb, const char* systemTempDir, const char* tempPrefix)
242 char tmpDir[FILENAME_MAX + 2];
\r
246 cb = jm_get_default_callbacks();
248 if(!systemTempDir) {
\r
249 systemTempDir = jm_get_system_temp_dir();
\r
250 if(!systemTempDir) systemTempDir = "./";
\r
255 len = strlen(systemTempDir);
\r
257 if(!jm_get_dir_abspath(cb, systemTempDir, tmpDir, FILENAME_MAX + 2)) {
\r
261 len = strlen(tmpDir);
\r
262 if(tmpDir[len-1] != FMI_FILE_SEP[0]) {
\r
263 tmpDir[len] = FMI_FILE_SEP[0];
\r
267 len += strlen(tempPrefix) + 6;
\r
268 if(len + 16 > FILENAME_MAX) {
\r
269 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
272 tmpPath = (char*)cb->malloc(len + 7);
\r
274 jm_log_fatal(cb, module,"Could not allocate memory");
\r
277 sprintf(tmpPath,"%s%sXXXXXX",tmpDir,tempPrefix);/*safe*/
\r
279 if (jm_mkdtemp(cb, tmpPath) == NULL) {
280 jm_log_fatal(cb, module,"Could not create a unique temporary directory");
286 char* jm_create_URL_from_abs_path(jm_callbacks* cb, const char* path) {
\r
287 /* worst case: all symbols are 4-byte UTF-8 and need to be %-encoded */
\r
288 #define MAX_URL_LENGTH (FILENAME_MAX * 4 * 3 + 7)
\r
289 char buffer[MAX_URL_LENGTH];
\r
293 cb = jm_get_default_callbacks();
296 #if defined(_WIN32) || defined(WIN32)
\r
298 DWORD pathLen = MAX_URL_LENGTH;
\r
299 HRESULT code = UrlCreateFromPathA(
\r
304 if( (code != S_FALSE) && (code != S_OK)) {
\r
305 jm_log_fatal(cb, module,"Could not constuct file URL from path %s", path);
\r
312 size_t i, len = strlen(path);
\r
313 char *curBuf = buffer + 7;
\r
315 strcpy(buffer, "file://");
\r
316 for( i = 0; i < len; i++) {
\r
317 ch = (unsigned char)path[i];
\r
318 if( (ch == '/') || ((ch >= 'A') && (ch <= 'Z'))
\r
319 || ((ch >= 'a') && (ch <= 'z'))
\r
320 || ((ch >= '0') && (ch <= '9'))
\r
321 || (ch == '-') || (ch == '_') || (ch == '.') ||(ch == '~')) {
\r
326 sprintf(curBuf, "%%%2X", (int)ch);/*safe*/
\r
330 urllen = curBuf - buffer;
\r
333 url = (char*)cb->malloc(urllen+1);
\r
335 jm_log_fatal(cb, module,"Could not allocate memory");
\r
338 strcpy(url, buffer);
\r
342 #ifndef HAVE_VSNPRINTF
343 int jm_rpl_vsnprintf(char *, size_t, const char *, va_list);
346 int jm_vsnprintf(char * str, size_t size, const char * fmt, va_list al) {
347 return jm_rpl_vsnprintf(str, size, fmt, al);
350 int jm_snprintf(char * str, size_t size, const char * fmt, ...) {
353 va_start (args, fmt);
354 ret = jm_vsnprintf(str, size, fmt, args);