e848ad8d0d38ccba5af0b2b8ee5d60fed13c2660
[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 int BLI_exists(const char *file) {
199         return BLI_exist(file);
200 }
201
202 #ifdef WIN32
203
204 static char str[MAXPATHLEN+12];
205
206 int BLI_delete(const char *file, int dir, int recursive) {
207         int err;
208
209         if (recursive) {
210                 callLocalErrorCallBack("Recursive delete is unsupported on Windows");
211                 err= 1;
212         } else if (dir) {
213                 err= !RemoveDirectory(file);
214                 if (err) printf ("Unable to remove directory");
215         } else {
216                 err= !DeleteFile(file);
217                 if (err) callLocalErrorCallBack("Unable to delete file");
218         }
219
220         return err;
221 }
222
223 int BLI_move(const char *file, const char *to) {
224         int err;
225
226         // windows doesn't support moveing to a directory
227         // it has to be 'mv filename filename' and not
228         // 'mv filename destdir'
229
230         BLI_strncpy(str, to, sizeof(str));
231         // points 'to' to a directory ?
232         if (BLI_last_slash(str) == (str + strlen(str) - 1)) {
233                 if (BLI_last_slash(file) != NULL) {
234                         strcat(str, BLI_last_slash(file) + 1);
235                 }
236         }
237
238         err= !MoveFile(file, str);
239         if (err) {
240                 callLocalErrorCallBack("Unable to move file");
241                 printf(" Move from '%s' to '%s' failed\n", file, str);
242         }
243
244         return err;
245 }
246
247
248 int BLI_copy_fileops(const char *file, const char *to) {
249         int err;
250
251         // windows doesn't support copying to a directory
252         // it has to be 'cp filename filename' and not
253         // 'cp filename destdir'
254
255         BLI_strncpy(str, to, sizeof(str));
256         // points 'to' to a directory ?
257         if (BLI_last_slash(str) == (str + strlen(str) - 1)) {
258                 if (BLI_last_slash(file) != NULL) {
259                         strcat(str, BLI_last_slash(file) + 1);
260                 }
261         }
262
263         err= !CopyFile(file,str,FALSE);
264         
265         if (err) {
266                 callLocalErrorCallBack("Unable to copy file!");
267                 printf(" Copy from '%s' to '%s' failed\n", file, str);
268         }
269
270         return err;
271 }
272
273 int BLI_link(const char *file, const char *to) {
274         callLocalErrorCallBack("Linking files is unsupported on Windows");
275         (void)file;
276         (void)to;
277         return 1;
278 }
279
280 void BLI_recurdir_fileops(const char *dirname) {
281         char *lslash;
282         char tmp[MAXPATHLEN];
283         
284         // First remove possible slash at the end of the dirname.
285         // This routine otherwise tries to create
286         // blah1/blah2/ (with slash) after creating
287         // blah1/blah2 (without slash)
288
289         BLI_strncpy(tmp, dirname, sizeof(tmp));
290         lslash= BLI_last_slash(tmp);
291
292         if (lslash == tmp + strlen(tmp) - 1) {
293                 *lslash = 0;
294         }
295         
296         if (BLI_exists(tmp)) return;
297                 
298         lslash= BLI_last_slash(tmp);
299         if (lslash) {
300                         /* Split about the last slash and recurse */    
301                 *lslash = 0;
302                 BLI_recurdir_fileops(tmp);
303         }
304         
305         if(dirname[0]) /* patch, this recursive loop tries to create a nameless directory */
306                 if (!CreateDirectory(dirname, NULL))
307                         callLocalErrorCallBack("Unable to create directory\n");
308 }
309
310 int BLI_rename(const char *from, const char *to) {
311         if (!BLI_exists(from)) return 0;
312
313         /* make sure the filenames are different (case insensitive) before removing */
314         if (BLI_exists(to) && BLI_strcasecmp(from, to))
315                 if(BLI_delete(to, 0, 0)) return 1;
316
317         return rename(from, to);
318 }
319
320 #else /* The UNIX world */
321
322 /*
323  * but the UNIX world is tied to the interface, and the system
324  * timer, and... We implement a callback mechanism. The system will
325  * have to initialise the callback before the functions will work!
326  * */
327 static char str[12 + (MAXPATHLEN * 2)];
328
329 int BLI_delete(const char *file, int dir, int recursive) 
330 {
331         if(strchr(file, '"')) {
332                 printf("Error: not deleted file %s because of quote!\n", file);
333         }
334         else {
335                 if (recursive) {
336                         BLI_snprintf(str, sizeof(str), "/bin/rm -rf \"%s\"", file);
337                         return system(str);
338                 }
339                 else if (dir) {
340                         BLI_snprintf(str, sizeof(str), "/bin/rmdir \"%s\"", file);
341                         return system(str);
342                 }
343                 else {
344                         return remove(file); //BLI_snprintf(str, sizeof(str), "/bin/rm -f \"%s\"", file);
345                 }
346         }
347         return -1;
348 }
349
350 int BLI_move(const char *file, const char *to) {
351         BLI_snprintf(str, sizeof(str), "/bin/mv -f \"%s\" \"%s\"", file, to);
352
353         return system(str);
354 }
355
356 int BLI_copy_fileops(const char *file, const char *to) {
357         BLI_snprintf(str, sizeof(str), "/bin/cp -rf \"%s\" \"%s\"", file, to);
358
359         return system(str);
360 }
361
362 int BLI_link(const char *file, const char *to) {
363         BLI_snprintf(str, sizeof(str), "/bin/ln -f \"%s\" \"%s\"", file, to);
364         
365         return system(str);
366 }
367
368 void BLI_recurdir_fileops(const char *dirname) {
369         char *lslash;
370         char tmp[MAXPATHLEN];
371                 
372         if (BLI_exists(dirname)) return;
373
374         BLI_strncpy(tmp, dirname, sizeof(tmp));
375                 
376         lslash= BLI_last_slash(tmp);
377         if (lslash) {
378                         /* Split about the last slash and recurse */    
379                 *lslash = 0;
380                 BLI_recurdir_fileops(tmp);
381         }
382
383         mkdir(dirname, 0777);
384 }
385
386 int BLI_rename(const char *from, const char *to) {
387         if (!BLI_exists(from)) return 0;
388         
389         if (BLI_exists(to))     if(BLI_delete(to, 0, 0)) return 1;
390
391         return rename(from, to);
392 }
393
394 #endif