Code cleanup: remove BLI_exist, now there is only BLI_exists. One function just
[blender.git] / source / blender / blenlib / intern / fileops.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/blenlib/intern/fileops.c
31  *  \ingroup bli
32  */
33
34
35 #include <string.h>
36 #include <stdio.h>
37
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41
42 #include <errno.h>
43
44 #include "zlib.h"
45
46 #ifdef WIN32
47 #include <io.h>
48 #include "BLI_winstuff.h"
49 #include "BLI_callbacks.h"
50 #else
51 #include <unistd.h> // for read close
52 #include <sys/param.h>
53 #endif
54
55 #include "MEM_guardedalloc.h"
56
57 #include "BLI_blenlib.h"
58
59 #include "BKE_utildefines.h"
60
61 #include "BLO_sys_types.h" // for intptr_t support
62
63
64 /* gzip the file in from and write it to "to". 
65  return -1 if zlib fails, -2 if the originating file does not exist
66  note: will remove the "from" file
67   */
68 int BLI_gzip(const char *from, const char *to) {
69         char buffer[10240];
70         int file;
71         int readsize = 0;
72         int rval= 0, err;
73         gzFile gzfile;
74
75         /* level 1 is very close to 3 (the default) in terms of file size,
76          * but about twice as fast, best use for speedy saving - campbell */
77         gzfile = gzopen(to, "wb1");
78         if(gzfile == NULL)
79                 return -1;
80         
81         file = open(from, O_BINARY|O_RDONLY);
82         if(file < 0)
83                 return -2;
84
85         while(1) {
86                 readsize = read(file, buffer, 10240);
87
88                 if(readsize < 0) {
89                         rval= -2; /* error happened in reading */
90                         fprintf(stderr, "Error reading file %s: %s.\n", from, strerror(errno));
91                         break;
92                 }
93                 else if(readsize == 0)
94                         break; /* done reading */
95                 
96                 if(gzwrite(gzfile, buffer, readsize) <= 0) {
97                         rval= -1; /* error happened in writing */
98                         fprintf(stderr, "Error writing gz file %s: %s.\n", to, gzerror(gzfile, &err));
99                         break;
100                 }
101         }
102         
103         gzclose(gzfile);
104         close(file);
105
106         return rval;
107 }
108
109 /* gzip the file in from_file and write it to memery to_mem, at most size bytes.
110    return the unziped size
111   */
112 char *BLI_ungzip_to_mem(const char *from_file, int *size_r)
113 {
114         gzFile gzfile;
115         int readsize, size, alloc_size=0;
116         char *mem= NULL;
117         const int chunk_size= 512*1024;
118
119         size= 0;
120
121         gzfile = gzopen( from_file, "rb" );
122
123         for(;;) {
124                 if(mem==NULL) {
125                         mem= MEM_callocN(chunk_size, "BLI_ungzip_to_mem");
126                         alloc_size= chunk_size;
127                 } else {
128                         mem= MEM_reallocN(mem, size+chunk_size);
129                         alloc_size+= chunk_size;
130                 }
131
132                 readsize= gzread(gzfile, mem+size, chunk_size);
133                 if(readsize>0) {
134                         size+= readsize;
135                 }
136                 else break;
137         }
138
139         if(size==0) {
140                 MEM_freeN(mem);
141                 mem= NULL;
142         }
143         else if(alloc_size!=size)
144                 mem= MEM_reallocN(mem, size);
145
146         *size_r= size;
147
148         return mem;
149 }
150
151
152 /* return 1 when file can be written */
153 int BLI_is_writable(const char *filename)
154 {
155         int file;
156         
157         /* first try to open without creating */
158         file = open(filename, O_BINARY | O_RDWR, 0666);
159         
160         if (file < 0) {
161                 /* now try to open and create. a test without actually
162                  * creating a file would be nice, but how? */
163                 file = open(filename, O_BINARY | O_RDWR | O_CREAT, 0666);
164                 
165                 if(file < 0) {
166                         return 0;
167                 }
168                 else {
169                         /* success, delete the file we create */
170                         close(file);
171                         BLI_delete(filename, 0, 0);
172                         return 1;
173                 }
174         }
175         else {
176                 close(file);
177                 return 1;
178         }
179 }
180
181 int BLI_touch(const char *file)
182 {
183         FILE *f = fopen(file,"r+b");
184         if (f != NULL) {
185                 char c = getc(f);
186                 rewind(f);
187                 putc(c,f);
188         } else {
189                 f = fopen(file,"wb");
190         }
191         if (f) {
192                 fclose(f);
193                 return 1;
194         }
195         return 0;
196 }
197
198 #ifdef WIN32
199
200 static char str[MAXPATHLEN+12];
201
202 int BLI_delete(const char *file, int dir, int recursive) {
203         int err;
204
205         if (recursive) {
206                 callLocalErrorCallBack("Recursive delete is unsupported on Windows");
207                 err= 1;
208         } else if (dir) {
209                 err= !RemoveDirectory(file);
210                 if (err) printf ("Unable to remove directory");
211         } else {
212                 err= !DeleteFile(file);
213                 if (err) callLocalErrorCallBack("Unable to delete file");
214         }
215
216         return err;
217 }
218
219 int BLI_move(const char *file, const char *to) {
220         int err;
221
222         // windows doesn't support moveing to a directory
223         // it has to be 'mv filename filename' and not
224         // 'mv filename destdir'
225
226         BLI_strncpy(str, to, sizeof(str));
227         // points 'to' to a directory ?
228         if (BLI_last_slash(str) == (str + strlen(str) - 1)) {
229                 if (BLI_last_slash(file) != NULL) {
230                         strcat(str, BLI_last_slash(file) + 1);
231                 }
232         }
233
234         err= !MoveFile(file, str);
235         if (err) {
236                 callLocalErrorCallBack("Unable to move file");
237                 printf(" Move from '%s' to '%s' failed\n", file, str);
238         }
239
240         return err;
241 }
242
243
244 int BLI_copy_fileops(const char *file, const char *to) {
245         int err;
246
247         // windows doesn't support copying to a directory
248         // it has to be 'cp filename filename' and not
249         // 'cp filename destdir'
250
251         BLI_strncpy(str, to, sizeof(str));
252         // points 'to' to a directory ?
253         if (BLI_last_slash(str) == (str + strlen(str) - 1)) {
254                 if (BLI_last_slash(file) != NULL) {
255                         strcat(str, BLI_last_slash(file) + 1);
256                 }
257         }
258
259         err= !CopyFile(file,str,FALSE);
260         
261         if (err) {
262                 callLocalErrorCallBack("Unable to copy file!");
263                 printf(" Copy from '%s' to '%s' failed\n", file, str);
264         }
265
266         return err;
267 }
268
269 int BLI_link(const char *file, const char *to) {
270         callLocalErrorCallBack("Linking files is unsupported on Windows");
271         (void)file;
272         (void)to;
273         return 1;
274 }
275
276 void BLI_recurdir_fileops(const char *dirname) {
277         char *lslash;
278         char tmp[MAXPATHLEN];
279         
280         // First remove possible slash at the end of the dirname.
281         // This routine otherwise tries to create
282         // blah1/blah2/ (with slash) after creating
283         // blah1/blah2 (without slash)
284
285         BLI_strncpy(tmp, dirname, sizeof(tmp));
286         lslash= BLI_last_slash(tmp);
287
288         if (lslash == tmp + strlen(tmp) - 1) {
289                 *lslash = 0;
290         }
291         
292         if (BLI_exists(tmp)) return;
293                 
294         lslash= BLI_last_slash(tmp);
295         if (lslash) {
296                         /* Split about the last slash and recurse */    
297                 *lslash = 0;
298                 BLI_recurdir_fileops(tmp);
299         }
300         
301         if(dirname[0]) /* patch, this recursive loop tries to create a nameless directory */
302                 if (!CreateDirectory(dirname, NULL))
303                         callLocalErrorCallBack("Unable to create directory\n");
304 }
305
306 int BLI_rename(const char *from, const char *to) {
307         if (!BLI_exists(from)) return 0;
308
309         /* make sure the filenames are different (case insensitive) before removing */
310         if (BLI_exists(to) && BLI_strcasecmp(from, to))
311                 if(BLI_delete(to, 0, 0)) return 1;
312
313         return rename(from, to);
314 }
315
316 #else /* The UNIX world */
317
318 /*
319  * but the UNIX world is tied to the interface, and the system
320  * timer, and... We implement a callback mechanism. The system will
321  * have to initialise the callback before the functions will work!
322  * */
323 static char str[12 + (MAXPATHLEN * 2)];
324
325 int BLI_delete(const char *file, int dir, int recursive) 
326 {
327         if(strchr(file, '"')) {
328                 printf("Error: not deleted file %s because of quote!\n", file);
329         }
330         else {
331                 if (recursive) {
332                         BLI_snprintf(str, sizeof(str), "/bin/rm -rf \"%s\"", file);
333                         return system(str);
334                 }
335                 else if (dir) {
336                         BLI_snprintf(str, sizeof(str), "/bin/rmdir \"%s\"", file);
337                         return system(str);
338                 }
339                 else {
340                         return remove(file); //BLI_snprintf(str, sizeof(str), "/bin/rm -f \"%s\"", file);
341                 }
342         }
343         return -1;
344 }
345
346 int BLI_move(const char *file, const char *to) {
347         BLI_snprintf(str, sizeof(str), "/bin/mv -f \"%s\" \"%s\"", file, to);
348
349         return system(str);
350 }
351
352 int BLI_copy_fileops(const char *file, const char *to) {
353         BLI_snprintf(str, sizeof(str), "/bin/cp -rf \"%s\" \"%s\"", file, to);
354
355         return system(str);
356 }
357
358 int BLI_link(const char *file, const char *to) {
359         BLI_snprintf(str, sizeof(str), "/bin/ln -f \"%s\" \"%s\"", file, to);
360         
361         return system(str);
362 }
363
364 void BLI_recurdir_fileops(const char *dirname) {
365         char *lslash;
366         char tmp[MAXPATHLEN];
367                 
368         if (BLI_exists(dirname)) return;
369
370         BLI_strncpy(tmp, dirname, sizeof(tmp));
371                 
372         lslash= BLI_last_slash(tmp);
373         if (lslash) {
374                         /* Split about the last slash and recurse */    
375                 *lslash = 0;
376                 BLI_recurdir_fileops(tmp);
377         }
378
379         mkdir(dirname, 0777);
380 }
381
382 int BLI_rename(const char *from, const char *to) {
383         if (!BLI_exists(from)) return 0;
384         
385         if (BLI_exists(to))     if(BLI_delete(to, 0, 0)) return 1;
386
387         return rename(from, to);
388 }
389
390 #endif