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