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