Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): none yet. 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include <stdio.h> 00034 #include <fcntl.h> 00035 #include <sys/stat.h> 00036 00037 #ifndef WIN32 00038 #include <unistd.h> 00039 #else 00040 #include <io.h> 00041 #endif 00042 #include <string.h> 00043 #include "MEM_guardedalloc.h" 00044 00045 #include "DNA_image_types.h" 00046 #include "DNA_sound_types.h" 00047 #include "DNA_vfont_types.h" 00048 #include "DNA_packedFile_types.h" 00049 00050 #include "BLI_blenlib.h" 00051 #include "BLI_utildefines.h" 00052 00053 #include "BKE_utildefines.h" 00054 #include "BKE_global.h" 00055 #include "BKE_main.h" 00056 #include "BKE_sound.h" 00057 #include "BKE_image.h" 00058 #include "BKE_packedFile.h" 00059 #include "BKE_report.h" 00060 00061 #ifdef _WIN32 00062 #define open _open 00063 #define close _close 00064 #define read _read 00065 #define write _write 00066 #endif 00067 00068 00069 int seekPackedFile(PackedFile *pf, int offset, int whence) 00070 { 00071 int oldseek = -1, seek = 0; 00072 00073 if (pf) { 00074 oldseek = pf->seek; 00075 switch(whence) { 00076 case SEEK_CUR: 00077 seek = oldseek + offset; 00078 break; 00079 case SEEK_END: 00080 seek = pf->size + offset; 00081 break; 00082 case SEEK_SET: 00083 seek = offset; 00084 break; 00085 default: 00086 oldseek = -1; 00087 } 00088 if (seek < 0) { 00089 seek = 0; 00090 } else if (seek > pf->size) { 00091 seek = pf->size; 00092 } 00093 pf->seek = seek; 00094 } 00095 00096 return(oldseek); 00097 } 00098 00099 void rewindPackedFile(PackedFile *pf) 00100 { 00101 seekPackedFile(pf, 0, SEEK_SET); 00102 } 00103 00104 int readPackedFile(PackedFile *pf, void *data, int size) 00105 { 00106 if ((pf != NULL) && (size >= 0) && (data != NULL)) { 00107 if (size + pf->seek > pf->size) { 00108 size = pf->size - pf->seek; 00109 } 00110 00111 if (size > 0) { 00112 memcpy(data, ((char *) pf->data) + pf->seek, size); 00113 } else { 00114 size = 0; 00115 } 00116 00117 pf->seek += size; 00118 } else { 00119 size = -1; 00120 } 00121 00122 return(size); 00123 } 00124 00125 int countPackedFiles(Main *bmain) 00126 { 00127 Image *ima; 00128 VFont *vf; 00129 bSound *sound; 00130 int count = 0; 00131 00132 // let's check if there are packed files... 00133 for(ima=bmain->image.first; ima; ima=ima->id.next) 00134 if(ima->packedfile) 00135 count++; 00136 00137 for(vf=bmain->vfont.first; vf; vf=vf->id.next) 00138 if(vf->packedfile) 00139 count++; 00140 00141 for(sound=bmain->sound.first; sound; sound=sound->id.next) 00142 if(sound->packedfile) 00143 count++; 00144 00145 return count; 00146 } 00147 00148 void freePackedFile(PackedFile *pf) 00149 { 00150 if(pf) { 00151 MEM_freeN(pf->data); 00152 MEM_freeN(pf); 00153 } 00154 else 00155 printf("freePackedFile: Trying to free a NULL pointer\n"); 00156 } 00157 00158 PackedFile *newPackedFileMemory(void *mem, int memlen) 00159 { 00160 PackedFile *pf = MEM_callocN(sizeof(*pf), "PackedFile"); 00161 pf->data = mem; 00162 pf->size = memlen; 00163 00164 return pf; 00165 } 00166 00167 PackedFile *newPackedFile(ReportList *reports, const char *filename, const char *basepath) 00168 { 00169 PackedFile *pf = NULL; 00170 int file, filelen; 00171 char name[FILE_MAX]; 00172 void *data; 00173 00174 /* render result has no filename and can be ignored 00175 * any other files with no name can be ignored too */ 00176 if(filename[0]=='\0') 00177 return NULL; 00178 00179 //XXX waitcursor(1); 00180 00181 // convert relative filenames to absolute filenames 00182 00183 BLI_strncpy(name, filename, sizeof(name)); 00184 BLI_path_abs(name, basepath); 00185 00186 // open the file 00187 // and create a PackedFile structure 00188 00189 file= open(name, O_BINARY|O_RDONLY); 00190 if (file <= 0) { 00191 BKE_reportf(reports, RPT_ERROR, "Unable to pack file, source path not found: \"%s\"", name); 00192 } else { 00193 filelen = BLI_file_descriptor_size(file); 00194 00195 if (filelen == 0) { 00196 // MEM_mallocN complains about MEM_mallocN(0, "bla"); 00197 // we don't care.... 00198 data = MEM_mallocN(1, "packFile"); 00199 } else { 00200 data = MEM_mallocN(filelen, "packFile"); 00201 } 00202 if (read(file, data, filelen) == filelen) { 00203 pf = newPackedFileMemory(data, filelen); 00204 } 00205 00206 close(file); 00207 } 00208 00209 //XXX waitcursor(0); 00210 00211 return (pf); 00212 } 00213 00214 void packAll(Main *bmain, ReportList *reports) 00215 { 00216 Image *ima; 00217 VFont *vf; 00218 bSound *sound; 00219 00220 for(ima=bmain->image.first; ima; ima=ima->id.next) { 00221 if(ima->packedfile == NULL && ima->id.lib==NULL) { 00222 if(ima->source==IMA_SRC_FILE) { 00223 ima->packedfile = newPackedFile(reports, ima->name, ID_BLEND_PATH(bmain, &ima->id)); 00224 } 00225 else if(ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { 00226 BKE_reportf(reports, RPT_WARNING, "Image '%s' skipped, movies and image sequences not supported.", ima->id.name+2); 00227 } 00228 } 00229 } 00230 00231 for(vf=bmain->vfont.first; vf; vf=vf->id.next) 00232 if(vf->packedfile == NULL && vf->id.lib==NULL && strcmp(vf->name, FO_BUILTIN_NAME) != 0) 00233 vf->packedfile = newPackedFile(reports, vf->name, bmain->name); 00234 00235 for(sound=bmain->sound.first; sound; sound=sound->id.next) 00236 if(sound->packedfile == NULL && sound->id.lib==NULL) 00237 sound->packedfile = newPackedFile(reports, sound->name, bmain->name); 00238 } 00239 00240 00241 #if 0 00242 00243 // attempt to create a function that generates an unique filename 00244 // this will work when all funtions in fileops.c understand relative filenames... 00245 00246 static char *find_new_name(char *name) 00247 { 00248 char tempname[FILE_MAX]; 00249 char *newname; 00250 size_t len; 00251 00252 if (fop_exists(name)) { 00253 for (number = 1; number <= 999; number++) { 00254 BLI_snprintf(tempname, sizeof(tempname), "%s.%03d", name, number); 00255 if (! fop_exists(tempname)) { 00256 break; 00257 } 00258 } 00259 } 00260 len= strlen(tempname) + 1; 00261 newname = MEM_mallocN(len, "find_new_name"); 00262 memcpy(newname, tempname, len * sizeof(char)); 00263 return newname; 00264 } 00265 #endif 00266 00267 int writePackedFile(ReportList *reports, const char *filename, PackedFile *pf, int guimode) 00268 { 00269 int file, number, remove_tmp = FALSE; 00270 int ret_value = RET_OK; 00271 char name[FILE_MAX]; 00272 char tempname[FILE_MAX]; 00273 /* void *data; */ 00274 00275 if (guimode) {} //XXX waitcursor(1); 00276 00277 BLI_strncpy(name, filename, sizeof(name)); 00278 BLI_path_abs(name, G.main->name); 00279 00280 if (BLI_exists(name)) { 00281 for (number = 1; number <= 999; number++) { 00282 BLI_snprintf(tempname, sizeof(tempname), "%s.%03d_", name, number); 00283 if (! BLI_exists(tempname)) { 00284 if (BLI_copy(name, tempname) == RET_OK) { 00285 remove_tmp = TRUE; 00286 } 00287 break; 00288 } 00289 } 00290 } 00291 00292 // make sure the path to the file exists... 00293 BLI_make_existing_file(name); 00294 00295 file = open(name, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666); 00296 if (file >= 0) { 00297 if (write(file, pf->data, pf->size) != pf->size) { 00298 BKE_reportf(reports, RPT_ERROR, "Error writing file: %s", name); 00299 ret_value = RET_ERROR; 00300 } 00301 close(file); 00302 } else { 00303 BKE_reportf(reports, RPT_ERROR, "Error creating file: %s", name); 00304 ret_value = RET_ERROR; 00305 } 00306 00307 if (remove_tmp) { 00308 if (ret_value == RET_ERROR) { 00309 if (BLI_rename(tempname, name) != 0) { 00310 BKE_reportf(reports, RPT_ERROR, "Error restoring tempfile. Check files: '%s' '%s'", tempname, name); 00311 } 00312 } else { 00313 if (BLI_delete(tempname, 0, 0) != 0) { 00314 BKE_reportf(reports, RPT_ERROR, "Error deleting '%s' (ignored)", tempname); 00315 } 00316 } 00317 } 00318 00319 if(guimode) {} //XXX waitcursor(0); 00320 00321 return (ret_value); 00322 } 00323 00324 /* 00325 00326 This function compares a packed file to a 'real' file. 00327 It returns an integer indicating if: 00328 00329 PF_EQUAL - the packed file and original file are identical 00330 PF_DIFFERENT - the packed file and original file differ 00331 PF_NOFILE - the original file doens't exist 00332 00333 */ 00334 00335 int checkPackedFile(const char *filename, PackedFile *pf) 00336 { 00337 struct stat st; 00338 int ret_val, i, len, file; 00339 char buf[4096]; 00340 char name[FILE_MAX]; 00341 00342 BLI_strncpy(name, filename, sizeof(name)); 00343 BLI_path_abs(name, G.main->name); 00344 00345 if (stat(name, &st)) { 00346 ret_val = PF_NOFILE; 00347 } else if (st.st_size != pf->size) { 00348 ret_val = PF_DIFFERS; 00349 } else { 00350 // we'll have to compare the two... 00351 00352 file = open(name, O_BINARY | O_RDONLY); 00353 if (file < 0) { 00354 ret_val = PF_NOFILE; 00355 } else { 00356 ret_val = PF_EQUAL; 00357 00358 for (i = 0; i < pf->size; i += sizeof(buf)) { 00359 len = pf->size - i; 00360 if (len > sizeof(buf)) { 00361 len = sizeof(buf); 00362 } 00363 00364 if (read(file, buf, len) != len) { 00365 // read error ... 00366 ret_val = PF_DIFFERS; 00367 break; 00368 } else { 00369 if (memcmp(buf, ((char *)pf->data) + i, len)) { 00370 ret_val = PF_DIFFERS; 00371 break; 00372 } 00373 } 00374 } 00375 00376 close(file); 00377 } 00378 } 00379 00380 return(ret_val); 00381 } 00382 00383 /* 00384 00385 unpackFile() looks at the existing files (abs_name, local_name) and a packed file. 00386 00387 It returns a char *to the existing file name / new file name or NULL when 00388 there was an error or when the user desides to cancel the operation. 00389 00390 */ 00391 00392 char *unpackFile(ReportList *reports, const char *abs_name, const char *local_name, PackedFile *pf, int how) 00393 { 00394 char *newname = NULL; 00395 const char *temp = NULL; 00396 00397 // char newabs[FILE_MAX]; 00398 // char newlocal[FILE_MAX]; 00399 00400 if (pf != NULL) { 00401 switch (how) { 00402 case -1: 00403 case PF_KEEP: 00404 break; 00405 case PF_REMOVE: 00406 temp= abs_name; 00407 break; 00408 case PF_USE_LOCAL: 00409 // if file exists use it 00410 if (BLI_exists(local_name)) { 00411 temp = local_name; 00412 break; 00413 } 00414 // else fall through and create it 00415 case PF_WRITE_LOCAL: 00416 if (writePackedFile(reports, local_name, pf, 1) == RET_OK) { 00417 temp = local_name; 00418 } 00419 break; 00420 case PF_USE_ORIGINAL: 00421 // if file exists use it 00422 if (BLI_exists(abs_name)) { 00423 temp = abs_name; 00424 break; 00425 } 00426 // else fall through and create it 00427 case PF_WRITE_ORIGINAL: 00428 if (writePackedFile(reports, abs_name, pf, 1) == RET_OK) { 00429 temp = abs_name; 00430 } 00431 break; 00432 default: 00433 printf("unpackFile: unknown return_value %d\n", how); 00434 break; 00435 } 00436 00437 if (temp) { 00438 newname= BLI_strdup(temp); 00439 } 00440 } 00441 00442 return newname; 00443 } 00444 00445 00446 int unpackVFont(ReportList *reports, VFont *vfont, int how) 00447 { 00448 char localname[FILE_MAX], fi[FILE_MAXFILE]; 00449 char *newname; 00450 int ret_value = RET_ERROR; 00451 00452 if (vfont != NULL) { 00453 BLI_strncpy(localname, vfont->name, sizeof(localname)); 00454 BLI_splitdirstring(localname, fi); 00455 00456 BLI_snprintf(localname, sizeof(localname), "//fonts/%s", fi); 00457 00458 newname = unpackFile(reports, vfont->name, localname, vfont->packedfile, how); 00459 if (newname != NULL) { 00460 ret_value = RET_OK; 00461 freePackedFile(vfont->packedfile); 00462 vfont->packedfile = NULL; 00463 BLI_strncpy(vfont->name, newname, sizeof(vfont->name)); 00464 MEM_freeN(newname); 00465 } 00466 } 00467 00468 return (ret_value); 00469 } 00470 00471 int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how) 00472 { 00473 char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; 00474 char *newname; 00475 int ret_value = RET_ERROR; 00476 00477 if (sound != NULL) { 00478 BLI_strncpy(localname, sound->name, sizeof(localname)); 00479 BLI_splitdirstring(localname, fi); 00480 BLI_snprintf(localname, sizeof(localname), "//sounds/%s", fi); 00481 00482 newname = unpackFile(reports, sound->name, localname, sound->packedfile, how); 00483 if (newname != NULL) { 00484 BLI_strncpy(sound->name, newname, sizeof(sound->name)); 00485 MEM_freeN(newname); 00486 00487 freePackedFile(sound->packedfile); 00488 sound->packedfile = NULL; 00489 00490 sound_load(bmain, sound); 00491 00492 ret_value = RET_OK; 00493 } 00494 } 00495 00496 return(ret_value); 00497 } 00498 00499 int unpackImage(ReportList *reports, Image *ima, int how) 00500 { 00501 char localname[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; 00502 char *newname; 00503 int ret_value = RET_ERROR; 00504 00505 if (ima != NULL) { 00506 BLI_strncpy(localname, ima->name, sizeof(localname)); 00507 BLI_splitdirstring(localname, fi); 00508 BLI_snprintf(localname, sizeof(localname), "//textures/%s", fi); 00509 00510 newname = unpackFile(reports, ima->name, localname, ima->packedfile, how); 00511 if (newname != NULL) { 00512 ret_value = RET_OK; 00513 freePackedFile(ima->packedfile); 00514 ima->packedfile = NULL; 00515 BLI_strncpy(ima->name, newname, sizeof(ima->name)); 00516 MEM_freeN(newname); 00517 BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); 00518 } 00519 } 00520 00521 return(ret_value); 00522 } 00523 00524 void unpackAll(Main *bmain, ReportList *reports, int how) 00525 { 00526 Image *ima; 00527 VFont *vf; 00528 bSound *sound; 00529 00530 for(ima=bmain->image.first; ima; ima=ima->id.next) 00531 if(ima->packedfile) 00532 unpackImage(reports, ima, how); 00533 00534 for(vf=bmain->vfont.first; vf; vf=vf->id.next) 00535 if(vf->packedfile) 00536 unpackVFont(reports, vf, how); 00537 00538 for(sound=bmain->sound.first; sound; sound=sound->id.next) 00539 if(sound->packedfile) 00540 unpackSound(bmain, reports, sound, how); 00541 } 00542