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