BLI_split_dirfile was being used in cases it should not have been,
[blender.git] / source / blender / blenlib / intern / bpath.c
1 /**
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): Campbell barton
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include "BLI_bpath.h"
30 #include "BKE_global.h"
31 #include "BIF_screen.h" /* only for wait cursor */
32 #include "DNA_ID.h" /* Library */
33 #include "DNA_vfont_types.h"
34 #include "DNA_image_types.h"
35 #include "DNA_sound_types.h"
36 #include "DNA_scene_types.h" /* to get the current frame */
37 #include "DNA_sequence_types.h"
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include "BKE_main.h" /* so we can access G.main->*.first */
42 #include "BKE_image.h" /* so we can check the image's type */
43
44 #include "blendef.h"
45 #include "BKE_utildefines.h"
46 #include "MEM_guardedalloc.h"
47
48 /* for sequence */
49 #include "BSE_sequence.h"
50
51 /* for writing to a textblock */
52 #include "BKE_text.h" 
53 #include "BLI_blenlib.h"
54 #include "DNA_text_types.h"
55
56 /* path/file handeling stuff */
57 #ifndef WIN32
58   #include <dirent.h>
59   #include <unistd.h>
60 #else
61   #include "BLI_winstuff.h"
62   #include <io.h>
63 #endif
64
65 #include <sys/stat.h>
66 #include <sys/types.h>
67
68 #include <fcntl.h>
69 #include <stdio.h>
70 #include <string.h>
71 #include <stdlib.h>
72
73
74 #define FILE_MAX                        240
75
76 /* TODO - BPATH_PLUGIN, BPATH_SEQ */
77 enum BPathTypes {
78         BPATH_IMAGE = 0,
79         BPATH_SOUND,
80         BPATH_FONT,
81         BPATH_LIB,
82         BPATH_SEQ,
83
84         BPATH_DONE
85 };
86
87 void BLI_bpathIterator_init( struct BPathIterator *bpi ) {
88         bpi->type = BPATH_IMAGE;
89         bpi->data = NULL;
90         
91         bpi->getpath_callback = NULL;
92         bpi->setpath_callback = NULL;
93         
94         /* Sequencer spesific */
95         bpi->seqdata.totseq = 0;
96         bpi->seqdata.seq = 0;
97         bpi->seqdata.seqar = NULL;
98         
99         BLI_bpathIterator_step(bpi);
100 }
101
102 void BLI_bpathIterator_free( struct BPathIterator *bpi ) {
103         if (bpi->seqdata.seqar)
104                 MEM_freeN((void *)bpi->seqdata.seqar);
105         bpi->seqdata.seqar = NULL;
106 }
107
108 void BLI_bpathIterator_getPath( struct BPathIterator *bpi, char *path) {
109         if (bpi->getpath_callback) {
110                 bpi->getpath_callback( bpi, path );
111         } else {
112                 strcpy(path, bpi->path); /* warning, we assume 'path' are long enough */
113         }
114 }
115
116 void BLI_bpathIterator_setPath( struct BPathIterator *bpi, char *path) {
117         if (bpi->setpath_callback) {
118                 bpi->setpath_callback( bpi, path );
119         } else {
120                 strcpy(bpi->path, path); /* warning, we assume 'path' are long enough */
121         }
122 }
123
124 void BLI_bpathIterator_getPathExpanded( struct BPathIterator *bpi, char *path_expanded) {
125         char *libpath;
126         
127         BLI_bpathIterator_getPath(bpi, path_expanded);
128         libpath = BLI_bpathIterator_getLib(bpi);
129         
130         if (libpath) { /* check the files location relative to its library path */
131                 BLI_convertstringcode(path_expanded, libpath, G.scene->r.cfra);
132         } else { /* local data, use the blend files path */
133                 BLI_convertstringcode(path_expanded, G.sce, G.scene->r.cfra);
134         }
135 }
136 char* BLI_bpathIterator_getLib( struct BPathIterator *bpi) {
137         return bpi->lib;
138 }
139 char* BLI_bpathIterator_getName( struct BPathIterator *bpi) {
140         return bpi->name;
141 }
142 int     BLI_bpathIterator_getType( struct BPathIterator *bpi) {
143         return bpi->type;
144 }
145 int     BLI_bpathIterator_getPathMaxLen( struct BPathIterator *bpi) {
146         return bpi->len;
147 }
148
149 /* gets the first or the next image that has a path - not a viewer node or generated image */
150 static struct Image *ima_stepdata__internal(struct Image *ima, int step_next) {
151         if (ima==NULL)
152                 return NULL;
153         
154         if (step_next)
155                 ima = ima->id.next;
156         
157         while (ima) {
158                 if (ima->packedfile==NULL && ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
159                         break;
160                 /* image is not a image with a path, skip it */
161                 ima = ima->id.next;
162         }       
163         return ima;
164 }
165
166 static struct VFont *vf_stepdata__internal(struct VFont *vf, int step_next) {
167         if (vf==NULL)
168                 return NULL;
169         
170         if (step_next)
171                 vf = vf->id.next;
172         
173         while (vf) {
174                 if (vf->packedfile==NULL && BLI_streq(vf->name, "<builtin>")==0) {
175                         break;
176                 }
177                 
178                 /* font with no path, skip it */
179                 vf = vf->id.next;
180         }       
181         return vf;
182 }
183
184 static struct bSound *snd_stepdata__internal(struct bSound *snd, int step_next) {
185         if (snd==NULL)
186                 return NULL;
187         
188         if (step_next)
189                 snd = snd->id.next;
190         
191         while (snd) {
192                 if (snd->packedfile==NULL) {
193                         break;
194                 }
195                 
196                 /* font with no path, skip it */
197                 snd = snd->id.next;
198         }       
199         return snd;
200 }
201
202 static struct Sequence *seq_stepdata__internal(struct BPathIterator *bpi, int step_next) {
203         Sequence *seq;
204         
205         if (G.scene->ed==NULL) {
206                 return NULL;
207         }
208         
209         if (bpi->seqdata.seqar == NULL) {
210                 /* allocate the sequencer array */
211                 build_seqar( &(((Editing *)G.scene->ed)->seqbase), &bpi->seqdata.seqar, &bpi->seqdata.totseq);          
212                 bpi->seqdata.seq = 0;
213         }
214         
215         if (step_next) {
216                 bpi->seqdata.seq++;
217         }
218         
219         if (bpi->seqdata.seq >= bpi->seqdata.totseq) {
220                 seq = NULL;
221         } else {
222                 seq = bpi->seqdata.seqar[bpi->seqdata.seq];
223                 while (!SEQ_HAS_PATH(seq)) {
224                         bpi->seqdata.seq++;
225                         if (bpi->seqdata.seq >= bpi->seqdata.totseq) {
226                                 seq = NULL;
227                                 break;
228                         }
229                         seq = bpi->seqdata.seqar[bpi->seqdata.seq];
230                 }
231         }
232         return seq ;
233 }
234
235 void seq_getpath(struct BPathIterator *bpi, char *path) {
236         Sequence *seq = (Sequence *)bpi->data;
237
238         
239         path[0] = '\0'; /* incase we cant get the path */
240         if (seq==NULL) return;
241         if (SEQ_HAS_PATH(seq)) {
242                 if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) {
243                         BLI_strncpy(path, seq->strip->dir, FILE_MAX);
244                         BLI_add_slash(path); /* incase its missing */
245                         if (seq->strip->stripdata) { /* should always be true! */
246                                 /* Using the first image is weak for image sequences */
247                                 strcat(path, seq->strip->stripdata->name);
248                         } 
249                 } else {
250                         /* simple case */
251                         BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir));
252                 }
253         }
254 }
255
256 void seq_setpath(struct BPathIterator *bpi, char *path) {
257         Sequence *seq = (Sequence *)bpi->data;
258         if (seq==NULL) return; 
259         
260         if (SEQ_HAS_PATH(seq)) {
261                 if (seq->type == SEQ_IMAGE || seq->type == SEQ_MOVIE) {
262                         BLI_split_dirfile_basic(path, seq->strip->dir, seq->strip->stripdata->name);
263                 } else {
264                         /* simple case */
265                         BLI_strncpy(seq->strip->dir, path, sizeof(seq->strip->dir));
266                 }
267         }
268 }
269
270 static void bpi_type_step__internal( struct BPathIterator *bpi) {
271         bpi->type++; /* advance to the next type */
272         bpi->data = NULL;
273         
274         switch (bpi->type) {
275         case BPATH_SEQ:
276                 bpi->getpath_callback = seq_getpath;
277                 bpi->setpath_callback = seq_setpath;
278                 break;
279         default:
280                 bpi->getpath_callback = NULL;
281                 bpi->setpath_callback = NULL;
282                 break;
283         }
284 }
285
286 void BLI_bpathIterator_step( struct BPathIterator *bpi) {
287         while (bpi->type != BPATH_DONE) {
288                 
289                 if  ((bpi->type) == BPATH_IMAGE) {
290                         /*if (bpi->data)        bpi->data = ((ID *)bpi->data)->next;*/
291                         if (bpi->data)  bpi->data = ima_stepdata__internal( (Image *)bpi->data, 1 ); /* must skip images that have no path */
292                         else                    bpi->data = ima_stepdata__internal(G.main->image.first, 0);
293                         
294                         if (bpi->data) {
295                                 /* get the path info from this datatype */
296                                 Image *ima = (Image *)bpi->data;
297                                 
298                                 bpi->lib = ima->id.lib ? ima->id.lib->filename : NULL;
299                                 bpi->path = ima->name;
300                                 bpi->name = ima->id.name+2;
301                                 bpi->len = sizeof(ima->name);
302                                 
303                                 /* we are done, advancing to the next item, this type worked fine */
304                                 break;
305                                 
306                         } else {
307                                 bpi_type_step__internal(bpi);
308                         }
309                         
310                         
311                 } else if  ((bpi->type) == BPATH_SOUND) {
312                         if (bpi->data)  bpi->data = snd_stepdata__internal( (bSound *)bpi->data, 1 ); /* must skip images that have no path */
313                         else                    bpi->data = snd_stepdata__internal(G.main->sound.first, 0);
314                         
315                         if (bpi->data) {
316                                 /* get the path info from this datatype */
317                                 bSound *snd = (bSound *)bpi->data;
318                                 
319                                 bpi->lib = snd->id.lib ? snd->id.lib->filename : NULL;
320                                 bpi->path = snd->sample->name;
321                                 bpi->name = snd->id.name+2;
322                                 bpi->len = sizeof(snd->sample->name);
323                                 
324                                 /* we are done, advancing to the next item, this type worked fine */
325                                 break;
326                         } else {
327                                 bpi_type_step__internal(bpi);
328                         }
329                         
330                         
331                 } else if  ((bpi->type) == BPATH_FONT) {
332                         
333                         if (bpi->data)  bpi->data = vf_stepdata__internal( (VFont *)bpi->data, 1 );
334                         else                    bpi->data = vf_stepdata__internal( G.main->vfont.first, 0 );
335                         
336                         if (bpi->data) {
337                                 /* get the path info from this datatype */
338                                 VFont *vf = (VFont *)bpi->data;
339                                 
340                                 bpi->lib = vf->id.lib ? vf->id.lib->filename : NULL;
341                                 bpi->path = vf->name;
342                                 bpi->name = vf->id.name+2;
343                                 bpi->len = sizeof(vf->name);
344                                 
345                                 /* we are done, advancing to the next item, this type worked fine */
346                                 break;
347                         } else {
348                                 bpi_type_step__internal(bpi);
349                         }
350                         
351                 } else if  ((bpi->type) == BPATH_LIB) {
352                         if (bpi->data)  bpi->data = ((ID *)bpi->data)->next;
353                         else                    bpi->data = G.main->library.first;
354                         
355                         if (bpi->data) {
356                                 /* get the path info from this datatype */
357                                 Library *lib = (Library *)bpi->data;
358                                 
359                                 bpi->lib = NULL;
360                                 bpi->path = lib->name;
361                                 bpi->name = NULL;
362                                 bpi->len = sizeof(lib->name);
363                                 
364                                 /* we are done, advancing to the next item, this type worked fine */
365                                 break;
366                         } else {
367                                 bpi_type_step__internal(bpi);
368                         }
369                 } else if  ((bpi->type) == BPATH_SEQ) {
370                         if (bpi->data)  bpi->data = seq_stepdata__internal( bpi, 1 );
371                         else                    bpi->data = seq_stepdata__internal( bpi, 0 );
372                         if (bpi->data) {
373                                 Sequence *seq = (Sequence *)bpi->data;
374                                 bpi->lib = NULL;
375                                 bpi->name = seq->name+2;
376                                 bpi->len = sizeof(seq->strip->stripdata->name);
377                                 break;
378                         } else {
379                                 bpi_type_step__internal(bpi);
380                         }
381                 }
382         }
383 }
384
385 int BLI_bpathIterator_isDone( struct BPathIterator *bpi) {
386         return bpi->type==BPATH_DONE;
387 }
388
389 /* include the path argument */
390 static void bpathToText(Text *btxt, struct BPathIterator *bpi)
391 {
392         char *name;
393         char path_expanded[FILE_MAXDIR*2];
394         
395         switch(BLI_bpathIterator_getType(bpi)) {
396         case BPATH_IMAGE:
397                 txt_insert_buf( btxt, "Image \"" );
398                 break;
399         case BPATH_SOUND:
400                 txt_insert_buf( btxt, "Sound \"" );
401                 break;
402         case BPATH_FONT:
403                 txt_insert_buf( btxt, "Font \"" );
404                 break;
405         case BPATH_LIB:
406                 txt_insert_buf( btxt, "Library \"" );
407                 break;
408         case BPATH_SEQ:
409                 txt_insert_buf( btxt, "Sequence \"" );
410                 break;
411         default:
412                 txt_insert_buf( btxt, "Unknown \"" );
413                 break;
414         }
415         
416         name = BLI_bpathIterator_getName(bpi);
417         
418         if (name) {
419                 txt_insert_buf( btxt, name );
420         }
421         txt_insert_buf( btxt, "\" " );
422         
423         BLI_bpathIterator_getPathExpanded(bpi, path_expanded);
424         
425         txt_insert_buf( btxt, path_expanded );
426         txt_insert_buf( btxt, "\n" );
427         txt_move_eof( btxt, 0 );
428 }
429
430 /* high level function */
431 void checkMissingFiles( char *txtname ) {
432         Text *btxt = NULL;
433         struct BPathIterator bpi;
434         
435         /* be sure there is low chance of the path being too short */
436         char filepath_expanded[FILE_MAXDIR*2]; 
437         char *libpath;
438         int files_missing = 0;
439         
440         BLI_bpathIterator_init(&bpi);
441         while (!BLI_bpathIterator_isDone(&bpi)) {
442                 libpath = BLI_bpathIterator_getLib(&bpi);
443                 
444                 BLI_bpathIterator_getPathExpanded( &bpi, filepath_expanded );
445                 
446                 if (!BLI_exists(filepath_expanded)) {
447                         if (!btxt) {
448                                 btxt = add_empty_text( "missing_files.log" );
449                                 if (txtname) {
450                                         BLI_strncpy(txtname, btxt->id.name+2, 24);
451                                 }
452                         }
453                         bpathToText(btxt, &bpi);
454                         files_missing = 1;
455                 }
456                 BLI_bpathIterator_step(&bpi);
457         }
458         BLI_bpathIterator_free(&bpi);
459 }
460
461 /* dont log any errors at the moment, should probably do this */
462 void makeFilesRelative(char *txtname, int *tot, int *changed, int *failed, int *linked) {
463         struct BPathIterator bpi;
464         char filepath[FILE_MAX], *libpath;
465         
466         /* be sure there is low chance of the path being too short */
467         char filepath_relative[(FILE_MAXDIR * 2) + FILE_MAXFILE];
468         
469         Text *btxt = NULL;
470         
471         *tot = *changed = *failed = *linked = 0;
472         
473         BLI_bpathIterator_init(&bpi);
474         while (!BLI_bpathIterator_isDone(&bpi)) {
475                 BLI_bpathIterator_getPath(&bpi, filepath);
476                 libpath = BLI_bpathIterator_getLib(&bpi);
477                 
478                 if(strncmp(filepath, "//", 2)) {
479                         if (libpath) { /* cant make relative if we are library - TODO, LOG THIS */
480                                 (*linked)++;
481                         } else { /* local data, use the blend files path */
482                                 BLI_strncpy(filepath_relative, filepath, sizeof(filepath_relative));
483                                 /* Important BLI_cleanup_dir runs before the path is made relative
484                                  * because it wont work for paths that start with "//../" */ 
485                                 BLI_cleanup_file(G.sce, filepath_relative); /* fix any /foo/../foo/ */
486                                 BLI_makestringcode(G.sce, filepath_relative);
487                                 /* be safe and check the length */
488                                 if (BLI_bpathIterator_getPathMaxLen(&bpi) <= strlen(filepath_relative)) {
489                                         if (!btxt) {
490                                                 btxt = add_empty_text( "missing_no_rel.log" );
491                                                 if (txtname) {
492                                                         BLI_strncpy(txtname, btxt->id.name+2, 24);
493                                                 }
494                                         }
495                                         bpathToText(btxt, &bpi);
496                                         (*failed)++;
497                                 } else {
498                                         if(strncmp(filepath_relative, "//", 2)==0) {
499                                                 BLI_bpathIterator_setPath(&bpi, filepath_relative);
500                                                 (*changed)++;
501                                         } else {
502                                                 if (!btxt) {
503                                                         btxt = add_empty_text( "missing_no_rel.log" );
504                                                         if (txtname) {
505                                                                 BLI_strncpy(txtname, btxt->id.name+2, 24);
506                                                         }
507                                                 }
508                                                 bpathToText(btxt, &bpi);
509                                                 (*failed)++;
510                                         }
511                                 }
512                         }
513                 }
514                 BLI_bpathIterator_step(&bpi);
515                 (*tot)++;
516         }
517         BLI_bpathIterator_free(&bpi);
518 }
519
520 /* dont log any errors at the moment, should probably do this -
521  * Verry similar to makeFilesRelative - keep in sync! */
522 void makeFilesAbsolute(char *txtname, int *tot, int *changed, int *failed, int *linked) {
523         struct BPathIterator bpi;
524         char filepath[FILE_MAX], *libpath;
525         
526         /* be sure there is low chance of the path being too short */
527         char filepath_absolute[(FILE_MAXDIR * 2) + FILE_MAXFILE];
528         
529         Text *btxt = NULL;
530         
531         *tot = *changed = *failed = *linked = 0;
532         
533         BLI_bpathIterator_init(&bpi);
534         while (!BLI_bpathIterator_isDone(&bpi)) {
535                 BLI_bpathIterator_getPath(&bpi, filepath);
536                 libpath = BLI_bpathIterator_getLib(&bpi);
537                 
538                 if(strncmp(filepath, "//", 2)==0) {
539                         if (libpath) { /* cant make absolute if we are library - TODO, LOG THIS */
540                                 (*linked)++;
541                         } else { /* get the expanded path and check it is relative or too long */
542                                 BLI_bpathIterator_getPathExpanded( &bpi, filepath_absolute );
543                                 BLI_cleanup_file(G.sce, filepath_absolute); /* fix any /foo/../foo/ */
544                                 /* to be safe, check the length */
545                                 if (BLI_bpathIterator_getPathMaxLen(&bpi) <= strlen(filepath_absolute)) {
546                                         if (!btxt) {
547                                                 btxt = add_empty_text( "missing_no_abs.log" );
548                                                 if (txtname) {
549                                                         BLI_strncpy(txtname, btxt->id.name+2, 24);
550                                                 }
551                                         }
552                                         bpathToText(btxt, &bpi);
553                                         (*failed)++;
554                                 } else {
555                                         if(strncmp(filepath_absolute, "//", 2)) {
556                                                 BLI_bpathIterator_setPath(&bpi, filepath_absolute);
557                                                 (*changed)++;
558                                         } else {
559                                                 if (!btxt) {
560                                                         btxt = add_empty_text( "missing_no_abs.log" );
561                                                         if (txtname) {
562                                                                 BLI_strncpy(txtname, btxt->id.name+2, 24);
563                                                         }
564                                                 }
565                                                 bpathToText(btxt, &bpi);
566                                                 (*failed)++;
567                                         }
568                                 }
569                         }
570                 }
571                 BLI_bpathIterator_step(&bpi);
572                 (*tot)++;
573         }
574         BLI_bpathIterator_free(&bpi);
575 }
576
577
578 /* find this file recursively, use the biggest file so thumbnails dont get used by mistake
579  - dir: subdir to search
580  - filename: set this filename
581  - filesize: filesize for the file
582 */
583 #define MAX_RECUR 16
584 static int findFileRecursive(char *filename_new, const char *dirname, const char *filename, int *filesize, int *recur_depth)
585 {
586         /* file searching stuff */
587         DIR *dir;
588         struct dirent *de;
589         struct stat status;
590         char path[FILE_MAX];
591         int size;
592         
593         dir = opendir(dirname);
594         
595         if (dir==0)
596                 return 0;
597         
598         if (*filesize == -1)
599                 *filesize = 0; /* dir opened fine */
600         
601         while ((de = readdir(dir)) != NULL) {
602                 
603                 if (strncmp(".", de->d_name, 2)==0 || strncmp("..", de->d_name, 3)==0)
604                         continue;
605                 
606                 BLI_join_dirfile(path, dirname, de->d_name);
607                 
608                 if (stat(path, &status) != 0)
609                         continue; /* cant stat, dont bother with this file, could print debug info here */
610                 
611                 if (S_ISREG(status.st_mode)) { /* is file */
612                         if (strncmp(filename, de->d_name, FILE_MAX)==0) { /* name matches */
613                                 /* open the file to read its size */
614                                 size = BLI_filepathsize(path);
615                                 if ((size > 0) && (size > *filesize)) { /* find the biggest file */
616                                         *filesize = size;
617                                         BLI_strncpy(filename_new, path, FILE_MAX);
618                                 }
619                         }
620                 } else if (S_ISDIR(status.st_mode)) { /* is subdir */
621                         if (*recur_depth <= MAX_RECUR) {
622                                 (*recur_depth)++;
623                                 findFileRecursive(filename_new, path, filename, filesize, recur_depth);
624                                 (*recur_depth)--;
625                         }
626                 }
627         }
628         closedir(dir);
629         return 1;
630 }
631
632 /* high level function - call from fileselector */
633 void findMissingFiles(char *str) {
634         struct BPathIterator bpi;
635         
636         /* be sure there is low chance of the path being too short */
637         char filepath_expanded[FILE_MAXDIR*2]; 
638         char filepath[FILE_MAX], *libpath;
639         int filesize, recur_depth;
640         
641         char dirname[FILE_MAX], filename[FILE_MAX], filename_new[FILE_MAX], dummyname[FILE_MAX];
642         
643         waitcursor( 1 );
644         
645         BLI_split_dirfile_basic(str, dirname, NULL);
646         
647         BLI_bpathIterator_init(&bpi);
648         
649         while (!BLI_bpathIterator_isDone(&bpi)) {
650                 BLI_bpathIterator_getPath(&bpi, filepath);
651                 libpath = BLI_bpathIterator_getLib(&bpi);
652                 
653                 /* Check if esc was pressed because searching files can be slow */
654                 if (blender_test_break()) {
655                         break;
656                 }
657                 
658                 if (libpath==NULL) {
659                         
660                         BLI_bpathIterator_getPathExpanded( &bpi, filepath_expanded );
661                         
662                         if (!BLI_exists(filepath_expanded)) {
663                                 /* can the dir be opened? */
664                                 filesize = -1;
665                                 recur_depth = 0;
666                                 BLI_split_dirfile_basic(filepath, NULL, filename); /* the file to find */
667                                 
668                                 findFileRecursive(filename_new, dirname, filename, &filesize, &recur_depth);
669                                 if (filesize == -1) { /* could not open dir */
670                                         printf("Could not open dir \"%s\"\n", dirname);
671                                         return;
672                                 }
673                                 
674                                 if (filesize > 0) {
675                                         
676                                         if (BLI_bpathIterator_getPathMaxLen( &bpi ) < strlen(filename_new)) { 
677                                                 printf("cannot set path \"%s\" too long!", filename_new);
678                                         } else {
679                                                 /* copy the found path into the old one */
680                                                 if (G.relbase_valid)
681                                                         BLI_makestringcode(G.sce, filename_new);
682                                                 
683                                                 BLI_bpathIterator_setPath( &bpi, filename_new );
684                                         }
685                                 }
686                         }
687                 }
688                 BLI_bpathIterator_step(&bpi);
689         }
690         BLI_bpathIterator_free(&bpi);
691         
692         waitcursor( 0 );
693 }