Blender  V3.3
packedFile.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include <fcntl.h>
9 #include <stdio.h>
10 #include <sys/stat.h>
11 
12 #ifndef WIN32
13 # include <unistd.h>
14 #else
15 # include <io.h>
16 #endif
17 #include "MEM_guardedalloc.h"
18 #include <string.h>
19 
20 #include "DNA_ID.h"
21 #include "DNA_image_types.h"
22 #include "DNA_packedFile_types.h"
23 #include "DNA_sound_types.h"
24 #include "DNA_vfont_types.h"
25 #include "DNA_volume_types.h"
26 
27 #include "BLI_blenlib.h"
28 #include "BLI_utildefines.h"
29 
30 #include "BKE_image.h"
31 #include "BKE_image_format.h"
32 #include "BKE_main.h"
33 #include "BKE_packedFile.h"
34 #include "BKE_report.h"
35 #include "BKE_sound.h"
36 #include "BKE_vfont.h"
37 #include "BKE_volume.h"
38 
39 #include "IMB_imbuf.h"
40 #include "IMB_imbuf_types.h"
41 
42 #include "BLO_read_write.h"
43 
44 int BKE_packedfile_seek(PackedFile *pf, int offset, int whence)
45 {
46  int oldseek = -1, seek = 0;
47 
48  if (pf) {
49  oldseek = pf->seek;
50  switch (whence) {
51  case SEEK_CUR:
52  seek = oldseek + offset;
53  break;
54  case SEEK_END:
55  seek = pf->size + offset;
56  break;
57  case SEEK_SET:
58  seek = offset;
59  break;
60  default:
61  oldseek = -1;
62  break;
63  }
64  if (seek < 0) {
65  seek = 0;
66  }
67  else if (seek > pf->size) {
68  seek = pf->size;
69  }
70  pf->seek = seek;
71  }
72 
73  return oldseek;
74 }
75 
77 {
78  BKE_packedfile_seek(pf, 0, SEEK_SET);
79 }
80 
82 {
83  if ((pf != NULL) && (size >= 0) && (data != NULL)) {
84  if (size + pf->seek > pf->size) {
85  size = pf->size - pf->seek;
86  }
87 
88  if (size > 0) {
89  memcpy(data, ((char *)pf->data) + pf->seek, size);
90  }
91  else {
92  size = 0;
93  }
94 
95  pf->seek += size;
96  }
97  else {
98  size = -1;
99  }
100 
101  return size;
102 }
103 
105 {
106  Image *ima;
107  VFont *vf;
108  bSound *sound;
109  Volume *volume;
110  int count = 0;
111 
112  /* let's check if there are packed files... */
113  for (ima = bmain->images.first; ima; ima = ima->id.next) {
114  if (BKE_image_has_packedfile(ima)) {
115  count++;
116  }
117  }
118 
119  for (vf = bmain->fonts.first; vf; vf = vf->id.next) {
120  if (vf->packedfile) {
121  count++;
122  }
123  }
124 
125  for (sound = bmain->sounds.first; sound; sound = sound->id.next) {
126  if (sound->packedfile) {
127  count++;
128  }
129  }
130 
131  for (volume = bmain->volumes.first; volume; volume = volume->id.next) {
132  if (volume->packedfile) {
133  count++;
134  }
135  }
136 
137  return count;
138 }
139 
141 {
142  if (pf) {
143  BLI_assert(pf->data != NULL);
144 
145  MEM_SAFE_FREE(pf->data);
146  MEM_freeN(pf);
147  }
148  else {
149  printf("%s: Trying to free a NULL pointer\n", __func__);
150  }
151 }
152 
154 {
155  BLI_assert(pf_src != NULL);
156  BLI_assert(pf_src->data != NULL);
157 
158  PackedFile *pf_dst;
159 
160  pf_dst = MEM_dupallocN(pf_src);
161  pf_dst->data = MEM_dupallocN(pf_src->data);
162 
163  return pf_dst;
164 }
165 
167 {
168  BLI_assert(mem != NULL);
169 
170  PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile");
171  pf->data = mem;
172  pf->size = memlen;
173 
174  return pf;
175 }
176 
177 PackedFile *BKE_packedfile_new(ReportList *reports, const char *filepath, const char *basepath)
178 {
179  PackedFile *pf = NULL;
180  int file, filelen;
181  char name[FILE_MAX];
182  void *data;
183 
184  /* render result has no filepath and can be ignored
185  * any other files with no name can be ignored too */
186  if (filepath[0] == '\0') {
187  return pf;
188  }
189 
190  // XXX waitcursor(1);
191 
192  /* convert relative filenames to absolute filenames */
193 
194  BLI_strncpy(name, filepath, sizeof(name));
195  BLI_path_abs(name, basepath);
196 
197  /* open the file
198  * and create a PackedFile structure */
199 
200  file = BLI_open(name, O_BINARY | O_RDONLY, 0);
201  if (file == -1) {
202  BKE_reportf(reports, RPT_ERROR, "Unable to pack file, source path '%s' not found", name);
203  }
204  else {
205  filelen = BLI_file_descriptor_size(file);
206 
207  if (filelen == 0) {
208  /* MEM_mallocN complains about MEM_mallocN(0, "bla");
209  * we don't care.... */
210  data = MEM_mallocN(1, "packFile");
211  }
212  else {
213  data = MEM_mallocN(filelen, "packFile");
214  }
215  if (read(file, data, filelen) == filelen) {
217  }
218  else {
219  MEM_freeN(data);
220  }
221 
222  close(file);
223  }
224 
225  // XXX waitcursor(0);
226 
227  return pf;
228 }
229 
230 void BKE_packedfile_pack_all(Main *bmain, ReportList *reports, bool verbose)
231 {
232  Image *ima;
233  VFont *vfont;
234  bSound *sound;
235  Volume *volume;
236  int tot = 0;
237 
238  for (ima = bmain->images.first; ima; ima = ima->id.next) {
239  if (BKE_image_has_packedfile(ima) == false && !ID_IS_LINKED(ima)) {
240  if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_TILED)) {
241  BKE_image_packfiles(reports, ima, ID_BLEND_PATH(bmain, &ima->id));
242  tot++;
243  }
244  else if (ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) && verbose) {
245  BKE_reportf(reports,
246  RPT_WARNING,
247  "Image '%s' skipped, packing movies or image sequences not supported",
248  ima->id.name + 2);
249  }
250  }
251  }
252 
253  for (vfont = bmain->fonts.first; vfont; vfont = vfont->id.next) {
254  if (vfont->packedfile == NULL && !ID_IS_LINKED(vfont) &&
255  BKE_vfont_is_builtin(vfont) == false) {
257  reports, vfont->filepath, BKE_main_blendfile_path(bmain));
258  tot++;
259  }
260  }
261 
262  for (sound = bmain->sounds.first; sound; sound = sound->id.next) {
263  if (sound->packedfile == NULL && !ID_IS_LINKED(sound)) {
265  reports, sound->filepath, BKE_main_blendfile_path(bmain));
266  tot++;
267  }
268  }
269 
270  for (volume = bmain->volumes.first; volume; volume = volume->id.next) {
271  if (volume->packedfile == NULL && !ID_IS_LINKED(volume)) {
272  volume->packedfile = BKE_packedfile_new(
273  reports, volume->filepath, BKE_main_blendfile_path(bmain));
274  tot++;
275  }
276  }
277 
278  if (tot > 0) {
279  BKE_reportf(reports, RPT_INFO, "Packed %d file(s)", tot);
280  }
281  else if (verbose) {
282  BKE_report(reports, RPT_INFO, "No new files have been packed");
283  }
284 }
285 
287  const char *ref_file_name,
288  const char *filepath,
289  PackedFile *pf,
290  const bool guimode)
291 {
292  int file, number;
293  int ret_value = RET_OK;
294  bool remove_tmp = false;
295  char name[FILE_MAX];
296  char tempname[FILE_MAX];
297  /* void *data; */
298 
299  if (guimode) {
300  } // XXX waitcursor(1);
301 
302  BLI_strncpy(name, filepath, sizeof(name));
303  BLI_path_abs(name, ref_file_name);
304 
305  if (BLI_exists(name)) {
306  for (number = 1; number <= 999; number++) {
307  BLI_snprintf(tempname, sizeof(tempname), "%s.%03d_", name, number);
308  if (!BLI_exists(tempname)) {
309  if (BLI_copy(name, tempname) == RET_OK) {
310  remove_tmp = true;
311  }
312  break;
313  }
314  }
315  }
316 
317  /* make sure the path to the file exists... */
319 
320  file = BLI_open(name, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666);
321  if (file == -1) {
322  BKE_reportf(reports, RPT_ERROR, "Error creating file '%s'", name);
323  ret_value = RET_ERROR;
324  }
325  else {
326  if (write(file, pf->data, pf->size) != pf->size) {
327  BKE_reportf(reports, RPT_ERROR, "Error writing file '%s'", name);
328  ret_value = RET_ERROR;
329  }
330  else {
331  BKE_reportf(reports, RPT_INFO, "Saved packed file to: %s", name);
332  }
333 
334  close(file);
335  }
336 
337  if (remove_tmp) {
338  if (ret_value == RET_ERROR) {
339  if (BLI_rename(tempname, name) != 0) {
340  BKE_reportf(reports,
341  RPT_ERROR,
342  "Error restoring temp file (check files '%s' '%s')",
343  tempname,
344  name);
345  }
346  }
347  else {
348  if (BLI_delete(tempname, false, false) != 0) {
349  BKE_reportf(reports, RPT_ERROR, "Error deleting '%s' (ignored)", tempname);
350  }
351  }
352  }
353 
354  if (guimode) {
355  } // XXX waitcursor(0);
356 
357  return ret_value;
358 }
359 
360 enum ePF_FileCompare BKE_packedfile_compare_to_file(const char *ref_file_name,
361  const char *filepath,
362  PackedFile *pf)
363 {
364  BLI_stat_t st;
365  enum ePF_FileCompare ret_val;
366  char buf[4096];
367  char name[FILE_MAX];
368 
369  BLI_strncpy(name, filepath, sizeof(name));
370  BLI_path_abs(name, ref_file_name);
371 
372  if (BLI_stat(name, &st) == -1) {
373  ret_val = PF_CMP_NOFILE;
374  }
375  else if (st.st_size != pf->size) {
376  ret_val = PF_CMP_DIFFERS;
377  }
378  else {
379  /* we'll have to compare the two... */
380 
381  const int file = BLI_open(name, O_BINARY | O_RDONLY, 0);
382  if (file == -1) {
383  ret_val = PF_CMP_NOFILE;
384  }
385  else {
386  ret_val = PF_CMP_EQUAL;
387 
388  for (int i = 0; i < pf->size; i += sizeof(buf)) {
389  int len = pf->size - i;
390  if (len > sizeof(buf)) {
391  len = sizeof(buf);
392  }
393 
394  if (read(file, buf, len) != len) {
395  /* read error ... */
396  ret_val = PF_CMP_DIFFERS;
397  break;
398  }
399 
400  if (memcmp(buf, ((char *)pf->data) + i, len) != 0) {
401  ret_val = PF_CMP_DIFFERS;
402  break;
403  }
404  }
405 
406  close(file);
407  }
408  }
409 
410  return ret_val;
411 }
412 
414  const char *ref_file_name,
415  const char *abs_name,
416  const char *local_name,
417  PackedFile *pf,
418  enum ePF_FileStatus how)
419 {
420  char *newname = NULL;
421  const char *temp = NULL;
422 
423  if (pf != NULL) {
424  switch (how) {
425  case PF_KEEP:
426  break;
427  case PF_REMOVE:
428  temp = abs_name;
429  break;
430  case PF_USE_LOCAL: {
431  char temp_abs[FILE_MAX];
432 
433  BLI_strncpy(temp_abs, local_name, sizeof(temp_abs));
434  BLI_path_abs(temp_abs, ref_file_name);
435 
436  /* if file exists use it */
437  if (BLI_exists(temp_abs)) {
438  temp = local_name;
439  break;
440  }
441  /* else create it */
443  }
444  case PF_WRITE_LOCAL:
445  if (BKE_packedfile_write_to_file(reports, ref_file_name, local_name, pf, 1) == RET_OK) {
446  temp = local_name;
447  }
448  break;
449  case PF_USE_ORIGINAL: {
450  char temp_abs[FILE_MAX];
451 
452  BLI_strncpy(temp_abs, abs_name, sizeof(temp_abs));
453  BLI_path_abs(temp_abs, ref_file_name);
454 
455  /* if file exists use it */
456  if (BLI_exists(temp_abs)) {
457  BKE_reportf(reports, RPT_INFO, "Use existing file (instead of packed): %s", abs_name);
458  temp = abs_name;
459  break;
460  }
461  /* else create it */
463  }
464  case PF_WRITE_ORIGINAL:
465  if (BKE_packedfile_write_to_file(reports, ref_file_name, abs_name, pf, 1) == RET_OK) {
466  temp = abs_name;
467  }
468  break;
469  default:
470  printf("%s: unknown return_value %u\n", __func__, how);
471  break;
472  }
473 
474  if (temp) {
475  newname = BLI_strdup(temp);
476  }
477  }
478 
479  return newname;
480 }
481 
482 static void unpack_generate_paths(const char *name,
483  ID *id,
484  char *r_abspath,
485  char *r_relpath,
486  size_t abspathlen,
487  size_t relpathlen)
488 {
489  const short id_type = GS(id->name);
490  char tempname[FILE_MAX];
491  char tempdir[FILE_MAXDIR];
492 
493  BLI_split_dirfile(name, tempdir, tempname, sizeof(tempdir), sizeof(tempname));
494 
495  if (tempname[0] == '\0') {
496  /* NOTE: we generally do not have any real way to re-create extension out of data. */
497  const size_t len = BLI_strncpy_rlen(tempname, id->name + 2, sizeof(tempname));
498  printf("%s\n", tempname);
499 
500  /* For images ensure that the temporary filename contains tile number information as well as
501  * a file extension based on the file magic. */
502  if (id_type == ID_IM) {
503  Image *ima = (Image *)id;
504  ImagePackedFile *imapf = ima->packedfiles.last;
505  if (imapf != NULL && imapf->packedfile != NULL) {
506  const PackedFile *pf = imapf->packedfile;
507  enum eImbFileType ftype = IMB_ispic_type_from_memory((const uchar *)pf->data, pf->size);
508  if (ima->source == IMA_SRC_TILED) {
509  char tile_number[6];
510  BLI_snprintf(tile_number, sizeof(tile_number), ".%d", imapf->tile_number);
511  BLI_strncpy(tempname + len, tile_number, sizeof(tempname) - len);
512  }
513  if (ftype != IMB_FTYPE_NONE) {
514  const int imtype = BKE_ftype_to_imtype(ftype, NULL);
515  BKE_image_path_ensure_ext_from_imtype(tempname, imtype);
516  }
517  }
518  }
519 
520  BLI_filename_make_safe(tempname);
521  printf("%s\n", tempname);
522  }
523 
524  if (tempdir[0] == '\0') {
525  /* Fallback to relative dir. */
526  BLI_strncpy(tempdir, "//", sizeof(tempdir));
527  }
528 
529  switch (id_type) {
530  case ID_VF:
531  BLI_snprintf(r_relpath, relpathlen, "//fonts/%s", tempname);
532  break;
533  case ID_SO:
534  BLI_snprintf(r_relpath, relpathlen, "//sounds/%s", tempname);
535  break;
536  case ID_IM:
537  BLI_snprintf(r_relpath, relpathlen, "//textures/%s", tempname);
538  break;
539  case ID_VO:
540  BLI_snprintf(r_relpath, relpathlen, "//volumes/%s", tempname);
541  break;
542  default:
543  break;
544  }
545 
546  {
547  size_t len = BLI_strncpy_rlen(r_abspath, tempdir, abspathlen);
548  BLI_strncpy(r_abspath + len, tempname, abspathlen - len);
549  }
550 }
551 
553  ReportList *reports,
554  ID *id,
555  const char *orig_file_path,
556  PackedFile *pf,
557  enum ePF_FileStatus how)
558 {
559  char localname[FILE_MAX], absname[FILE_MAX];
560  char *new_name = NULL;
561 
562  if (id != NULL) {
564  orig_file_path, id, absname, localname, sizeof(absname), sizeof(localname));
566  reports, BKE_main_blendfile_path(bmain), absname, localname, pf, how);
567  }
568 
569  return new_name;
570 }
571 
573  ReportList *reports,
574  VFont *vfont,
575  enum ePF_FileStatus how)
576 {
577  int ret_value = RET_ERROR;
578  if (vfont) {
579  char *new_file_path = BKE_packedfile_unpack(
580  bmain, reports, (ID *)vfont, vfont->filepath, vfont->packedfile, how);
581 
582  if (new_file_path != NULL) {
583  ret_value = RET_OK;
584  BKE_packedfile_free(vfont->packedfile);
585  vfont->packedfile = NULL;
586  BLI_strncpy(vfont->filepath, new_file_path, sizeof(vfont->filepath));
587  MEM_freeN(new_file_path);
588  }
589  }
590 
591  return ret_value;
592 }
593 
595  ReportList *reports,
596  bSound *sound,
597  enum ePF_FileStatus how)
598 {
599  int ret_value = RET_ERROR;
600 
601  if (sound != NULL) {
602  char *new_file_path = BKE_packedfile_unpack(
603  bmain, reports, (ID *)sound, sound->filepath, sound->packedfile, how);
604  if (new_file_path != NULL) {
605  BLI_strncpy(sound->filepath, new_file_path, sizeof(sound->filepath));
606  MEM_freeN(new_file_path);
607 
608  BKE_packedfile_free(sound->packedfile);
609  sound->packedfile = NULL;
610 
611  BKE_sound_load(bmain, sound);
612 
613  ret_value = RET_OK;
614  }
615  }
616 
617  return ret_value;
618 }
619 
621  ReportList *reports,
622  Image *ima,
623  enum ePF_FileStatus how)
624 {
625  int ret_value = RET_ERROR;
626 
627  if (ima != NULL) {
628  while (ima->packedfiles.last) {
629  ImagePackedFile *imapf = ima->packedfiles.last;
630  char *new_file_path = BKE_packedfile_unpack(
631  bmain, reports, (ID *)ima, imapf->filepath, imapf->packedfile, how);
632 
633  if (new_file_path != NULL) {
634  ImageView *iv;
635 
636  ret_value = ret_value == RET_ERROR ? RET_ERROR : RET_OK;
638  imapf->packedfile = NULL;
639 
640  /* update the new corresponding view filepath */
641  iv = BLI_findstring(&ima->views, imapf->filepath, offsetof(ImageView, filepath));
642  if (iv) {
643  BLI_strncpy(iv->filepath, new_file_path, sizeof(imapf->filepath));
644  }
645 
646  /* keep the new name in the image for non-pack specific reasons */
647  if (how != PF_REMOVE) {
648  BLI_strncpy(ima->filepath, new_file_path, sizeof(imapf->filepath));
649  if (ima->source == IMA_SRC_TILED) {
650  /* Ensure that the Image filepath is kept in a tokenized format. */
651  char *filename = (char *)BLI_path_basename(ima->filepath);
652  BKE_image_ensure_tile_token(filename);
653  }
654  }
655  MEM_freeN(new_file_path);
656  }
657  else {
658  ret_value = RET_ERROR;
659  }
660 
661  BLI_remlink(&ima->packedfiles, imapf);
662  MEM_freeN(imapf);
663  }
664  }
665 
666  if (ret_value == RET_OK) {
668  }
669 
670  return ret_value;
671 }
672 
674  ReportList *reports,
675  Volume *volume,
676  enum ePF_FileStatus how)
677 {
678  int ret_value = RET_ERROR;
679 
680  if (volume != NULL) {
681  char *new_file_path = BKE_packedfile_unpack(
682  bmain, reports, (ID *)volume, volume->filepath, volume->packedfile, how);
683  if (new_file_path != NULL) {
684  BLI_strncpy(volume->filepath, new_file_path, sizeof(volume->filepath));
685  MEM_freeN(new_file_path);
686 
687  BKE_packedfile_free(volume->packedfile);
688  volume->packedfile = NULL;
689 
690  BKE_volume_unload(volume);
691 
692  ret_value = RET_OK;
693  }
694  }
695 
696  return ret_value;
697 }
698 
700 {
701  Library *lib;
702  char *newname;
703  int ret_value = RET_ERROR;
704 
705  for (lib = bmain->libraries.first; lib; lib = lib->id.next) {
706  if (lib->packedfile && lib->filepath[0]) {
707 
708  newname = BKE_packedfile_unpack_to_file(reports,
710  lib->filepath_abs,
711  lib->filepath_abs,
712  lib->packedfile,
714  if (newname != NULL) {
715  ret_value = RET_OK;
716 
717  printf("Unpacked .blend library: %s\n", newname);
718 
719  BKE_packedfile_free(lib->packedfile);
720  lib->packedfile = NULL;
721 
722  MEM_freeN(newname);
723  }
724  }
725  }
726 
727  return ret_value;
728 }
729 
731 {
732  Library *lib;
733 
734  /* Test for relativeness. */
735  for (lib = bmain->libraries.first; lib; lib = lib->id.next) {
736  if (!BLI_path_is_rel(lib->filepath)) {
737  break;
738  }
739  }
740 
741  if (lib) {
742  BKE_reportf(reports, RPT_ERROR, "Cannot pack absolute file: '%s'", lib->filepath);
743  return;
744  }
745 
746  for (lib = bmain->libraries.first; lib; lib = lib->id.next) {
747  if (lib->packedfile == NULL) {
748  lib->packedfile = BKE_packedfile_new(reports, lib->filepath, BKE_main_blendfile_path(bmain));
749  }
750  }
751 }
752 
753 void BKE_packedfile_unpack_all(Main *bmain, ReportList *reports, enum ePF_FileStatus how)
754 {
755  Image *ima;
756  VFont *vf;
757  bSound *sound;
758  Volume *volume;
759 
760  for (ima = bmain->images.first; ima; ima = ima->id.next) {
761  if (BKE_image_has_packedfile(ima)) {
762  BKE_packedfile_unpack_image(bmain, reports, ima, how);
763  }
764  }
765 
766  for (vf = bmain->fonts.first; vf; vf = vf->id.next) {
767  if (vf->packedfile) {
768  BKE_packedfile_unpack_vfont(bmain, reports, vf, how);
769  }
770  }
771 
772  for (sound = bmain->sounds.first; sound; sound = sound->id.next) {
773  if (sound->packedfile) {
774  BKE_packedfile_unpack_sound(bmain, reports, sound, how);
775  }
776  }
777 
778  for (volume = bmain->volumes.first; volume; volume = volume->id.next) {
779  if (volume->packedfile) {
780  BKE_packedfile_unpack_volume(bmain, reports, volume, how);
781  }
782  }
783 }
784 
786 {
787  switch (GS(id->name)) {
788  case ID_IM: {
789  const Image *ima = (const Image *)id;
790  return BKE_image_has_packedfile(ima);
791  }
792  case ID_VF: {
793  const VFont *vf = (const VFont *)id;
794  return vf->packedfile != NULL;
795  }
796  case ID_SO: {
797  const bSound *snd = (const bSound *)id;
798  return snd->packedfile != NULL;
799  }
800  case ID_VO: {
801  const Volume *volume = (const Volume *)id;
802  return volume->packedfile != NULL;
803  }
804  case ID_LI: {
805  const Library *li = (const Library *)id;
806  return li->packedfile != NULL;
807  }
808  default:
809  break;
810  }
811  return false;
812 }
813 
814 void BKE_packedfile_id_unpack(Main *bmain, ID *id, ReportList *reports, enum ePF_FileStatus how)
815 {
816  switch (GS(id->name)) {
817  case ID_IM: {
818  Image *ima = (Image *)id;
819  if (BKE_image_has_packedfile(ima)) {
820  BKE_packedfile_unpack_image(bmain, reports, ima, how);
821  }
822  break;
823  }
824  case ID_VF: {
825  VFont *vf = (VFont *)id;
826  if (vf->packedfile) {
827  BKE_packedfile_unpack_vfont(bmain, reports, vf, how);
828  }
829  break;
830  }
831  case ID_SO: {
832  bSound *snd = (bSound *)id;
833  if (snd->packedfile) {
834  BKE_packedfile_unpack_sound(bmain, reports, snd, how);
835  }
836  break;
837  }
838  case ID_VO: {
839  Volume *volume = (Volume *)id;
840  if (volume->packedfile) {
841  BKE_packedfile_unpack_volume(bmain, reports, volume, how);
842  }
843  break;
844  }
845  case ID_LI: {
846  Library *li = (Library *)id;
847  BKE_reportf(reports, RPT_ERROR, "Cannot unpack individual Library file, '%s'", li->filepath);
848  break;
849  }
850  default:
851  break;
852  }
853 }
854 
856 {
857  if (pf == NULL) {
858  return;
859  }
860  BLO_write_struct(writer, PackedFile, pf);
861  BLO_write_raw(writer, pf->size, pf->data);
862 }
863 
865 {
866  BLO_read_packed_address(reader, pf_p);
867  PackedFile *pf = *pf_p;
868  if (pf == NULL) {
869  return;
870  }
871 
872  BLO_read_packed_address(reader, &pf->data);
873  if (pf->data == NULL) {
874  /* We cannot allow a PackedFile with a NULL data field,
875  * the whole code assumes this is not possible. See T70315. */
876  printf("%s: NULL packedfile data, cleaning up...\n", __func__);
877  MEM_SAFE_FREE(pf);
878  }
879 }
void BKE_image_packfiles(struct ReportList *reports, struct Image *ima, const char *basepath)
bool BKE_image_has_packedfile(const struct Image *image)
void BKE_image_ensure_tile_token(char *filename)
#define IMA_SIGNAL_RELOAD
Definition: BKE_image.h:129
void BKE_image_signal(struct Main *bmain, struct Image *ima, struct ImageUser *iuser, int signal)
int BKE_image_path_ensure_ext_from_imtype(char *string, char imtype)
char BKE_ftype_to_imtype(int ftype, const struct ImbFormatOptions *options)
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
ePF_FileCompare
@ PF_CMP_EQUAL
@ PF_CMP_NOFILE
@ PF_CMP_DIFFERS
#define RET_OK
#define RET_ERROR
ePF_FileStatus
@ PF_USE_ORIGINAL
@ PF_USE_LOCAL
@ PF_KEEP
@ PF_REMOVE
@ PF_WRITE_ORIGINAL
@ PF_WRITE_LOCAL
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
void BKE_sound_load(struct Main *main, struct bSound *sound)
bool BKE_vfont_is_builtin(const struct VFont *vfont)
Definition: vfont.c:223
Volume data-block.
void BKE_volume_unload(struct Volume *volume)
Definition: volume.cc:930
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define ATTR_FALLTHROUGH
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:314
#define O_BINARY
Definition: BLI_fileops.h:319
int BLI_stat(const char *path, BLI_stat_t *buffer) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
size_t BLI_file_descriptor_size(int file) ATTR_WARN_UNUSED_RESULT
Definition: storage.c:178
int BLI_delete(const char *file, bool dir, bool recursive) ATTR_NONNULL()
Definition: fileops.c:934
int BLI_rename(const char *from, const char *to) ATTR_NONNULL()
Definition: fileops.c:1268
struct stat BLI_stat_t
Definition: BLI_fileops.h:73
int BLI_copy(const char *file, const char *to) ATTR_NONNULL()
Definition: fileops.c:1198
int BLI_open(const char *filepath, int oflag, int pmode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:920
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
const char * BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1653
bool BLI_path_is_rel(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:347
bool BLI_make_existing_file(const char *name)
Definition: path_util.c:1197
void BLI_split_dirfile(const char *string, char *dir, char *file, size_t dirlen, size_t filelen)
Definition: path_util.c:1465
#define FILE_MAX
bool BLI_filename_make_safe(char *fname) ATTR_NONNULL(1)
Definition: path_util.c:309
#define FILE_MAXDIR
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:897
size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:120
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
unsigned char uchar
Definition: BLI_sys_types.h:70
#define ELEM(...)
#define BLO_read_packed_address(reader, ptr_p)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_write_raw(BlendWriter *writer, size_t size_in_bytes, const void *data_ptr)
Definition: writefile.c:1489
ID and Library types, which are fundamental for sdna.
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
#define ID_BLEND_PATH(_bmain, _id)
Definition: DNA_ID.h:559
@ ID_LI
Definition: DNA_ID_enums.h:46
@ ID_IM
Definition: DNA_ID_enums.h:53
@ ID_VO
Definition: DNA_ID_enums.h:83
@ ID_SO
Definition: DNA_ID_enums.h:64
@ ID_VF
Definition: DNA_ID_enums.h:61
@ IMA_SRC_FILE
@ IMA_SRC_MOVIE
@ IMA_SRC_TILED
@ IMA_SRC_SEQUENCE
int IMB_ispic_type_from_memory(const unsigned char *buf, size_t buf_size)
Definition: util.c:138
Contains defines and structs used throughout the imbuf module.
#define IMB_FTYPE_NONE
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
static int verbose
Definition: cineonlib.c:29
struct ListBase packedfiles
short source
FILE * file
int len
Definition: draw_manager.c:108
DRWShaderLibrary * lib
#define pf(_x, _i)
Prefetch 64.
Definition: gim_memory.h:48
eImbFileType
int count
#define GS(x)
Definition: iris.c:225
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static const pxr::TfToken st("st", pxr::TfToken::Immortal)
int BKE_packedfile_unpack_all_libraries(Main *bmain, ReportList *reports)
Definition: packedFile.c:699
void BKE_packedfile_blend_write(BlendWriter *writer, PackedFile *pf)
Definition: packedFile.c:855
void BKE_packedfile_free(PackedFile *pf)
Definition: packedFile.c:140
int BKE_packedfile_count_all(Main *bmain)
Definition: packedFile.c:104
PackedFile * BKE_packedfile_new(ReportList *reports, const char *filepath, const char *basepath)
Definition: packedFile.c:177
static void unpack_generate_paths(const char *name, ID *id, char *r_abspath, char *r_relpath, size_t abspathlen, size_t relpathlen)
Definition: packedFile.c:482
bool BKE_packedfile_id_check(const ID *id)
Definition: packedFile.c:785
char * BKE_packedfile_unpack_to_file(ReportList *reports, const char *ref_file_name, const char *abs_name, const char *local_name, PackedFile *pf, enum ePF_FileStatus how)
Definition: packedFile.c:413
void BKE_packedfile_blend_read(BlendDataReader *reader, PackedFile **pf_p)
Definition: packedFile.c:864
int BKE_packedfile_unpack_sound(Main *bmain, ReportList *reports, bSound *sound, enum ePF_FileStatus how)
Definition: packedFile.c:594
void BKE_packedfile_unpack_all(Main *bmain, ReportList *reports, enum ePF_FileStatus how)
Definition: packedFile.c:753
void BKE_packedfile_pack_all_libraries(Main *bmain, ReportList *reports)
Definition: packedFile.c:730
int BKE_packedfile_read(PackedFile *pf, void *data, int size)
Definition: packedFile.c:81
int BKE_packedfile_unpack_image(Main *bmain, ReportList *reports, Image *ima, enum ePF_FileStatus how)
Definition: packedFile.c:620
enum ePF_FileCompare BKE_packedfile_compare_to_file(const char *ref_file_name, const char *filepath, PackedFile *pf)
Definition: packedFile.c:360
int BKE_packedfile_unpack_vfont(Main *bmain, ReportList *reports, VFont *vfont, enum ePF_FileStatus how)
Definition: packedFile.c:572
char * BKE_packedfile_unpack(Main *bmain, ReportList *reports, ID *id, const char *orig_file_path, PackedFile *pf, enum ePF_FileStatus how)
Definition: packedFile.c:552
void BKE_packedfile_rewind(PackedFile *pf)
Definition: packedFile.c:76
int BKE_packedfile_write_to_file(ReportList *reports, const char *ref_file_name, const char *filepath, PackedFile *pf, const bool guimode)
Definition: packedFile.c:286
int BKE_packedfile_seek(PackedFile *pf, int offset, int whence)
Definition: packedFile.c:44
PackedFile * BKE_packedfile_duplicate(const PackedFile *pf_src)
Definition: packedFile.c:153
int BKE_packedfile_unpack_volume(Main *bmain, ReportList *reports, Volume *volume, enum ePF_FileStatus how)
Definition: packedFile.c:673
void BKE_packedfile_pack_all(Main *bmain, ReportList *reports, bool verbose)
Definition: packedFile.c:230
void BKE_packedfile_id_unpack(Main *bmain, ID *id, ReportList *reports, enum ePF_FileStatus how)
Definition: packedFile.c:814
PackedFile * BKE_packedfile_new_from_memory(void *mem, int memlen)
Definition: packedFile.c:166
Definition: DNA_ID.h:368
void * next
Definition: DNA_ID.h:369
char name[66]
Definition: DNA_ID.h:378
struct PackedFile * packedfile
char filepath[1024]
char filepath[1024]
struct PackedFile * packedfile
Definition: DNA_ID.h:476
char filepath[1024]
Definition: DNA_ID.h:461
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
ListBase volumes
Definition: BKE_main.h:210
ListBase fonts
Definition: BKE_main.h:184
ListBase sounds
Definition: BKE_main.h:188
ListBase libraries
Definition: BKE_main.h:169
ListBase images
Definition: BKE_main.h:176
char filepath[1024]
struct PackedFile * packedfile
char filepath[1024]
struct PackedFile * packedfile
struct PackedFile * packedfile
char filepath[1024]