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