|
WizardsToolkit
1.0.7
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % BBBB L OOO BBBB % 00007 % B B L O O B B % 00008 % BBBB L O O BBBB % 00009 % B B L O O B B % 00010 % BBBB LLLLL OOO BBBB % 00011 % % 00012 % % 00013 % Wizard's Toolkit Binary Large OBjectS Methods % 00014 % % 00015 % % 00016 % Software Design % 00017 % John Cristy % 00018 % March 2003 % 00019 % % 00020 % % 00021 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization % 00022 % dedicated to making software imaging solutions freely available. % 00023 % % 00024 % You may not use this file except in compliance with the License. You may % 00025 % obtain a copy of the License at % 00026 % % 00027 % http://www.wizards-toolkit.org/script/license.php % 00028 % % 00029 % Unless required by applicable law or agreed to in writing, software % 00030 % distributed under the License is distributed on an "AS IS" BASIS, % 00031 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00032 % See the License for the specific language governing permissions and % 00033 % limitations under the License. % 00034 % % 00035 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00036 % 00037 % 00038 % 00039 */ 00040 00041 /* 00042 Include declarations. 00043 */ 00044 #include "wizard/studio.h" 00045 #include "wizard/blob.h" 00046 #include "wizard/blob-private.h" 00047 #include "wizard/cipher.h" 00048 #include "wizard/exception.h" 00049 #include "wizard/exception-private.h" 00050 #include "wizard/memory_.h" 00051 #include "wizard/semaphore.h" 00052 #include "wizard/string-private.h" 00053 #include "wizard/utility.h" 00054 #include "wizard/utility-private.h" 00055 #include "blob.h" 00056 #if defined(WIZARDSTOOLKIT_HAVE_MMAP_FILEIO) && !defined(WIZARDSTOOLKIT_WINDOWS_SUPPORT) 00057 # include <sys/mman.h> 00058 #endif 00059 #include "bzlib.h" 00060 #include "zlib.h" 00061 00062 /* 00063 Define declarations. 00064 */ 00065 #define WizardMaxBlobExtent 65541 00066 # if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) 00067 # define MAP_ANONYMOUS MAP_ANON 00068 # endif 00069 #if !defined(MAP_FAILED) 00070 #define MAP_FAILED ((void *) -1) 00071 #endif 00072 #if !defined(MS_SYNC) 00073 #define MS_SYNC 0x04 00074 #endif 00075 00076 /* 00077 Typedef declarations. 00078 */ 00079 typedef enum 00080 { 00081 UndefinedStream, 00082 FileStream, 00083 StandardStream, 00084 PipeStream, 00085 ZipStream, 00086 BZipStream, 00087 BlobStream 00088 } StreamType; 00089 00090 struct _BlobInfo 00091 { 00092 char 00093 filename[MaxTextExtent]; 00094 00095 size_t 00096 length, 00097 extent, 00098 quantum; 00099 00100 WizardBooleanType 00101 mapped, 00102 eof; 00103 00104 WizardOffsetType 00105 offset; 00106 00107 WizardSizeType 00108 size; 00109 00110 WizardBooleanType 00111 exempt, 00112 status, 00113 temporary; 00114 00115 StreamType 00116 type; 00117 00118 FILE 00119 *file; 00120 00121 struct stat 00122 properties; 00123 00124 unsigned char 00125 *data; 00126 00127 WizardBooleanType 00128 debug; 00129 00130 SemaphoreInfo 00131 *semaphore; 00132 00133 ssize_t 00134 reference_count; 00135 00136 size_t 00137 signature; 00138 }; 00139 00140 /* 00141 Forward declarations. 00142 */ 00143 static unsigned char 00144 *DetachBlob(BlobInfo *); 00145 00146 /* 00147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00148 % % 00149 % % 00150 % % 00151 + A t t a c h B l o b % 00152 % % 00153 % % 00154 % % 00155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00156 % 00157 % AttachBlob() attaches a blob to the BlobInfo structure. 00158 % 00159 % The format of the AttachBlob method is: 00160 % 00161 % void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length) 00162 % 00163 % A description of each parameter follows: 00164 % 00165 % o blob_info: the blob info. 00166 % 00167 % o blob: the character stream to attach. 00168 % 00169 % o length: the length in bytes of the blob. 00170 % 00171 */ 00172 static void AttachBlob(BlobInfo *blob_info,const void *blob,const size_t length) 00173 { 00174 assert(blob_info != (BlobInfo *) NULL); 00175 if (blob_info->debug != WizardFalse) 00176 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 00177 blob_info->length=length; 00178 blob_info->extent=length; 00179 blob_info->quantum=(size_t) WizardMaxBlobExtent; 00180 blob_info->offset=0; 00181 blob_info->type=BlobStream; 00182 blob_info->file=(FILE *) NULL; 00183 blob_info->data=(unsigned char *) blob; 00184 blob_info->mapped=WizardFalse; 00185 } 00186 00187 /* 00188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00189 % % 00190 % % 00191 % % 00192 + C l o s e B l o b % 00193 % % 00194 % % 00195 % % 00196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00197 % 00198 % CloseBlob() closes a stream associated with the blob_info. 00199 % 00200 % The format of the CloseBlob method is: 00201 % 00202 % WizardBooleanType CloseBlob(BlobInfo *blob_info) 00203 % 00204 % A description of each parameter follows: 00205 % 00206 % o blob_info: the blob info. 00207 % 00208 */ 00209 WizardExport WizardBooleanType CloseBlob(BlobInfo *blob_info) 00210 { 00211 int 00212 status; 00213 00214 /* 00215 Close blob_info file. 00216 */ 00217 assert(blob_info != (BlobInfo *) NULL); 00218 assert(blob_info->signature == WizardSignature); 00219 if (blob_info->debug != WizardFalse) 00220 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s", 00221 blob_info->filename); 00222 if (blob_info->type == UndefinedStream) 00223 return(WizardTrue); 00224 (void) SyncBlob(blob_info); 00225 blob_info->size=GetBlobSize(blob_info); 00226 blob_info->eof=WizardFalse; 00227 if (blob_info->exempt != WizardFalse) 00228 { 00229 blob_info->type=UndefinedStream; 00230 return(WizardTrue); 00231 } 00232 status=0; 00233 switch (blob_info->type) 00234 { 00235 case UndefinedStream: 00236 break; 00237 case FileStream: 00238 case StandardStream: 00239 case PipeStream: 00240 { 00241 status=ferror(blob_info->file); 00242 break; 00243 } 00244 case ZipStream: 00245 { 00246 #if defined(WIZARDSTOOLKIT_ZLIB_DELEGATE) 00247 (void) gzerror(blob_info->file,&status); 00248 #endif 00249 break; 00250 } 00251 case BZipStream: 00252 { 00253 #if defined(WIZARDSTOOLKIT_BZLIB_DELEGATE) 00254 (void) BZ2_bzerror((BZFILE *) blob_info->file,&status); 00255 #endif 00256 break; 00257 } 00258 case BlobStream: 00259 break; 00260 } 00261 blob_info->status=status < 0 ? WizardTrue : WizardFalse; 00262 switch (blob_info->type) 00263 { 00264 case UndefinedStream: 00265 break; 00266 case FileStream: 00267 case StandardStream: 00268 { 00269 status=fclose(blob_info->file); 00270 break; 00271 } 00272 case PipeStream: 00273 { 00274 #if defined(WIZARDSTOOLKIT_HAVE_POPEN) 00275 status=pclose(blob_info->file); 00276 #endif 00277 break; 00278 } 00279 case ZipStream: 00280 { 00281 #if defined(WIZARDSTOOLKIT_ZLIB_DELEGATE) 00282 status=gzclose(blob_info->file); 00283 #endif 00284 break; 00285 } 00286 case BZipStream: 00287 { 00288 #if defined(WIZARDSTOOLKIT_BZLIB_DELEGATE) 00289 BZ2_bzclose((BZFILE *) blob_info->file); 00290 #endif 00291 break; 00292 } 00293 case BlobStream: 00294 break; 00295 } 00296 (void) DetachBlob(blob_info); 00297 blob_info->status=status < 0 ? WizardTrue : WizardFalse; 00298 return(blob_info->status); 00299 } 00300 00301 /* 00302 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00303 % % 00304 % % 00305 % % 00306 + D e s t r o y B l o b % 00307 % % 00308 % % 00309 % % 00310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00311 % 00312 % DestroyBlob() deallocates memory associated with a blob. 00313 % 00314 % The format of the DestroyBlob method is: 00315 % 00316 % BlobInfo *DestroyBlob(BlobInfo *blob_info) 00317 % 00318 % A description of each parameter follows: 00319 % 00320 % o blob_info: the blob info. 00321 % 00322 */ 00323 WizardExport BlobInfo *DestroyBlob(BlobInfo *blob_info) 00324 { 00325 WizardBooleanType 00326 destroy; 00327 00328 assert(blob_info != (BlobInfo *) NULL); 00329 assert(blob_info->signature == WizardSignature); 00330 if (blob_info->debug != WizardFalse) 00331 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s", 00332 blob_info->filename); 00333 destroy=WizardFalse; 00334 LockSemaphoreInfo(blob_info->semaphore); 00335 blob_info->reference_count--; 00336 if (blob_info->reference_count == 0) 00337 destroy=WizardTrue; 00338 UnlockSemaphoreInfo(blob_info->semaphore); 00339 if (destroy == WizardFalse) 00340 return(blob_info); 00341 (void) CloseBlob(blob_info); 00342 if (blob_info->mapped != WizardFalse) 00343 (void) UnmapBlob(blob_info->data,blob_info->length); 00344 if (blob_info->semaphore != (SemaphoreInfo *) NULL) 00345 DestroySemaphoreInfo(&blob_info->semaphore); 00346 blob_info->signature=(~WizardSignature); 00347 blob_info=(BlobInfo *) RelinquishWizardMemory(blob_info); 00348 return(blob_info); 00349 } 00350 00351 /* 00352 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00353 % % 00354 % % 00355 % % 00356 + D e t a c h B l o b % 00357 % % 00358 % % 00359 % % 00360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00361 % 00362 % DetachBlob() detaches a blob from the BlobInfo structure. 00363 % 00364 % The format of the DetachBlob method is: 00365 % 00366 % unsigned char *DetachBlob(BlobInfo *blob_info) 00367 % 00368 % A description of each parameter follows: 00369 % 00370 % o blob_info: the blob info. 00371 % 00372 */ 00373 static unsigned char *DetachBlob(BlobInfo *blob_info) 00374 { 00375 unsigned char 00376 *data; 00377 00378 assert(blob_info != (BlobInfo *) NULL); 00379 if (blob_info->debug != WizardFalse) 00380 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 00381 if (blob_info->mapped != WizardFalse) 00382 (void) UnmapBlob(blob_info->data,blob_info->length); 00383 blob_info->mapped=WizardFalse; 00384 blob_info->length=0; 00385 blob_info->offset=0; 00386 blob_info->eof=WizardFalse; 00387 blob_info->exempt=WizardFalse; 00388 blob_info->type=UndefinedStream; 00389 blob_info->file=(FILE *) NULL; 00390 data=blob_info->data; 00391 blob_info->data=(unsigned char *) NULL; 00392 return(data); 00393 } 00394 00395 /* 00396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00397 % % 00398 % % 00399 % % 00400 + E O F B l o b % 00401 % % 00402 % % 00403 % % 00404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00405 % 00406 % EOFBlob() returns a non-zero value when EOF has been detected reading from 00407 % a blob or file. 00408 % 00409 % The format of the EOFBlob method is: 00410 % 00411 % int EOFBlob(BlobInfo *blob_info) 00412 % 00413 % A description of each parameter follows: 00414 % 00415 % o blob_info: the blob info. 00416 % 00417 */ 00418 WizardExport int EOFBlob(BlobInfo *blob_info) 00419 { 00420 assert(blob_info != (BlobInfo *) NULL); 00421 assert(blob_info->signature == WizardSignature); 00422 if (blob_info->debug != WizardFalse) 00423 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"..."); 00424 assert(blob_info->type != UndefinedStream); 00425 switch (blob_info->type) 00426 { 00427 case UndefinedStream: 00428 break; 00429 case FileStream: 00430 case StandardStream: 00431 case PipeStream: 00432 { 00433 blob_info->eof=feof(blob_info->file) != 0 ? WizardTrue : WizardFalse; 00434 break; 00435 } 00436 case ZipStream: 00437 { 00438 blob_info->eof=WizardFalse; 00439 break; 00440 } 00441 case BZipStream: 00442 { 00443 #if defined(WIZARDSTOOLKIT_BZLIB_DELEGATE) 00444 int 00445 status; 00446 00447 status=0; 00448 (void) BZ2_bzerror((BZFILE *) blob_info->file,&status); 00449 blob_info->eof=status == BZ_UNEXPECTED_EOF ? WizardTrue : WizardFalse; 00450 #endif 00451 break; 00452 } 00453 case BlobStream: 00454 break; 00455 } 00456 return((int) blob_info->eof); 00457 } 00458 00459 /* 00460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00461 % % 00462 % % 00463 % % 00464 % F i l e T o B l o b % 00465 % % 00466 % % 00467 % % 00468 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00469 % 00470 % FileToBlob() returns the contents of a file as a blob. It returns the 00471 % file as a blob and its length. If an error occurs, NULL is returned. 00472 % 00473 % The format of the FileToBlob method is: 00474 % 00475 % void *FileToBlob(const char *filename,const size_t extent,size_t *length, 00476 % ExceptionInfo *exception) 00477 % 00478 % A description of each parameter follows: 00479 % 00480 % o blob: FileToBlob() returns the contents of a file as a blob. If 00481 % an error occurs NULL is returned. 00482 % 00483 % o filename: The filename. 00484 % 00485 % o extent: The maximum length of the blob. 00486 % 00487 % o length: On return, it reflects the actual length of the blob. 00488 % 00489 % o exception: Return any errors or warnings in this structure. 00490 % 00491 */ 00492 WizardExport unsigned char *FileToBlob(const char *filename,const size_t extent, 00493 size_t *length,ExceptionInfo *exception) 00494 { 00495 int 00496 file; 00497 00498 register size_t 00499 i; 00500 00501 ssize_t 00502 count; 00503 00504 unsigned char 00505 *blob; 00506 00507 WizardOffsetType 00508 offset; 00509 00510 void 00511 *map; 00512 00513 assert(filename != (const char *) NULL); 00514 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",filename); 00515 assert(exception != (ExceptionInfo *) NULL); 00516 *length=0; 00517 file=fileno(stdin); 00518 if (strcmp(filename,"-") != 0) 00519 file=open_utf8(filename,O_RDONLY | O_BINARY,0); 00520 if (file == -1) 00521 { 00522 (void) ThrowWizardException(exception,GetWizardModule(),BlobError, 00523 "unable to open file `%s': %s",filename,strerror(errno)); 00524 return((unsigned char *) NULL); 00525 } 00526 offset=lseek(file,0,SEEK_END); 00527 count=0; 00528 if ((offset < 0) || (offset != (WizardOffsetType) ((ssize_t) offset))) 00529 { 00530 size_t 00531 quantum; 00532 00533 struct stat 00534 file_info; 00535 00536 /* 00537 Stream is not seekable. 00538 */ 00539 quantum=(size_t) WizardMaxBufferExtent; 00540 if ((fstat(file,&file_info) == 0) && (file_info.st_size != 0)) 00541 quantum=Min((size_t) file_info.st_size,WizardMaxBufferExtent); 00542 blob=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*blob)); 00543 for (i=0; blob != (unsigned char *) NULL; i+=count) 00544 { 00545 count=read(file,blob+i,quantum); 00546 if (count <= 0) 00547 { 00548 count=0; 00549 if (errno != EINTR) 00550 break; 00551 } 00552 if (~(1UL*i) < (quantum+1)) 00553 { 00554 blob=(unsigned char *) RelinquishWizardMemory(blob); 00555 break; 00556 } 00557 blob=(unsigned char *) ResizeQuantumMemory(blob,i+quantum+1, 00558 sizeof(*blob)); 00559 if ((size_t) (i+count) >= extent) 00560 break; 00561 } 00562 if (close(file) == -1) 00563 (void) ThrowWizardException(exception,GetWizardModule(),BlobError, 00564 "unable to close file `%s': %s",filename,strerror(errno)); 00565 if (blob == (unsigned char *) NULL) 00566 { 00567 (void) ThrowWizardException(exception,GetWizardModule(),ResourceError, 00568 "memory allocation failed: `%s'",filename); 00569 return((unsigned char *) NULL); 00570 } 00571 *length=Min(i+count,extent); 00572 blob[*length]='\0'; 00573 return(blob); 00574 } 00575 *length=Min((size_t) offset,extent); 00576 blob=(unsigned char *) NULL; 00577 if (~(*length) >= (MaxCipherBlocksize-1)) 00578 blob=(unsigned char *) AcquireQuantumMemory(*length+MaxCipherBlocksize, 00579 sizeof(*blob)); 00580 if (blob == (unsigned char *) NULL) 00581 { 00582 if (close(file) == -1) 00583 { 00584 (void) ThrowWizardException(exception,GetWizardModule(),BlobError, 00585 "unable to close file `%s': %s",filename,strerror(errno)); 00586 return((unsigned char *) NULL); 00587 } 00588 (void) ThrowWizardException(exception,GetWizardModule(),BlobError, 00589 "memory allocation failed `%s'",strerror(errno)); 00590 return((unsigned char *) NULL); 00591 } 00592 map=MapBlob(file,ReadMode,0,*length); 00593 if (map != (void *) NULL) 00594 { 00595 (void) memcpy(blob,map,*length); 00596 if (UnmapBlob(map,*length) == WizardFalse) 00597 (void) ThrowWizardException(exception,GetWizardModule(),BlobError, 00598 "unable to unmap blob `%s': %s",filename,strerror(errno)); 00599 } 00600 else 00601 { 00602 register size_t 00603 i; 00604 00605 ssize_t 00606 count; 00607 00608 if (lseek(file,0,SEEK_SET) < 0) 00609 (void) ThrowWizardException(exception,GetWizardModule(),BlobError, 00610 "unable to seek blob `%s': %s",filename,strerror(errno)); 00611 for (i=0; i < *length; i+=count) 00612 { 00613 count=read(file,blob+i,Min(*length-i,(size_t) SSIZE_MAX)); 00614 if (count <= 0) 00615 { 00616 count=0; 00617 if (errno != EINTR) 00618 break; 00619 } 00620 } 00621 if (i < *length) 00622 { 00623 if (close(file) == -1) 00624 (void) ThrowWizardException(exception,GetWizardModule(),BlobError, 00625 "unable to close file `%s': %s",filename,strerror(errno)); 00626 blob=(unsigned char *) RelinquishWizardMemory(blob); 00627 (void) ThrowWizardException(exception,GetWizardModule(),BlobError, 00628 "unable to read file `%s'",filename); 00629 return((unsigned char *) NULL); 00630 } 00631 } 00632 if (close(file) == -1) 00633 (void) ThrowWizardException(exception,GetWizardModule(),BlobError, 00634 "unable to close file `%s': %s",filename,strerror(errno)); 00635 blob[*length]=(unsigned char) '\0'; 00636 return(blob); 00637 } 00638 00639 /* 00640 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00641 % % 00642 % % 00643 % % 00644 + G e t B l o b F i l e n a m e % 00645 % % 00646 % % 00647 % % 00648 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00649 % 00650 % GetBlobFilename() returns the blob filename. 00651 % 00652 % The format of the GetBlobFilename method is: 00653 % 00654 % const char *GetBlobFilename(const BlobInfo *blob_info) 00655 % 00656 % A description of each parameter follows: 00657 % 00658 % o blob_info: the blob info info. 00659 % 00660 */ 00661 WizardExport const char *GetBlobFilename(const BlobInfo *blob_info) 00662 { 00663 assert(blob_info != (BlobInfo *) NULL); 00664 if (blob_info->debug != WizardFalse) 00665 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s", 00666 blob_info->filename); 00667 return(blob_info->filename); 00668 } 00669 00670 /* 00671 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00672 % % 00673 % % 00674 % % 00675 + G e t B l o b I n f o % 00676 % % 00677 % % 00678 % % 00679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00680 % 00681 % GetBlobInfo() initializes the BlobInfo structure. 00682 % 00683 % The format of the GetBlobInfo method is: 00684 % 00685 % void GetBlobInfo(BlobInfo *blob_info) 00686 % 00687 % A description of each parameter follows: 00688 % 00689 % o blob_info: Specifies a pointer to a BlobInfo structure. 00690 % 00691 */ 00692 WizardExport void GetBlobInfo(BlobInfo *blob_info) 00693 { 00694 assert(blob_info != (BlobInfo *) NULL); 00695 (void) ResetWizardMemory(blob_info,0,sizeof(*blob_info)); 00696 blob_info->type=UndefinedStream; 00697 blob_info->quantum=(size_t) WizardMaxBlobExtent; 00698 blob_info->debug=IsEventLogging(); 00699 blob_info->reference_count=1; 00700 blob_info->semaphore=AllocateSemaphoreInfo(); 00701 blob_info->signature=WizardSignature; 00702 } 00703 00704 /* 00705 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00706 % % 00707 % % 00708 % % 00709 + G e t B l o b S i z e % 00710 % % 00711 % % 00712 % % 00713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00714 % 00715 % GetBlobSize() returns the current length of the blob; zero is returned if 00716 % the size cannot be determined. 00717 % 00718 % The format of the GetBlobSize method is: 00719 % 00720 % WizardSizeType GetBlobSize(BlobInfo *blob_info) 00721 % 00722 % A description of each parameter follows: 00723 % 00724 % o blob_info: the blob info. 00725 % 00726 */ 00727 WizardExport WizardSizeType GetBlobSize(BlobInfo *blob_info) 00728 { 00729 WizardSizeType 00730 length; 00731 00732 assert(blob_info != (BlobInfo *) NULL); 00733 if (blob_info->debug != WizardFalse) 00734 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s", 00735 blob_info->filename); 00736 length=0; 00737 switch (blob_info->type) 00738 { 00739 case UndefinedStream: 00740 { 00741 length=blob_info->size; 00742 break; 00743 } 00744 case FileStream: 00745 { 00746 if (fstat(fileno(blob_info->file),&blob_info->properties) == 0) 00747 length=(WizardSizeType) blob_info->properties.st_size; 00748 break; 00749 } 00750 case StandardStream: 00751 case PipeStream: 00752 { 00753 length=blob_info->size; 00754 break; 00755 } 00756 case ZipStream: 00757 { 00758 #if defined(WIZARDSTOOLKIT_ZLIB_DELEGATE) 00759 if (fstat(fileno(blob_info->file),&blob_info->properties) == 0) 00760 length=(WizardSizeType) blob_info->properties.st_size; 00761 #endif 00762 break; 00763 } 00764 case BZipStream: 00765 { 00766 #if defined(WIZARDSTOOLKIT_BZLIB_DELEGATE) 00767 if (fstat(fileno(blob_info->file),&blob_info->properties) == 0) 00768 length=(WizardSizeType) blob_info->properties.st_size; 00769 #endif 00770 break; 00771 } 00772 case BlobStream: 00773 { 00774 length=(WizardSizeType) blob_info->length; 00775 break; 00776 } 00777 } 00778 return(length); 00779 } 00780 00781 /* 00782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00783 % % 00784 % % 00785 % % 00786 % G e t B l o b P r o p e r t i e s % 00787 % % 00788 % % 00789 % % 00790 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00791 % 00792 % GetBlobProperties() returns information about a blob. 00793 % 00794 % The format of the GetBlobProperties method is: 00795 % 00796 % const struct stat *GetBlobProperties(const BlobInfo *blob_info) 00797 % 00798 % A description of each parameter follows: 00799 % 00800 % o blob_info: the blob info. 00801 % 00802 */ 00803 WizardExport const struct stat *GetBlobProperties(const BlobInfo *blob_info) 00804 { 00805 assert(blob_info != (BlobInfo *) NULL); 00806 if (blob_info->debug != WizardFalse) 00807 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s", 00808 blob_info->filename); 00809 return(&blob_info->properties); 00810 } 00811 00812 /* 00813 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00814 % % 00815 % % 00816 % % 00817 + M a p B l o b % 00818 % % 00819 % % 00820 % % 00821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00822 % 00823 % MapBlob() creates a mapping from a file to a binary large object. 00824 % 00825 % The format of the MapBlob method is: 00826 % 00827 % void *MapBlob(int file,const MapMode mode,const WizardOffsetType offset, 00828 % const size_t length) 00829 % 00830 % A description of each parameter follows: 00831 % 00832 % o file: map this file descriptor. 00833 % 00834 % o mode: ReadMode, WriteMode, or IOMode. 00835 % 00836 % o offset: starting at this offset within the file. 00837 % 00838 % o length: the length of the mapping is returned in this pointer. 00839 % 00840 */ 00841 WizardExport void *MapBlob(int file,const MapMode mode, 00842 const WizardOffsetType offset,const size_t length) 00843 { 00844 #if defined(WIZARDSTOOLKIT_HAVE_MMAP_FILEIO) 00845 int 00846 flags, 00847 protection; 00848 00849 unsigned char 00850 *map; 00851 00852 /* 00853 Map file. 00854 */ 00855 flags=0; 00856 if (file == -1) 00857 #if defined(MAP_ANONYMOUS) 00858 flags|=MAP_ANONYMOUS; 00859 #else 00860 return((unsigned char *) NULL); 00861 #endif 00862 flags|=MAP_PRIVATE; 00863 switch (mode) 00864 { 00865 case ReadMode: 00866 default: 00867 { 00868 protection=PROT_READ; 00869 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file, 00870 (off_t) offset); 00871 break; 00872 } 00873 case WriteMode: 00874 { 00875 protection=PROT_WRITE; 00876 if (file != -1) 00877 flags|=MAP_SHARED; 00878 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file, 00879 (off_t) offset); 00880 #if defined(WIZARDTOOLKIT_HAVE_POSIX_MADVISE) 00881 (void) posix_madvise(map,length,POSIX_MADV_SEQUENTIAL | 00882 POSIX_MADV_WILLNEED); 00883 #endif 00884 break; 00885 } 00886 case IOMode: 00887 { 00888 protection=PROT_READ | PROT_WRITE; 00889 if (file != -1) 00890 flags|=MAP_SHARED; 00891 map=(unsigned char *) mmap((char *) NULL,length,protection,flags,file, 00892 (off_t) offset); 00893 break; 00894 } 00895 } 00896 if (map == (unsigned char *) MAP_FAILED) 00897 return((unsigned char *) NULL); 00898 return(map); 00899 #else 00900 return((unsigned char *) NULL); 00901 #endif 00902 } 00903 00904 /* 00905 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00906 % % 00907 % % 00908 % % 00909 + O p e n B l o b % 00910 % % 00911 % % 00912 % % 00913 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00914 % 00915 % OpenBlob() opens a file associated with the blob. A file name of '-' sets 00916 % the file to stdin for type 'r' and stdout for type 'w'. If the filename 00917 % suffix is '.gz' or '.Z', the blob_info is decompressed for type 'r' and 00918 % compressed for type 'w'. If the filename prefix is '|', it is piped to or 00919 % from a system command. 00920 % 00921 % The format of the OpenBlob method is: 00922 % 00923 % BlobInfo *OpenBlob(const char *filename,const BlobMode mode, 00924 % const WizardBooleanType compress,ExceptionInfo *exception) 00925 % 00926 % A description of each parameter follows: 00927 % 00928 % o filename: the filename. 00929 % 00930 % o mode: the mode for opening the file. 00931 % 00932 % o compress: a value other than 0 (de)compresses BZIP or ZIP files. 00933 % 00934 % o exception: return any errors or warnings in this structure. 00935 */ 00936 WizardExport BlobInfo *OpenBlob(const char *filename,const BlobMode mode, 00937 const WizardBooleanType compress,ExceptionInfo *exception) 00938 { 00939 BlobInfo 00940 *blob_info; 00941 00942 const char 00943 *type; 00944 00945 WizardBooleanType 00946 status; 00947 00948 assert(filename != (const char *) NULL); 00949 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",filename); 00950 assert(exception != (ExceptionInfo *) NULL); 00951 blob_info=(BlobInfo *) AcquireWizardMemory(sizeof(*blob_info)); 00952 if (blob_info == (BlobInfo *) NULL) 00953 { 00954 (void) ThrowWizardException(exception,GetWizardModule(),ResourceError, 00955 "memory allocation failed: `%s'",filename); 00956 return((BlobInfo *) NULL); 00957 } 00958 GetBlobInfo(blob_info); 00959 switch (mode) 00960 { 00961 default: type="r"; break; 00962 case ReadBlobMode: type="r"; break; 00963 case ReadBinaryBlobMode: type="rb"; break; 00964 case WriteBlobMode: type="w"; break; 00965 case WriteBinaryBlobMode: type="w+b"; break; 00966 } 00967 /* 00968 Open file. 00969 */ 00970 (void) CopyWizardString(blob_info->filename,filename,MaxTextExtent); 00971 if (LocaleCompare(filename,"-") == 0) 00972 { 00973 blob_info->file=(*type == 'r') ? stdin : stdout; 00974 #if defined(WIZARDSTOOLKIT_WINDOWS_SUPPORT) 00975 if (strchr(type,'b') != (char *) NULL) 00976 setmode(_fileno(blob_info->file),_O_BINARY); 00977 #endif 00978 blob_info->type=StandardStream; 00979 blob_info->exempt=WizardTrue; 00980 return(blob_info); 00981 } 00982 if (LocaleNCompare(filename,"fd:",3) == 0) 00983 { 00984 char 00985 mode[MaxTextExtent]; 00986 00987 *mode=(*type); 00988 mode[1]='\0'; 00989 blob_info->file=fdopen((long) StringToLong(filename+3),mode); 00990 #if defined(WIZARDSTOOLKIT_WINDOWS_SUPPORT) 00991 if (strchr(type,'b') != (char *) NULL) 00992 setmode(_fileno(blob_info->file),_O_BINARY); 00993 #endif 00994 blob_info->type=StandardStream; 00995 blob_info->exempt=WizardTrue; 00996 return(blob_info); 00997 } 00998 #if defined(WIZARDSTOOLKIT_HAVE_POPEN) 00999 if (*filename == '|') 01000 { 01001 char 01002 mode[MaxTextExtent]; 01003 01004 /* 01005 Pipe blob_info to or from a system command. 01006 */ 01007 #if defined(SIGPIPE) 01008 if (*type == 'w') 01009 (void) signal(SIGPIPE,SIG_IGN); 01010 #endif 01011 *mode=(*type); 01012 mode[1]='\0'; 01013 blob_info->file=(FILE *) popen_utf8(filename+1,mode); 01014 if (blob_info->file == (FILE *) NULL) 01015 { 01016 (void) ThrowWizardException(exception,GetWizardModule(),BlobError, 01017 "unable to open file `%s': %s",filename,strerror(errno)); 01018 blob_info=(BlobInfo *) RelinquishWizardMemory(blob_info); 01019 return((BlobInfo *) NULL); 01020 } 01021 blob_info->type=PipeStream; 01022 blob_info->exempt=WizardTrue; 01023 return(blob_info); 01024 } 01025 #endif 01026 status=stat_utf8(filename,&blob_info->properties) == 0 ? WizardTrue : 01027 WizardFalse; 01028 #if defined(S_ISFIFO) 01029 if ((status == WizardTrue) && S_ISFIFO(blob_info->properties.st_mode)) 01030 { 01031 blob_info->file=fopen_utf8(filename,type); 01032 if (blob_info->file == (FILE *) NULL) 01033 { 01034 (void) ThrowWizardException(exception,GetWizardModule(),BlobError, 01035 "unable to open file `%s': %s",filename,strerror(errno)); 01036 blob_info=(BlobInfo *) RelinquishWizardMemory(blob_info); 01037 return((BlobInfo *) NULL); 01038 } 01039 blob_info->type=FileStream; 01040 blob_info->exempt=WizardTrue; 01041 return(blob_info); 01042 } 01043 #endif 01044 if (*type == 'r') 01045 { 01046 blob_info->file=fopen_utf8(filename,type); 01047 if (blob_info->file != (FILE *) NULL) 01048 { 01049 size_t 01050 count; 01051 01052 unsigned char 01053 magick[3]; 01054 01055 blob_info->type=FileStream; 01056 #if defined(WIZARDSTOOLKIT_HAVE_SETVBUF) 01057 (void) setvbuf(blob_info->file,(char *) NULL,(int) _IOFBF,16384); 01058 #endif 01059 (void) ResetWizardMemory(magick,0,sizeof(magick)); 01060 count=fread(magick,1,sizeof(magick),blob_info->file); 01061 (void) rewind(blob_info->file); 01062 (void) LogWizardEvent(BlobEvent,GetWizardModule(), 01063 " read %.20g magic header bytes",(double) count); 01064 #if defined(WIZARDSTOOLKIT_ZLIB_DELEGATE) 01065 if ((compress != WizardFalse) && ((int) magick[0] == 0x1F) && 01066 ((int) magick[1] == 0x8B) && ((int) magick[2] == 0x08)) 01067 { 01068 (void) fclose(blob_info->file); 01069 blob_info->file=(FILE *) gzopen(filename,type); 01070 if (blob_info->file != (FILE *) NULL) 01071 blob_info->type=ZipStream; 01072 } 01073 #endif 01074 #if defined(WIZARDSTOOLKIT_BZLIB_DELEGATE) 01075 if ((compress != WizardFalse) && 01076 (strncmp((char *) magick,"BZh",3) == 0)) 01077 { 01078 (void) fclose(blob_info->file); 01079 blob_info->file=(FILE *) BZ2_bzopen(filename,type); 01080 if (blob_info->file != (FILE *) NULL) 01081 blob_info->type=BZipStream; 01082 } 01083 #endif 01084 if (blob_info->type == FileStream) 01085 { 01086 size_t 01087 length; 01088 01089 struct stat 01090 *properties; 01091 01092 void 01093 *blob; 01094 01095 properties=(&blob_info->properties); 01096 length=(size_t) properties->st_size; 01097 blob=MapBlob(fileno(blob_info->file),ReadMode,0,length); 01098 if (blob != (void *) NULL) 01099 { 01100 /* 01101 Use memory-mapped I/O. 01102 */ 01103 (void) fclose(blob_info->file); 01104 blob_info->file=(FILE *) NULL; 01105 AttachBlob(blob_info,blob,length); 01106 blob_info->mapped=WizardTrue; 01107 } 01108 } 01109 } 01110 } 01111 else 01112 { 01113 char 01114 extension[MaxTextExtent]; 01115 01116 GetPathComponent(filename,ExtensionPath,extension); 01117 #if defined(WIZARDSTOOLKIT_ZLIB_DELEGATE) 01118 if ((compress != WizardFalse) && 01119 ((LocaleCompare(extension,"Z") == 0) || 01120 (LocaleCompare(extension,"gz") == 0))) 01121 { 01122 blob_info->file=(FILE *) gzopen(filename,type); 01123 if (blob_info->file != (FILE *) NULL) 01124 blob_info->type=ZipStream; 01125 } 01126 else 01127 #endif 01128 #if defined(WIZARDSTOOLKIT_BZLIB_DELEGATE) 01129 if ((compress != WizardFalse) && (LocaleCompare(extension,".bz2") == 0)) 01130 { 01131 blob_info->file=(FILE *) BZ2_bzopen(filename,type); 01132 if (blob_info->file != (FILE *) NULL) 01133 blob_info->type=BZipStream; 01134 } 01135 else 01136 #endif 01137 { 01138 blob_info->file=fopen_utf8(filename,type); 01139 if (blob_info->file != (FILE *) NULL) 01140 { 01141 blob_info->type=FileStream; 01142 #if defined(WIZARDSTOOLKIT_HAVE_SETVBUF) 01143 (void) setvbuf(blob_info->file,(char *) NULL,(int) _IOFBF, 01144 16384); 01145 #endif 01146 } 01147 } 01148 } 01149 blob_info->status=WizardFalse; 01150 if (blob_info->type != UndefinedStream) 01151 blob_info->size=GetBlobSize(blob_info); 01152 else 01153 { 01154 (void) ThrowWizardException(exception,GetWizardModule(),BlobError, 01155 "unable to open file `%s': %s",filename,strerror(errno)); 01156 blob_info=(BlobInfo *) RelinquishWizardMemory(blob_info); 01157 return((BlobInfo *) NULL); 01158 } 01159 return(blob_info); 01160 } 01161 01162 /* 01163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01164 % % 01165 % % 01166 % % 01167 + R e a d B l o b % 01168 % % 01169 % % 01170 % % 01171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01172 % 01173 % ReadBlob() reads data from the blob and returns it. It returns the number 01174 % of bytes read. 01175 % 01176 % The format of the ReadBlob method is: 01177 % 01178 % ssize_t ReadBlob(BlobInfo *blob_info,const size_t length, 01179 % unsigned char *data) 01180 % 01181 % A description of each parameter follows: 01182 % 01183 % o blob_info: the blob info. 01184 % 01185 % o length: number of bytes to read from the blob. 01186 % 01187 % o data: area to place the information requested from the blob. 01188 % 01189 */ 01190 01191 static inline size_t WizardMin(const size_t x,const size_t y) 01192 { 01193 if (x < y) 01194 return(x); 01195 return(y); 01196 } 01197 01198 WizardExport ssize_t ReadBlob(BlobInfo *blob_info,const size_t length, 01199 unsigned char *data) 01200 { 01201 int 01202 c; 01203 01204 register unsigned char 01205 *q; 01206 01207 ssize_t 01208 count; 01209 01210 assert(blob_info != (BlobInfo *) NULL); 01211 assert(blob_info->signature == WizardSignature); 01212 assert(blob_info != (BlobInfo *) NULL); 01213 assert(blob_info->type != UndefinedStream); 01214 if (length == 0) 01215 return(0); 01216 assert(data != (void *) NULL); 01217 count=0; 01218 q=data; 01219 switch (blob_info->type) 01220 { 01221 case UndefinedStream: 01222 break; 01223 case FileStream: 01224 case StandardStream: 01225 case PipeStream: 01226 { 01227 switch (length) 01228 { 01229 default: 01230 { 01231 count=(ssize_t) fread(q,1,length,blob_info->file); 01232 break; 01233 } 01234 case 2: 01235 { 01236 c=getc(blob_info->file); 01237 if (c == EOF) 01238 break; 01239 *q++=(unsigned char) c; 01240 count++; 01241 } 01242 case 1: 01243 { 01244 c=getc(blob_info->file); 01245 if (c == EOF) 01246 break; 01247 *q++=(unsigned char) c; 01248 count++; 01249 } 01250 case 0: 01251 break; 01252 } 01253 break; 01254 } 01255 case ZipStream: 01256 { 01257 #if defined(WIZARDSTOOLKIT_ZLIB_DELEGATE) 01258 switch (length) 01259 { 01260 default: 01261 { 01262 count=(ssize_t) gzread(blob_info->file,q,(unsigned int) length); 01263 break; 01264 } 01265 case 2: 01266 { 01267 c=gzgetc(blob_info->file); 01268 if (c == EOF) 01269 break; 01270 *q++=(unsigned char) c; 01271 count++; 01272 } 01273 case 1: 01274 { 01275 c=gzgetc(blob_info->file); 01276 if (c == EOF) 01277 break; 01278 *q++=(unsigned char) c; 01279 count++; 01280 } 01281 case 0: 01282 break; 01283 } 01284 #endif 01285 break; 01286 } 01287 case BZipStream: 01288 { 01289 #if defined(WIZARDSTOOLKIT_BZLIB_DELEGATE) 01290 count=(ssize_t) BZ2_bzread((BZFILE *) blob_info->file,q,(int) length); 01291 #endif 01292 break; 01293 } 01294 case BlobStream: 01295 { 01296 register const unsigned char 01297 *p; 01298 01299 if (blob_info->offset >= (WizardOffsetType) blob_info->length) 01300 { 01301 blob_info->eof=WizardTrue; 01302 break; 01303 } 01304 p=blob_info->data+blob_info->offset; 01305 count=(ssize_t) WizardMin(length,(size_t) (blob_info->length- 01306 blob_info->offset)); 01307 blob_info->offset+=count; 01308 if (count != (ssize_t) length) 01309 blob_info->eof=WizardTrue; 01310 (void) memcpy(q,p,(size_t) count); 01311 break; 01312 } 01313 } 01314 return(count); 01315 } 01316 01317 /* 01318 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01319 % % 01320 % % 01321 % % 01322 + R e a d B l o b B y t e % 01323 % % 01324 % % 01325 % % 01326 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01327 % 01328 % ReadBlobByte() reads a single byte from the blob_info file and returns it. 01329 % 01330 % The format of the ReadBlobByte method is: 01331 % 01332 % int ReadBlobByte(BlobInfo *blob_info) 01333 % 01334 % A description of each parameter follows. 01335 % 01336 % o blob_info: the blob info. 01337 % 01338 */ 01339 01340 static inline const unsigned char *ReadBlobStream(BlobInfo *blob_info, 01341 const size_t length,unsigned char *data,ssize_t *count) 01342 { 01343 assert(count != (ssize_t *) NULL); 01344 assert(blob_info != (BlobInfo *) NULL); 01345 if (blob_info->type != BlobStream) 01346 { 01347 *count=ReadBlob(blob_info,length,data); 01348 return(data); 01349 } 01350 if (blob_info->offset >= (WizardOffsetType) blob_info->length) 01351 { 01352 *count=0; 01353 blob_info->eof=WizardTrue; 01354 return(data); 01355 } 01356 data=blob_info->data+blob_info->offset; 01357 *count=(ssize_t) WizardMin(length,(size_t) (blob_info->length- 01358 blob_info->offset)); 01359 blob_info->offset+=(*count); 01360 if (*count != (ssize_t) length) 01361 blob_info->eof=WizardTrue; 01362 return(data); 01363 } 01364 01365 WizardExport int ReadBlobByte(BlobInfo *blob_info) 01366 { 01367 register const unsigned char 01368 *p; 01369 01370 ssize_t 01371 count; 01372 01373 unsigned char 01374 buffer[1]; 01375 01376 assert(blob_info != (BlobInfo *) NULL); 01377 assert(blob_info->signature == WizardSignature); 01378 p=ReadBlobStream(blob_info,1,buffer,&count); 01379 if (count != 1) 01380 return(EOF); 01381 return((int) (*p)); 01382 } 01383 01384 /* 01385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01386 % % 01387 % % 01388 % % 01389 + R e a d B l o b C h u n k % 01390 % % 01391 % % 01392 % % 01393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01394 % 01395 % ReadBlobChunk() reads data from the blob and returns it. It returns the 01396 % number of bytes read. ReadBlobChunk() differs from ReadBlob() by making an 01397 % effort to return the number of bytes that was requested except in the event 01398 % an EOF is encountered. 01399 % 01400 % The format of the ReadBlobChunk method is: 01401 % 01402 % ssize_t ReadBlobChunk(BlobInfo *blob_info,const size_t length, 01403 % unsigned char *data) 01404 % 01405 % A description of each parameter follows: 01406 % 01407 % o blob_info: the blob info. 01408 % 01409 % o length: the number of bytes to read from the blob. 01410 % 01411 % o data: the area to place the information requested from the blob. 01412 % 01413 */ 01414 WizardExport ssize_t ReadBlobChunk(BlobInfo *blob_info,const size_t length, 01415 unsigned char *data) 01416 { 01417 register ssize_t 01418 i; 01419 01420 ssize_t 01421 count; 01422 01423 assert(blob_info != (BlobInfo *) NULL); 01424 assert(blob_info->signature == WizardSignature); 01425 assert(blob_info->type != UndefinedStream); 01426 assert(data != (void *) NULL); 01427 if (blob_info->type == BlobStream) 01428 return(ReadBlob(blob_info,length,data)); 01429 count=0; 01430 for (i=0; i < (ssize_t) length; i+=count) 01431 { 01432 count=ReadBlob(blob_info,WizardMin(length-i,(size_t) SSIZE_MAX),data+i); 01433 if (count <= 0) 01434 { 01435 count=0; 01436 if (errno != EINTR) 01437 break; 01438 } 01439 } 01440 return(i); 01441 } 01442 01443 /* 01444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01445 % % 01446 % % 01447 % % 01448 + S e t B l o b E x t e n t % 01449 % % 01450 % % 01451 % % 01452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01453 % 01454 % SetBlobExtent() ensures enough space is allocated for the blob. If the 01455 % method is successful, subsequent writes to bytes in the specified range are 01456 % guaranteed not to fail. 01457 % 01458 % The format of the SetBlobExtent method is: 01459 % 01460 % WizardBooleanType SetBlobExtent(BlobInfo *blob_info, 01461 % const WizardSizeType extent) 01462 % 01463 % A description of each parameter follows: 01464 % 01465 % o blob_info: the blob info. 01466 % 01467 % o extent: the blob maximum extent. 01468 % 01469 */ 01470 WizardExport WizardBooleanType SetBlobExtent(BlobInfo *blob_info, 01471 const WizardSizeType extent) 01472 { 01473 assert(blob_info != (BlobInfo *) NULL); 01474 assert(blob_info->signature == WizardSignature); 01475 switch (blob_info->type) 01476 { 01477 case UndefinedStream: 01478 break; 01479 case FileStream: 01480 { 01481 if (extent != (WizardSizeType) ((off_t) extent)) 01482 return(WizardFalse); 01483 #if !defined(WIZARDSTOOLKIT_HAVE_POSIX_FALLOCATE) 01484 return(WizardFalse); 01485 #else 01486 { 01487 int 01488 status; 01489 01490 WizardOffsetType 01491 offset; 01492 01493 offset=TellBlob(blob_info); 01494 status=posix_fallocate(fileno(blob_info->file),(off_t) offset, 01495 (off_t) (extent-offset)); 01496 if (status != 0) 01497 return(WizardFalse); 01498 } 01499 #endif 01500 break; 01501 } 01502 case StandardStream: 01503 case PipeStream: 01504 case ZipStream: 01505 { 01506 return(WizardFalse); 01507 break; 01508 } 01509 case BZipStream: 01510 return(WizardFalse); 01511 case BlobStream: 01512 { 01513 if (blob_info->mapped != WizardFalse) 01514 { 01515 if (blob_info->file == (FILE *) NULL) 01516 return(WizardFalse); 01517 (void) UnmapBlob(blob_info->data,blob_info->length); 01518 #if !defined(WIZARDSTOOLKIT_HAVE_POSIX_FALLOCATE) 01519 return(WizardFalse); 01520 #else 01521 { 01522 int 01523 status; 01524 01525 WizardOffsetType 01526 offset; 01527 01528 offset=TellBlob(blob_info); 01529 status=posix_fallocate(fileno(blob_info->file),(off_t) offset, 01530 (off_t) (extent-offset)); 01531 if (status != 0) 01532 return(WizardFalse); 01533 } 01534 blob_info->data=(unsigned char*) MapBlob(fileno(blob_info->file), 01535 WriteMode,0,(size_t) extent); 01536 blob_info->extent=(size_t) extent; 01537 blob_info->length=(size_t) extent; 01538 (void) SyncBlob(blob_info); 01539 break; 01540 #endif 01541 } 01542 if (extent != (WizardSizeType) ((size_t) extent)) 01543 return(WizardFalse); 01544 blob_info->extent=(size_t) extent; 01545 blob_info->data=(unsigned char *) ResizeQuantumMemory( 01546 blob_info->data,blob_info->extent,sizeof(*blob_info->data)); 01547 (void) SyncBlob(blob_info); 01548 if (blob_info->data == (unsigned char *) NULL) 01549 { 01550 (void) DetachBlob(blob_info); 01551 return(WizardFalse); 01552 } 01553 break; 01554 } 01555 } 01556 return(WizardTrue); 01557 } 01558 01559 /* 01560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01561 % % 01562 % % 01563 % % 01564 % S y n c B l o b % 01565 % % 01566 % % 01567 % % 01568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01569 % 01570 % SyncBlob() flushes the datastream if it is a file or synchonizes the data 01571 % attributes if it is an blob. 01572 % 01573 % The format of the SyncBlob method is: 01574 % 01575 % int SyncBlob(BlobInfo *blob_info) 01576 % 01577 % A description of each parameter follows: 01578 % 01579 % o blob_info: the blob info. 01580 % 01581 */ 01582 WizardExport int SyncBlob(BlobInfo *blob_info) 01583 { 01584 int 01585 status; 01586 01587 assert(blob_info != (BlobInfo *) NULL); 01588 assert(blob_info->signature == WizardSignature); 01589 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",blob_info->filename); 01590 status=0; 01591 switch (blob_info->type) 01592 { 01593 case UndefinedStream: 01594 break; 01595 case FileStream: 01596 case StandardStream: 01597 case PipeStream: 01598 { 01599 status=fflush(blob_info->file); 01600 break; 01601 } 01602 case ZipStream: 01603 { 01604 #if defined(WIZARDSTOOLKIT_ZLIB_DELEGATE) 01605 status=gzflush(blob_info->file,Z_SYNC_FLUSH); 01606 #endif 01607 break; 01608 } 01609 case BZipStream: 01610 { 01611 #if defined(WIZARDSTOOLKIT_BZLIB_DELEGATE) 01612 status=BZ2_bzflush((BZFILE *) blob_info->file); 01613 #endif 01614 break; 01615 } 01616 case BlobStream: 01617 { 01618 #if defined(WIZARDSTOOLKIT_HAVE_MMAP_FILEIO) 01619 if (blob_info->mapped != WizardFalse) 01620 status=msync(blob_info->data,blob_info->length,MS_SYNC); 01621 #endif 01622 break; 01623 } 01624 } 01625 return(status); 01626 } 01627 01628 /* 01629 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01630 % % 01631 % % 01632 % % 01633 + T e l l B l o b % 01634 % % 01635 % % 01636 % % 01637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01638 % 01639 % TellBlob() obtains the current value of the blob or file position. 01640 % 01641 % The format of the TellBlob method is: 01642 % 01643 % WizardOffsetType TellBlob(const BlobInfo *blob_info) 01644 % 01645 % A description of each parameter follows: 01646 % 01647 % o image: The image. 01648 % 01649 */ 01650 WizardExport WizardOffsetType TellBlob(const BlobInfo *blob_info) 01651 { 01652 WizardOffsetType 01653 offset; 01654 01655 assert(blob_info != (BlobInfo *) NULL); 01656 assert(blob_info->signature == WizardSignature); 01657 assert(blob_info->type != UndefinedStream); 01658 (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",blob_info->filename); 01659 offset=(-1); 01660 switch (blob_info->type) 01661 { 01662 case UndefinedStream: 01663 break; 01664 case FileStream: 01665 { 01666 offset=ftell(blob_info->file); 01667 break; 01668 } 01669 case StandardStream: 01670 case PipeStream: 01671 break; 01672 case ZipStream: 01673 { 01674 #if defined(WIZARDSTOOLKIT_ZLIB_DELEGATE) 01675 offset=(WizardOffsetType) gztell(blob_info->file); 01676 #endif 01677 break; 01678 } 01679 case BZipStream: 01680 break; 01681 case BlobStream: 01682 { 01683 offset=blob_info->offset; 01684 break; 01685 } 01686 } 01687 return(offset); 01688 } 01689 01690 /* 01691 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01692 % % 01693 % % 01694 % % 01695 + U n m a p B l o b % 01696 % % 01697 % % 01698 % % 01699 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01700 % 01701 % UnmapBlob() deallocates the binary large object previously allocated with 01702 % the MapBlob method. 01703 % 01704 % The format of the UnmapBlob method is: 01705 % 01706 % WizardBooleanType UnmapBlob(void *map,const size_t length) 01707 % 01708 % A description of each parameter follows: 01709 % 01710 % o map: The address of the binary large object. 01711 % 01712 % o length: The length of the binary large object. 01713 % 01714 */ 01715 WizardExport WizardBooleanType UnmapBlob(void *map,const size_t length) 01716 { 01717 #if defined(WIZARDSTOOLKIT_HAVE_MMAP_FILEIO) 01718 int 01719 status; 01720 01721 status=munmap(map,length); 01722 return(status == -1 ? WizardFalse : WizardTrue); 01723 #else 01724 return(WizardFalse); 01725 #endif 01726 } 01727 01728 /* 01729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01730 % % 01731 % % 01732 % % 01733 + W r i t e B l o b % 01734 % % 01735 % % 01736 % % 01737 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01738 % 01739 % WriteBlob() writes data to a blob or blob_info file. It returns the number 01740 % of bytes written. 01741 % 01742 % The format of the WriteBlob method is: 01743 % 01744 % ssize_t WriteBlob(BlobInfo *blob_info,const size_t length, 01745 % const unsigned char *data) 01746 % 01747 % A description of each parameter follows: 01748 % 01749 % o blob_info: the blob. 01750 % 01751 % o length: the number of bytes to write to the blob. 01752 % 01753 % o data: the area to place the information requested from the blob. 01754 % 01755 */ 01756 WizardExport ssize_t WriteBlob(BlobInfo *blob_info,const size_t length, 01757 const unsigned char *data) 01758 { 01759 int 01760 c; 01761 01762 register const unsigned char 01763 *p; 01764 01765 ssize_t 01766 count; 01767 01768 assert(blob_info != (BlobInfo *) NULL); 01769 assert(blob_info->signature == WizardSignature); 01770 assert(data != (const unsigned char *) NULL); 01771 if (length == 0) 01772 return(0); 01773 count=0; 01774 p=data; 01775 switch (blob_info->type) 01776 { 01777 case UndefinedStream: 01778 break; 01779 case FileStream: 01780 case StandardStream: 01781 case PipeStream: 01782 { 01783 switch (length) 01784 { 01785 default: 01786 { 01787 count=(ssize_t) fwrite((const char *) data,1,length, 01788 blob_info->file); 01789 break; 01790 } 01791 case 2: 01792 { 01793 c=putc((int) *p++,blob_info->file); 01794 if (c == EOF) 01795 break; 01796 count++; 01797 } 01798 case 1: 01799 { 01800 c=putc((int) *p++,blob_info->file); 01801 if (c == EOF) 01802 break; 01803 count++; 01804 } 01805 case 0: 01806 break; 01807 } 01808 break; 01809 } 01810 case ZipStream: 01811 { 01812 #if defined(WIZARDSTOOLKIT_ZLIB_DELEGATE) 01813 switch (length) 01814 { 01815 default: 01816 { 01817 count=(ssize_t) gzwrite(blob_info->file,(void *) data, 01818 (unsigned int) length); 01819 break; 01820 } 01821 case 2: 01822 { 01823 c=gzputc(blob_info->file,(int) *p++); 01824 if (c == EOF) 01825 break; 01826 count++; 01827 } 01828 case 1: 01829 { 01830 c=gzputc(blob_info->file,(int) *p++); 01831 if (c == EOF) 01832 break; 01833 count++; 01834 } 01835 case 0: 01836 break; 01837 } 01838 #endif 01839 break; 01840 } 01841 case BZipStream: 01842 { 01843 #if defined(WIZARDSTOOLKIT_BZLIB_DELEGATE) 01844 count=(ssize_t) BZ2_bzwrite((BZFILE *) blob_info->file,(void *) data, 01845 (int) length); 01846 #endif 01847 break; 01848 } 01849 case BlobStream: 01850 { 01851 register unsigned char 01852 *q; 01853 01854 if ((blob_info->offset+(WizardOffsetType) length) >= 01855 (WizardOffsetType) blob_info->extent) 01856 { 01857 if (blob_info->mapped != WizardFalse) 01858 return(0); 01859 blob_info->quantum<<=1; 01860 blob_info->extent+=length+blob_info->quantum; 01861 blob_info->data=(unsigned char *) ResizeQuantumMemory( 01862 blob_info->data,blob_info->extent+1, 01863 sizeof(*blob_info->data)); 01864 (void) SyncBlob(blob_info); 01865 if (blob_info->data == (unsigned char *) NULL) 01866 { 01867 (void) DetachBlob(blob_info); 01868 return(0); 01869 } 01870 } 01871 q=blob_info->data+blob_info->offset; 01872 (void) memcpy(q,p,length); 01873 blob_info->offset+=length; 01874 if (blob_info->offset >= (WizardOffsetType) blob_info->length) 01875 blob_info->length=(size_t) blob_info->offset; 01876 count=(ssize_t) length; 01877 } 01878 } 01879 return(count); 01880 } 01881 01882 /* 01883 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01884 % % 01885 % % 01886 % % 01887 + W r i t e B l o b B y t e % 01888 % % 01889 % % 01890 % % 01891 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01892 % 01893 % WriteBlobByte() write an integer to a blob. It returns the number of bytes 01894 % written (either 0 or 1); 01895 % 01896 % The format of the WriteBlobByte method is: 01897 % 01898 % ssize_t WriteBlobByte(BlobInfo *blob_info,const unsigned char value) 01899 % 01900 % A description of each parameter follows. 01901 % 01902 % o blob_info: the blob info. 01903 % 01904 % o value: the value to write. 01905 % 01906 */ 01907 01908 static inline ssize_t WriteBlobStream(BlobInfo *blob_info,const size_t length, 01909 const unsigned char *data) 01910 { 01911 register unsigned char 01912 *q; 01913 01914 WizardSizeType 01915 extent; 01916 01917 assert(blob_info != (BlobInfo *) NULL); 01918 if (blob_info->type != BlobStream) 01919 return(WriteBlob(blob_info,length,data)); 01920 assert(blob_info->type != UndefinedStream); 01921 assert(data != (void *) NULL); 01922 extent=(WizardSizeType) (blob_info->offset+(WizardOffsetType) length); 01923 if (extent >= blob_info->extent) 01924 { 01925 blob_info->quantum<<=1; 01926 extent=blob_info->extent+blob_info->quantum+length; 01927 if (SetBlobExtent(blob_info,extent) == WizardFalse) 01928 return(0); 01929 } 01930 q=blob_info->data+blob_info->offset; 01931 (void) memcpy(q,data,length); 01932 blob_info->offset+=length; 01933 if (blob_info->offset >= (WizardOffsetType) blob_info->length) 01934 blob_info->length=(size_t) blob_info->offset; 01935 return((ssize_t) length); 01936 } 01937 01938 WizardExport ssize_t WriteBlobByte(BlobInfo *blob_info, 01939 const unsigned char value) 01940 { 01941 assert(blob_info != (BlobInfo *) NULL); 01942 assert(blob_info->signature == WizardSignature); 01943 return(WriteBlobStream(blob_info,1,&value)); 01944 } 01945 01946 /* 01947 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01948 % % 01949 % % 01950 % % 01951 + W r i t e B l o b C h u n k % 01952 % % 01953 % % 01954 % % 01955 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01956 % 01957 % WriteBlobChunk() writes data to a blob or blob_info file. It returns the 01958 % number of bytes written. WriteBlobChunk() differs from WriteBlob() by 01959 % making an effort to write the number of bytes that was requested except in 01960 % the event an EOF is encountered. 01961 % 01962 % The format of the WriteBlob method is: 01963 % 01964 % ssize_t WriteBlobChunk(BlobInfo *blob_info,const size_t length, 01965 % const unsigned char *data) 01966 % 01967 % A description of each parameter follows: 01968 % 01969 % o blob_info: the blob. 01970 % 01971 % o length: the number of bytes to write to the blob. 01972 % 01973 % o data: the area to place the information requested from the blob. 01974 % 01975 */ 01976 WizardExport ssize_t WriteBlobChunk(BlobInfo *blob_info,const size_t length, 01977 const unsigned char *data) 01978 { 01979 register ssize_t 01980 i; 01981 01982 ssize_t 01983 count; 01984 01985 assert(blob_info != (BlobInfo *) NULL); 01986 assert(blob_info->signature == WizardSignature); 01987 assert(data != (const unsigned char *) NULL); 01988 if (blob_info->type == BlobStream) 01989 return(WriteBlob(blob_info,length,data)); 01990 count=0; 01991 for (i=0; i < (ssize_t) length; i+=count) 01992 { 01993 count=WriteBlob(blob_info,WizardMin(length-i,(size_t) SSIZE_MAX),data+i); 01994 if (count <= 0) 01995 { 01996 count=0; 01997 if (errno != EINTR) 01998 break; 01999 } 02000 } 02001 return(i); 02002 } 02003 02004 /* 02005 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02006 % % 02007 % % 02008 % % 02009 + W r i t e B l o b S t r i n g % 02010 % % 02011 % % 02012 % % 02013 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02014 % 02015 % WriteBlobString() write a string to a blob. It returns the number of 02016 % characters written. 02017 % 02018 % The format of the WriteBlobString method is: 02019 % 02020 % ssize_t WriteBlobString(BlobInfo *blob_info,const char *string) 02021 % 02022 % A description of each parameter follows. 02023 % 02024 % o image: The image. 02025 % 02026 % o string: Specifies the string to write. 02027 % 02028 */ 02029 WizardExport ssize_t WriteBlobString(BlobInfo *blob_info,const char *string) 02030 { 02031 ssize_t 02032 count; 02033 02034 assert(blob_info != (BlobInfo *) NULL); 02035 assert(blob_info->signature == WizardSignature); 02036 assert(string != (const char *) NULL); 02037 count=WriteBlobStream(blob_info,strlen(string),(const unsigned char *) 02038 string); 02039 return(count); 02040 }