Coverity: fileio module memory errors fixed.
[scilab.git] / scilab / modules / fileio / src / c / copyfile_others.c
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2009 - 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 #ifndef _MSC_VER
17 #include <stdio.h>
18 #include <sys/stat.h>
19 #include <sys/types.h>
20 #include <utime.h>
21 #include <time.h>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <dirent.h>
25 #include <errno.h>
26 #include <string.h>
27 #include "copyfile.h"
28 #include "BOOL.h"
29 #include "charEncoding.h"
30 #include "sci_malloc.h"
31 #include "isdir.h"
32 #include "FileExist.h"
33 #include "createdirectory.h"
34 #include "PATH_MAX.h"
35 #include "fullpath.h"
36 #include "os_string.h"
37 /*--------------------------------------------------------------------------*/
38 static int CopyFileFunction_others(wchar_t *DestinationFilename, wchar_t *SourceFilename);
39 static int CopyDirectoryFunction_others(wchar_t *DestinationDirectory, wchar_t *SourceDirectory);
40 static int RecursiveCopyDirectory(char *DestinationDir, char *SourceDir);
41 /*--------------------------------------------------------------------------*/
42 int CopyFileFunction(wchar_t *DestinationFilename, wchar_t *SourceFilename)
43 {
44     if (os_wcsicmp(DestinationFilename, SourceFilename) == 0)
45     {
46         return EPERM;
47     }
48     return CopyFileFunction_others(DestinationFilename, SourceFilename);
49 }
50 /*--------------------------------------------------------------------------*/
51 int CopyDirectoryFunction(wchar_t *DestinationDirectory, wchar_t *SourceDirectory)
52 {
53     /* remove last file separator if it does not exists */
54     if ( (SourceDirectory[wcslen(SourceDirectory) - 1] == L'\\') ||
55             (SourceDirectory[wcslen(SourceDirectory) - 1] == L'/') )
56     {
57         SourceDirectory[wcslen(SourceDirectory) - 1] = L'\0';
58     }
59
60     /* remove last file separator if it does not exists */
61     if ( (DestinationDirectory[wcslen(DestinationDirectory) - 1] == L'\\') ||
62             (DestinationDirectory[wcslen(DestinationDirectory) - 1] == L'/') )
63     {
64         DestinationDirectory[wcslen(DestinationDirectory) - 1] = L'\0';
65     }
66
67     return CopyDirectoryFunction_others(DestinationDirectory, SourceDirectory);
68
69 }
70 /*--------------------------------------------------------------------------*/
71 /* Copy file with all attributes  */
72 static int CopyFileFunction_others(wchar_t *DestinationFilename, wchar_t *SourceFilename)
73 {
74     char *pStrDest = wide_string_to_UTF8(DestinationFilename);
75     char *pStrSrc = wide_string_to_UTF8(SourceFilename);
76
77     char strDestFullPath[PATH_MAX * 2 + 1];
78     char strSrcFullPath[PATH_MAX * 2 + 1];
79
80     int sfd = -1;
81     int dfd = -1;
82     struct stat st;
83     char buf[1024 * 32];
84     char *ptr = NULL;
85     int nread = 0, nwritten = 0;
86     int status = 0;
87
88     get_full_path(strDestFullPath, pStrDest, PATH_MAX * 2);
89     get_full_path(strSrcFullPath, pStrSrc, PATH_MAX * 2);
90
91     if (strcmp(strDestFullPath, strSrcFullPath) == 0)
92     {
93         status = EPERM;
94         goto err;
95     }
96
97     if ((sfd = open (pStrSrc, O_RDONLY, 0)) < 0)
98     {
99         status = errno;
100         goto err;
101     }
102
103     if (fstat (sfd, &st) < 0)
104     {
105         status = errno;
106         goto err;
107     }
108
109     if ((dfd = open (pStrDest, O_WRONLY | O_CREAT | O_TRUNC, st.st_mode & 0777)) < 0)
110     {
111         status = errno;
112         goto err;
113     }
114
115     while ((nread = read (sfd, buf, sizeof (buf))) > 0)
116     {
117         ptr = buf;
118         while (nread > 0)
119         {
120             nwritten = write (dfd, ptr, nread);
121             if (nwritten <= 0)
122             {
123                 status = errno;
124                 goto err;
125             }
126             nread -= nwritten;
127             ptr += nwritten;
128         }
129     }
130
131     if (nread < 0)
132     {
133         status = errno;
134         goto err;
135     }
136
137     if (close (dfd) < 0)
138     {
139         status = errno;
140         goto err;
141     }
142
143     fchmod (dfd, st.st_mode & 0777);
144     close (sfd);
145     FREE(pStrDest);
146     pStrDest = NULL;
147     FREE(pStrSrc);
148     pStrSrc = NULL;
149     return 0;
150
151 err:
152     if (sfd >= 0)
153     {
154         close (sfd);
155     }
156     if (dfd >= 0)
157     {
158         close (dfd);
159         unlink (pStrDest);
160     }
161
162     FREE(pStrDest);
163     pStrDest = NULL;
164     FREE(pStrSrc);
165     pStrSrc = NULL;
166     return status;
167 }
168 /*--------------------------------------------------------------------------*/
169 static int CopyDirectoryFunction_others(wchar_t *DestinationDirectory, wchar_t *SourceDirectory)
170 {
171     char *pStrDest = wide_string_to_UTF8(DestinationDirectory);
172     char *pStrSrc = wide_string_to_UTF8(SourceDirectory);
173
174     int ierr = 0;
175
176     /* we check directory source exists */
177     if (!isdir(pStrSrc))
178     {
179         if (pStrDest)
180         {
181             FREE(pStrDest);
182             pStrDest = NULL;
183         }
184         FREE(pStrSrc);
185         return ENOTDIR;
186     }
187
188     /* we check destination directory exists */
189     if (!isdir(pStrDest))
190     {
191         if (FileExistW(DestinationDirectory))
192         {
193             FREE(pStrDest);
194             FREE(pStrSrc);
195             return ENOTDIR;
196         }
197         else
198         {
199             if (!createdirectoryW(DestinationDirectory))
200             {
201                 FREE(pStrDest);
202                 FREE(pStrSrc);
203                 return ENOTDIR;
204             }
205         }
206     }
207
208     ierr = RecursiveCopyDirectory(pStrDest, pStrSrc);
209
210     FREE(pStrDest);
211     FREE(pStrSrc);
212
213     if (ierr)
214     {
215         return errno;
216     }
217
218     return 0;
219 }
220 /*--------------------------------------------------------------------------*/
221 static int RecursiveCopyDirectory(char *DestinationDir, char *SourceDir)
222 {
223     DIR *dir;
224     struct dirent *ent;
225
226     dir = opendir(SourceDir) ;
227
228     if (dir == NULL)
229     {
230         return errno;
231     }
232
233     while ((ent = readdir(dir)) != NULL)
234     {
235         char *filenameSRC = NULL;
236         char *filenameDST = NULL;
237
238         if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
239         {
240             continue ;
241         }
242
243         filenameSRC = (char*)MALLOC(sizeof(char) * (strlen(SourceDir) + 1 + strlen(ent->d_name) + 1 + 1)) ;
244         filenameDST = (char*)MALLOC(sizeof(char) * (strlen(DestinationDir) + 1 + strlen(ent->d_name) + 1 + 1)) ;
245
246         sprintf(filenameSRC, "%s/%s", SourceDir, ent->d_name);
247
248         if (DestinationDir[strlen(DestinationDir) - 1] == '/')
249         {
250             sprintf(filenameDST, "%s%s", DestinationDir, ent->d_name);
251         }
252         else
253         {
254             sprintf(filenameDST, "%s/%s", DestinationDir, ent->d_name);
255         }
256
257         if (isdir(filenameSRC))
258         {
259             int ierr = 0;
260             BOOL bOK = createdirectory(filenameDST);
261             if (!bOK)
262             {
263                 FREE(filenameDST);
264                 FREE(filenameSRC);
265                 closedir(dir);
266                 return EACCES;
267             }
268
269             ierr = RecursiveCopyDirectory(filenameDST, filenameSRC);
270             if (ierr)
271             {
272                 FREE(filenameDST);
273                 FREE(filenameSRC);
274                 closedir(dir);
275                 return ierr;
276             }
277         }
278         else
279         {
280             wchar_t* wcfileDest = to_wide_string(filenameDST);
281             wchar_t* wcfileSrc = to_wide_string(filenameSRC);
282
283             int ierr = CopyFileFunction_others(wcfileDest,  wcfileSrc);
284             FREE(wcfileDest);
285             FREE(wcfileSrc);
286
287             if (ierr)
288             {
289                 FREE(filenameDST);
290                 FREE(filenameSRC);
291                 closedir(dir);
292                 return ierr;
293             }
294         }
295
296         FREE(filenameDST);
297         FREE(filenameSRC);
298     }
299
300     closedir(dir);
301     return 0;
302 }
303 /*--------------------------------------------------------------------------*/
304 #endif /* #ifndef _MSC_VER */
305 /*--------------------------------------------------------------------------*/