WizardsToolkit  1.0.7
file.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                         FFFFF  IIIII  L      EEEEE                          %
00006 %                         F        I    L      E                              %
00007 %                         FFF      I    L      EEE                            %
00008 %                         F        I    L      E                              %
00009 %                         F      IIIII  LLLLL  EEEEE                          %
00010 %                                                                             %
00011 %                                                                             %
00012 %                         Wizard's Toolkit File Methods                       %
00013 %                                                                             %
00014 %                             Software Design                                 %
00015 %                               John Cristy                                   %
00016 %                               March 2003                                    %
00017 %                                                                             %
00018 %                                                                             %
00019 %  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
00020 %  dedicated to making software imaging solutions freely available.           %
00021 %                                                                             %
00022 %  You may not use this file except in compliance with the License.  You may  %
00023 %  obtain a copy of the License at                                            %
00024 %                                                                             %
00025 %    http://www.wizards-toolkit.org/script/license.php                        %
00026 %                                                                             %
00027 %  Unless required by applicable law or agreed to in writing, software        %
00028 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00029 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00030 %  See the License for the specific language governing permissions and        %
00031 %  limitations under the License.                                             %
00032 %                                                                             %
00033 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00034 %
00035 %
00036 %
00037 */
00038 
00039 /*
00040   Include declarations.
00041 */
00042 #include "wizard/studio.h"
00043 #include "wizard/blob.h"
00044 #include "wizard/exception.h"
00045 #include "wizard/exception-private.h"
00046 #include "wizard/file.h"
00047 #include "wizard/memory_.h"
00048 #include "wizard/semaphore.h"
00049 #include "wizard/string_.h"
00050 #include "wizard/utility.h"
00051 #include "wizard/utility-private.h"
00052 #if defined(WIZARDSTOOLKIT_THREAD_SUPPORT)
00053 #include <pthread.h>
00054 #endif
00055 #if defined(WIZARDSTOOLKIT_WINDOWS_SUPPORT)
00056 #include <windows.h>
00057 #endif
00058 
00059 /*
00060   Forward declarations.
00061 */
00062 static WizardBooleanType
00063   RelinquishFileLock(FileInfo *,ExceptionInfo *);
00064 
00065 /*
00066   Typedef declarations.
00067 */
00068 struct _FileInfo
00069 {
00070   char
00071     *path;
00072 
00073   int
00074     file;
00075 
00076   struct stat
00077     properties;
00078 
00079   SemaphoreInfo
00080     *semaphore;
00081 
00082   time_t
00083     timestamp;
00084 
00085   size_t
00086     signature;
00087 };
00088 
00089 /*
00090 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00091 %                                                                             %
00092 %                                                                             %
00093 %                                                                             %
00094 %   A c q u i r e F i l e L o c k                                             %
00095 %                                                                             %
00096 %                                                                             %
00097 %                                                                             %
00098 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00099 %
00100 %  AcquireFileLock() acquires a lock for a file.
00101 %
00102 %  The format of the AcquireFileLock method is:
00103 %
00104 %      WizardBooleanType AcquireFileLock(FileInfo *file_info,
00105 %        ExceptionInfo *exception)
00106 %
00107 %  A description of each parameter follows:
00108 %
00109 %    o file_info: The file info.
00110 %
00111 %    o exception: Return any errors or warnings in this structure.
00112 %
00113 */
00114 
00115 static size_t GetWizardThreadId(void)
00116 {
00117 #if defined(WIZARDSTOOLKIT_THREAD_SUPPORT)
00118   return((size_t) pthread_self());
00119 #endif
00120 #if defined(WIZARDSTOOLKIT_WINDOWS_SUPPORT)
00121   return((size_t) GetCurrentThreadId());
00122 #endif
00123   return((size_t) getpid());
00124 }
00125 
00126 static WizardBooleanType AcquireFileLock(FileInfo *file_info,
00127   ExceptionInfo *exception)
00128 {
00129   char
00130     *path;
00131 
00132   ssize_t
00133     pid;
00134 
00135   register ssize_t
00136     i;
00137 
00138   size_t
00139     tid;
00140 
00141   WizardStatusType
00142     status;
00143 
00144   /*
00145     Engage primitive atomic lock.
00146   */
00147   assert(file_info != (FileInfo *) NULL);
00148   assert(file_info->signature == WizardSignature);
00149   (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",file_info->path);
00150   LockSemaphoreInfo(file_info->semaphore);
00151   path=AcquireString(file_info->path);
00152   AppendFileExtension("lck",path);
00153   for (i=0; i < 10; i++)
00154   {
00155     file_info->file=open_utf8(path,O_WRONLY | O_CREAT | O_EXCL,S_MODE);
00156     if (file_info->file == -1)
00157       {
00158         if (errno != EEXIST)
00159           break;
00160         file_info->file=open_utf8(path,O_RDONLY,0);
00161         if (file_info->file == -1)
00162           break;
00163         pid=(-1);
00164         tid=(~0UL);
00165         status=ReadFileChunk(file_info,&pid,sizeof(pid));
00166         status|=ReadFileChunk(file_info,&tid,sizeof(tid));
00167         if (close(file_info->file) == -1)
00168           (void) ThrowWizardException(exception,GetWizardModule(),FileError,
00169             "unable to close file `%s': %s",path,strerror(errno));
00170         file_info->file=(-1);
00171         if (status != WizardFalse)
00172           {
00173             WizardBooleanType
00174               active_process;
00175 
00176             if ((pid == (ssize_t) getpid()) && (tid == GetWizardThreadId()))
00177               {
00178                 path=DestroyString(path);
00179                 UnlockSemaphoreInfo(file_info->semaphore);
00180                 return(WizardTrue);
00181               }
00182 #if defined(WIZARDSTOOLKIT_WINDOWS_SUPPORT)
00183             {
00184               HANDLE
00185                 handle;
00186 
00187               handle=OpenProcess(PROCESS_ALL_ACCESS,FALSE,(DWORD) pid);
00188               active_process=handle == (HANDLE) NULL ? WizardFalse : WizardTrue;
00189               if (handle != (HANDLE) NULL)
00190                 CloseHandle(handle);
00191             }
00192 #else
00193             active_process=kill((pid_t) pid,0) == -1 ? WizardFalse : WizardTrue;
00194 #endif
00195             if (active_process == WizardFalse)
00196               {
00197                 if (errno != ESRCH)
00198                   break;
00199                 i--;
00200                 if (remove_utf8(path) == -1)
00201                   (void) ThrowWizardException(exception,GetWizardModule(),
00202                     FileError,"unable to remove file `%s': %s",path,
00203                     strerror(errno));
00204                 break;
00205               }
00206           }
00207         (void) sleep(1);
00208         continue;
00209       }
00210     pid=(ssize_t) getpid();
00211     status=WriteFileChunk(file_info,&pid,sizeof(pid));
00212     tid=GetWizardThreadId();
00213     status=WriteFileChunk(file_info,&tid,sizeof(tid));
00214     if (close(file_info->file) == -1)
00215       (void) ThrowWizardException(exception,GetWizardModule(),FileError,
00216         "unable to close file `%s': %s",path,strerror(errno));
00217     file_info->file=(-1);
00218     if (status == WizardFalse)
00219       break;
00220     i--;
00221   }
00222   path=DestroyString(path);
00223   UnlockSemaphoreInfo(file_info->semaphore);
00224   return(WizardFalse);
00225 }
00226 
00227 /*
00228 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %                                                                             %
00229 %                                                                             %
00230 %                                                                             %
00231 %   A c q u i r e F i l e I n f o                                             %
00232 %                                                                             %
00233 %                                                                             %
00234 %                                                                             %
00235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00236 %
00237 %  AcquireFileInfo() opens the file for reading or writing and returns a
00238 %  FileInfo structure.
00239 %
00240 %  The format of the AcquireFileInfo method is:
00241 %
00242 %      FileInfo *AcquireFileInfo(const char *path,const char *relative_path,
00243 %        const FileMode mode,ExceptionInfo *exception)
00244 %
00245 %  A description of each parameter follows:
00246 %
00247 %    o path: The file path.
00248 %
00249 %    o relative_path: The path relative to the default path.
00250 %
00251 %    o mode: The file I/O mode.
00252 %
00253 %    o exception: Return any errors or warnings in this structure.
00254 %
00255 */
00256 WizardExport FileInfo *AcquireFileInfo(const char *path,
00257   const char *relative_path,const FileMode mode,ExceptionInfo *exception)
00258 {
00259   char
00260     *home;
00261 
00262   FileInfo
00263     *file_info;
00264 
00265   /*
00266     Acquire file info.
00267   */
00268   assert(relative_path != (char *) NULL);
00269   (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",relative_path);
00270   assert(exception != (ExceptionInfo *) NULL);
00271   file_info=(FileInfo *) AcquireWizardMemory(sizeof(*file_info));
00272   if (file_info == (FileInfo *) NULL)
00273     {
00274       (void) ThrowWizardException(exception,GetWizardModule(),FileError,
00275         "memory allocation failed `%s'",strerror(errno));
00276       return((FileInfo *) NULL);
00277     }
00278   (void) ResetWizardMemory(file_info,0,sizeof(*file_info));
00279   file_info->path=AcquireString((char *) NULL);
00280   file_info->file=(-1);
00281   file_info->semaphore=AllocateSemaphoreInfo();
00282   file_info->timestamp=time((time_t *) NULL);
00283   file_info->signature=WizardSignature;
00284   if (path != (char *) NULL)
00285     (void) CopyWizardString(file_info->path,path,MaxTextExtent);
00286   else
00287     {
00288       /*
00289         Default location for key ring, random state, etc.
00290       */
00291       *file_info->path='\0';
00292       home=GetEnvironmentValue("WIZARD_HOME");
00293       if (home != (char *) NULL)
00294         {
00295           (void) CopyWizardString(file_info->path,home,MaxTextExtent);
00296           (void) ConcatenateWizardString(file_info->path,DirectorySeparator,
00297             MaxTextExtent);
00298           home=(char *) RelinquishWizardMemory(home);
00299         }
00300       else
00301         {
00302           home=GetEnvironmentValue("HOME");
00303           if (home == (char *) NULL)
00304             home=GetEnvironmentValue("USERPROFILE");
00305           if (home != (char *) NULL)
00306             {
00307               (void) CopyWizardString(file_info->path,home,MaxTextExtent);
00308               (void) ConcatenateWizardString(file_info->path,
00309                 DirectorySeparator,MaxTextExtent);
00310               (void) ConcatenateWizardString(file_info->path,".wizard",
00311                 MaxTextExtent);
00312 #if defined(WIZARDSTOOLKIT_WINDOWS_SUPPORT)
00313               (void) mkdir(file_info->path);
00314 #else
00315               (void) mkdir(file_info->path,0700);
00316 #endif
00317               (void) ConcatenateWizardString(file_info->path,
00318                 DirectorySeparator,MaxTextExtent);
00319               home=(char *) RelinquishWizardMemory(home);
00320             }
00321         }
00322       (void) ConcatenateWizardString(file_info->path,relative_path,
00323         MaxTextExtent);
00324     }
00325   if (AcquireFileLock(file_info,exception) == WizardFalse)
00326     {
00327       file_info=DestroyFileInfo(file_info,exception);
00328       return((FileInfo *) NULL);
00329     }
00330   /*
00331     Open file.
00332   */
00333   switch (mode)
00334   {
00335     case ReadFileMode:
00336     {
00337       file_info->file=open_utf8(file_info->path,O_RDONLY | O_BINARY,0);
00338       break;
00339     }
00340     case WriteFileMode:
00341     {
00342       file_info->file=open_utf8(file_info->path,O_RDWR | O_CREAT | O_BINARY,
00343         S_MODE);
00344       break;
00345     }
00346     default:
00347     {
00348       (void) ThrowWizardException(exception,GetWizardModule(),FileError,
00349         "Invalid file mode `%s'",path);
00350       file_info=DestroyFileInfo(file_info,exception);
00351       return((FileInfo *) NULL);
00352     }
00353   }
00354   if (file_info->file < 0)
00355     {
00356       file_info=DestroyFileInfo(file_info,exception);
00357       return((FileInfo *) NULL);
00358     }
00359   (void) fstat(file_info->file,&file_info->properties);
00360   return(file_info);
00361 }
00362 
00363 /*
00364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00365 %                                                                             %
00366 %                                                                             %
00367 %                                                                             %
00368 %   D e s t r o y F i l e                                                     %
00369 %                                                                             %
00370 %                                                                             %
00371 %                                                                             %
00372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00373 %
00374 %  DestroyFile() destroys the file on disk.
00375 %
00376 %  The format of the DestroyFile method is:
00377 %
00378 %      WizardBooleanType DestroyFile(FileInfo *file_info,
00379 %        Exceptioninfo *exception)
00380 %
00381 %  A description of each parameter follows:
00382 %
00383 %    o file_info: The file info.
00384 %
00385 %    o exception: Return any errors or warnings in this structure.
00386 %
00387 */
00388 WizardExport WizardBooleanType DestroyFile(FileInfo *file_info,
00389   ExceptionInfo *exception)
00390 {
00391   if (file_info->file >= 0)
00392     if (close(file_info->file) == -1)
00393       {
00394         (void) ThrowWizardException(exception,GetWizardModule(),FileError,
00395           "unable to close file `%s': %s",file_info->path,strerror(errno));
00396         return(WizardFalse);
00397       }
00398   file_info->file=(-1);
00399   if (remove_utf8(file_info->path) == -1)
00400     {
00401       (void) ThrowWizardException(exception,GetWizardModule(),FileError,
00402         "unable to close file `%s': %s",file_info->path,strerror(errno));
00403       return(WizardFalse);
00404     }
00405   return(WizardTrue);
00406 }
00407 
00408 /*
00409 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00410 %                                                                             %
00411 %                                                                             %
00412 %                                                                             %
00413 %   D e s t r o y F i l e I n f o                                             %
00414 %                                                                             %
00415 %                                                                             %
00416 %                                                                             %
00417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00418 %
00419 %  DestroyFileInfo() destroys the file info structure.
00420 %
00421 %  The format of the DestroyFileInfo method is:
00422 %
00423 %      FileInfo *DestroyFileInfo(FileInfo *file_info)
00424 %
00425 %  A description of each parameter follows:
00426 %
00427 %    o path: The file name.
00428 %
00429 */
00430 WizardExport FileInfo *DestroyFileInfo(FileInfo *file_info,
00431   ExceptionInfo *exception)
00432 {
00433   assert(file_info != (FileInfo *) NULL);
00434   assert(file_info->signature == WizardSignature);
00435   (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",file_info->path);
00436   LockSemaphoreInfo(file_info->semaphore);
00437   if (file_info->file >= 0)
00438     if (close(file_info->file) == -1)
00439       (void) ThrowWizardException(exception,GetWizardModule(),FileError,
00440         "unable to close file `%s': %s",file_info->path,strerror(errno));
00441   file_info->file=(-1);
00442   (void) RelinquishFileLock(file_info,exception);
00443   if (file_info->path != (char *) NULL)
00444     file_info->path=DestroyString(file_info->path);
00445   file_info->signature=(~WizardSignature);
00446   UnlockSemaphoreInfo(file_info->semaphore);
00447   DestroySemaphoreInfo(&file_info->semaphore);
00448   file_info=(FileInfo *) RelinquishWizardMemory(file_info);
00449   return(file_info);
00450 }
00451 
00452 /*
00453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00454 %                                                                             %
00455 %                                                                             %
00456 %                                                                             %
00457 %   G e t F i l e D e s c r i p t o r                                         %
00458 %                                                                             %
00459 %                                                                             %
00460 %                                                                             %
00461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00462 %
00463 %  GetFileDescriptor() returns the file descriptor.
00464 %
00465 %  The format of the GetFileDescriptor method is:
00466 %
00467 %      int GetFileDescriptor(const FileInfo *file_info)
00468 %
00469 %  A description of each parameter follows:
00470 %
00471 %    o file_info: The file info.
00472 %
00473 */
00474 WizardExport int GetFileDescriptor(const FileInfo *file_info)
00475 {
00476   (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
00477   assert(file_info != (FileInfo *) NULL);
00478   assert(file_info->signature == WizardSignature);
00479   return(file_info->file);
00480 }
00481 
00482 /*
00483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00484 %                                                                             %
00485 %                                                                             %
00486 %                                                                             %
00487 %   G e t F i l e P a t h                                                     %
00488 %                                                                             %
00489 %                                                                             %
00490 %                                                                             %
00491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00492 %
00493 %  GetFilePath() returns the file path.
00494 %
00495 %  The format of the GetFilePath method is:
00496 %
00497 %      const const char *GetFilePath(const FileInfo *file_info)
00498 %
00499 %  A description of each parameter follows:
00500 %
00501 %    o file_info: The file info.
00502 %
00503 */
00504 WizardExport const char *GetFilePath(const FileInfo *file_info)
00505 {
00506   (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
00507   assert(file_info != (FileInfo *) NULL);
00508   assert(file_info->signature == WizardSignature);
00509   return(file_info->path);
00510 }
00511 
00512 /*
00513 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00514 %                                                                             %
00515 %                                                                             %
00516 %                                                                             %
00517 %   G e t F i l e P r o p e r t i e s                                         %
00518 %                                                                             %
00519 %                                                                             %
00520 %                                                                             %
00521 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00522 %
00523 %  GetFileproperties() returns the file properties.
00524 %
00525 %  The format of the GetFileProperties method is:
00526 %
00527 %      const struct stat *GetFileProperties(const FileInfo *file_info)
00528 %
00529 %  A description of each parameter follows:
00530 %
00531 %    o file_info: The file info.
00532 %
00533 */
00534 WizardExport const struct stat *GetFileProperties(const FileInfo *file_info)
00535 {
00536   (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
00537   assert(file_info != (FileInfo *) NULL);
00538   assert(file_info->signature == WizardSignature);
00539   return(&file_info->properties);
00540 }
00541 
00542 /*
00543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00544 %                                                                             %
00545 %                                                                             %
00546 %                                                                             %
00547 %  R e a d F i l e B y t e                                                    %
00548 %                                                                             %
00549 %                                                                             %
00550 %                                                                             %
00551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00552 %
00553 %  ReadFileByte() returns the character read as an unsigned char cast to an
00554 %  integer or EOF on end of file or error.
00555 %
00556 %  The format of the ReadFileByte method is:
00557 %
00558 %      int ReadFileByte(FileInfo *file_info)
00559 %
00560 %  A description of each parameter follows.
00561 %
00562 %    o file_info: the blob info.
00563 %
00564 */
00565 WizardExport int ReadFileByte(FileInfo *file_info)
00566 {
00567   unsigned char
00568     buffer[1];
00569 
00570   assert(file_info != (FileInfo *) NULL);
00571   assert(file_info->signature == WizardSignature);
00572   if (ReadFileChunk(file_info,buffer,1) == WizardFalse)
00573     return(EOF);
00574   return((int) (*buffer));
00575 }
00576 
00577 /*
00578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00579 %                                                                             %
00580 %                                                                             %
00581 %                                                                             %
00582 %   R e a d F i l e C h u n k                                                 %
00583 %                                                                             %
00584 %                                                                             %
00585 %                                                                             %
00586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00587 %
00588 %  ReadFileChunk() reliably reads a chunk of data from a file.  It returns
00589 %  WizardTrue if all the data requested is read otherwise WizardFalse.
00590 %
00591 %  The format of the ReadFileChunk method is:
00592 %
00593 %      WizardBooleanType ReadFileChunk(FileInfo *file_info,const void *data,
00594 %        const size_t length)
00595 %
00596 %  A description of each parameter follows:
00597 %
00598 %    o file_info: The file info.
00599 %
00600 %    o data: The data.
00601 %
00602 %    o length: The data length in bytes.
00603 %
00604 */
00605 WizardExport WizardBooleanType ReadFileChunk(FileInfo *file_info,void *data,
00606   const size_t length)
00607 {
00608   register ssize_t
00609     i;
00610 
00611   ssize_t
00612     count;
00613 
00614   assert(file_info != (FileInfo *) NULL);
00615   assert(file_info->signature == WizardSignature);
00616   (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",file_info->path);
00617   for (i=0; i < (ssize_t) length; i+=count)
00618   {
00619     count=read(file_info->file,(unsigned char *) data+i,Min(length-i,(size_t)
00620       WizardMaxBufferExtent));
00621     if (count <= 0)
00622       {
00623         count=0;
00624         if (errno != EINTR)
00625           break;
00626       }
00627   }
00628   if (i < (ssize_t) length)
00629     return(WizardFalse);
00630   return(WizardTrue);
00631 }
00632 
00633 /*
00634 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00635 %                                                                             %
00636 %                                                                             %
00637 %                                                                             %
00638 %  R e a d F i l e 1 6 B i t s                                                %
00639 %                                                                             %
00640 %                                                                             %
00641 %                                                                             %
00642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00643 %
00644 %  ReadFile16Bits() reads a 16-bit quantity in least-significant byte first
00645 %  order and returns it.
00646 %
00647 %  The format of the ReadFile16Bits method is:
00648 %
00649 %      WizardBooleanType ReadFile16Bits(FileInfo *file_info,
00650 %        unsigned short *value)
00651 %
00652 %  A description of each parameter follows.
00653 %
00654 %    o file_info: The image.
00655 %
00656 %    o value: The value.
00657 %
00658 */
00659 WizardExport WizardBooleanType ReadFile16Bits(FileInfo *file_info,
00660   unsigned short *value)
00661 {
00662   WizardBooleanType
00663     status;
00664 
00665   unsigned char
00666     buffer[2];
00667 
00668   assert(file_info != (FileInfo *) NULL);
00669   assert(file_info->signature == WizardSignature);
00670   *buffer=(unsigned char) '\0';
00671   status=ReadFileChunk(file_info,buffer,sizeof(buffer));
00672   if (status == WizardFalse)
00673     return(status);
00674   *value=(unsigned short) (buffer[1] << 8);
00675   *value|=(unsigned short) buffer[0];
00676   return(status);
00677 }
00678 
00679 /*
00680 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00681 %                                                                             %
00682 %                                                                             %
00683 %                                                                             %
00684 %  R e a d F i l e 3 2 B i t s                                                %
00685 %                                                                             %
00686 %                                                                             %
00687 %                                                                             %
00688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00689 %
00690 %  ReadFile32Bits() reads a 32-bit quantity in least-significant byte first
00691 %  order and returns it.
00692 %
00693 %  The format of the ReadFile32Bits method is:
00694 %
00695 %      WizardBooleanType ReadFile32Bits(FileInfo *file_info,
00696 %        size_t *value)
00697 %
00698 %  A description of each parameter follows.
00699 %
00700 %    o file_info: The image.
00701 %
00702 %    o value: The value.
00703 %
00704 */
00705 WizardExport WizardBooleanType ReadFile32Bits(FileInfo *file_info,
00706   size_t *value)
00707 {
00708   WizardBooleanType
00709     status;
00710 
00711   unsigned char
00712     buffer[4];
00713 
00714   assert(file_info != (FileInfo *) NULL);
00715   assert(file_info->signature == WizardSignature);
00716   *buffer=(unsigned char) '\0';
00717   status=ReadFileChunk(file_info,buffer,sizeof(buffer));
00718   if (status == WizardFalse)
00719     return(status);
00720   *value=((size_t) buffer[3]) << 24;
00721   *value|=((size_t) buffer[2]) << 16;
00722   *value|=((size_t) buffer[1]) << 8;
00723   *value|=((size_t) buffer[0]);
00724   return(status);
00725 }
00726 
00727 /*
00728 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00729 %                                                                             %
00730 %                                                                             %
00731 %                                                                             %
00732 %  R e a d F i l e 6 4 B i t s                                                %
00733 %                                                                             %
00734 %                                                                             %
00735 %                                                                             %
00736 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00737 %
00738 %  ReadFile64Bits() reads a 64-bit quantity in least-significant byte first
00739 %  order and returns it.
00740 %
00741 %  The format of the ReadFile64Bits method is:
00742 %
00743 %      WizardBooleanType ReadFile64Bits(FileInfo *file_info,
00744 %        WizardSizeType *value)
00745 %
00746 %  A description of each parameter follows.
00747 %
00748 %    o file_info: The image.
00749 %
00750 %    o value: The value.
00751 %
00752 */
00753 WizardExport WizardBooleanType ReadFile64Bits(FileInfo *file_info,
00754   WizardSizeType *value)
00755 {
00756   WizardBooleanType
00757     status;
00758 
00759   unsigned char
00760     buffer[8];
00761 
00762   assert(file_info != (FileInfo *) NULL);
00763   assert(file_info->signature == WizardSignature);
00764   *buffer=(unsigned char) '\0';
00765   status=ReadFileChunk(file_info,buffer,sizeof(buffer));
00766   if (status == WizardFalse)
00767     return(status);
00768   *value=((WizardSizeType) buffer[7]) << 56;
00769   *value|=((WizardSizeType) buffer[6]) << 48;
00770   *value|=((WizardSizeType) buffer[5]) << 40;
00771   *value|=((WizardSizeType) buffer[4]) << 32;
00772   *value|=((WizardSizeType) buffer[3]) << 24;
00773   *value|=((WizardSizeType) buffer[2]) << 16;
00774   *value|=((WizardSizeType) buffer[1]) << 8;
00775   *value|=(WizardSizeType) buffer[0];
00776   return(status);
00777 }
00778 
00779 /*
00780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00781 %                                                                             %
00782 %                                                                             %
00783 %                                                                             %
00784 %   R e l i n q u i s h F i l e L o c k                                       %
00785 %                                                                             %
00786 %                                                                             %
00787 %                                                                             %
00788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00789 %
00790 %  RelinquishFileLock() relinquishes a file lock.
00791 %
00792 %  The format of the RelinquishFileLock method is:
00793 %
00794 %      WizardBooleanType RelinquishFileLock(FileInfo *file_info,
00795 %        ExceptionInfo *exception)
00796 %
00797 %  A description of each parameter follows:
00798 %
00799 %    o file_info: The file info.
00800 %
00801 %    o exception: Return any errors or warnings in this structure.
00802 %
00803 */
00804 static WizardBooleanType RelinquishFileLock(FileInfo *file_info,
00805   ExceptionInfo *exception)
00806 {
00807   char
00808     *path;
00809 
00810   path=AcquireString(file_info->path);
00811   AppendFileExtension("lck",path);
00812   if (remove_utf8(path) == -1)
00813     {
00814       (void) ThrowWizardException(exception,GetWizardModule(),FileError,
00815         "unable to remove file `%s': %s",path,strerror(errno));
00816       path=DestroyString(path);
00817       return(WizardFalse);
00818     }
00819   path=DestroyString(path);
00820   return(WizardTrue);
00821 }
00822 
00823 /*
00824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00825 %                                                                             %
00826 %                                                                             %
00827 %                                                                             %
00828 %   W r i t e F i l e C h u n k                                               %
00829 %                                                                             %
00830 %                                                                             %
00831 %                                                                             %
00832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00833 %
00834 %  WriteFileChunk() reliably writes data to a file.
00835 %
00836 %  The format of the WriteFileChunk method is:
00837 %
00838 %      WizardBooleanType WriteFileChunk(FileInfo *file_info,const void *data,
00839 %        const size_t length)
00840 %
00841 %  A description of each parameter follows:
00842 %
00843 %    o file_info: The file info.
00844 %
00845 %    o data: The data.
00846 %
00847 %    o lenth: The data length in bytes.
00848 %
00849 */
00850 WizardExport WizardBooleanType WriteFileChunk(FileInfo *file_info,
00851   const void *data,const size_t length)
00852 {
00853   register ssize_t
00854     i;
00855 
00856   ssize_t
00857     count;
00858 
00859   assert(file_info != (FileInfo *) NULL);
00860   assert(file_info->signature == WizardSignature);
00861   (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",file_info->path);
00862   for (i=0; i < (ssize_t) length; i+=count)
00863   {
00864     count=write(file_info->file,(unsigned char *) data+i,length-i);
00865     if (count <= 0)
00866       {
00867         count=0;
00868         if (errno != EINTR)
00869           break;
00870       }
00871   }
00872   if (i < (ssize_t) length)
00873     return(WizardFalse);
00874   return(WizardTrue);
00875 }
00876 
00877 /*
00878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00879 %                                                                             %
00880 %                                                                             %
00881 %                                                                             %
00882 %  W r i t e F i l e 1 6 B i t s                                              %
00883 %                                                                             %
00884 %                                                                             %
00885 %                                                                             %
00886 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00887 %
00888 %  WriteFile16Bits() writes a ssize_t value as a 16-bit quantity in
00889 %  least-significant byte first order.
00890 %
00891 %  The format of the WriteFile16Bits method is:
00892 %
00893 %      WizardBooleanType WriteFile16Bits(FileInfo *file_info,
00894 %        const unsigned short value)
00895 %
00896 %  A description of each parameter follows.
00897 %
00898 %    o value:  Specifies the value to write.
00899 %
00900 %    o file_info: The image.
00901 %
00902 */
00903 WizardExport WizardBooleanType WriteFile16Bits(FileInfo *file_info,
00904   const unsigned short value)
00905 {
00906   unsigned char
00907     buffer[2];
00908 
00909   assert(file_info != (FileInfo *) NULL);
00910   assert(file_info->signature == WizardSignature);
00911   buffer[0]=(unsigned char) value;
00912   buffer[1]=(unsigned char) (value >> 8);
00913   return(WriteFileChunk(file_info,buffer,sizeof(buffer)));
00914 }
00915 
00916 /*
00917 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00918 %                                                                             %
00919 %                                                                             %
00920 %                                                                             %
00921 %  W r i t e F i l e 3 2 B i t s                                              %
00922 %                                                                             %
00923 %                                                                             %
00924 %                                                                             %
00925 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00926 %
00927 %  WriteFile32Bits() writes a ssize_t value as a 32-bit quantity in
00928 %  least-significant byte first order.
00929 %
00930 %  The format of the WriteFile32Bits method is:
00931 %
00932 %      WizardBooleanType WriteFile32Bits(FileInfo *file_info,
00933 %        const size_t value)
00934 %
00935 %  A description of each parameter follows.
00936 %
00937 %    o value:  Specifies the value to write.
00938 %
00939 %    o file_info: The image.
00940 %
00941 */
00942 WizardExport WizardBooleanType WriteFile32Bits(FileInfo *file_info,
00943   const size_t value)
00944 {
00945   unsigned char
00946     buffer[4];
00947 
00948   (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
00949   assert(file_info != (FileInfo *) NULL);
00950   buffer[0]=(unsigned char) value;
00951   buffer[1]=(unsigned char) (value >> 8);
00952   buffer[2]=(unsigned char) (value >> 16);
00953   buffer[3]=(unsigned char) (value >> 24);
00954   return(WriteFileChunk(file_info,buffer,sizeof(buffer)));
00955 }
00956 
00957 /*
00958 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00959 %                                                                             %
00960 %                                                                             %
00961 %                                                                             %
00962 %  W r i t e F i l e 6 4 B i t s                                              %
00963 %                                                                             %
00964 %                                                                             %
00965 %                                                                             %
00966 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00967 %
00968 %  WriteFile64Bits() writes a ssize_t value as a 64-bit quantity in
00969 %  least-significant byte first order.
00970 %
00971 %  The format of the WriteFile64Bits method is:
00972 %
00973 %      WizardBooleanType WriteFile64Bits(FileInfo *file_info,
00974 %        const WizardSizeType value)
00975 %
00976 %  A description of each parameter follows.
00977 %
00978 %    o value:  Specifies the value to write.
00979 %
00980 %    o file_info: The image.
00981 %
00982 */
00983 WizardExport WizardBooleanType WriteFile64Bits(FileInfo *file_info,
00984   const WizardSizeType value)
00985 {
00986   unsigned char
00987     buffer[8];
00988 
00989   (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
00990   assert(file_info != (FileInfo *) NULL);
00991   buffer[0]=(unsigned char) value;
00992   buffer[1]=(unsigned char) (value >> 8);
00993   buffer[2]=(unsigned char) (value >> 16);
00994   buffer[3]=(unsigned char) (value >> 24);
00995   buffer[4]=(unsigned char) (value >> 32);
00996   buffer[5]=(unsigned char) (value >> 40);
00997   buffer[6]=(unsigned char) (value >> 48);
00998   buffer[7]=(unsigned char) (value >> 56);
00999   return(WriteFileChunk(file_info,buffer,sizeof(buffer)));
01000 }