* Bug 16328 fixed: typos exists => exist
[scilab.git] / scilab / modules / ast / src / cpp / system_env / sci_home.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2010 - DIGITEO - Antoine ELIAS
4 *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13 *
14 */
15
16
17 #include "configvariable.hxx"
18
19 #include "string.hxx"
20 #include "context.hxx"
21
22 extern "C"
23 {
24 #include "sci_malloc.h"
25 #include "sci_home.h"
26 #include "os_string.h"
27 #include "charEncoding.h"
28 #include "PATH_MAX.h"
29 #include "machine.h"
30 #include "version.h"
31 #include "setenvc.h"
32 #include "getenvc.h"
33 #include "setenvvar.h"
34 #include "getshortpathname.h"
35 #include "sciprint.h"
36 #include "isdir.h"
37 #include "createdirectory.h"
38 #ifndef _MSC_VER
39 #include <sys/stat.h>
40 #else
41 #include <Shlwapi.h>
42 #endif
43 }
44
45 static void setSCIHOMEW(const wchar_t* _sci_home);
46 static void putenvSCIHOME(const char* _sci_home);
47 static char* computeSCIHOME(const char* path = "");
48 static wchar_t* computeSCIHOMEW(const wchar_t* path = L"");
49 static bool createDirectoryRecursivelyW(const std::wstring& path);
50 static bool createDirectoryRecursively(const std::string& path);
51
52
53 /*--------------------------------------------------------------------------*/
54 wchar_t* getSCIHOMEW(void)
55 {
56     return os_wcsdup(ConfigVariable::getSCIHOME().c_str());
57 }
58 /*--------------------------------------------------------------------------*/
59 char* getSCIHOME(void)
60 {
61     std::wstring tmpSCIHOME = ConfigVariable::getSCIHOME();
62     if (tmpSCIHOME == L"")
63     {
64         tmpSCIHOME = L"empty_SCIHOME";
65     }
66     return wide_string_to_UTF8(tmpSCIHOME.c_str());
67 }
68 /*--------------------------------------------------------------------------*/
69 static void setSCIHOME(const char* _sci_home)
70 {
71     wchar_t* pstTemp = to_wide_string(_sci_home);
72     setSCIHOMEW(pstTemp);
73     FREE(pstTemp);
74 }
75 /*--------------------------------------------------------------------------*/
76 static void setSCIHOMEW(const wchar_t* _sci_home)
77 {
78     //add SCI value in context as variable
79     types::String *pS = new types::String(_sci_home);
80     symbol::Context::getInstance()->put(symbol::Symbol(L"SCIHOME"), pS);
81
82     std::wstring sci_home(_sci_home);
83     ConfigVariable::setSCIHOME(sci_home);
84 }
85
86 /*--------------------------------------------------------------------------*/
87 static wchar_t* computeSCIHOMEW(const wchar_t* path)
88 {
89     char* pstHome = wide_string_to_UTF8(path);
90     char* pstTemp = computeSCIHOME(pstHome);
91     wchar_t* pstReturn = to_wide_string(pstTemp);
92     FREE(pstTemp);
93     FREE(pstHome);
94     return pstReturn;
95 }
96 /*--------------------------------------------------------------------------*/
97 #ifdef _MSC_VER
98 static char* computeSCIHOME(const char* path)
99 {
100 #define BASEDIR "Scilab"
101     int ierr = 0;
102     int buflen = PATH_MAX;
103     int iflag = 0;
104
105     char USERPATHSCILAB[PATH_MAX];
106     char SCIHOMEPATH[PATH_MAX * 2];
107     char* SHORTUSERHOMESYSTEM = NULL;
108
109     char USERHOMESYSTEM[PATH_MAX];
110
111     BOOL bConverted = FALSE;
112
113     getenvc(&ierr, "APPDATA", USERHOMESYSTEM, &buflen, &iflag);
114
115     /* if APPDATA not found we try with USERPROFILE */
116     if (ierr)
117     {
118         getenvc(&ierr, "USERPROFILE", USERHOMESYSTEM, &buflen, &iflag);
119     }
120
121     /* convert long path to short path format : remove some special characters */
122     SHORTUSERHOMESYSTEM = getshortpathname(USERHOMESYSTEM, &bConverted);
123     if (SHORTUSERHOMESYSTEM)
124     {
125         if (!isdir(SHORTUSERHOMESYSTEM))
126         {
127             /* last chance, we try to get default all users profile */
128             getenvc(&ierr, "ALLUSERSPROFILE", USERHOMESYSTEM, &buflen, &iflag);
129             if (ierr)
130             {
131                 delete []SHORTUSERHOMESYSTEM;
132                 return NULL;
133             }
134
135             /* convert long path to short path format : remove some special characters */
136             SHORTUSERHOMESYSTEM = getshortpathname(USERHOMESYSTEM, &bConverted);
137
138             if ((!SHORTUSERHOMESYSTEM) || !isdir(SHORTUSERHOMESYSTEM))
139             {
140                 if (SHORTUSERHOMESYSTEM)
141                 {
142                     delete []SHORTUSERHOMESYSTEM;
143                 }
144                 return NULL;
145             }
146         }
147     }
148     else
149     {
150         if (SHORTUSERHOMESYSTEM)
151         {
152             delete []SHORTUSERHOMESYSTEM;
153         }
154         return NULL;
155     }
156
157     /* checks that directory exists */
158     os_strcpy(USERHOMESYSTEM, SHORTUSERHOMESYSTEM);
159     if (SHORTUSERHOMESYSTEM)
160     {
161         delete []SHORTUSERHOMESYSTEM;
162     }
163
164     /* Set SCIHOME environment variable */
165     os_sprintf(USERPATHSCILAB, "%s%s%s", USERHOMESYSTEM, DIR_SEPARATOR, BASEDIR);
166     if (path && path[0] != '\0')
167     {
168         os_sprintf(SCIHOMEPATH, "%s%s%s", USERPATHSCILAB, DIR_SEPARATOR, path);
169     }
170     else
171     {
172         os_sprintf(SCIHOMEPATH, "%s%s%s", USERPATHSCILAB, DIR_SEPARATOR, SCI_VERSION_STRING);
173     }
174
175     /* creates directory if it does not exist */
176     if (!isdir(SCIHOMEPATH))
177     {
178         if (!isdir(USERPATHSCILAB))
179         {
180             createDirectoryRecursively(USERPATHSCILAB);
181         }
182
183         if (createDirectoryRecursively(SCIHOMEPATH))
184         {
185
186             return os_strdup(SCIHOMEPATH);
187         }
188     }
189     else
190     {
191         return os_strdup(SCIHOMEPATH);
192     }
193
194     return NULL;
195 }
196 #else
197 static char* computeSCIHOME(const char* path)
198 {
199 #define BASEDIR ".Scilab"
200     int ierr   = 0;
201     int buflen = PATH_MAX;
202     int iflag  = 0;
203     char USERPATHSCILAB[PATH_MAX];
204     char USERHOMESYSTEM[PATH_MAX];
205     char SCIHOMEPATH[PATH_MAX * 2];
206     char HOME[] = "HOME";
207
208     getenvc(&ierr, HOME, USERHOMESYSTEM, &buflen, &iflag);
209     if (ierr)
210     {
211         return NULL;
212     }
213
214     /* Set SCIHOME environment variable */
215     sprintf(USERPATHSCILAB, "%s%s%s", USERHOMESYSTEM, DIR_SEPARATOR, BASEDIR);
216     if (path && path[0] != '\0')
217     {
218         sprintf(SCIHOMEPATH, "%s%s%s", USERPATHSCILAB, DIR_SEPARATOR, path);
219     }
220     else
221     {
222         sprintf(SCIHOMEPATH, "%s%s%s", USERPATHSCILAB, DIR_SEPARATOR, SCI_VERSION_STRING);
223     }
224
225     /* creates directory if it does not exist */
226     if (!isdir(SCIHOMEPATH))
227     {
228         if (!isdir(USERPATHSCILAB))
229         {
230             createDirectoryRecursively(USERPATHSCILAB);
231         }
232
233         if (createDirectoryRecursively(SCIHOMEPATH))
234         {
235             return os_strdup(SCIHOMEPATH);
236         }
237     }
238     else
239     {
240         return os_strdup(SCIHOMEPATH);
241     }
242
243     return NULL;
244 }
245 #endif
246
247 /*--------------------------------------------------------------------------*/
248 static char* getenvSCIHOME(void)
249 {
250     int ierr, iflag = 0;
251     int lbuf = PATH_MAX;
252     char *SciHome = new char[PATH_MAX];
253
254     if (SciHome)
255     {
256         getenvc(&ierr, "SCIHOME", SciHome, &lbuf, &iflag);
257
258         if (ierr == 1)
259         {
260             delete[] SciHome;
261             return NULL;
262         }
263     }
264     return SciHome;
265 }
266 /*--------------------------------------------------------------------------*/
267 static wchar_t* getenvSCIHOMEW(void)
268 {
269     char *SciHome = getenvSCIHOME();
270     wchar_t* pstTemp = to_wide_string(SciHome);
271     delete[] SciHome;
272     return pstTemp;
273 }
274 /*--------------------------------------------------------------------------*/
275 static void putenvSCIHOMEW(const wchar_t* _sci_home)
276 {
277     char* pstTemp = wide_string_to_UTF8(_sci_home);
278     putenvSCIHOME(pstTemp);
279     FREE(pstTemp);
280     return;
281 }
282
283 static void putenvSCIHOME(const char* _sci_home)
284 {
285     char *ShortPath = NULL;
286     char *CopyOfDefaultPath = NULL;
287
288     /* to be sure that it's unix 8.3 format */
289     /* c:/progra~1/scilab-5.0 */
290     BOOL bConvertOK = FALSE;
291     ShortPath = getshortpathname(_sci_home, &bConvertOK);
292
293     CopyOfDefaultPath = new char[strlen(_sci_home) + 1];
294     AntislashToSlash(ShortPath, CopyOfDefaultPath);
295
296     setenvc("SCIHOME", ShortPath);
297
298     delete[] CopyOfDefaultPath;
299     FREE(ShortPath);
300 }
301 /*--------------------------------------------------------------------------*/
302 static bool createDirectoryRecursivelyW(const std::wstring& path)
303 {
304     char* c = wide_string_to_UTF8(path.data());
305     std::string s(c);
306     FREE(c);
307     return createDirectoryRecursively(s);
308 }
309
310 static bool createDirectoryRecursively(const std::string& path)
311 {
312 #ifdef _MSC_VER
313     size_t pos = 0;
314     do
315     {
316         pos = path.find_first_of("\\/", pos + 1);
317         if (CreateDirectoryA(path.substr(0, pos).c_str(), NULL) == FALSE)
318         {
319             DWORD d = GetLastError();
320             if (d == ERROR_PATH_NOT_FOUND)
321             {
322                 return false;
323             }
324         }
325     } while (pos != std::string::npos);
326
327     return true;
328 #else
329     char* file_path = os_strdup(path.data());
330
331     char* p = NULL;
332     for (p = strchr(file_path + 1, '/'); p; p = strchr(p + 1, '/'))
333     {
334         *p = '\0';
335         if (mkdir(file_path, 0777) == -1)
336         {
337             if (errno != EEXIST)
338             {
339                 *p = '/';
340                 FREE(file_path);
341                 return false;
342             }
343         }
344         *p = '/';
345     }
346
347     //create final folder
348     if (mkdir(path.data(), 0777) == -1)
349     {
350         if (errno != EEXIST)
351         {
352             if (p != NULL)
353             { 
354                 *p = '/';
355             }
356             FREE(file_path);
357             return false;
358         }
359     }
360
361     FREE(file_path);
362     return true;
363 #endif
364 }
365 /*--------------------------------------------------------------------------*/
366 static bool isAbsolutePath(const wchar_t* path)
367 {
368 #ifdef _MSC_VER
369     if(PathIsRelative(path))
370     {
371         return false;
372     }
373     else
374     {
375         return true;
376     }
377 #else
378     return path[0] == L'/';
379 #endif
380 }
381
382 void defineSCIHOME()
383 {
384     wchar_t* sci_home = getSCIHOMEW();
385     if (wcscmp(sci_home, L"") == 0)
386     {
387         FREE(sci_home);
388         sci_home = computeSCIHOMEW();
389     }
390     else
391     {
392         if (isAbsolutePath(sci_home))
393         {
394             if (createDirectoryRecursivelyW(sci_home) == false)
395             {
396                 sciprint("Unable to create SCIHOME in `%ls`.\n", sci_home);
397                 sciprint("Back to normal behaviour.\n");
398                 FREE(sci_home);
399                 sci_home = computeSCIHOMEW();
400             }
401         }
402         else
403         {
404             std::wstring w(sci_home);
405             FREE(sci_home);
406             sci_home = computeSCIHOMEW(w.data());
407         }
408     }
409
410     setSCIHOMEW(sci_home);
411     putenvSCIHOMEW(sci_home);
412     FREE(sci_home);
413 }