Coverity #1247398, #1199692, #1321278, #1321279, #1321280, #1321281, #1097625 fixed...
[scilab.git] / scilab / modules / io / sci_gateway / cpp / sci_file.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2006 - INRIA - Allan CORNET
4  * Copyright (C) 2009-2010 - DIGITEO - Allan CORNET
5  * Copyright (C) 2013 - Scilab Enterprises - Cedric Delamarre
6  *
7  * Copyright (C) 2012 - 2016 - Scilab Enterprises
8  *
9  * This file is hereby licensed under the terms of the GNU GPL v2.0,
10  * pursuant to article 5.3.4 of the CeCILL v.2.1.
11  * This file was originally licensed under the terms of the CeCILL v2.1,
12  * and continues to be available under such terms.
13  * For more information, see the COPYING file which you should have received
14  * along with this program.
15  *
16  */
17
18 /*--------------------------------------------------------------------------*/
19 #include "context.hxx"
20 #include "io_gw.hxx"
21 #include "filemanager.hxx"
22 #include "function.hxx"
23 #include "string.hxx"
24 #include "double.hxx"
25
26 extern "C"
27 {
28 #include "os_string.h"
29 #include "localization.h"
30 #include "Scierror.h"
31 #include "sci_malloc.h"
32 #include "FileExist.h"
33 #include "mclose.h"
34 #include "mseek.h"
35
36     extern int C2F(clunit)(int* , char const*, int*, int);
37     extern int C2F(rewindinter)(int*);
38     extern int C2F(backspaceinter)(int*);
39     extern int C2F(readinter)(int*, char const*, int);
40 }
41 /*--------------------------------------------------------------------------*/
42 types::Function::ReturnValue sci_file_no_rhs(types::typed_list &in, int _iRetCount, types::typed_list &out);
43 types::Function::ReturnValue sci_file_one_rhs(types::typed_list &in, int _iRetCount, types::typed_list &out);
44 /*--------------------------------------------------------------------------*/
45 types::Function::ReturnValue sci_file(types::typed_list &in, int _iRetCount, types::typed_list &out)
46 {
47     types::String* pSAction = NULL;
48
49     if (in.size() > 6)
50     {
51         Scierror(77, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "file", 0, 6);
52         return types::Function::Error;
53     }
54
55     if (in.size() == 0)
56     {
57         return sci_file_no_rhs(in, _iRetCount, out);
58     }
59
60     if (in.size() == 1)
61     {
62         return sci_file_one_rhs(in, _iRetCount, out);
63     }
64
65     // get action
66     if (in[0]->isString() == false)
67     {
68         Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "file", 1);
69         return types::Function::Error;
70     }
71
72     pSAction = in[0]->getAs<types::String>();
73
74     if (pSAction->isScalar() == false)
75     {
76         Scierror(999, _("%s: Wrong type for input argument #%d : A single string expected.\n"), "file", 1);
77         return types::Function::Error;
78     }
79
80     if (wcscmp(pSAction->get(0), L"open") == 0)
81     {
82         types::String* pSPath   = NULL;
83         types::String* pSOption = NULL;
84         types::Double* pSRecl   = NULL;
85
86         int iStatus = 0;
87         int iAccess = 0;
88         int iForm   = 0;
89         int iRecl   = 0;
90
91         int piMode[2] = {0, 0};
92
93         // get path
94         if (in[1]->isString() == false)
95         {
96             Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "file", 2);
97             return types::Function::Error;
98         }
99
100         pSPath = in[1]->getAs<types::String>();
101
102         if (pSPath->isScalar() == false)
103         {
104             Scierror(999, _("%s: Wrong type for input argument #%d : A single string expected.\n"), "file", 2);
105             return types::Function::Error;
106         }
107
108         // get optional inputs
109         for (int i = 2; i < in.size(); i++)
110         {
111             if (in[i]->isString())
112             {
113                 pSOption = in[i]->getAs<types::String>();
114             }
115             else if (i != 2 && in[i]->isDouble())
116             {
117                 pSRecl = in[i]->getAs<types::Double>();
118                 if (pSRecl->isScalar() == false)
119                 {
120                     Scierror(999, _("%s: Wrong type for input argument #%d : A scalar expected.\n"), "file", i + 1);
121                     return types::Function::Error;
122                 }
123
124                 iRecl = (int)pSRecl->get(0);
125                 piMode[1] = iRecl;
126                 continue;
127             }
128             else
129             {
130                 Scierror(999, _("%s: Wrong type for input argument #%d : string expected.\n"), "file", i + 1);
131                 return types::Function::Error;
132             }
133
134             if (pSOption->isScalar() == false)
135             {
136                 Scierror(999, _("%s: Wrong type for input argument #%d : A single string expected.\n"), "file", i + 1);
137                 return types::Function::Error;
138             }
139
140             if (wcscmp(pSOption->get(0), L"new") == 0)
141             {
142                 iStatus = 0;
143             }
144             else if (wcscmp(pSOption->get(0), L"old") == 0)
145             {
146                 iStatus = 1;
147                 // file must already exists.
148                 if (FileExistW(pSPath->get(0)) == false)
149                 {
150                     if (_iRetCount == 2)
151                     {
152                         out.push_back(types::Double::Empty());
153                         out.push_back(new types::Double(240));
154                         return types::Function::OK;
155                     }
156                     else
157                     {
158                         char* pstrFilename = wide_string_to_UTF8(pSPath->get(0));
159                         if (pstrFilename)
160                         {
161                             Scierror(240, _("%s: The file \"%s\" does not exist.\n"), "file", pstrFilename);
162                             FREE(pstrFilename);
163                             pstrFilename = NULL;
164                         }
165                         else
166                         {
167                             Scierror(240, _("%s: The file does not exist.\n"), "file");
168                         }
169
170                         return types::Function::Error;
171                     }
172                 }
173             }
174             else if (wcscmp(pSOption->get(0), L"scratch") == 0)
175             {
176                 iStatus = 2;
177             }
178             else if (wcscmp(pSOption->get(0), L"unknown") == 0)
179             {
180                 iStatus = 3;
181             }
182             else if (wcscmp(pSOption->get(0), L"sequential") == 0)
183             {
184                 iAccess = 0;
185             }
186             else if (wcscmp(pSOption->get(0), L"direct") == 0)
187             {
188                 iAccess = 1;
189             }
190             else if (wcscmp(pSOption->get(0), L"formatted") == 0)
191             {
192                 iForm = 0;
193             }
194             else if (wcscmp(pSOption->get(0), L"unformatted") == 0)
195             {
196                 iForm = 1;
197             }
198             else
199             {
200                 Scierror(999, _("%s: Wrong value for input argument #%d.\n"), "file", i + 1);
201                 return types::Function::Error;
202             }
203         }
204
205         piMode[0] = iStatus + 10 * (iAccess + 10 * iForm);
206         int lunit = 0; // file unit. 0 mean we open the file by this name.
207         char* pstFilename = wide_string_to_UTF8(pSPath->get(0));
208         int iErr = C2F(clunit)(&lunit, pstFilename, piMode, (int)strlen(pstFilename));
209         if (iErr)
210         {
211             if (_iRetCount == 1)
212             {
213                 switch (iErr)
214                 {
215                     case 65  :
216                         Scierror(iErr, _("%s: %d logical unit already used.\n"), "file", lunit);
217                         break;
218                     case 66  :
219                         Scierror(iErr, _("%s: Too many files opened!\n"), "file");
220                         break;
221                     case 67  :
222                         Scierror(iErr, _("%s: Unknown file format.\n"), "file");
223                         break;
224                     case 240 :
225                         Scierror(iErr, _("%s: File \"%s\" already exists or directory write access denied.\n"), "file", pstFilename);
226                         break;
227                     case 241 :
228                         Scierror(iErr, _("%s: File \"%s\" does not exist or read access denied.\n"), "file", pstFilename);
229                         break;
230                     default  :
231                         Scierror(iErr, _("%s: Can not open File \"%s\"\n"), "file", pstFilename);
232                 }
233
234                 return types::Function::Error;
235             }
236             else
237             {
238                 out.push_back(types::Double::Empty());
239                 out.push_back(new types::Double((double)iErr));
240                 return types::Function::OK;
241             }
242         }
243
244         out.push_back(new types::Double((double)lunit));
245         if (_iRetCount == 2)
246         {
247             out.push_back(new types::Double(0.0));
248         }
249
250         FREE(pstFilename);
251     }
252     else if (wcscmp(pSAction->get(0), L"close") == 0 ||
253              wcscmp(pSAction->get(0), L"rewind") == 0 ||
254              wcscmp(pSAction->get(0), L"backspace") == 0 ||
255              wcscmp(pSAction->get(0), L"last") == 0)
256     {
257         if (_iRetCount != 1)
258         {
259             Scierror(78, _("%s: Wrong number of output argument(s): %d expected.\n"), "file", 1);
260             return types::Function::Error;
261         }
262
263         if (in.size() != 2)
264         {
265             Scierror(77, _("%s: Wrong number of input argument(s): %d expected.\n"), "file", 2);
266             return types::Function::Error;
267         }
268
269         if (in[1]->isDouble() == false)
270         {
271             Scierror(999, _("%s: Wrong type for input argument #%d : A matrix expected.\n"), "file", 2);
272             return types::Function::Error;
273         }
274
275         types::Double* pDblFileUnit = in[1]->getAs<types::Double>();
276         double* pdblUnit = pDblFileUnit->get();
277
278         if (wcscmp(pSAction->get(0), L"close") == 0)
279         {
280             for (int i = 0; i < pDblFileUnit->getSize(); i++)
281             {
282                 int iErr = mclose((int)(pdblUnit[i]));
283                 if (iErr)
284                 {
285                     Scierror(999, _("%s: Cannot close file %d.\n"), "file", (int)pdblUnit[i]);
286                     return types::Function::Error;
287                 }
288             }
289         }
290         else if (wcscmp(pSAction->get(0), L"rewind") == 0)
291         {
292             int iFileUnit = (int)pdblUnit[0];
293             types::File* pFile = FileManager::getFile(iFileUnit);
294
295             if (pFile && pFile->getFileType() == 2)
296             {
297                 mseek(iFileUnit, 0, SEEK_SET);
298             }
299             else if (pFile && pFile->getFileType() == 1)
300             {
301                 C2F(rewindinter)(&iFileUnit);
302             }
303             else
304             {
305                 Scierror(999, _("%s: Unknown file format.\n"), "file");
306                 return types::Function::Error;
307             }
308         }
309         else if (wcscmp(pSAction->get(0), L"backspace") == 0)
310         {
311             int iFileUnit = (int)pdblUnit[0];
312             types::File* pFile = FileManager::getFile(iFileUnit);
313
314             if (pFile && pFile->getFileType() == 2)
315             {
316                 Scierror(999, _("%s: Wrong input argument #%d.\n"), "file", 1);
317                 return types::Function::Error;
318             }
319             else if (pFile && pFile->getFileType() == 1)
320             {
321                 C2F(backspaceinter)(&iFileUnit);
322             }
323             else
324             {
325                 Scierror(67, _("%s: Unknown file format.\n"), "file");
326                 return types::Function::Error;
327             }
328         }
329         else if (wcscmp(pSAction->get(0), L"last") == 0)
330         {
331             int iFileUnit = (int)pdblUnit[0];
332             types::File* pFile = FileManager::getFile(iFileUnit);
333
334             if (pFile && pFile->getFileType() == 2)
335             {
336                 mseek(iFileUnit, 0, SEEK_END);
337             }
338             else if (pFile && pFile->getFileType() == 1)
339             {
340                 int iErr = 0;
341                 while (iErr == 0)
342                 {
343                     iErr = C2F(readinter)(&iFileUnit, "(a)", 1L);
344                 }
345
346                 if (iErr == 2)
347                 {
348                     Scierror(999, _("%s: \n"), "file");
349                     return types::Function::Error;
350                 }
351
352                 C2F(backspaceinter)(&iFileUnit);
353             }
354             else
355             {
356                 Scierror(67, _("%s: Unknown file format.\n"), "file");
357                 return types::Function::Error;
358             }
359         }
360     }
361     else
362     {
363         Scierror(49, _("%s: Wrong value for input argument #%d: \"%s\", \"%s\", \"%s\", \"%s\", \"%s\" \n"), "file", 1, "open", "close", "rewind", "backspace", "last");
364         return types::Function::Error;
365     }
366
367     return types::Function::OK;
368 }
369 /*--------------------------------------------------------------------------*/
370 types::Function::ReturnValue sci_file_no_rhs(types::typed_list &in, int _iRetCount, types::typed_list &out)
371 {
372     int iCount = FileManager::getOpenedCount();
373     if (iCount == 0)
374     {
375         for (int i = 0 ; i < _iRetCount ; i++)
376         {
377             out.push_back(types::Double::Empty());
378         }
379         return types::Function::OK;
380     }
381
382     int* piIds = FileManager::getIDs();
383     if (piIds)
384     {
385         types::Double *pD = new types::Double(1, iCount);
386         pD->setInt(piIds);
387         out.push_back(pD);
388         delete[] piIds;
389     }
390
391     if (_iRetCount > 1) /*types*/
392     {
393         wchar_t** pstTypes = FileManager::getTypesAsString();
394         if (pstTypes != NULL)
395         {
396             types::String* pS = new types::String(1, iCount);
397             pS->set(pstTypes);
398             out.push_back(pS);
399             for (int i = 0 ; i < iCount ; i++)
400             {
401                 delete[] pstTypes[i];
402             }
403             delete[] pstTypes;
404         }
405     }
406
407     if (_iRetCount > 2) /*names*/
408     {
409         wchar_t** pstNames = FileManager::getFilenames();
410         if (pstNames != NULL)
411         {
412             types::String* pS = new types::String(1, iCount);
413             pS->set(pstNames);
414             out.push_back(pS);
415             for (int i = 0 ; i < iCount ; i++)
416             {
417                 delete[] pstNames[i];
418             }
419             delete[] pstNames;
420         }
421     }
422
423     if (_iRetCount > 3) /* mod */
424     {
425         double* pdblModes = FileManager::getModes();
426         if (pdblModes != NULL)
427         {
428             types::Double* pD = new types::Double(1, iCount);
429             pD->set(pdblModes);
430             out.push_back(pD);
431             delete[] pdblModes;
432         }
433     }
434
435     if (_iRetCount > 4) /* swap */
436     {
437         double* pdblSwaps = FileManager::getSwaps();
438         if (pdblSwaps != NULL)
439         {
440             types::Double* pD = new types::Double(1, iCount);
441             pD->set(pdblSwaps);
442             out.push_back(pD);
443             delete[] pdblSwaps;
444         }
445     }
446
447     return types::Function::OK;
448 }
449 /*--------------------------------------------------------------------------*/
450 types::Function::ReturnValue sci_file_one_rhs(types::typed_list &in, int _iRetCount, types::typed_list &out)
451 {
452     if (in[0]->isDouble() == false || in[0]->getAs<types::Double>()->getSize() != 1)
453     {
454         Scierror(201, _("%s: Wrong type for input argument #%d: A scalar expected.\n"), "file", 1);
455         return types::Function::Error;
456     }
457
458     types::Double* pD = in[0]->getAs<types::Double>();
459     int iID = static_cast<int>(pD->getReal()[0]);
460
461     //check if double value is an integer to exclude decimal values
462     if (static_cast<double>(iID) != pD->getReal()[0])
463     {
464         Scierror(201, _("%s: Wrong type for input argument #%d: A scalar expected.\n"), "file", 1);
465         return types::Function::Error;
466     }
467
468     types::File *pF = FileManager::getFile(iID);
469     if (pF == NULL)
470     {
471         for (int i = 0 ; i < _iRetCount ; i++)
472         {
473             out.push_back(types::Double::Empty());
474         }
475         return types::Function::OK;
476     }
477
478     out.push_back(new types::Double(iID));
479     if (_iRetCount > 1) /*type*/
480     {
481         wchar_t* pstType = os_wcsdup(pF->getFileTypeAsString().c_str());
482         if (pstType != NULL)
483         {
484             types::String* pS = new types::String(pstType);
485             out.push_back(pS);
486             FREE(pstType);
487         }
488     }
489
490     if (_iRetCount > 2) /*name*/
491     {
492         wchar_t* pstName =  os_wcsdup(pF->getFilename().c_str());
493         if (pstName != NULL)
494         {
495             types::String* pS = new types::String(pstName);
496             out.push_back(pS);
497             FREE(pstName);
498         }
499     }
500
501     if (_iRetCount > 3) /* mod */
502     {
503         if (pF->getFileType() == 1)
504         {
505             out.push_back(new types::Double((double)pF->getFileFortranMode()));
506         }
507         else // if(pF->getFileType() == 2)
508         {
509             out.push_back(new types::Double((double)pF->getFileModeAsInt()));
510         }
511     }
512
513     if (_iRetCount > 4) /* swap */
514     {
515         out.push_back(new types::Double(pF->getFileSwap()));
516     }
517     return types::Function::OK;
518 }