4b5ea44e97c2e5b33f6b5aff6dbd7f8dfc981c1c
[blender.git] / source / blender / blenlib / intern / fileops.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenlib/intern/fileops.c
29  *  \ingroup bli
30  */
31
32
33 #include <string.h>
34 #include <stdio.h>
35
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39
40 #include <errno.h>
41
42 #include "zlib.h"
43
44 #ifdef WIN32
45 #include <io.h>
46 #  include "BLI_winstuff.h"
47 #  include "BLI_callbacks.h"
48 #  include "utf_winfunc.h"
49 #  include "utfconv.h"
50 #else
51 #  include <unistd.h> // for read close
52 #  include <sys/param.h>
53 #  include <dirent.h>
54 #  include <unistd.h>
55 #  include <sys/stat.h>
56 #endif
57
58 #include "MEM_guardedalloc.h"
59
60 #include "BLI_blenlib.h"
61 #include "BLI_utildefines.h"
62
63 #include "BKE_utildefines.h"
64
65 #include "BLO_sys_types.h" // for intptr_t support
66
67
68 /* gzip the file in from and write it to "to". 
69  * return -1 if zlib fails, -2 if the originating file does not exist
70  * note: will remove the "from" file
71  */
72 int BLI_file_gzip(const char *from, const char *to)
73 {
74         char buffer[10240];
75         int file;
76         int readsize = 0;
77         int rval= 0, err;
78         gzFile gzfile;
79
80         /* level 1 is very close to 3 (the default) in terms of file size,
81          * but about twice as fast, best use for speedy saving - campbell */
82         gzfile = BLI_gzopen(to, "wb1");
83         if (gzfile == NULL)
84                 return -1;
85         file = BLI_open(from, O_BINARY|O_RDONLY,0);
86         if (file < 0)
87                 return -2;
88
89         while (1) {
90                 readsize = read(file, buffer, sizeof(buffer));
91
92                 if (readsize < 0) {
93                         rval= -2; /* error happened in reading */
94                         fprintf(stderr, "Error reading file %s: %s.\n", from, strerror(errno));
95                         break;
96                 }
97                 else if (readsize == 0)
98                         break; /* done reading */
99                 
100                 if (gzwrite(gzfile, buffer, readsize) <= 0) {
101                         rval= -1; /* error happened in writing */
102                         fprintf(stderr, "Error writing gz file %s: %s.\n", to, gzerror(gzfile, &err));
103                         break;
104                 }
105         }
106         
107         gzclose(gzfile);
108         close(file);
109
110         return rval;
111 }
112
113 /* gzip the file in from_file and write it to memery to_mem, at most size bytes.
114  * return the unziped size
115  */
116 char *BLI_file_ungzip_to_mem(const char *from_file, int *size_r)
117 {
118         gzFile gzfile;
119         int readsize, size, alloc_size=0;
120         char *mem= NULL;
121         const int chunk_size= 512*1024;
122
123         size= 0;
124
125         gzfile = BLI_gzopen( from_file, "rb" );
126         for (;;) {
127                 if (mem==NULL) {
128                         mem= MEM_callocN(chunk_size, "BLI_ungzip_to_mem");
129                         alloc_size= chunk_size;
130                 }
131                 else {
132                         mem= MEM_reallocN(mem, size+chunk_size);
133                         alloc_size+= chunk_size;
134                 }
135
136                 readsize= gzread(gzfile, mem+size, chunk_size);
137                 if (readsize>0) {
138                         size+= readsize;
139                 }
140                 else break;
141         }
142
143         if (size==0) {
144                 MEM_freeN(mem);
145                 mem= NULL;
146         }
147         else if (alloc_size!=size)
148                 mem= MEM_reallocN(mem, size);
149
150         *size_r= size;
151
152         return mem;
153 }
154
155
156 /* return 1 when file can be written */
157 int BLI_file_is_writable(const char *filename)
158 {
159         int file;
160         
161         /* first try to open without creating */
162         file = BLI_open(filename, O_BINARY | O_RDWR, 0666);
163         
164         if (file < 0) {
165                 /* now try to open and create. a test without actually
166                  * creating a file would be nice, but how? */
167                 file = BLI_open(filename, O_BINARY | O_RDWR | O_CREAT, 0666);
168                 
169                 if (file < 0) {
170                         return 0;
171                 }
172                 else {
173                         /* success, delete the file we create */
174                         close(file);
175                         BLI_delete(filename, 0, 0);
176                         return 1;
177                 }
178         }
179         else {
180                 close(file);
181                 return 1;
182         }
183 }
184
185 int BLI_file_touch(const char *file)
186 {
187         FILE *f = BLI_fopen(file, "r+b");
188         if (f != NULL) {
189                 char c = getc(f);
190                 rewind(f);
191                 putc(c, f);
192         }
193         else {
194                 f = BLI_fopen(file, "wb");
195         }
196         if (f) {
197                 fclose(f);
198                 return 1;
199         }
200         return 0;
201 }
202
203 #ifdef WIN32
204
205 static char str[MAXPATHLEN + 12];
206
207 FILE *BLI_fopen(const char *filename, const char *mode)
208 {
209         return ufopen(filename, mode);
210 }
211
212 void *BLI_gzopen(const char *filename, const char *mode)
213 {
214         gzFile gzfile;
215
216         if (!filename || !mode) {
217                 return 0;
218         }
219         else {
220                 wchar_t short_name_16[256];
221                 char short_name[256];
222                 int i = 0;
223
224                 /* xxx Creates file before transcribing the path */
225                 if (mode[0] == 'w')
226                         fclose(ufopen(filename,"a"));
227
228                 UTF16_ENCODE(filename);
229
230                 GetShortPathNameW(filename_16,short_name_16, 256);
231
232                 for (i = 0; i < 256; i++) {
233                         short_name[i] = short_name_16[i];
234                 }
235
236                 gzfile = gzopen(short_name,mode);
237
238                 UTF16_UN_ENCODE(filename);
239         }
240
241         return gzfile;
242 }
243
244 int   BLI_open(const char *filename, int oflag, int pmode)
245 {
246         return uopen(filename, oflag, pmode);
247 }
248
249 int BLI_delete(const char *file, int dir, int recursive)
250 {
251         int err;
252         
253         UTF16_ENCODE(file);
254
255         if (recursive) {
256                 callLocalErrorCallBack("Recursive delete is unsupported on Windows");
257                 err= 1;
258         }
259         else if (dir) {
260                 err= !RemoveDirectoryW(file_16);
261                 if (err) printf ("Unable to remove directory");
262         }
263         else {
264                 err= !DeleteFileW(file_16);
265                 if (err) callLocalErrorCallBack("Unable to delete file");
266         }
267
268         UTF16_UN_ENCODE(file);
269
270         return err;
271 }
272
273 int BLI_move(const char *file, const char *to)
274 {
275         int err;
276
277         // windows doesn't support moveing to a directory
278         // it has to be 'mv filename filename' and not
279         // 'mv filename destdir'
280
281         BLI_strncpy(str, to, sizeof(str));
282         // points 'to' to a directory ?
283         if (BLI_last_slash(str) == (str + strlen(str) - 1)) {
284                 if (BLI_last_slash(file) != NULL) {
285                         strcat(str, BLI_last_slash(file) + 1);
286                 }
287         }
288         
289         UTF16_ENCODE(file);
290         UTF16_ENCODE(str);
291         err= !MoveFileW(file_16, str_16);
292         UTF16_UN_ENCODE(str);
293         UTF16_UN_ENCODE(file);
294
295         if (err) {
296                 callLocalErrorCallBack("Unable to move file");
297                 printf(" Move from '%s' to '%s' failed\n", file, str);
298         }
299
300         return err;
301 }
302
303
304 int BLI_copy(const char *file, const char *to)
305 {
306         int err;
307
308         // windows doesn't support copying to a directory
309         // it has to be 'cp filename filename' and not
310         // 'cp filename destdir'
311
312         BLI_strncpy(str, to, sizeof(str));
313         // points 'to' to a directory ?
314         if (BLI_last_slash(str) == (str + strlen(str) - 1)) {
315                 if (BLI_last_slash(file) != NULL) {
316                         strcat(str, BLI_last_slash(file) + 1);
317                 }
318         }
319
320         UTF16_ENCODE(file);
321         UTF16_ENCODE(str);
322         err = !CopyFileW(file_16, str_16, FALSE);
323         UTF16_UN_ENCODE(str);
324         UTF16_UN_ENCODE(file);
325
326         if (err) {
327                 callLocalErrorCallBack("Unable to copy file!");
328                 printf(" Copy from '%s' to '%s' failed\n", file, str);
329         }
330
331         return err;
332 }
333
334 int BLI_create_symlink(const char *file, const char *to)
335 {
336         callLocalErrorCallBack("Linking files is unsupported on Windows");
337         (void)file;
338         (void)to;
339         return 1;
340 }
341
342 void BLI_dir_create_recursive(const char *dirname)
343 {
344         char *lslash;
345         char tmp[MAXPATHLEN];
346         
347         /* First remove possible slash at the end of the dirname.
348          * This routine otherwise tries to create
349          * blah1/blah2/ (with slash) after creating
350          * blah1/blah2 (without slash) */
351
352         BLI_strncpy(tmp, dirname, sizeof(tmp));
353         lslash= BLI_last_slash(tmp);
354         
355         if (lslash == tmp + strlen(tmp) - 1) {
356                 *lslash = 0;
357         }
358         
359         if (BLI_exists(tmp)) return;
360
361         lslash= BLI_last_slash(tmp);
362         if (lslash) {
363                 /* Split about the last slash and recurse */
364                 *lslash = 0;
365                 BLI_dir_create_recursive(tmp);
366         }
367         
368         if (dirname[0]) /* patch, this recursive loop tries to create a nameless directory */
369                 if (umkdir(dirname)==-1)
370                         printf("Unable to create directory %s\n",dirname);
371 }
372
373 int BLI_rename(const char *from, const char *to)
374 {
375         if (!BLI_exists(from)) return 0;
376
377         /* make sure the filenames are different (case insensitive) before removing */
378         if (BLI_exists(to) && BLI_strcasecmp(from, to))
379                 if (BLI_delete(to, 0, 0)) return 1;
380         
381         return urename(from, to);
382 }
383
384 #else /* The UNIX world */
385
386 enum {
387         /* operation succeeded succeeded */
388         recursiveOp_Callback_OK = 0,
389
390         /* operation requested not to perform recursive digging for current path */
391         recursiveOp_Callback_StopRecurs = 1,
392
393         /* error occured in callback and recursive walking should stop immediately */
394         recursiveOp_Callback_Error = 2
395 } recuresiveOp_Callback_Result;
396
397 typedef int (*recursiveOp_Callback) (const char *from, const char *to);
398
399 /* appending of filename to dir (ensures for buffer size before appending) */
400 static void join_dirfile_alloc(char **dst, size_t *alloc_len, const char *dir, const char *file)
401 {
402         size_t len = strlen(dir) + strlen(file) + 1;
403
404         if (!*dst)
405                 *dst = MEM_callocN(len + 1, "join_dirfile_alloc path");
406         else if (*alloc_len < len)
407                 *dst = MEM_reallocN(*dst, len + 1);
408
409         *alloc_len = len;
410
411         BLI_join_dirfile(*dst, len + 1, dir, file);
412 }
413
414 static char *strip_last_slash(const char *dir)
415 {
416         char *result = BLI_strdup(dir);
417         BLI_del_slash(result);
418
419         return result;
420 }
421
422 static int recursive_operation(const char *startfrom, const char *startto, recursiveOp_Callback callback_dir_pre,
423                                recursiveOp_Callback callback_file, recursiveOp_Callback callback_dir_post)
424 {
425         struct dirent **dirlist;
426         struct stat st;
427         char *from = NULL, *to = NULL;
428         char *from_path = NULL, *to_path = NULL;
429         size_t from_alloc_len = -1, to_alloc_len = -1;
430         int i, n, ret = 0;
431
432         /* ensure there's no trailing slash in file path */
433         from = strip_last_slash(startfrom);
434         if (startto)
435                 to = strip_last_slash(startto);
436
437         ret = lstat(from, &st);
438         if (ret < 0) {
439                 /* source wasn't found, nothing to operate with */
440                 return ret;
441         }
442
443         if (!S_ISDIR(st.st_mode)) {
444                 /* source isn't a directory, can't do recursive walking for it,
445                  * so just call file callback and leave */
446                 if (callback_file) {
447                         ret = callback_file(from, to);
448
449                         if (ret != recursiveOp_Callback_OK)
450                                 ret = -1;
451                 }
452
453                 MEM_freeN(from);
454                 if (to) MEM_freeN(to);
455
456                 return ret;
457         }
458
459
460         n = scandir(startfrom, &dirlist, 0, alphasort);
461         if (n < 0) {
462                 /* error opening directory for listing */
463                 perror("scandir");
464
465                 MEM_freeN(from);
466                 if (to) MEM_freeN(to);
467
468                 return -1;
469         }
470
471         if (callback_dir_pre) {
472                 /* call pre-recursive walking directory callback */
473                 ret = callback_dir_pre(from, to);
474
475                 if (ret != recursiveOp_Callback_OK) {
476                         MEM_freeN(from);
477                         if (to) free(to);
478
479                         if (ret == recursiveOp_Callback_StopRecurs) {
480                                 /* callback requested not to perform recursive walking, not an error */
481                                 return 0;
482                         }
483
484                         return -1;
485                 }
486         }
487
488         for (i = 0; i < n; i++) {
489                 struct dirent *dirent = dirlist[i];
490
491                 if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..")) {
492                         free(dirent);
493                         continue;
494                 }
495
496                 join_dirfile_alloc(&from_path, &from_alloc_len, from, dirent->d_name);
497
498                 if (to)
499                         join_dirfile_alloc(&to_path, &to_alloc_len, to, dirent->d_name);
500
501                 if (dirent->d_type == DT_DIR) {
502                         /* recursively dig into a folder */
503                         ret = recursive_operation(from_path, to_path, callback_dir_pre, callback_file, callback_dir_post);
504                 }
505                 else if (callback_file) {
506                         /* call file callback for current path */
507                         ret = callback_file(from_path, to_path);
508                         if (ret != recursiveOp_Callback_OK)
509                                 ret = -1;
510                 }
511
512                 if (ret != 0) {
513                         while (i < n)
514                                 free(dirlist[i]);
515                         break;
516                 }
517         }
518
519         free(dirlist);
520
521         if (ret == 0) {
522                 if (callback_dir_post) {
523                         /* call post-recursive directory callback */
524                         ret = callback_dir_post(from, to);
525                         if (ret != recursiveOp_Callback_OK)
526                                 ret = -1;
527                 }
528         }
529
530         if (from_path) MEM_freeN(from_path);
531         if (to_path) MEM_freeN(to_path);
532
533         MEM_freeN(from);
534         if (to) MEM_freeN(to);
535
536         return ret;
537 }
538
539 static int delete_callback_post(const char *from, const char *UNUSED(to))
540 {
541         if (rmdir(from)) {
542                 perror("rmdir");
543
544                 return recursiveOp_Callback_Error;
545         }
546
547         return recursiveOp_Callback_OK;
548 }
549
550 static int delete_single_file(const char *from, const char *UNUSED(to))
551 {
552         if (unlink(from)) {
553                 perror("unlink");
554
555                 return recursiveOp_Callback_Error;
556         }
557
558         return recursiveOp_Callback_OK;
559 }
560
561 FILE *BLI_fopen(const char *filename, const char *mode)
562 {
563         return fopen(filename, mode);
564 }
565
566 void *BLI_gzopen(const char *filename, const char *mode)
567 {
568         return gzopen(filename, mode);
569 }
570
571 int BLI_open(const char *filename, int oflag, int pmode)
572 {
573         return open(filename, oflag, pmode);
574 }
575
576 int BLI_delete(const char *file, int dir, int recursive) 
577 {
578         if (strchr(file, '"')) {
579                 printf("Error: not deleted file %s because of quote!\n", file);
580         }
581         else {
582                 if (recursive) {
583                         return recursive_operation(file, NULL, NULL, delete_single_file, delete_callback_post);
584                 }
585                 else if (dir) {
586                         return rmdir(file);
587                 }
588                 else {
589                         return remove(file); //BLI_snprintf(str, sizeof(str), "/bin/rm -f \"%s\"", file);
590                 }
591         }
592         return -1;
593 }
594
595 static int check_the_same(const char *path_a, const char *path_b)
596 {
597         struct stat st_a, st_b;
598
599         if (lstat(path_a, &st_a))
600                 return 0;
601
602         if (lstat(path_b, &st_b))
603                 return 0;
604
605         return st_a.st_dev == st_b.st_dev && st_a.st_ino == st_b.st_ino;
606 }
607
608 static int set_permissions(const char *file, struct stat *st)
609 {
610         if (chown(file, st->st_uid, st->st_gid)) {
611                 perror("chown");
612                 return -1;
613         }
614
615         if (chmod(file, st->st_mode)) {
616                 perror("chmod");
617                 return -1;
618         }
619
620         return 0;
621 }
622
623 /* pre-recursive callback for copying operation
624  * creates a destination directory where all source content fill be copied to */
625 static int copy_callback_pre(const char *from, const char *to)
626 {
627         struct stat st;
628
629         if (check_the_same(from, to)) {
630                 fprintf(stderr, "%s: '%s' is the same as '%s'\n", __func__, from, to);
631                 return recursiveOp_Callback_Error;
632         }
633
634         if (lstat(from, &st)) {
635                 perror("stat");
636                 return recursiveOp_Callback_Error;
637         }
638
639         /* create a directory */
640         if (mkdir(to, st.st_mode)) {
641                 perror("mkdir");
642                 return recursiveOp_Callback_Error;
643         }
644
645         /* set proper owner and group on new directory */
646         if (chown(to, st.st_uid, st.st_gid)) {
647                 perror("chown");
648                 return recursiveOp_Callback_Error;
649         }
650
651         return recursiveOp_Callback_OK;
652 }
653
654 static int copy_single_file(const char *from, const char *to)
655 {
656         FILE *from_stream, *to_stream;
657         struct stat st;
658         char buf[4096];
659         size_t len;
660
661         if (check_the_same(from, to)) {
662                 fprintf(stderr, "%s: '%s' is the same as '%s'\n", __func__, from, to);
663                 return recursiveOp_Callback_Error;
664         }
665
666         if (lstat(from, &st)) {
667                 perror("lstat");
668                 return recursiveOp_Callback_Error;
669         }
670
671         if (S_ISLNK(st.st_mode)) {
672                 /* symbolic links should be copied in special way */
673                 char *link_buffer;
674                 int need_free;
675                 ssize_t link_len;
676
677                 /* get large enough buffer to read link content */
678                 if (st.st_size < sizeof(buf)) {
679                         link_buffer = buf;
680                         need_free = 0;
681                 }
682                 else {
683                         link_buffer = MEM_callocN(st.st_size+2, "copy_single_file link_buffer");
684                         need_free = 1;
685                 }
686
687                 link_len = readlink(from, link_buffer, st.st_size+1);
688                 if (link_len < 0) {
689                         perror("readlink");
690
691                         if (need_free) MEM_freeN(link_buffer);
692
693                         return recursiveOp_Callback_Error;
694                 }
695
696                 link_buffer[link_len] = 0;
697
698                 if (symlink(link_buffer, to)) {
699                         perror("symlink");
700                         if (need_free) MEM_freeN(link_buffer);
701                         return recursiveOp_Callback_Error;
702                 }
703
704                 if (need_free)
705                         MEM_freeN(link_buffer);
706
707                 return recursiveOp_Callback_OK;
708         }
709         else if (S_ISCHR (st.st_mode) ||
710                 S_ISBLK (st.st_mode) ||
711                 S_ISFIFO (st.st_mode) ||
712                 S_ISSOCK (st.st_mode))
713         {
714                 /* copy special type of file */
715                 if (mknod(to, st.st_mode, st.st_rdev)) {
716                         perror("mknod");
717                         return recursiveOp_Callback_Error;
718                 }
719
720                 if (set_permissions(to, &st))
721                         return recursiveOp_Callback_Error;
722
723                 return recursiveOp_Callback_OK;
724         }
725         else if (!S_ISREG(st.st_mode)) {
726                 fprintf(stderr, "Copying of this kind of files isn't supported yet\n");
727                 return recursiveOp_Callback_Error;
728         }
729
730         from_stream = fopen(from, "rb");
731         if (!from_stream) {
732                 perror("fopen");
733                 return recursiveOp_Callback_Error;
734         }
735
736         to_stream = fopen(to, "wb");
737         if (!to_stream) {
738                 perror("fopen");
739                 fclose(from_stream);
740                 return recursiveOp_Callback_Error;
741         }
742
743         while ((len = fread(buf, 1, sizeof(buf), from_stream)) > 0) {
744                 fwrite(buf, 1, len, to_stream);
745         }
746
747         fclose(to_stream);
748         fclose(from_stream);
749
750         if (set_permissions(to, &st))
751                 return recursiveOp_Callback_Error;
752
753         return recursiveOp_Callback_OK;
754 }
755
756 static int move_callback_pre(const char *from, const char *to)
757 {
758         int ret = rename(from, to);
759
760         if (ret)
761                 return copy_callback_pre(from, to);
762
763         return recursiveOp_Callback_StopRecurs;
764 }
765
766 static int move_single_file(const char *from, const char *to)
767 {
768         int ret = rename(from, to);
769
770         if (ret)
771                 return copy_single_file(from, to);
772
773         return recursiveOp_Callback_OK;
774 }
775
776 int BLI_move(const char *file, const char *to)
777 {
778         int ret = recursive_operation(file, to, move_callback_pre, move_single_file, NULL);
779
780         if (ret) {
781                 return recursive_operation(file, NULL, NULL, delete_single_file, delete_callback_post);
782         }
783
784         return ret;
785 }
786
787 static char *check_destination(const char *file, const char *to)
788 {
789         struct stat st;
790
791         if (!stat(to, &st)) {
792                 if (S_ISDIR(st.st_mode)) {
793                         char *str, *filename, *path;
794                         size_t len = 0;
795
796                         str = strip_last_slash(file);
797                         filename = BLI_last_slash(str);
798
799                         if (!filename) {
800                                 MEM_freeN(str);
801                                 return (char*)to;
802                         }
803
804                         /* skip slash */
805                         filename += 1;
806
807                         len = strlen(to) + strlen(filename) + 1;
808                         path = MEM_callocN(len + 1, "check_destination path");
809                         BLI_join_dirfile(path, len + 1, to, filename);
810
811                         MEM_freeN(str);
812
813                         return path;
814                 }
815         }
816
817         return (char*)to;
818 }
819
820 int BLI_copy(const char *file, const char *to)
821 {
822         char *actual_to = check_destination(file, to);
823         int ret;
824
825         ret = recursive_operation(file, actual_to, copy_callback_pre, copy_single_file, NULL);
826
827         if (actual_to!=to)
828                 MEM_freeN(actual_to);
829
830         return ret;
831 }
832
833 int BLI_create_symlink(const char *file, const char *to)
834 {
835         return symlink(to, file);
836 }
837
838 void BLI_dir_create_recursive(const char *dirname)
839 {
840         char *lslash;
841         size_t size;
842 #ifdef MAXPATHLEN
843         char static_buf[MAXPATHLEN];
844 #endif
845         char *tmp;
846         int needs_free;
847
848         if (BLI_exists(dirname)) return;
849
850 #ifdef MAXPATHLEN
851         size = MAXPATHLEN;
852         tmp = static_buf;
853         needs_free = 0;
854 #else
855         size = strlen(dirname)+1;
856         tmp = MEM_callocN(size, "BLI_dir_create_recursive tmp");
857         needs_free = 1;
858 #endif
859
860         BLI_strncpy(tmp, dirname, size);
861                 
862         lslash= BLI_last_slash(tmp);
863         if (lslash) {
864                         /* Split about the last slash and recurse */    
865                 *lslash = 0;
866                 BLI_dir_create_recursive(tmp);
867         }
868
869         if (needs_free)
870                 MEM_freeN(tmp);
871
872         mkdir(dirname, 0777);
873 }
874
875 int BLI_rename(const char *from, const char *to)
876 {
877         if (!BLI_exists(from)) return 0;
878         
879         if (BLI_exists(to))
880                 if (BLI_delete(to, 0, 0)) return 1;
881
882         return rename(from, to);
883 }
884
885 #endif
886