Cleanup: Remove more #if 0 blocks
[blender.git] / source / blender / blenkernel / intern / packedFile.c
index 03342d0..8d7a832 100644 (file)
@@ -34,7 +34,7 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 
-#ifndef WIN32 
+#ifndef WIN32
 #include <unistd.h>
 #else
 #include <io.h>
 #include "MEM_guardedalloc.h"
 
 #include "DNA_image_types.h"
+#include "DNA_ID.h"
+#include "DNA_packedFile_types.h"
 #include "DNA_sound_types.h"
 #include "DNA_vfont_types.h"
-#include "DNA_packedFile_types.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_utildefines.h"
 #include "BKE_report.h"
 #include "BKE_sound.h"
 
-#ifdef _WIN32
-#define open _open
-#define close _close
-#define read _read
-#define write _write
-#endif
-
-
 int seekPackedFile(PackedFile *pf, int offset, int whence)
 {
        int oldseek = -1, seek = 0;
@@ -84,6 +77,7 @@ int seekPackedFile(PackedFile *pf, int offset, int whence)
                                break;
                        default:
                                oldseek = -1;
+                               break;
                }
                if (seek < 0) {
                        seek = 0;
@@ -96,14 +90,14 @@ int seekPackedFile(PackedFile *pf, int offset, int whence)
 
        return(oldseek);
 }
-       
+
 void rewindPackedFile(PackedFile *pf)
 {
        seekPackedFile(pf, 0, SEEK_SET);
 }
 
 int readPackedFile(PackedFile *pf, void *data, int size)
-{ 
+{
        if ((pf != NULL) && (size >= 0) && (data != NULL)) {
                if (size + pf->seek > pf->size) {
                        size = pf->size - pf->seek;
@@ -131,11 +125,11 @@ int countPackedFiles(Main *bmain)
        VFont *vf;
        bSound *sound;
        int count = 0;
-       
+
        /* let's check if there are packed files... */
        for (ima = bmain->image.first; ima; ima = ima->id.next)
-               if (ima->packedfile)
-                       count++;
+               if (BKE_image_has_packedfile(ima))
+                       count ++;
 
        for (vf = bmain->vfont.first; vf; vf = vf->id.next)
                if (vf->packedfile)
@@ -173,7 +167,7 @@ PackedFile *newPackedFileMemory(void *mem, int memlen)
        PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile");
        pf->data = mem;
        pf->size = memlen;
-       
+
        return pf;
 }
 
@@ -183,14 +177,14 @@ PackedFile *newPackedFile(ReportList *reports, const char *filename, const char
        int file, filelen;
        char name[FILE_MAX];
        void *data;
-       
+
        /* render result has no filename and can be ignored
         * any other files with no name can be ignored too */
        if (filename[0] == '\0')
                return NULL;
 
        //XXX waitcursor(1);
-       
+
        /* convert relative filenames to absolute filenames */
 
        BLI_strncpy(name, filename, sizeof(name));
@@ -200,8 +194,8 @@ PackedFile *newPackedFile(ReportList *reports, const char *filename, const char
         * and create a PackedFile structure */
 
        file = BLI_open(name, O_BINARY | O_RDONLY, 0);
-       if (file <= 0) {
-               BKE_reportf(reports, RPT_ERROR, "Unable to pack file, source path not found: \"%s\"", name);
+       if (file == -1) {
+               BKE_reportf(reports, RPT_ERROR, "Unable to pack file, source path '%s' not found", name);
        }
        else {
                filelen = BLI_file_descriptor_size(file);
@@ -217,147 +211,143 @@ PackedFile *newPackedFile(ReportList *reports, const char *filename, const char
                if (read(file, data, filelen) == filelen) {
                        pf = newPackedFileMemory(data, filelen);
                }
+               else {
+                       MEM_freeN(data);
+               }
 
                close(file);
        }
 
        //XXX waitcursor(0);
-               
+
        return (pf);
 }
 
-void packAll(Main *bmain, ReportList *reports)
+/* no libraries for now */
+void packAll(Main *bmain, ReportList *reports, bool verbose)
 {
        Image *ima;
        VFont *vfont;
        bSound *sound;
-       
+       int tot = 0;
+
        for (ima = bmain->image.first; ima; ima = ima->id.next) {
-               if (ima->packedfile == NULL && ima->id.lib == NULL) {
+               if (BKE_image_has_packedfile(ima) == false && !ID_IS_LINKED(ima)) {
                        if (ima->source == IMA_SRC_FILE) {
-                               ima->packedfile = newPackedFile(reports, ima->name, ID_BLEND_PATH(bmain, &ima->id));
+                               BKE_image_packfiles(reports, ima, ID_BLEND_PATH(bmain, &ima->id));
+                               tot ++;
                        }
-                       else if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
-                               BKE_reportf(reports, RPT_WARNING, "Image '%s' skipped, movies and image sequences not supported.", ima->id.name + 2);
+                       else if (BKE_image_is_animated(ima) && verbose) {
+                               BKE_reportf(reports, RPT_WARNING, "Image '%s' skipped, movies and image sequences not supported",
+                                           ima->id.name + 2);
                        }
                }
        }
 
-       for (vfont = bmain->vfont.first; vfont; vfont = vfont->id.next)
-               if (vfont->packedfile == NULL && vfont->id.lib == NULL && BKE_vfont_is_builtin(vfont) == FALSE)
-                       vfont->packedfile = newPackedFile(reports, vfont->name, bmain->name);
-
-       for (sound = bmain->sound.first; sound; sound = sound->id.next)
-               if (sound->packedfile == NULL && sound->id.lib == NULL)
-                       sound->packedfile = newPackedFile(reports, sound->name, bmain->name);
-}
-
-
-#if 0
-
-// attempt to create a function that generates an unique filename
-// this will work when all funtions in fileops.c understand relative filenames...
+       for (vfont = bmain->vfont.first; vfont; vfont = vfont->id.next) {
+               if (vfont->packedfile == NULL && !ID_IS_LINKED(vfont) && BKE_vfont_is_builtin(vfont) == false) {
+                       vfont->packedfile = newPackedFile(reports, vfont->name, BKE_main_blendfile_path(bmain));
+                       tot ++;
+               }
+       }
 
-static char *find_new_name(char *name)
-{
-       char tempname[FILE_MAX];
-       char *newname;
-       size_t len;
-       
-       if (fop_exists(name)) {
-               for (number = 1; number <= 999; number++) {
-                       BLI_snprintf(tempname, sizeof(tempname), "%s.%03d", name, number);
-                       if (!fop_exists(tempname)) {
-                               break;
-                       }
+       for (sound = bmain->sound.first; sound; sound = sound->id.next) {
+               if (sound->packedfile == NULL && !ID_IS_LINKED(sound)) {
+                       sound->packedfile = newPackedFile(reports, sound->name, BKE_main_blendfile_path(bmain));
+                       tot++;
                }
        }
-       len = strlen(tempname) + 1;
-       newname = MEM_mallocN(len, "find_new_name");
-       memcpy(newname, tempname, len * sizeof(char));
-       return newname;
+
+       if (tot > 0)
+               BKE_reportf(reports, RPT_INFO, "Packed %d files", tot);
+       else if (verbose)
+               BKE_report(reports, RPT_INFO, "No new files have been packed");
 }
-#endif
 
-int writePackedFile(ReportList *reports, const char *filename, PackedFile *pf, int guimode)
+int writePackedFile(
+        ReportList *reports, const char *ref_file_name, const char *filename, PackedFile *pf, const bool guimode)
 {
-       int file, number, remove_tmp = FALSE;
+       int file, number;
        int ret_value = RET_OK;
+       bool remove_tmp = false;
        char name[FILE_MAX];
        char tempname[FILE_MAX];
 /*      void *data; */
-       
+
        if (guimode) {} //XXX  waitcursor(1);
-       
+
        BLI_strncpy(name, filename, sizeof(name));
-       BLI_path_abs(name, G.main->name);
-       
+       BLI_path_abs(name, ref_file_name);
+
        if (BLI_exists(name)) {
                for (number = 1; number <= 999; number++) {
                        BLI_snprintf(tempname, sizeof(tempname), "%s.%03d_", name, number);
                        if (!BLI_exists(tempname)) {
                                if (BLI_copy(name, tempname) == RET_OK) {
-                                       remove_tmp = TRUE;
+                                       remove_tmp = true;
                                }
                                break;
                        }
                }
        }
-       
+
        /* make sure the path to the file exists... */
        BLI_make_existing_file(name);
-       
+
        file = BLI_open(name, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666);
-       if (file >= 0) {
+       if (file == -1) {
+               BKE_reportf(reports, RPT_ERROR, "Error creating file '%s'", name);
+               ret_value = RET_ERROR;
+       }
+       else {
                if (write(file, pf->data, pf->size) != pf->size) {
-                       BKE_reportf(reports, RPT_ERROR, "Error writing file: %s", name);
+                       BKE_reportf(reports, RPT_ERROR, "Error writing file '%s'", name);
                        ret_value = RET_ERROR;
                }
+               else {
+                       BKE_reportf(reports, RPT_INFO, "Saved packed file to: %s", name);
+               }
+
                close(file);
        }
-       else {
-               BKE_reportf(reports, RPT_ERROR, "Error creating file: %s", name);
-               ret_value = RET_ERROR;
-       }
-       
+
        if (remove_tmp) {
                if (ret_value == RET_ERROR) {
                        if (BLI_rename(tempname, name) != 0) {
-                               BKE_reportf(reports, RPT_ERROR, "Error restoring tempfile. Check files: '%s' '%s'", tempname, name);
+                               BKE_reportf(reports, RPT_ERROR, "Error restoring temp file (check files '%s' '%s')", tempname, name);
                        }
                }
                else {
-                       if (BLI_delete(tempname, 0, 0) != 0) {
+                       if (BLI_delete(tempname, false, false) != 0) {
                                BKE_reportf(reports, RPT_ERROR, "Error deleting '%s' (ignored)", tempname);
                        }
                }
        }
-       
+
        if (guimode) {} //XXX waitcursor(0);
 
        return (ret_value);
 }
-       
-/*
+
+/**
  * This function compares a packed file to a 'real' file.
  * It returns an integer indicating if:
  *
- * PF_EQUAL            - the packed file and original file are identical
- * PF_DIFFERENT        - the packed file and original file differ
- * PF_NOFILE   - the original file doens't exist
+ * - PF_EQUAL:     the packed file and original file are identical
+ * - PF_DIFFERENT: the packed file and original file differ
+ * - PF_NOFILE:    the original file doesn't exist
  */
-
-int checkPackedFile(const char *filename, PackedFile *pf)
+int checkPackedFile(const char *ref_file_name, const char *filename, PackedFile *pf)
 {
-       struct stat st;
+       BLI_stat_t st;
        int ret_val, i, len, file;
        char buf[4096];
        char name[FILE_MAX];
-       
+
        BLI_strncpy(name, filename, sizeof(name));
-       BLI_path_abs(name, G.main->name);
-       
-       if (stat(name, &st)) {
+       BLI_path_abs(name, ref_file_name);
+
+       if (BLI_stat(name, &st) == -1) {
                ret_val = PF_NOFILE;
        }
        else if (st.st_size != pf->size) {
@@ -367,7 +357,7 @@ int checkPackedFile(const char *filename, PackedFile *pf)
                /* we'll have to compare the two... */
 
                file = BLI_open(name, O_BINARY | O_RDONLY, 0);
-               if (file < 0) {
+               if (file == -1) {
                        ret_val = PF_NOFILE;
                }
                else {
@@ -391,28 +381,29 @@ int checkPackedFile(const char *filename, PackedFile *pf)
                                        }
                                }
                        }
-                       
+
                        close(file);
                }
        }
-       
+
        return(ret_val);
 }
 
-/* unpackFile() looks at the existing files (abs_name, local_name) and a packed file.
+/**
+ * unpackFile() looks at the existing files (abs_name, local_name) and a packed file.
  *
  * It returns a char *to the existing file name / new file name or NULL when
  * there was an error or when the user decides to cancel the operation.
+ *
+ * \warning 'abs_name' may be relative still! (use a "//" prefix) be sure to run #BLI_path_abs on it first.
  */
-
-char *unpackFile(ReportList *reports, const char *abs_name, const char *local_name, PackedFile *pf, int how)
+char *unpackFile(
+        ReportList *reports, const char *ref_file_name,
+        const char *abs_name, const char *local_name, PackedFile *pf, int how)
 {
        char *newname = NULL;
        const char *temp = NULL;
-       
-       // char newabs[FILE_MAX];
-       // char newlocal[FILE_MAX];
-       
+
        if (pf != NULL) {
                switch (how) {
                        case -1:
@@ -422,26 +413,43 @@ char *unpackFile(ReportList *reports, const char *abs_name, const char *local_na
                                temp = abs_name;
                                break;
                        case PF_USE_LOCAL:
+                       {
+                               char temp_abs[FILE_MAX];
+
+                               BLI_strncpy(temp_abs, local_name, sizeof(temp_abs));
+                               BLI_path_abs(temp_abs, ref_file_name);
+
                                /* if file exists use it */
-                               if (BLI_exists(local_name)) {
+                               if (BLI_exists(temp_abs)) {
                                        temp = local_name;
                                        break;
                                }
-                       /* else fall through and create it */
+                               /* else create it */
+                               ATTR_FALLTHROUGH;
+                       }
                        case PF_WRITE_LOCAL:
-                               if (writePackedFile(reports, local_name, pf, 1) == RET_OK) {
+                               if (writePackedFile(reports, ref_file_name, local_name, pf, 1) == RET_OK) {
                                        temp = local_name;
                                }
                                break;
                        case PF_USE_ORIGINAL:
+                       {
+                               char temp_abs[FILE_MAX];
+
+                               BLI_strncpy(temp_abs, abs_name, sizeof(temp_abs));
+                               BLI_path_abs(temp_abs, ref_file_name);
+
                                /* if file exists use it */
-                               if (BLI_exists(abs_name)) {
+                               if (BLI_exists(temp_abs)) {
+                                       BKE_reportf(reports, RPT_INFO, "Use existing file (instead of packed): %s", abs_name);
                                        temp = abs_name;
                                        break;
                                }
-                       /* else fall through and create it */
+                               /* else create it */
+                               ATTR_FALLTHROUGH;
+                       }
                        case PF_WRITE_ORIGINAL:
-                               if (writePackedFile(reports, abs_name, pf, 1) == RET_OK) {
+                               if (writePackedFile(reports, ref_file_name, abs_name, pf, 1) == RET_OK) {
                                        temp = abs_name;
                                }
                                break;
@@ -449,29 +457,65 @@ char *unpackFile(ReportList *reports, const char *abs_name, const char *local_na
                                printf("unpackFile: unknown return_value %d\n", how);
                                break;
                }
-               
+
                if (temp) {
                        newname = BLI_strdup(temp);
                }
        }
-       
+
        return newname;
 }
 
+static void unpack_generate_paths(
+        const char *name, ID *id, char *r_abspath, char *r_relpath, size_t abspathlen, size_t relpathlen)
+{
+       char tempname[FILE_MAX];
+       char tempdir[FILE_MAXDIR];
 
-int unpackVFont(ReportList *reports, VFont *vfont, int how)
+       BLI_split_dirfile(name, tempdir, tempname, sizeof(tempdir), sizeof(tempname));
+
+       if (tempname[0] == '\0') {
+               /* Note: we do not have any real way to re-create extension out of data... */
+               BLI_strncpy(tempname, id->name + 2, sizeof(tempname));
+               printf("%s\n", tempname);
+               BLI_filename_make_safe(tempname);
+               printf("%s\n", tempname);
+       }
+
+       if (tempdir[0] == '\0') {
+               /* Fallback to relative dir. */
+               BLI_strncpy(tempdir, "//", sizeof(tempdir));
+       }
+
+       switch (GS(id->name)) {
+               case ID_VF:
+                       BLI_snprintf(r_relpath, relpathlen, "//fonts/%s", tempname);
+                       break;
+               case ID_SO:
+                       BLI_snprintf(r_relpath, relpathlen, "//sounds/%s", tempname);
+                       break;
+               case ID_IM:
+                       BLI_snprintf(r_relpath, relpathlen, "//textures/%s", tempname);
+                       break;
+               default:
+                       break;
+       }
+
+       {
+               size_t len = BLI_strncpy_rlen(r_abspath, tempdir, abspathlen);
+               BLI_strncpy(r_abspath + len, tempname, abspathlen - len);
+       }
+}
+
+int unpackVFont(Main *bmain, ReportList *reports, VFont *vfont, int how)
 {
-       char localname[FILE_MAX], fi[FILE_MAXFILE];
+       char localname[FILE_MAX], absname[FILE_MAX];
        char *newname;
        int ret_value = RET_ERROR;
-       
+
        if (vfont != NULL) {
-               BLI_strncpy(localname, vfont->name, sizeof(localname));
-               BLI_splitdirstring(localname, fi);
-               
-               BLI_snprintf(localname, sizeof(localname), "//fonts/%s", fi);
-               
-               newname = unpackFile(reports, vfont->name, localname, vfont->packedfile, how);
+               unpack_generate_paths(vfont->name, (ID *)vfont, absname, localname, sizeof(absname), sizeof(localname));
+               newname = unpackFile(reports, BKE_main_blendfile_path(bmain), absname, localname, vfont->packedfile, how);
                if (newname != NULL) {
                        ret_value = RET_OK;
                        freePackedFile(vfont->packedfile);
@@ -480,22 +524,19 @@ int unpackVFont(ReportList *reports, VFont *vfont, int how)
                        MEM_freeN(newname);
                }
        }
-       
+
        return (ret_value);
 }
 
 int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how)
 {
-       char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX];
+       char localname[FILE_MAX], absname[FILE_MAX];
        char *newname;
        int ret_value = RET_ERROR;
 
        if (sound != NULL) {
-               BLI_strncpy(localname, sound->name, sizeof(localname));
-               BLI_splitdirstring(localname, fi);
-               BLI_snprintf(localname, sizeof(localname), "//sounds/%s", fi);
-
-               newname = unpackFile(reports, sound->name, localname, sound->packedfile, how);
+               unpack_generate_paths(sound->name, (ID *)sound, absname, localname, sizeof(absname), sizeof(localname));
+               newname = unpackFile(reports, BKE_main_blendfile_path(bmain), absname, localname, sound->packedfile, how);
                if (newname != NULL) {
                        BLI_strncpy(sound->name, newname, sizeof(sound->name));
                        MEM_freeN(newname);
@@ -503,40 +544,108 @@ int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how)
                        freePackedFile(sound->packedfile);
                        sound->packedfile = NULL;
 
-                       sound_load(bmain, sound);
+                       BKE_sound_load(bmain, sound);
 
                        ret_value = RET_OK;
                }
        }
-       
+
+       return(ret_value);
+}
+
+int unpackImage(Main *bmain, ReportList *reports, Image *ima, int how)
+{
+       int ret_value = RET_ERROR;
+
+       if (ima != NULL) {
+               while (ima->packedfiles.last) {
+                       char localname[FILE_MAX], absname[FILE_MAX];
+                       char *newname;
+                       ImagePackedFile *imapf = ima->packedfiles.last;
+
+                       unpack_generate_paths(imapf->filepath, (ID *)ima, absname, localname, sizeof(absname), sizeof(localname));
+                       newname = unpackFile(reports, BKE_main_blendfile_path(bmain), absname, localname, imapf->packedfile, how);
+
+                       if (newname != NULL) {
+                               ImageView *iv;
+
+                               ret_value = ret_value == RET_ERROR ? RET_ERROR : RET_OK;
+                               freePackedFile(imapf->packedfile);
+                               imapf->packedfile = NULL;
+
+                               /* update the new corresponding view filepath */
+                               iv = BLI_findstring(&ima->views, imapf->filepath, offsetof(ImageView, filepath));
+                               if (iv) {
+                                       BLI_strncpy(iv->filepath, newname, sizeof(imapf->filepath));
+                               }
+
+                               /* keep the new name in the image for non-pack specific reasons */
+                               if (how != PF_REMOVE) {
+                                       BLI_strncpy(ima->name, newname, sizeof(imapf->filepath));
+                               }
+                               MEM_freeN(newname);
+                       }
+                       else {
+                               ret_value = RET_ERROR;
+                       }
+
+                       BLI_remlink(&ima->packedfiles, imapf);
+                       MEM_freeN(imapf);
+               }
+       }
+
+       if (ret_value == RET_OK) {
+               BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_RELOAD);
+       }
+
        return(ret_value);
 }
 
-int unpackImage(ReportList *reports, Image *ima, int how)
+int unpackLibraries(Main *bmain, ReportList *reports)
 {
-       char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX];
+       Library *lib;
        char *newname;
        int ret_value = RET_ERROR;
-       
-       if (ima != NULL && ima->name[0]) {
-               BLI_strncpy(localname, ima->name, sizeof(localname));
-               BLI_splitdirstring(localname, fi);
-               BLI_snprintf(localname, sizeof(localname), "//textures/%s", fi);
 
-               newname = unpackFile(reports, ima->name, localname, ima->packedfile, how);
-               if (newname != NULL) {
-                       ret_value = RET_OK;
-                       freePackedFile(ima->packedfile);
-                       ima->packedfile = NULL;
-                       BLI_strncpy(ima->name, newname, sizeof(ima->name));
-                       MEM_freeN(newname);
-                       BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD);
+       for (lib = bmain->library.first; lib; lib = lib->id.next) {
+               if (lib->packedfile && lib->name[0]) {
+
+                       newname = unpackFile(reports, BKE_main_blendfile_path(bmain), lib->filepath, lib->filepath, lib->packedfile, PF_WRITE_ORIGINAL);
+                       if (newname != NULL) {
+                               ret_value = RET_OK;
+
+                               printf("Unpacked .blend library: %s\n", newname);
+
+                               freePackedFile(lib->packedfile);
+                               lib->packedfile = NULL;
+
+                               MEM_freeN(newname);
+                       }
                }
        }
-       
+
        return(ret_value);
 }
 
+void packLibraries(Main *bmain, ReportList *reports)
+{
+       Library *lib;
+
+       /* test for relativenss */
+       for (lib = bmain->library.first; lib; lib = lib->id.next)
+               if (!BLI_path_is_rel(lib->name))
+                       break;
+
+       if (lib) {
+               BKE_reportf(reports, RPT_ERROR, "Cannot pack absolute file: '%s'", lib->name);
+               return;
+       }
+
+       for (lib = bmain->library.first; lib; lib = lib->id.next)
+               if (lib->packedfile == NULL)
+                       lib->packedfile = newPackedFile(reports, lib->name, BKE_main_blendfile_path(bmain));
+}
+
 void unpackAll(Main *bmain, ReportList *reports, int how)
 {
        Image *ima;
@@ -544,15 +653,83 @@ void unpackAll(Main *bmain, ReportList *reports, int how)
        bSound *sound;
 
        for (ima = bmain->image.first; ima; ima = ima->id.next)
-               if (ima->packedfile)
-                       unpackImage(reports, ima, how);
+               if (BKE_image_has_packedfile(ima))
+                       unpackImage(bmain, reports, ima, how);
 
        for (vf = bmain->vfont.first; vf; vf = vf->id.next)
                if (vf->packedfile)
-                       unpackVFont(reports, vf, how);
+                       unpackVFont(bmain, reports, vf, how);
 
        for (sound = bmain->sound.first; sound; sound = sound->id.next)
                if (sound->packedfile)
                        unpackSound(bmain, reports, sound, how);
 }
 
+/* ID should be not NULL, return 1 if there's a packed file */
+bool BKE_pack_check(ID *id)
+{
+       switch (GS(id->name)) {
+               case ID_IM:
+               {
+                       Image *ima = (Image *)id;
+                       return BKE_image_has_packedfile(ima);
+               }
+               case ID_VF:
+               {
+                       VFont *vf = (VFont *)id;
+                       return vf->packedfile != NULL;
+               }
+               case ID_SO:
+               {
+                       bSound *snd = (bSound *)id;
+                       return snd->packedfile != NULL;
+               }
+               case ID_LI:
+               {
+                       Library *li = (Library *)id;
+                       return li->packedfile != NULL;
+               }
+               default:
+                       break;
+       }
+       return false;
+}
+
+/* ID should be not NULL */
+void BKE_unpack_id(Main *bmain, ID *id, ReportList *reports, int how)
+{
+       switch (GS(id->name)) {
+               case ID_IM:
+               {
+                       Image *ima = (Image *)id;
+                       if (BKE_image_has_packedfile(ima)) {
+                               unpackImage(bmain, reports, ima, how);
+                       }
+                       break;
+               }
+               case ID_VF:
+               {
+                       VFont *vf = (VFont *)id;
+                       if (vf->packedfile) {
+                               unpackVFont(bmain, reports, vf, how);
+                       }
+                       break;
+               }
+               case ID_SO:
+               {
+                       bSound *snd = (bSound *)id;
+                       if (snd->packedfile) {
+                               unpackSound(bmain, reports, snd, how);
+                       }
+                       break;
+               }
+               case ID_LI:
+               {
+                       Library *li = (Library *)id;
+                       BKE_reportf(reports, RPT_ERROR, "Cannot unpack individual Library file, '%s'", li->name);
+                       break;
+               }
+               default:
+                       break;
+       }
+}