Merge remote-tracking branch 'origin/master' into windows
[scilab.git] / scilab / modules / fileio / sci_gateway / c / sci_movefile.c
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2009-2012 - DIGITEO - Allan CORNET
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 #ifndef _MSC_VER
18 #include <errno.h>
19 #include <string.h>
20 #else
21 #include <windows.h>
22 #endif
23 #include "gw_fileio.h"
24 #include "sci_malloc.h"
25 #include "localization.h"
26 #include "api_scilab.h"
27 #include "Scierror.h"
28 #include "FileExist.h"
29 #include "movefile.h"
30 #include "isdir.h"
31 #include "splitpath.h"
32 #include "freeArrayOfString.h"
33 #include "charEncoding.h"
34 #include "expandPathVariable.h"
35 #include "os_string.h"
36 /*--------------------------------------------------------------------------*/
37 static char* getFilenameWithExtensionForMove(char*  fullFilename);
38 static int returnMoveFileResultOnStack(int ierr, char *fname, void* pvApiCtx);
39 /*--------------------------------------------------------------------------*/
40 int sci_movefile(char *fname, void* pvApiCtx)
41 {
42     SciErr sciErr;
43     int *piAddressVarOne = NULL;
44     char* pStVarOne = NULL;
45     char* pStVarOneExpanded = NULL;
46
47     int *piAddressVarTwo = NULL;
48     char* pStVarTwo = NULL;
49     char* pStVarTwoExpanded = NULL;
50
51     /* Check Input & Output parameters */
52     CheckRhs(2, 2);
53     CheckLhs(1, 2);
54
55     sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddressVarOne);
56     if (sciErr.iErr)
57     {
58         printError(&sciErr, 0);
59         Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 1);
60         return 0;
61     }
62
63     if (isStringType(pvApiCtx, piAddressVarOne) == 0 || isScalar(pvApiCtx, piAddressVarOne) == 0)
64     {
65         Scierror(999, _("%s: Wrong type for input argument #%d: string expected.\n"), fname, 1);
66         return 0;
67     }
68
69     sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddressVarTwo);
70     if (sciErr.iErr)
71     {
72         printError(&sciErr, 0);
73         Scierror(999, _("%s: Can not read input argument #%d.\n"), fname, 2);
74         return 0;
75     }
76
77     if (isStringType(pvApiCtx, piAddressVarTwo) == 0 || isScalar(pvApiCtx, piAddressVarTwo) == 0)
78     {
79         Scierror(999, _("%s: Wrong type for input argument #%d: string expected.\n"), fname, 2);
80         return 0;
81     }
82
83     if (getAllocatedSingleString(pvApiCtx, piAddressVarOne, &pStVarOne))
84     {
85         if (pStVarOne)
86         {
87             freeAllocatedSingleString(pStVarOne);
88         }
89
90         Scierror(999, _("%s: Memory allocation error.\n"), fname);
91         return 0;
92     }
93
94     if (getAllocatedSingleString(pvApiCtx, piAddressVarTwo, &pStVarTwo))
95     {
96         freeAllocatedSingleString(pStVarOne);
97         freeAllocatedSingleString(pStVarTwo);
98         Scierror(999, _("%s: Memory allocation error.\n"), fname);
99         return 0;
100     }
101
102     pStVarOneExpanded = expandPathVariable(pStVarOne);
103     pStVarTwoExpanded = expandPathVariable(pStVarTwo);
104
105     freeAllocatedSingleString(pStVarOne);
106     freeAllocatedSingleString(pStVarTwo);
107
108     if (isdir(pStVarOneExpanded) || FileExist(pStVarOneExpanded))
109     {
110         int ierrMove = 0;
111
112         if (isdir(pStVarOneExpanded))
113         {
114             /* move a directory into a directory */
115             ierrMove = MoveDirectoryFunction(pStVarTwoExpanded, pStVarOneExpanded);
116         }
117         else if (FileExist(pStVarOneExpanded))
118         {
119             if (isdir(pStVarTwoExpanded))
120             {
121                 /* move file into a existing directory */
122                 /* copy file into a existing directory */
123                 char* filename = getFilenameWithExtensionForMove(pStVarOneExpanded);
124
125                 if (filename)
126                 {
127 #define FORMAT_FULLFILENAME "%s/%s"
128                     char* destFullFilename = NULL;
129
130                     /* remove last file separator if it exists */
131                     if ((pStVarTwoExpanded[strlen(pStVarTwoExpanded) - 1] == '\\') || (pStVarTwoExpanded[strlen(pStVarTwoExpanded) - 1] == '/'))
132                     {
133                         pStVarTwoExpanded[strlen(pStVarTwoExpanded) - 1] = '\0';
134                     }
135
136                     destFullFilename = (char*)MALLOC(sizeof(char) * ((int)strlen(pStVarTwoExpanded) + (int)strlen(filename) + (int)strlen("/") + 1));
137                     strcpy(destFullFilename, pStVarTwoExpanded);
138                     strcat(destFullFilename, "/");
139                     strcat(destFullFilename, filename);
140
141                     ierrMove = MoveFileFunction(destFullFilename, pStVarOneExpanded);
142
143                     FREE(filename);
144                     filename = NULL;
145                     FREE(destFullFilename);
146                     destFullFilename = NULL;
147                 }
148                 else
149                 {
150                     FREE(pStVarOneExpanded);
151                     FREE(pStVarTwoExpanded);
152                     Scierror(999, _("%s: Memory allocation error.\n"), fname);
153                     return 0;
154                 }
155             }
156             else
157             {
158                 /* move a file into a file */
159                 ierrMove = MoveFileFunction(pStVarTwoExpanded, pStVarOneExpanded);
160             }
161         }
162         else
163         {
164             FREE(pStVarOneExpanded);
165             FREE(pStVarTwoExpanded);
166             Scierror(999, _("%s: Wrong value for input argument #%d: A valid filename or directory expected.\n"), fname, 1);
167             return 0;
168         }
169
170         returnMoveFileResultOnStack(ierrMove, fname, pvApiCtx);
171     }
172     else
173     {
174         Scierror(999, _("%s: Wrong value for input argument #%d: A valid filename or directory expected.\n"), fname, 1);
175     }
176
177     FREE(pStVarOneExpanded);
178     FREE(pStVarTwoExpanded);
179
180     return 0;
181 }
182
183 /*--------------------------------------------------------------------------*/
184 static char* getFilenameWithExtensionForMove(char*  fullFilename)
185 {
186     char* wcfilename = NULL;
187
188     if (fullFilename)
189     {
190         int len = (int)strlen(fullFilename);
191         char* wcdrv = (char*)MALLOC(sizeof(char) * (len + 1));
192         char* wcdir = (char*)MALLOC(sizeof(char) * (len + 1));
193         char* wcname = (char*)MALLOC(sizeof(char) * (len + 1));
194         char* wcext = (char*)MALLOC(sizeof(char) * (len + 1));
195
196         wcfilename = (char*)MALLOC(sizeof(char) * (len + 1));
197
198         if (wcdrv == NULL || wcdir == NULL || wcname == NULL || wcext == NULL || wcfilename == NULL)
199         {
200             FREE(wcdrv);
201             FREE(wcdir);
202             FREE(wcname);
203             FREE(wcext);
204             FREE(wcfilename);
205             return NULL;
206         }
207
208         splitpath(fullFilename, FALSE, wcdrv, wcdir, wcname, wcext);
209
210         strcpy(wcfilename, wcname);
211         strcat(wcfilename, wcext);
212
213         FREE(wcdrv);
214         FREE(wcdir);
215         FREE(wcname);
216         FREE(wcext);
217     }
218     return wcfilename;
219 }
220 /*--------------------------------------------------------------------------*/
221 static int returnMoveFileResultOnStack(int ierr, char *fname, void* pvApiCtx)
222 {
223     double dError = 0.;
224     char* sciError = NULL;
225
226 #ifdef _MSC_VER
227     if (ierr)
228     {
229 #define BUFFER_SIZE 1024
230         DWORD dw = GetLastError();
231         char buffer[BUFFER_SIZE];
232
233         if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
234                            dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, BUFFER_SIZE, NULL) == 0)
235         {
236             strcpy(buffer, "Unknown Error");
237         }
238
239         // for compatibilty with copyfile, we return 0 (error)
240         //dError = (double) dw;
241         dError = (double)0;
242
243         sciError = (char* ) MALLOC(sizeof(char) * ((int)strlen(buffer) + 1));
244         if (sciError == NULL)
245         {
246             Scierror(999, _("%s: Memory allocation error.\n"), fname);
247             return 0;
248         }
249
250         strcpy(sciError, buffer);
251     }
252     else
253     {
254         dError = 1.;
255         sciError = (char* ) MALLOC(sizeof(char) * 1);
256         if (sciError == NULL)
257         {
258             Scierror(999, _("%s: Memory allocation error.\n"), fname);
259             return 0;
260         }
261
262         strcpy(sciError, "");
263     }
264 #else
265     if (ierr)
266     {
267         // for compatibilty with copyfile, we return 0 (error)
268         //dError = (double) ierr;
269         dError = (double)0.;
270         sciError = strerror(errno);
271     }
272     else
273     {
274         dError = 1.;
275         sciError = os_strdup("");
276     }
277 #endif
278
279     createScalarDouble(pvApiCtx, Rhs + 1, dError);
280     LhsVar(1) = Rhs + 1;
281
282     if (Lhs == 2)
283     {
284         createSingleString(pvApiCtx, Rhs + 2, sciError);
285         LhsVar(2) = Rhs + 2;
286     }
287
288     FREE(sciError);
289
290     PutLhsVar();
291     return 0;
292 }
293 /*--------------------------------------------------------------------------*/