Blender  V2.93
bpath.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 /* TODO,
22  * currently there are some cases we don't support.
23  * - passing output paths to the visitor?, like render out.
24  * - passing sequence strips with many images.
25  * - passing directory paths - visitors don't know which path is a dir or a file.
26  */
27 
28 #include <sys/stat.h>
29 
30 #include <string.h>
31 
32 /* path/file handling stuff */
33 #ifndef WIN32
34 # include <dirent.h>
35 # include <unistd.h>
36 #else
37 # include "BLI_winstuff.h"
38 # include <io.h>
39 #endif
40 
41 #include "MEM_guardedalloc.h"
42 
43 #include "DNA_brush_types.h"
44 #include "DNA_cachefile_types.h"
45 #include "DNA_fluid_types.h"
46 #include "DNA_freestyle_types.h"
47 #include "DNA_image_types.h"
48 #include "DNA_material_types.h"
49 #include "DNA_mesh_types.h"
50 #include "DNA_modifier_types.h"
51 #include "DNA_movieclip_types.h"
52 #include "DNA_node_types.h"
54 #include "DNA_object_force_types.h"
55 #include "DNA_object_types.h"
56 #include "DNA_particle_types.h"
57 #include "DNA_pointcache_types.h"
58 #include "DNA_scene_types.h"
59 #include "DNA_sequence_types.h"
60 #include "DNA_sound_types.h"
61 #include "DNA_text_types.h"
62 #include "DNA_texture_types.h"
63 #include "DNA_vfont_types.h"
64 #include "DNA_volume_types.h"
65 
66 #include "BLI_blenlib.h"
67 #include "BLI_utildefines.h"
68 
69 #include "BKE_font.h"
70 #include "BKE_image.h"
71 #include "BKE_lib_id.h"
72 #include "BKE_library.h"
73 #include "BKE_main.h"
74 #include "BKE_node.h"
75 #include "BKE_report.h"
76 
77 #include "BKE_bpath.h" /* own include */
78 
79 #include "CLG_log.h"
80 
81 #include "SEQ_iterator.h"
82 
83 #ifndef _MSC_VER
84 # include "BLI_strict_flags.h"
85 #endif
86 
87 static CLG_LogRef LOG = {"bke.bpath"};
88 
89 /* -------------------------------------------------------------------- */
93 static bool checkMissingFiles_visit_cb(void *userdata,
94  char *UNUSED(path_dst),
95  const char *path_src)
96 {
97  ReportList *reports = (ReportList *)userdata;
98 
99  if (!BLI_exists(path_src)) {
100  BKE_reportf(reports, RPT_WARNING, "Path '%s' not found", path_src);
101  }
102 
103  return false;
104 }
105 
106 /* high level function */
108 {
112  reports);
113 }
114 
117 /* -------------------------------------------------------------------- */
121 typedef struct BPathRebase_Data {
122  const char *basedir_src;
123  const char *basedir_dst;
125 
130 
131 static bool bpath_relative_rebase_visit_cb(void *userdata, char *path_dst, const char *path_src)
132 {
133  BPathRebase_Data *data = (BPathRebase_Data *)userdata;
134 
135  data->count_tot++;
136 
137  if (BLI_path_is_rel(path_src)) {
138  char filepath[(FILE_MAXDIR * 2) + FILE_MAXFILE];
139  BLI_strncpy(filepath, path_src, FILE_MAX);
140  if (BLI_path_abs(filepath, data->basedir_src)) {
141  BLI_path_normalize(NULL, filepath);
142 
143  /* This may fail, if so it's fine to leave absolute since the path is still valid. */
144  BLI_path_rel(filepath, data->basedir_dst);
145 
146  BLI_strncpy(path_dst, filepath, FILE_MAX);
147  data->count_changed++;
148  return true;
149  }
150 
151  /* Failed to make relative path absolute. */
152  BLI_assert(0);
153  BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src);
154  data->count_failed++;
155  return false;
156  }
157 
158  /* Absolute, leave this as-is. */
159  return false;
160 }
161 
163  const char *basedir_src,
164  const char *basedir_dst,
165  ReportList *reports)
166 {
169 
170  BLI_assert(basedir_src[0] != '\0');
171  BLI_assert(basedir_dst[0] != '\0');
172 
173  data.basedir_src = basedir_src;
174  data.basedir_dst = basedir_dst;
175  data.reports = reports;
176 
178 
179  BKE_reportf(reports,
180  data.count_failed ? RPT_WARNING : RPT_INFO,
181  "Total files %d | Changed %d | Failed %d",
182  data.count_tot,
183  data.count_changed,
184  data.count_failed);
185 }
186 
189 /* -------------------------------------------------------------------- */
193 typedef struct BPathRemap_Data {
194  const char *basedir;
196 
201 
202 static bool bpath_relative_convert_visit_cb(void *userdata, char *path_dst, const char *path_src)
203 {
204  BPathRemap_Data *data = (BPathRemap_Data *)userdata;
205 
206  data->count_tot++;
207 
208  if (BLI_path_is_rel(path_src)) {
209  return false; /* already relative */
210  }
211 
212  strcpy(path_dst, path_src);
213  BLI_path_rel(path_dst, data->basedir);
214  if (BLI_path_is_rel(path_dst)) {
215  data->count_changed++;
216  }
217  else {
218  BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made relative", path_src);
219  data->count_failed++;
220  }
221  return true;
222 }
223 
224 void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports)
225 {
227  const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
228 
229  if (basedir[0] == '\0') {
230  CLOG_ERROR(&LOG, "basedir='', this is a bug");
231  return;
232  }
233 
234  data.basedir = basedir;
235  data.reports = reports;
236 
238 
239  BKE_reportf(reports,
240  data.count_failed ? RPT_WARNING : RPT_INFO,
241  "Total files %d | Changed %d | Failed %d",
242  data.count_tot,
243  data.count_changed,
244  data.count_failed);
245 }
246 
249 /* -------------------------------------------------------------------- */
253 static bool bpath_absolute_convert_visit_cb(void *userdata, char *path_dst, const char *path_src)
254 {
255  BPathRemap_Data *data = (BPathRemap_Data *)userdata;
256 
257  data->count_tot++;
258 
259  if (BLI_path_is_rel(path_src) == false) {
260  return false; /* already absolute */
261  }
262 
263  strcpy(path_dst, path_src);
264  BLI_path_abs(path_dst, data->basedir);
265  if (BLI_path_is_rel(path_dst) == false) {
266  data->count_changed++;
267  }
268  else {
269  BKE_reportf(data->reports, RPT_WARNING, "Path '%s' cannot be made absolute", path_src);
270  data->count_failed++;
271  }
272  return true;
273 }
274 
275 /* similar to BKE_bpath_relative_convert - keep in sync! */
276 void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports)
277 {
279  const int flag = BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
280 
281  if (basedir[0] == '\0') {
282  CLOG_ERROR(&LOG, "basedir='', this is a bug");
283  return;
284  }
285 
286  data.basedir = basedir;
287  data.reports = reports;
288 
290 
291  BKE_reportf(reports,
292  data.count_failed ? RPT_WARNING : RPT_INFO,
293  "Total files %d | Changed %d | Failed %d",
294  data.count_tot,
295  data.count_changed,
296  data.count_failed);
297 }
298 
301 /* -------------------------------------------------------------------- */
314 #define MAX_RECUR 16
315 static bool missing_files_find__recursive(char *filename_new,
316  const char *dirname,
317  const char *filename,
318  int64_t *r_filesize,
319  int *r_recur_depth)
320 {
321  /* file searching stuff */
322  DIR *dir;
323  struct dirent *de;
324  BLI_stat_t status;
325  char path[FILE_MAX];
326  int64_t size;
327  bool found = false;
328 
329  dir = opendir(dirname);
330 
331  if (dir == NULL) {
332  return found;
333  }
334 
335  if (*r_filesize == -1) {
336  *r_filesize = 0; /* dir opened fine */
337  }
338 
339  while ((de = readdir(dir)) != NULL) {
340 
341  if (FILENAME_IS_CURRPAR(de->d_name)) {
342  continue;
343  }
344 
345  BLI_join_dirfile(path, sizeof(path), dirname, de->d_name);
346 
347  if (BLI_stat(path, &status) == -1) {
348  continue; /* cant stat, don't bother with this file, could print debug info here */
349  }
350 
351  if (S_ISREG(status.st_mode)) { /* is file */
352  if (BLI_path_ncmp(filename, de->d_name, FILE_MAX) == 0) { /* name matches */
353  /* open the file to read its size */
354  size = status.st_size;
355  if ((size > 0) && (size > *r_filesize)) { /* find the biggest file */
356  *r_filesize = size;
357  BLI_strncpy(filename_new, path, FILE_MAX);
358  found = true;
359  }
360  }
361  }
362  else if (S_ISDIR(status.st_mode)) { /* is subdir */
363  if (*r_recur_depth <= MAX_RECUR) {
364  (*r_recur_depth)++;
366  filename_new, path, filename, r_filesize, r_recur_depth);
367  (*r_recur_depth)--;
368  }
369  }
370  }
371  closedir(dir);
372  return found;
373 }
374 
375 typedef struct BPathFind_Data {
376  const char *basedir;
377  const char *searchdir;
379  bool find_all;
381 
382 static bool missing_files_find__visit_cb(void *userdata, char *path_dst, const char *path_src)
383 {
384  BPathFind_Data *data = (BPathFind_Data *)userdata;
385  char filename_new[FILE_MAX];
386 
387  int64_t filesize = -1;
388  int recur_depth = 0;
389  bool found;
390 
391  if (data->find_all == false) {
392  if (BLI_exists(path_src)) {
393  return false;
394  }
395  }
396 
397  filename_new[0] = '\0';
398 
400  filename_new, data->searchdir, BLI_path_basename(path_src), &filesize, &recur_depth);
401 
402  if (filesize == -1) { /* could not open dir */
403  BKE_reportf(data->reports,
404  RPT_WARNING,
405  "Could not open directory '%s'",
406  BLI_path_basename(data->searchdir));
407  return false;
408  }
409  if (found == false) {
410  BKE_reportf(data->reports,
411  RPT_WARNING,
412  "Could not find '%s' in '%s'",
413  BLI_path_basename(path_src),
414  data->searchdir);
415  return false;
416  }
417 
418  bool was_relative = BLI_path_is_rel(path_dst);
419 
420  BLI_strncpy(path_dst, filename_new, FILE_MAX);
421 
422  /* keep path relative if the previous one was relative */
423  if (was_relative) {
424  BLI_path_rel(path_dst, data->basedir);
425  }
426 
427  return true;
428 }
429 
431  const char *searchpath,
432  ReportList *reports,
433  const bool find_all)
434 {
435  struct BPathFind_Data data = {NULL};
437 
438  data.basedir = BKE_main_blendfile_path(bmain);
439  data.reports = reports;
440  data.searchdir = searchpath;
441  data.find_all = find_all;
442 
444 }
445 
448 /* -------------------------------------------------------------------- */
455 static bool rewrite_path_fixed(char *path,
456  BPathVisitor visit_cb,
457  const char *absbase,
458  void *userdata)
459 {
460  char path_src_buf[FILE_MAX];
461  const char *path_src;
462  char path_dst[FILE_MAX];
463 
464  if (absbase) {
465  BLI_strncpy(path_src_buf, path, sizeof(path_src_buf));
466  BLI_path_abs(path_src_buf, absbase);
467  path_src = path_src_buf;
468  }
469  else {
470  path_src = path;
471  }
472 
473  /* so functions can check old value */
474  BLI_strncpy(path_dst, path, FILE_MAX);
475 
476  if (visit_cb(userdata, path_dst, path_src)) {
477  BLI_strncpy(path, path_dst, FILE_MAX);
478  return true;
479  }
480 
481  return false;
482 }
483 
484 static bool rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR],
485  char path_file[FILE_MAXFILE],
486  BPathVisitor visit_cb,
487  const char *absbase,
488  void *userdata)
489 {
490  char path_src[FILE_MAX];
491  char path_dst[FILE_MAX];
492 
493  BLI_join_dirfile(path_src, sizeof(path_src), path_dir, path_file);
494 
495  /* so functions can check old value */
496  BLI_strncpy(path_dst, path_src, FILE_MAX);
497 
498  if (absbase) {
499  BLI_path_abs(path_src, absbase);
500  }
501 
502  if (visit_cb(userdata, path_dst, (const char *)path_src)) {
503  BLI_split_dirfile(path_dst, path_dir, path_file, FILE_MAXDIR, FILE_MAXFILE);
504  return true;
505  }
506 
507  return false;
508 }
509 
510 static bool rewrite_path_alloc(char **path,
511  BPathVisitor visit_cb,
512  const char *absbase,
513  void *userdata)
514 {
515  char path_src_buf[FILE_MAX];
516  const char *path_src;
517  char path_dst[FILE_MAX];
518 
519  if (absbase) {
520  BLI_strncpy(path_src_buf, *path, sizeof(path_src_buf));
521  BLI_path_abs(path_src_buf, absbase);
522  path_src = path_src_buf;
523  }
524  else {
525  path_src = *path;
526  }
527 
528  if (visit_cb(userdata, path_dst, path_src)) {
529  MEM_freeN(*path);
530  (*path) = BLI_strdup(path_dst);
531  return true;
532  }
533 
534  return false;
535 }
536 
541  Main *bmain, ID *id, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
542 {
543  const char *absbase = (flag & BKE_BPATH_TRAVERSE_ABS) ? ID_BLEND_PATH(bmain, id) : NULL;
544 
545  if ((flag & BKE_BPATH_TRAVERSE_SKIP_LIBRARY) && ID_IS_LINKED(id)) {
546  return;
547  }
548 
549  switch (GS(id->name)) {
550  case ID_IM: {
551  Image *ima;
552  ima = (Image *)id;
553  if (BKE_image_has_packedfile(ima) == false || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
554  /* Skip empty file paths, these are typically from generated images and
555  * don't make sense to add directories to until the image has been saved
556  * once to give it a meaningful value. */
558  ima->filepath[0]) {
559  if (rewrite_path_fixed(ima->filepath, visit_cb, absbase, bpath_user_data)) {
561  if (!BKE_image_has_packedfile(ima) &&
562  /* image may have been painted onto (and not saved, T44543) */
563  !BKE_image_is_dirty(ima)) {
565  }
566  }
567  }
568  }
569  }
570  break;
571  }
572  case ID_BR: {
573  Brush *brush = (Brush *)id;
574  if (brush->icon_filepath[0]) {
575  rewrite_path_fixed(brush->icon_filepath, visit_cb, absbase, bpath_user_data);
576  }
577  break;
578  }
579  case ID_OB: {
580  Object *ob = (Object *)id;
581  ModifierData *md;
582  ParticleSystem *psys;
583 
584 #define BPATH_TRAVERSE_POINTCACHE(ptcaches) \
585  { \
586  PointCache *cache; \
587  for (cache = (ptcaches).first; cache; cache = cache->next) { \
588  if (cache->flag & PTCACHE_DISK_CACHE) { \
589  rewrite_path_fixed(cache->path, visit_cb, absbase, bpath_user_data); \
590  } \
591  } \
592  } \
593  (void)0
594 
595  for (md = ob->modifiers.first; md; md = md->next) {
596  if (md->type == eModifierType_Fluidsim) {
598  if (fluidmd->fss) {
599  rewrite_path_fixed(fluidmd->fss->surfdataPath, visit_cb, absbase, bpath_user_data);
600  }
601  }
602  else if (md->type == eModifierType_Fluid) {
604  if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) {
605  rewrite_path_fixed(fmd->domain->cache_directory, visit_cb, absbase, bpath_user_data);
606  }
607  }
608  else if (md->type == eModifierType_Cloth) {
609  ClothModifierData *clmd = (ClothModifierData *)md;
611  }
612  else if (md->type == eModifierType_Ocean) {
614  rewrite_path_fixed(omd->cachepath, visit_cb, absbase, bpath_user_data);
615  }
616  else if (md->type == eModifierType_MeshCache) {
618  rewrite_path_fixed(mcmd->filepath, visit_cb, absbase, bpath_user_data);
619  }
620  }
621 
622  if (ob->soft) {
624  }
625 
626  for (psys = ob->particlesystem.first; psys; psys = psys->next) {
628  }
629 
630 #undef BPATH_TRAVERSE_POINTCACHE
631 
632  break;
633  }
634  case ID_SO: {
635  bSound *sound = (bSound *)id;
636  if (sound->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
637  rewrite_path_fixed(sound->filepath, visit_cb, absbase, bpath_user_data);
638  }
639  break;
640  }
641  case ID_VO: {
642  Volume *volume = (Volume *)id;
643  if (volume->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
644  rewrite_path_fixed(volume->filepath, visit_cb, absbase, bpath_user_data);
645  }
646  break;
647  }
648  case ID_TXT:
649  if (((Text *)id)->filepath) {
650  rewrite_path_alloc(&((Text *)id)->filepath, visit_cb, absbase, bpath_user_data);
651  }
652  break;
653  case ID_VF: {
654  VFont *vfont = (VFont *)id;
655  if (vfont->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
656  if (BKE_vfont_is_builtin(vfont) == false) {
657  rewrite_path_fixed(((VFont *)id)->filepath, visit_cb, absbase, bpath_user_data);
658  }
659  }
660  break;
661  }
662  case ID_MA: {
663  Material *ma = (Material *)id;
664  bNodeTree *ntree = ma->nodetree;
665 
666  if (ntree) {
667  bNode *node;
668 
669  for (node = ntree->nodes.first; node; node = node->next) {
670  if (node->type == SH_NODE_SCRIPT) {
671  NodeShaderScript *nss = (NodeShaderScript *)node->storage;
672  rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data);
673  }
674  else if (node->type == SH_NODE_TEX_IES) {
675  NodeShaderTexIES *ies = (NodeShaderTexIES *)node->storage;
676  rewrite_path_fixed(ies->filepath, visit_cb, absbase, bpath_user_data);
677  }
678  }
679  }
680  break;
681  }
682  case ID_NT: {
683  bNodeTree *ntree = (bNodeTree *)id;
684  bNode *node;
685 
686  if (ntree->type == NTREE_SHADER) {
687  /* same as lines above */
688  for (node = ntree->nodes.first; node; node = node->next) {
689  if (node->type == SH_NODE_SCRIPT) {
690  NodeShaderScript *nss = (NodeShaderScript *)node->storage;
691  rewrite_path_fixed(nss->filepath, visit_cb, absbase, bpath_user_data);
692  }
693  else if (node->type == SH_NODE_TEX_IES) {
694  NodeShaderTexIES *ies = (NodeShaderTexIES *)node->storage;
695  rewrite_path_fixed(ies->filepath, visit_cb, absbase, bpath_user_data);
696  }
697  }
698  }
699  break;
700  }
701  case ID_SCE: {
702  Scene *scene = (Scene *)id;
703  if (scene->ed) {
704  Sequence *seq;
705 
706  SEQ_ALL_BEGIN (scene->ed, seq) {
707  if (SEQ_HAS_PATH(seq)) {
708  StripElem *se = seq->strip->stripdata;
709 
710  if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM) && se) {
712  seq->strip->dir, se->name, visit_cb, absbase, bpath_user_data);
713  }
714  else if ((seq->type == SEQ_TYPE_IMAGE) && se) {
715  /* might want an option not to loop over all strips */
716  unsigned int len = (unsigned int)MEM_allocN_len(se) / (unsigned int)sizeof(*se);
717  unsigned int i;
718 
720  /* only operate on one path */
721  len = MIN2(1u, len);
722  }
723 
724  for (i = 0; i < len; i++, se++) {
726  seq->strip->dir, se->name, visit_cb, absbase, bpath_user_data);
727  }
728  }
729  else {
730  /* simple case */
731  rewrite_path_fixed(seq->strip->dir, visit_cb, absbase, bpath_user_data);
732  }
733  }
734  }
735  SEQ_ALL_END;
736  }
737  break;
738  }
739  case ID_ME: {
740  Mesh *me = (Mesh *)id;
741  if (me->ldata.external) {
742  rewrite_path_fixed(me->ldata.external->filename, visit_cb, absbase, bpath_user_data);
743  }
744  break;
745  }
746  case ID_LI: {
747  Library *lib = (Library *)id;
748  /* keep packedfile paths always relative to the blend */
749  if (lib->packedfile == NULL) {
750  if (rewrite_path_fixed(lib->filepath, visit_cb, absbase, bpath_user_data)) {
751  BKE_library_filepath_set(bmain, lib, lib->filepath);
752  }
753  }
754  break;
755  }
756  case ID_MC: {
757  MovieClip *clip = (MovieClip *)id;
758  rewrite_path_fixed(clip->filepath, visit_cb, absbase, bpath_user_data);
759  break;
760  }
761  case ID_CF: {
762  CacheFile *cache_file = (CacheFile *)id;
763  rewrite_path_fixed(cache_file->filepath, visit_cb, absbase, bpath_user_data);
764  break;
765  }
766  default:
767  /* Nothing to do for other IDs that don't contain file paths. */
768  break;
769  }
770 }
771 
773  Main *bmain, ListBase *lb, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
774 {
775  ID *id;
776  for (id = lb->first; id; id = id->next) {
777  BKE_bpath_traverse_id(bmain, id, visit_cb, flag, bpath_user_data);
778  }
779 }
780 
782  BPathVisitor visit_cb,
783  const int flag,
784  void *bpath_user_data)
785 {
786  ListBase *lbarray[INDEX_ID_MAX];
787  int a = set_listbasepointers(bmain, lbarray);
788  while (a--) {
789  BKE_bpath_traverse_id_list(bmain, lbarray[a], visit_cb, flag, bpath_user_data);
790  }
791 }
792 
797 bool BKE_bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *path_src)
798 {
799  /* be sure there is low chance of the path being too short */
800  char filepath[(FILE_MAXDIR * 2) + FILE_MAXFILE];
801  const char *base_new = ((char **)pathbase_v)[0];
802  const char *base_old = ((char **)pathbase_v)[1];
803 
804  if (BLI_path_is_rel(base_old)) {
805  CLOG_ERROR(&LOG, "old base path '%s' is not absolute.", base_old);
806  return false;
807  }
808 
809  /* Make referenced file absolute. This would be a side-effect of
810  * BLI_path_normalize, but we do it explicitly so we know if it changed. */
811  BLI_strncpy(filepath, path_src, FILE_MAX);
812  if (BLI_path_abs(filepath, base_old)) {
813  /* Path was relative and is now absolute. Remap.
814  * Important BLI_path_normalize runs before the path is made relative
815  * because it wont work for paths that start with "//../" */
816  BLI_path_normalize(base_new, filepath);
817  BLI_path_rel(filepath, base_new);
818  BLI_strncpy(path_dst, filepath, FILE_MAX);
819  return true;
820  }
821 
822  /* Path was not relative to begin with. */
823  return false;
824 }
825 
828 /* -------------------------------------------------------------------- */
834 struct PathStore {
835  struct PathStore *next, *prev;
836 };
837 
838 static bool bpath_list_append(void *userdata, char *UNUSED(path_dst), const char *path_src)
839 {
840  /* store the path and string in a single alloc */
841  ListBase *ls = userdata;
842  size_t path_size = strlen(path_src) + 1;
843  struct PathStore *path_store = MEM_mallocN(sizeof(struct PathStore) + path_size, __func__);
844  char *filepath = (char *)(path_store + 1);
845 
846  memcpy(filepath, path_src, path_size);
847  BLI_addtail(ls, path_store);
848  return false;
849 }
850 
851 static bool bpath_list_restore(void *userdata, char *path_dst, const char *path_src)
852 {
853  /* assume ls->first wont be NULL because the number of paths can't change!
854  * (if they do caller is wrong) */
855  ListBase *ls = userdata;
856  struct PathStore *path_store = ls->first;
857  const char *filepath = (char *)(path_store + 1);
858  bool ret;
859 
860  if (STREQ(path_src, filepath)) {
861  ret = false;
862  }
863  else {
864  BLI_strncpy(path_dst, filepath, FILE_MAX);
865  ret = true;
866  }
867 
868  BLI_freelinkN(ls, path_store);
869  return ret;
870 }
871 
872 /* return ls_handle */
873 void *BKE_bpath_list_backup(Main *bmain, const int flag)
874 {
875  ListBase *ls = MEM_callocN(sizeof(ListBase), __func__);
876 
877  BKE_bpath_traverse_main(bmain, bpath_list_append, flag, ls);
878 
879  return ls;
880 }
881 
882 void BKE_bpath_list_restore(Main *bmain, const int flag, void *ls_handle)
883 {
884  ListBase *ls = ls_handle;
885 
887 }
888 
889 void BKE_bpath_list_free(void *ls_handle)
890 {
891  ListBase *ls = ls_handle;
892  BLI_assert(BLI_listbase_is_empty(ls)); /* assumes we were used */
893  BLI_freelistN(ls);
894  MEM_freeN(ls);
895 }
896 
@ BKE_BPATH_TRAVERSE_SKIP_MULTIFILE
Definition: BKE_bpath.h:70
@ BKE_BPATH_TRAVERSE_SKIP_LIBRARY
Definition: BKE_bpath.h:63
@ BKE_BPATH_TRAVERSE_ABS
Definition: BKE_bpath.h:61
@ BKE_BPATH_TRAVERSE_SKIP_PACKED
Definition: BKE_bpath.h:65
@ BKE_BPATH_TRAVERSE_RELOAD_EDITED
Definition: BKE_bpath.h:72
bool(* BPathVisitor)(void *userdata, char *path_dst, const char *path_src)
Definition: BKE_bpath.h:36
bool BKE_vfont_is_builtin(struct VFont *vfont)
Definition: font.c:222
bool BKE_image_has_packedfile(struct Image *image)
Definition: image.c:5627
bool BKE_image_is_dirty(struct Image *image)
Definition: image.c:5681
#define IMA_SIGNAL_RELOAD
Definition: BKE_image.h:162
void BKE_image_signal(struct Main *bmain, struct Image *ima, struct ImageUser *iuser, int signal)
Definition: image.c:3499
void BKE_library_filepath_set(struct Main *bmain, struct Library *lib, const char *filepath)
Definition: library.c:92
int set_listbasepointers(struct Main *main, struct ListBase *lb[])
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
#define SH_NODE_TEX_IES
Definition: BKE_node.h:1059
#define SH_NODE_SCRIPT
Definition: BKE_node.h:1036
void BKE_reportf(ReportList *reports, ReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
#define BLI_assert(a)
Definition: BLI_assert.h:58
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:349
int BLI_stat(const char *path, BLI_stat_t *buffer) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
struct stat BLI_stat_t
Definition: BLI_fileops.h:67
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:281
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
const char * BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1868
#define BLI_path_ncmp
bool BLI_path_is_rel(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:411
#define FILE_MAXFILE
#define FILE_MAX
void BLI_path_normalize(const char *relabase, char *path) ATTR_NONNULL(2)
Definition: path_util.c:173
void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL()
Definition: path_util.c:1737
#define FILENAME_IS_CURRPAR(_n)
void BLI_path_rel(char *file, const char *relfile) ATTR_NONNULL()
Definition: path_util.c:519
void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen)
Definition: path_util.c:1654
#define FILE_MAXDIR
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:1016
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:70
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
#define UNUSED(x)
#define ELEM(...)
#define MIN2(a, b)
#define STREQ(a, b)
Compatibility-like things for windows.
struct __dirstream DIR
Definition: BLI_winstuff.h:100
int closedir(DIR *dp)
#define S_ISDIR(x)
Definition: BLI_winstuff.h:64
const char * dirname(char *path)
#define S_ISREG(x)
Definition: BLI_winstuff.h:61
struct dirent * readdir(DIR *dp)
DIR * opendir(const char *path)
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:204
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:426
#define ID_BLEND_PATH(_bmain, _id)
Definition: DNA_ID.h:419
@ INDEX_ID_MAX
Definition: DNA_ID.h:859
@ ID_MC
Definition: DNA_ID_enums.h:85
@ ID_CF
Definition: DNA_ID_enums.h:90
@ ID_LI
Definition: DNA_ID_enums.h:58
@ ID_IM
Definition: DNA_ID_enums.h:65
@ ID_VO
Definition: DNA_ID_enums.h:95
@ ID_NT
Definition: DNA_ID_enums.h:80
@ ID_TXT
Definition: DNA_ID_enums.h:74
@ ID_SO
Definition: DNA_ID_enums.h:76
@ ID_SCE
Definition: DNA_ID_enums.h:57
@ ID_BR
Definition: DNA_ID_enums.h:81
@ ID_MA
Definition: DNA_ID_enums.h:63
@ ID_VF
Definition: DNA_ID_enums.h:73
@ ID_ME
Definition: DNA_ID_enums.h:60
@ ID_OB
Definition: DNA_ID_enums.h:59
@ IMA_SRC_FILE
@ IMA_SRC_MOVIE
@ IMA_SRC_TILED
@ IMA_SRC_SEQUENCE
@ eModifierType_Fluidsim
@ eModifierType_Cloth
@ eModifierType_Fluid
@ eModifierType_Ocean
@ eModifierType_MeshCache
@ MOD_FLUID_TYPE_DOMAIN
#define NTREE_SHADER
Object is a sort of wrapper for general info.
#define SEQ_HAS_PATH(_seq)
@ SEQ_TYPE_SOUND_RAM
@ SEQ_TYPE_IMAGE
@ SEQ_TYPE_MOVIE
Read Guarded memory(de)allocation.
#define SEQ_ALL_END
Definition: SEQ_iterator.h:48
#define SEQ_ALL_BEGIN(ed, _seq)
Definition: SEQ_iterator.h:41
void BKE_bpath_relative_rebase(Main *bmain, const char *basedir_src, const char *basedir_dst, ReportList *reports)
Definition: bpath.c:162
void BKE_bpath_relative_convert(Main *bmain, const char *basedir, ReportList *reports)
Definition: bpath.c:224
static bool missing_files_find__recursive(char *filename_new, const char *dirname, const char *filename, int64_t *r_filesize, int *r_recur_depth)
Definition: bpath.c:315
#define BPATH_TRAVERSE_POINTCACHE(ptcaches)
#define MAX_RECUR
Definition: bpath.c:314
static bool bpath_absolute_convert_visit_cb(void *userdata, char *path_dst, const char *path_src)
Definition: bpath.c:253
static bool bpath_relative_convert_visit_cb(void *userdata, char *path_dst, const char *path_src)
Definition: bpath.c:202
static bool rewrite_path_fixed_dirfile(char path_dir[FILE_MAXDIR], char path_file[FILE_MAXFILE], BPathVisitor visit_cb, const char *absbase, void *userdata)
Definition: bpath.c:484
void BKE_bpath_list_restore(Main *bmain, const int flag, void *ls_handle)
Definition: bpath.c:882
static bool rewrite_path_alloc(char **path, BPathVisitor visit_cb, const char *absbase, void *userdata)
Definition: bpath.c:510
void BKE_bpath_traverse_id_list(Main *bmain, ListBase *lb, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
Definition: bpath.c:772
void BKE_bpath_absolute_convert(Main *bmain, const char *basedir, ReportList *reports)
Definition: bpath.c:276
void BKE_bpath_traverse_main(Main *bmain, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
Definition: bpath.c:781
struct BPathRemap_Data BPathRemap_Data
static bool bpath_list_restore(void *userdata, char *path_dst, const char *path_src)
Definition: bpath.c:851
void * BKE_bpath_list_backup(Main *bmain, const int flag)
Definition: bpath.c:873
static bool checkMissingFiles_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src)
Definition: bpath.c:93
struct BPathRebase_Data BPathRebase_Data
void BKE_bpath_list_free(void *ls_handle)
Definition: bpath.c:889
static CLG_LogRef LOG
Definition: bpath.c:87
static bool bpath_list_append(void *userdata, char *UNUSED(path_dst), const char *path_src)
Definition: bpath.c:838
static bool rewrite_path_fixed(char *path, BPathVisitor visit_cb, const char *absbase, void *userdata)
Definition: bpath.c:455
struct BPathFind_Data BPathFind_Data
bool BKE_bpath_relocate_visitor(void *pathbase_v, char *path_dst, const char *path_src)
Definition: bpath.c:797
static bool missing_files_find__visit_cb(void *userdata, char *path_dst, const char *path_src)
Definition: bpath.c:382
void BKE_bpath_missing_files_check(Main *bmain, ReportList *reports)
Definition: bpath.c:107
static bool bpath_relative_rebase_visit_cb(void *userdata, char *path_dst, const char *path_src)
Definition: bpath.c:131
void BKE_bpath_missing_files_find(Main *bmain, const char *searchpath, ReportList *reports, const bool find_all)
Definition: bpath.c:430
void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int flag, void *bpath_user_data)
Definition: bpath.c:540
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
char filepath[1024]
short source
OperationNode * node
Scene scene
bNodeTree * ntree
DRWShaderLibrary * lib
#define GS(x)
Definition: iris.c:241
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
size_t(* MEM_allocN_len)(const void *vmemh)
Definition: mallocn.c:40
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static unsigned a[3]
Definition: RandGen.cpp:92
return ret
__int64 int64_t
Definition: stdint.h:92
const char * searchdir
Definition: bpath.c:377
const char * basedir
Definition: bpath.c:376
ReportList * reports
Definition: bpath.c:378
bool find_all
Definition: bpath.c:379
int count_changed
Definition: bpath.c:127
const char * basedir_dst
Definition: bpath.c:123
ReportList * reports
Definition: bpath.c:124
int count_failed
Definition: bpath.c:128
const char * basedir_src
Definition: bpath.c:122
int count_failed
Definition: bpath.c:199
ReportList * reports
Definition: bpath.c:195
int count_tot
Definition: bpath.c:197
const char * basedir
Definition: bpath.c:194
int count_changed
Definition: bpath.c:198
char icon_filepath[1024]
char filepath[1024]
struct ListBase ptcaches
CustomDataExternal * external
char cache_directory[1024]
struct FluidDomainSettings * domain
struct FluidsimSettings * fss
Definition: DNA_ID.h:273
void * next
Definition: DNA_ID.h:274
char name[66]
Definition: DNA_ID.h:283
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
struct bNodeTree * nodetree
struct CustomData pdata ldata
struct ModifierData * next
char filepath[1024]
ListBase particlesystem
ListBase modifiers
struct SoftBody * soft
struct ListBase ptcaches
struct ParticleSystem * next
struct PathStore * next
Definition: bpath.c:835
struct PathStore * prev
Definition: bpath.c:835
struct Editing * ed
struct ListBase ptcaches
struct SoftBody_Shared * shared
char name[256]
StripElem * stripdata
char dir[768]
struct PackedFile * packedfile
char filepath[1024]
struct PackedFile * packedfile
ListBase nodes
struct PackedFile * packedfile
char filepath[1024]
char * d_name
Definition: BLI_winstuff.h:96
uint len