ecere/sys/ECON: Fixed ECON parsing bug with : inside string
[sdk] / ecere / src / sys / System.c
1 #define _Noreturn
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <stdarg.h>
6 #include <string.h>
7
8 #define UNICODE
9
10 #if (defined(__unix__) || defined(__APPLE__)) && !defined(__dos__)
11 #define DIR_SEP   '/'
12 #define DIR_SEPS  "/"
13 #else
14 #define DIR_SEP   '\\'
15 #define DIR_SEPS  "\\"
16 #endif
17
18 // Maximum length for a vsprintf string
19 #define MAX_F_STRING 1025
20
21 #if defined(__WIN32__)
22
23 #define WIN32_LEAN_AND_MEAN
24 #include <windows.h>
25 #include <io.h>
26 #include <direct.h>
27 #include <shellapi.h>
28
29 #else
30
31 #include <unistd.h>
32 #include <sys/stat.h>
33
34 #endif
35
36 typedef int bool;
37 typedef unsigned int FileAttribs;
38 typedef unsigned char byte;
39 typedef unsigned int FileSize;
40 typedef unsigned short uint16;
41 typedef unsigned int uint;
42 typedef unsigned long long uint64;
43 typedef uint64 FileSize64;
44
45 #define false 0
46 #define true 1
47
48 #define null ((void *)0)
49
50 #define isDirectory  0x0040
51
52 #define MAX_LOCATION 797
53 #define MAX_FILENAME 274
54
55 void __ecereNameSpace__ecere__com__eSystem_Delete(void * memory);
56 void * __ecereNameSpace__ecere__com__eSystem_New(unsigned int size);
57 void * __ecereNameSpace__ecere__com__eSystem_New0(unsigned int size);
58 void * __ecereNameSpace__ecere__com__eSystem_Renew(void * memory, unsigned int size);
59 void * __ecereNameSpace__ecere__com__eSystem_Renew0(void * memory, unsigned int size);
60
61 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16(const char * source, int * wordCount);
62 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer(const char * source, uint16 * dest, int max);
63 char * __ecereNameSpace__ecere__sys__UTF16toUTF8(const uint16 * source);
64 char * __ecereNameSpace__ecere__sys__UTF16toUTF8Buffer(const uint16 * source, char * dest, int max);
65
66 char * __ecereNameSpace__ecere__sys__StripLastDirectory(const char * string, char * output);
67
68 char * __ecereNameSpace__ecere__sys__GetEnvironment(const char * envName, char * envValue, int max);
69 char * __ecereNameSpace__ecere__sys__SearchString(const char * buffer, int start, const char * subStr, bool matchCase, bool matchWord);
70
71 FileAttribs FILE_FileExists(const char * fileName);
72
73 bool System_MoveFile(const char * source, const char * dest, uint replaceAndFlush)
74 {
75 #ifdef __WIN32__
76    bool result;
77    uint16 * _wsource = __ecereNameSpace__ecere__sys__UTF8toUTF16(source, null);
78    uint16 * _wdest = __ecereNameSpace__ecere__sys__UTF8toUTF16(dest, null);
79                                                                   // TODO: Select options individually
80    result = MoveFileEx(_wsource, _wdest, MOVEFILE_COPY_ALLOWED | (replaceAndFlush ? MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH : 0)) != 0;
81    __ecereNameSpace__ecere__com__eSystem_Delete(_wsource);
82    __ecereNameSpace__ecere__com__eSystem_Delete(_wdest);
83    return result;
84 #else
85    return rename(source, dest) == 0;
86 #endif
87 }
88
89 bool System_RenameFile(const char * oldName, const char * newName)
90 {
91 #if defined(__WIN32__)
92    bool result;
93    uint16 * _woldName = __ecereNameSpace__ecere__sys__UTF8toUTF16(oldName, null);
94    uint16 * _wnewName = __ecereNameSpace__ecere__sys__UTF8toUTF16(newName, null);
95    result = _wrename(_woldName, _wnewName) == 0;
96    __ecereNameSpace__ecere__com__eSystem_Delete(_woldName);
97    __ecereNameSpace__ecere__com__eSystem_Delete(_wnewName);
98    return result;
99
100 #else
101    return rename(oldName, newName) == 0;
102 #endif
103 }
104
105 bool System_DeleteFile(const char * fileName)
106 {
107    bool result = true;
108 #if defined(__WIN32__)
109    uint16 * _wfileName = __ecereNameSpace__ecere__sys__UTF8toUTF16(fileName, null);
110    if(_wunlink(_wfileName))
111       result = false;
112       //if(errno == 13/*EACCES*/) printf("delete file access error\n");
113       //else if(errno == 2/*ENOENT*/) printf("delete file file does not exist error\n");
114    __ecereNameSpace__ecere__com__eSystem_Delete(_wfileName);
115 #else
116    unlink(fileName);
117 #endif
118    return result;
119 }
120
121 bool System_MakeDir(const char * path)
122 {
123    bool result = false;
124    char location[MAX_LOCATION] = "";
125    int locationLen = 0;
126    int c = 0;
127 #ifdef __WIN32__
128    if(path[0] && path[1] == ':')
129       c = 2;
130    else if(path[0] == '\\' && path[1] == '\\')
131       c = 2;
132    else
133 #endif
134    if(path[0] == '/' || path[0] == '\\')
135       c = 1;
136
137    strncpy(location, path, c);
138    location[c] = '\0';
139    locationLen = c;
140
141    for(; path[c]; )
142    {
143       char directory[MAX_FILENAME];
144       int len = 0;
145       char ch;
146       for(;(ch = path[c]) && (ch == '/' || ch == '\\'); c++);
147       for(;(ch = path[c]) && (ch != '/' && ch != '\\'); c++)
148       {
149          if(len < MAX_FILENAME)
150             directory[len++] = ch;
151       }
152       directory[len] = '\0';
153       if(locationLen > 0 &&
154          (location[locationLen-1] != '\\' && location[locationLen-1] != '/'))
155          strcat(location, DIR_SEPS);
156       strcat(location, directory);
157       locationLen = strlen(location);
158
159       if(FILE_FileExists(location) != isDirectory)
160       {
161 #if defined(__unix__) || defined(__APPLE__)
162          result = !mkdir(location, 0755);
163 #else
164          uint16 _wlocation[MAX_LOCATION];
165          __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer(location, _wlocation, MAX_LOCATION);
166          result = !_wmkdir(_wlocation);
167 #endif
168       }
169    }
170    return result;
171 }
172
173 bool System_RemoveDir(const char * path)
174 {
175    bool result = false;
176    char location[MAX_LOCATION] = "";
177    int locationLen = 0;
178    int c = 0;
179 #ifdef __WIN32__
180    if(path[0] && path[1] == ':')
181       c = 2;
182    else if(path[0] == '\\' && path[1] == '\\')
183       c = 2;
184    else
185 #endif
186    if(path[0] == '/' || path[0] == '\\')
187       c = 1;
188
189    strncpy(location, path, c);
190    location[c] = '\0';
191    locationLen = c;
192
193    for(; path[c]; )
194    {
195       char directory[MAX_FILENAME];
196       int len = 0;
197       char ch;
198       for(;(ch = path[c]) && (ch == '/' || ch == '\\'); c++);
199       for(;(ch = path[c]) && (ch != '/' && ch != '\\'); c++)
200       {
201          if(len < MAX_FILENAME)
202             directory[len++] = ch;
203       }
204       directory[len] = '\0';
205       if(locationLen > 0 &&
206          (location[locationLen-1] != '\\' && location[locationLen-1] != '/'))
207          strcat(location, DIR_SEPS);
208       strcat(location, directory);
209       locationLen = strlen(location);
210
211       if(FILE_FileExists(location) == isDirectory)
212       {
213 #if defined(__unix__) || defined(__APPLE__)
214          rmdir(location);
215 #else
216          uint16 _wlocation[MAX_LOCATION];
217          __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer(location, _wlocation, MAX_LOCATION);
218          _wrmdir(_wlocation);
219 #endif
220          result = true;
221       }
222    }
223    return result;
224 }
225
226 char * System_GetWorkingDir(char * buf, int size)
227 {
228 #if defined(__WIN32__)
229    uint16 * _wbuf = __ecereNameSpace__ecere__com__eSystem_New(sizeof(uint16) * size);
230    _wgetcwd(_wbuf, size);
231    __ecereNameSpace__ecere__sys__UTF16toUTF8Buffer(_wbuf, buf, size);
232    __ecereNameSpace__ecere__com__eSystem_Delete(_wbuf);
233    return buf;
234 #else
235    return getcwd(buf, size);
236 #endif
237 }
238
239 bool System_ChangeWorkingDir(const char * buf)
240 {
241 #if defined(__WIN32__)
242    bool result;
243    uint16 * _wbuf = __ecereNameSpace__ecere__sys__UTF8toUTF16(buf, null);
244    result = !chdir(buf);
245    __ecereNameSpace__ecere__com__eSystem_Delete(_wbuf);
246    return result;
247 #else
248    return !chdir(buf);
249 #endif
250 }
251
252 const char * System_GetEnvironment(const char * envName, char * envValue, int max)
253 {
254 #if defined(__WIN32__)
255    uint16 * _wenvName = __ecereNameSpace__ecere__sys__UTF8toUTF16(envName, null);
256    //uint16 * result;
257    uint16 result[2048];
258    int success;
259
260    success = GetEnvironmentVariable(_wenvName, result, sizeof(result) / sizeof(uint16));
261    //result = _wgetenv(_wenvName);
262    //if(result)
263    if(success && success < sizeof(result) / sizeof(uint16))
264       __ecereNameSpace__ecere__sys__UTF16toUTF8Buffer(result, envValue, max);
265    else
266       envValue[0] = 0;
267
268    __ecereNameSpace__ecere__com__eSystem_Delete(_wenvName);
269    // Distinguish empty vs. unexisting environment variables with GetLastError()
270    return (success || !GetLastError()) ? envValue : null;
271 #else
272    char * result = getenv(envName);
273    if(result)
274       strncpy(envValue, result, max);
275    else
276       envValue[0] = 0;
277    return result ? envValue : null;
278 #endif
279 }
280
281 void System_SetEnvironment(const char * envName, const char * envValue)
282 {
283 #if defined(__WIN32__)
284    uint16 * _wenvName = __ecereNameSpace__ecere__sys__UTF8toUTF16(envName, null);
285    uint16 * _wenvValue = __ecereNameSpace__ecere__sys__UTF8toUTF16(envValue, null);
286    SetEnvironmentVariable(_wenvName, _wenvValue);
287    __ecereNameSpace__ecere__com__eSystem_Delete(_wenvName);
288    __ecereNameSpace__ecere__com__eSystem_Delete(_wenvValue);
289 #else
290    setenv(envName, envValue, 1);
291 #endif
292 }
293
294 void System_UnsetEnvironment(const char * envName)
295 {
296 #if defined(__WIN32__)
297    uint16 * _wenvName = __ecereNameSpace__ecere__sys__UTF8toUTF16(envName, null);
298    SetEnvironmentVariable(_wenvName, null);
299    __ecereNameSpace__ecere__com__eSystem_Delete(_wenvName);
300 #else
301    unsetenv(envName);
302 #endif
303 }
304
305 bool System_Execute(const char * env, const char * command, va_list args, bool wait)
306 {
307    bool result = false;
308    char commandLine[MAX_F_STRING*4];
309    vsnprintf(commandLine, sizeof(commandLine)-1, command, args);
310    commandLine[sizeof(commandLine)-1] = 0;
311
312 #ifndef __WIN32__
313    {
314       if(!wait) strcat(commandLine, "&");
315       result = system(commandLine) != -1;
316    }
317 #else
318    {
319       PROCESS_INFORMATION pi;
320       STARTUPINFO si = { 0 };
321       uint16 * _wcommandLine = __ecereNameSpace__ecere__sys__UTF8toUTF16(commandLine, null);
322
323       // Set up the start up info struct.
324       si.cb = sizeof(STARTUPINFO);
325       // if(CreateProcess(null, _wcommandLine, null, null, TRUE, 0, env, null, &si, &pi))
326       if(CreateProcess(null, _wcommandLine, null, null, TRUE, CREATE_NEW_CONSOLE, (void *)env, null, &si, &pi))
327       {
328          if(wait)
329             WaitForSingleObject(pi.hProcess, INFINITE);
330
331          CloseHandle(pi.hProcess);
332          CloseHandle(pi.hThread);
333          result = true;
334       }
335       __ecereNameSpace__ecere__com__eSystem_Delete(_wcommandLine);
336    }
337 #endif
338    return result;
339 }
340
341 bool System_ShellOpen(const char * fileName, va_list args)
342 {
343    bool result = false;
344    char filePath[MAX_F_STRING*4];
345    int len;
346 #if defined(__WIN32__)
347    filePath[0] = '"';
348    vsnprintf(filePath+1, sizeof(filePath)-2,fileName, args);
349 #else
350    vsnprintf(filePath, sizeof(filePath), fileName, args);
351 #endif
352    filePath[sizeof(filePath)-1] = 0;
353
354    len = strlen(filePath);
355 #if defined(__WIN32__)
356    filePath[len] = '"';
357    filePath[len+1] = '\0';
358 #else
359    filePath[len] = '\0';
360 #endif
361
362 #if !defined(__WIN32__)
363    {
364       char command[MAX_LOCATION] = "";
365       char desktop[MAX_F_STRING];
366       __ecereNameSpace__ecere__sys__GetEnvironment("ECERE_DESKTOP", desktop, sizeof(desktop));
367       if(__ecereNameSpace__ecere__sys__SearchString(desktop, 0, "ecere", false, false))
368          sprintf(command, "ede-open \"%s\" &", filePath);
369       else
370       {
371          __ecereNameSpace__ecere__sys__GetEnvironment("DESKTOP_SESSION", desktop, sizeof(desktop));
372          if(__ecereNameSpace__ecere__sys__SearchString(desktop, 0, "gnome", false, false))
373             sprintf(command, "gnome-open \"%s\" &", filePath);
374          else if(__ecereNameSpace__ecere__sys__SearchString(desktop, 0, "kde", false, false))
375             sprintf(command, "kde-open \"%s\" &", filePath);
376          else
377             sprintf(command, "xdg-open \"%s\" &", filePath);
378       }
379
380       if(command[0] && system(command) != -1)
381          result = true;
382    }
383 #elif defined(ECERE_VANILLA)
384    {
385       uint16 * _wfilePath = __ecereNameSpace__ecere__sys__UTF8toUTF16(filePath, null);
386       if(_wsystem(_wfilePath) != -1)
387          result = true;
388       __ecereNameSpace__ecere__com__eSystem_Delete(_wfilePath);
389    }
390 #else
391    {
392       uint16 * _wfilePath = __ecereNameSpace__ecere__sys__UTF8toUTF16(filePath, null);
393       char curDir[MAX_LOCATION];
394       uint16 * _wcurDir;
395       __ecereNameSpace__ecere__sys__StripLastDirectory(filePath, curDir);
396       _wcurDir = __ecereNameSpace__ecere__sys__UTF8toUTF16(curDir, null);
397       //if(ShellExecute(null, "open", _wfilePath, null, curDir, SW_SHOWNORMAL) > 32)
398       if((void *)ShellExecute(null, null, _wfilePath, null, _wcurDir, SW_SHOWNORMAL) > (void *)32)
399          result = true;
400       __ecereNameSpace__ecere__com__eSystem_Delete(_wfilePath);
401       __ecereNameSpace__ecere__com__eSystem_Delete(_wcurDir);
402    }
403 #endif
404    return result;
405 }
406
407 void System_GetFreeSpace(const char * path, FileSize64 * size)
408 {
409    uint64 freeSize = 0;
410 #ifdef __WIN32__
411    uint16 * _wpath = __ecereNameSpace__ecere__sys__UTF8toUTF16(path, null);
412    GetDiskFreeSpaceEx(_wpath, (PULARGE_INTEGER)&freeSize, null, null);
413    __ecereNameSpace__ecere__com__eSystem_Delete(_wpath);
414 #endif
415    *size = (FileSize64)freeSize;
416 }