Blender  V3.3
blend_validate.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
12 #include <string.h> /* for #strrchr #strncmp #strstr */
13 
14 #include "BLI_utildefines.h"
15 
16 #include "BLI_blenlib.h"
17 #include "BLI_linklist.h"
18 
19 #include "MEM_guardedalloc.h"
20 
21 #include "DNA_collection_types.h"
22 #include "DNA_key_types.h"
23 #include "DNA_node_types.h"
24 #include "DNA_sdna_types.h"
26 
27 #include "BKE_key.h"
28 #include "BKE_lib_id.h"
29 #include "BKE_library.h"
30 #include "BKE_main.h"
31 #include "BKE_node.h"
32 #include "BKE_report.h"
33 
34 #include "BLO_blend_validate.h"
35 #include "BLO_readfile.h"
36 
37 #include "readfile.h"
38 
40 {
41  ListBase mainlist;
42  bool is_valid = true;
43 
44  BKE_main_lock(bmain);
45 
46  blo_split_main(&mainlist, bmain);
47 
48  ListBase *lbarray[INDEX_ID_MAX];
49  int i = set_listbasepointers(bmain, lbarray);
50  while (i--) {
51  for (ID *id = lbarray[i]->first; id != NULL; id = id->next) {
52  if (ID_IS_LINKED(id)) {
53  is_valid = false;
54  BKE_reportf(reports,
55  RPT_ERROR,
56  "ID %s is in local database while being linked from library %s!",
57  id->name,
58  id->lib->filepath);
59  }
60  }
61  }
62 
63  for (Main *curmain = bmain->next; curmain != NULL; curmain = curmain->next) {
64  Library *curlib = curmain->curlib;
65  if (curlib == NULL) {
66  BKE_report(reports, RPT_ERROR, "Library database with NULL library data-block!");
67  continue;
68  }
69 
70  BKE_library_filepath_set(bmain, curlib, curlib->filepath);
71  BlendFileReadReport bf_reports = {.reports = reports};
72  BlendHandle *bh = BLO_blendhandle_from_file(curlib->filepath_abs, &bf_reports);
73 
74  if (bh == NULL) {
75  BKE_reportf(reports,
76  RPT_ERROR,
77  "Library ID %s not found at expected path %s!",
78  curlib->id.name,
79  curlib->filepath_abs);
80  continue;
81  }
82 
83  i = set_listbasepointers(curmain, lbarray);
84  while (i--) {
85  ID *id = lbarray[i]->first;
86  if (id == NULL) {
87  continue;
88  }
89 
90  if (GS(id->name) == ID_LI) {
91  is_valid = false;
92  BKE_reportf(reports,
93  RPT_ERROR,
94  "Library ID %s in library %s, this should not happen!",
95  id->name,
96  curlib->filepath);
97  continue;
98  }
99 
100  int totnames = 0;
101  LinkNode *names = BLO_blendhandle_get_datablock_names(bh, GS(id->name), false, &totnames);
102  for (; id != NULL; id = id->next) {
103  if (!ID_IS_LINKED(id)) {
104  is_valid = false;
105  BKE_reportf(reports,
106  RPT_ERROR,
107  "ID %s has NULL lib pointer while being in library %s!",
108  id->name,
109  curlib->filepath);
110  continue;
111  }
112  if (id->lib != curlib) {
113  is_valid = false;
114  BKE_reportf(reports, RPT_ERROR, "ID %s has mismatched lib pointer!", id->name);
115  continue;
116  }
117 
118  LinkNode *name = names;
119  for (; name; name = name->next) {
120  char *str_name = (char *)name->link;
121  if (id->name[2] == str_name[0] && STREQ(str_name, id->name + 2)) {
122  break;
123  }
124  }
125 
126  if (name == NULL) {
127  is_valid = false;
128  BKE_reportf(reports,
129  RPT_ERROR,
130  "ID %s not found in library %s anymore!",
131  id->name,
132  id->lib->filepath);
133  continue;
134  }
135  }
136 
138  }
139 
141  }
142 
143  blo_join_main(&mainlist);
144 
146  BLI_assert(mainlist.first == (void *)bmain);
147 
148  BKE_main_unlock(bmain);
149 
150  return is_valid;
151 }
152 
154 {
155  ListBase *lb;
156  ID *id;
157  bool is_valid = true;
158 
159  BKE_main_lock(bmain);
160 
161  FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
163  if (!BKE_key_idtype_support(GS(id->name))) {
164  break;
165  }
166  if (!ID_IS_LINKED(id)) {
167  /* We assume lib data is valid... */
168  Key *shapekey = BKE_key_from_id(id);
169  if (shapekey != NULL && shapekey->from != id) {
170  is_valid = false;
171  BKE_reportf(reports,
172  RPT_ERROR,
173  "ID %s uses shapekey %s, but its 'from' pointer is invalid (%p), fixing...",
174  id->name,
175  shapekey->id.name,
176  shapekey->from);
177  shapekey->from = id;
178  }
179  }
180  }
182  }
184 
185  BKE_main_unlock(bmain);
186 
187  /* NOTE: #BKE_id_delete also locks `bmain`, so we need to do this loop outside of the lock here.
188  */
189  LISTBASE_FOREACH_MUTABLE (Key *, shapekey, &bmain->shapekeys) {
190  if (shapekey->from != NULL) {
191  continue;
192  }
193 
194  BKE_reportf(reports,
195  RPT_ERROR,
196  "Shapekey %s has an invalid 'from' pointer (%p), it will be deleted",
197  shapekey->id.name,
198  shapekey->from);
199  BKE_id_delete(bmain, shapekey);
200  }
201 
202  return is_valid;
203 }
204 
206 {
207  ID *id_iter;
208  FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
209  bNodeTree *node_tree = ntreeFromID(id_iter);
210  if (node_tree) {
211  if (node_tree->id.flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE) {
212  if (!ID_IS_OVERRIDE_LIBRARY(id_iter)) {
214  }
215  }
216  }
217 
218  if (GS(id_iter->name) == ID_SCE) {
219  Scene *scene = (Scene *)id_iter;
220  if (scene->master_collection &&
223  }
224  }
225  }
227 }
struct Key * BKE_key_from_id(struct ID *id)
Definition: key.c:1783
bool BKE_key_idtype_support(short id_type)
Definition: key.c:1746
void BKE_id_delete(struct Main *bmain, void *idv) ATTR_NONNULL()
void BKE_library_filepath_set(struct Main *bmain, struct Library *lib, const char *filepath)
Definition: library.c:112
#define FOREACH_MAIN_ID_END
Definition: BKE_main.h:367
#define FOREACH_MAIN_LISTBASE_ID_END
Definition: BKE_main.h:336
int set_listbasepointers(struct Main *main, struct ListBase *lb[])
Definition: main.c:654
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
Definition: BKE_main.h:330
#define FOREACH_MAIN_LISTBASE_END
Definition: BKE_main.h:348
void BKE_main_unlock(struct Main *bmain)
Definition: main.c:219
void BKE_main_lock(struct Main *bmain)
Definition: main.c:214
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb)
Definition: BKE_main.h:341
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition: BKE_main.h:361
struct bNodeTree * ntreeFromID(struct ID *id)
Definition: node.cc:3231
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
Definition: BLI_listbase.h:354
void void BLI_INLINE bool BLI_listbase_is_single(const struct ListBase *lb)
Definition: BLI_listbase.h:265
#define UNUSED(x)
#define STREQ(a, b)
Utilities ensuring .blend file (i.e. Main) is in valid state during write and/or read process.
external readfile function prototypes.
BlendHandle * BLO_blendhandle_from_file(const char *filepath, struct BlendFileReadReport *reports)
Definition: readblenentry.c:48
struct LinkNode * BLO_blendhandle_get_datablock_names(BlendHandle *bh, int ofblocktype, bool use_assets_only, int *r_tot_names)
struct BlendHandle BlendHandle
Definition: BLO_readfile.h:35
void BLO_blendhandle_close(BlendHandle *bh)
@ INDEX_ID_MAX
Definition: DNA_ID.h:1058
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
@ LIB_EMBEDDED_DATA_LIB_OVERRIDE
Definition: DNA_ID.h:646
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
@ ID_LI
Definition: DNA_ID_enums.h:46
@ ID_SCE
Definition: DNA_ID_enums.h:45
Object groups, one object can be in many groups at once.
Read Guarded memory(de)allocation.
void BLO_main_validate_embedded_liboverrides(Main *bmain, ReportList *UNUSED(reports))
bool BLO_main_validate_libraries(Main *bmain, ReportList *reports)
bool BLO_main_validate_shapekeys(Main *bmain, ReportList *reports)
Scene scene
bool is_valid
#define GS(x)
Definition: iris.c:225
static char ** names
Definition: makesdna.c:65
void blo_split_main(ListBase *mainlist, Main *main)
Definition: readfile.c:496
void blo_join_main(ListBase *mainlist)
Definition: readfile.c:455
struct ReportList * reports
Definition: BLO_readfile.h:80
Definition: DNA_ID.h:368
struct Library * lib
Definition: DNA_ID.h:372
short flag
Definition: DNA_ID.h:383
char name[66]
Definition: DNA_ID.h:378
ID * from
Definition: DNA_key_types.h:88
ID id
Definition: DNA_key_types.h:63
char filepath[1024]
Definition: DNA_ID.h:461
ID id
Definition: DNA_ID.h:458
char filepath_abs[1024]
Definition: DNA_ID.h:471
void * link
Definition: BLI_linklist.h:24
struct LinkNode * next
Definition: BLI_linklist.h:23
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
struct Main * next
Definition: BKE_main.h:122
ListBase shapekeys
Definition: BKE_main.h:181
struct Collection * master_collection