root/WizardsToolkit/trunk/wizard/file.c

Revision 459, 34.9 KB (checked in by cristy, 4 weeks ago)
Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                         FFFFF  IIIII  L      EEEEE                          %
6%                         F        I    L      E                              %
7%                         FFF      I    L      EEE                            %
8%                         F        I    L      E                              %
9%                         F      IIIII  LLLLL  EEEEE                          %
10%                                                                             %
11%                                                                             %
12%                         Wizard's Toolkit File Methods                       %
13%                                                                             %
14%                             Software Design                                 %
15%                               John Cristy                                   %
16%                               March 2003                                    %
17%                                                                             %
18%                                                                             %
19%  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
20%  dedicated to making software imaging solutions freely available.           %
21%                                                                             %
22%  You may not use this file except in compliance with the License.  You may  %
23%  obtain a copy of the License at                                            %
24%                                                                             %
25%    http://www.wizards-toolkit.org/script/license.php                        %
26%                                                                             %
27%  Unless required by applicable law or agreed to in writing, software        %
28%  distributed under the License is distributed on an "AS IS" BASIS,          %
29%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
30%  See the License for the specific language governing permissions and        %
31%  limitations under the License.                                             %
32%                                                                             %
33%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34%
35%
36%
37*/
38
39/*
40  Include declarations.
41*/
42#include "wizard/studio.h"
43#include "wizard/blob.h"
44#include "wizard/exception.h"
45#include "wizard/exception-private.h"
46#include "wizard/file.h"
47#include "wizard/memory_.h"
48#include "wizard/semaphore.h"
49#include "wizard/string_.h"
50#include "wizard/utility.h"
51#if defined(WIZARDSTOOLKIT_HAVE_PTHREAD)
52#include <pthread.h>
53#endif
54#if defined(__WINDOWS__)
55#include <windows.h>
56#endif
57
58/*
59  Forward declarations.
60*/
61static WizardBooleanType
62  RelinquishFileLock(FileInfo *,ExceptionInfo *);
63
64/*
65  Typedef declarations.
66*/
67struct _FileInfo
68{
69  char
70    *path;
71
72  int
73    file;
74
75  struct stat
76    properties;
77
78  SemaphoreInfo
79    *semaphore;
80
81  time_t
82    timestamp;
83
84  unsigned long
85    signature;
86};
87
88/*
89%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
90%                                                                             %
91%                                                                             %
92%                                                                             %
93%   A c q u i r e F i l e L o c k                                             %
94%                                                                             %
95%                                                                             %
96%                                                                             %
97%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
98%
99%  AcquireFileLock() acquires a lock for a file.
100%
101%  The format of the AcquireFileLock method is:
102%
103%      WizardBooleanType AcquireFileLock(FileInfo *file_info,
104%        ExceptionInfo *exception)
105%
106%  A description of each parameter follows:
107%
108%    o file_info: The file info.
109%
110%    o exception: Return any errors or warnings in this structure.
111%
112*/
113
114static unsigned long GetWizardThreadId(void)
115{
116#if defined(WIZARDSTOOLKIT_HAVE_PTHREAD)
117  return((unsigned long) pthread_self());
118#endif
119#if defined(__WINDOWS__)
120  return((unsigned long) GetCurrentThreadId());
121#endif
122  return((unsigned long) getpid());
123}
124
125static WizardBooleanType AcquireFileLock(FileInfo *file_info,
126  ExceptionInfo *exception)
127{
128  char
129    *path;
130
131  long
132    pid;
133
134  register long
135    i;
136
137  unsigned long
138    tid;
139
140  WizardStatusType
141    status;
142
143  /*
144    Engage primitive atomic lock.
145  */
146  assert(file_info != (FileInfo *) NULL);
147  assert(file_info->signature == WizardSignature);
148  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",file_info->path);
149  (void) LockSemaphoreInfo(file_info->semaphore);
150  path=AcquireString(file_info->path);
151  AppendFileExtension("lck",path);
152  for (i=0; i < 10; i++)
153  {
154    file_info->file=open(path,O_WRONLY | O_CREAT | O_EXCL,S_MODE);
155    if (file_info->file == -1)
156      {
157        if (errno != EEXIST)
158          break;
159        file_info->file=open(path,O_RDONLY);
160        if (file_info->file == -1)
161          break;
162        pid=(-1);
163        tid=(~0UL);
164        status=ReadFileChunk(file_info,&pid,sizeof(pid));
165        status|=ReadFileChunk(file_info,&tid,sizeof(tid));
166        if (close(file_info->file) == -1)
167          (void) ThrowWizardException(exception,GetWizardModule(),FileError,
168            "unable to close file `%s': %s",path,strerror(errno));
169        file_info->file=(-1);
170        if (status != WizardFalse)
171          {
172            WizardBooleanType
173              active_process;
174
175            if ((pid == (long) getpid()) && (tid == GetWizardThreadId()))
176              {
177                path=DestroyString(path);
178                (void) UnlockSemaphoreInfo(file_info->semaphore);
179                return(WizardTrue);
180              }
181#if defined(__WINDOWS__)
182            {
183              HANDLE
184                handle;
185
186              handle=OpenProcess(PROCESS_ALL_ACCESS,FALSE,(DWORD) pid);
187              active_process=handle == (HANDLE) NULL ? WizardFalse : WizardTrue;
188              if (handle != (HANDLE) NULL)
189                CloseHandle(handle);
190            }
191#else
192            active_process=kill((pid_t) pid,0) == -1 ? WizardFalse : WizardTrue;
193#endif
194            if (active_process == WizardFalse)
195              {
196                if (errno != ESRCH)
197                  break;
198                i--;
199                if (remove(path) == -1)
200                  (void) ThrowWizardException(exception,GetWizardModule(),
201                    FileError,"unable to remove file `%s': %s",path,
202                    strerror(errno));
203                break;
204              }
205          }
206        (void) sleep(1);
207        continue;
208      }
209    pid=(long) getpid();
210    status=WriteFileChunk(file_info,&pid,sizeof(pid));
211    tid=GetWizardThreadId();
212    status=WriteFileChunk(file_info,&tid,sizeof(tid));
213    if (close(file_info->file) == -1)
214      (void) ThrowWizardException(exception,GetWizardModule(),FileError,
215        "unable to close file `%s': %s",path,strerror(errno));
216    file_info->file=(-1);
217    if (status == WizardFalse)
218      break;
219    i--;
220  }
221  path=DestroyString(path);
222  (void) UnlockSemaphoreInfo(file_info->semaphore);
223  return(WizardFalse);
224}
225
226/*
227%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %                                                                             %
228%                                                                             %
229%                                                                             %
230%   A c q u i r e F i l e I n f o                                             %
231%                                                                             %
232%                                                                             %
233%                                                                             %
234%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235%
236%  AcquireFileInfo() opens the file for reading or writing and returns a
237%  FileInfo structure.
238%
239%  The format of the AcquireFileInfo method is:
240%
241%      FileInfo *AcquireFileInfo(const char *path,const char *relative_path,
242%        const FileMode mode,ExceptionInfo *exception)
243%
244%  A description of each parameter follows:
245%
246%    o path: The file path.
247%
248%    o relative_path: The path relative to the default path.
249%
250%    o mode: The file I/O mode.
251%
252%    o exception: Return any errors or warnings in this structure.
253%
254*/
255WizardExport FileInfo *AcquireFileInfo(const char *path,
256  const char *relative_path,const FileMode mode,ExceptionInfo *exception)
257{
258  char
259    *home;
260
261  FileInfo
262    *file_info;
263
264  /*
265    Acquire file info.
266  */
267  assert(relative_path != (char *) NULL);
268  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",relative_path);
269  assert(exception != (ExceptionInfo *) NULL);
270  file_info=(FileInfo *) AcquireWizardMemory(sizeof(*file_info));
271  if (file_info == (FileInfo *) NULL)
272    {
273      (void) ThrowWizardException(exception,GetWizardModule(),FileError,
274        "memory allocation failed `%s'",strerror(errno));
275      return((FileInfo *) NULL);
276    }
277  (void) ResetWizardMemory(file_info,0,sizeof(*file_info));
278  file_info->path=AcquireString((char *) NULL);
279  file_info->file=(-1);
280  file_info->semaphore=AllocateSemaphoreInfo();
281  file_info->timestamp=time((time_t *) NULL);
282  file_info->signature=WizardSignature;
283  if (path != (char *) NULL)
284    (void) CopyWizardString(file_info->path,path,MaxTextExtent);
285  else
286    {
287      /*
288        Default location for key ring, random state, etc.
289      */
290      *file_info->path='\0';
291      home=GetEnvironmentValue("WIZARD_HOME");
292      if (home != (char *) NULL)
293        {
294          (void) CopyWizardString(file_info->path,home,MaxTextExtent);
295          (void) ConcatenateWizardString(file_info->path,DirectorySeparator,
296            MaxTextExtent);
297          home=(char *) RelinquishWizardMemory(home);
298        }
299      else
300        {
301          home=GetEnvironmentValue("HOME");
302          if (home == (char *) NULL)
303            home=GetEnvironmentValue("USERPROFILE");
304          if (home != (char *) NULL)
305            {
306              (void) CopyWizardString(file_info->path,home,MaxTextExtent);
307              (void) ConcatenateWizardString(file_info->path,
308                DirectorySeparator,MaxTextExtent);
309              (void) ConcatenateWizardString(file_info->path,".wizard",
310                MaxTextExtent);
311#if defined(__WINDOWS__)
312              (void) mkdir(file_info->path);
313#else
314              (void) mkdir(file_info->path,0700);
315#endif
316              (void) ConcatenateWizardString(file_info->path,
317                DirectorySeparator,MaxTextExtent);
318              home=(char *) RelinquishWizardMemory(home);
319            }
320        }
321      (void) ConcatenateWizardString(file_info->path,relative_path,
322        MaxTextExtent);
323    }
324  if (AcquireFileLock(file_info,exception) == WizardFalse)
325    {
326      file_info=DestroyFileInfo(file_info,exception);
327      return((FileInfo *) NULL);
328    }
329  /*
330    Open file.
331  */
332  switch (mode)
333  {
334    case ReadFileMode:
335    {
336      file_info->file=open(file_info->path,O_RDONLY | O_BINARY);
337      break;
338    }
339    case WriteFileMode:
340    {
341      file_info->file=open(file_info->path,O_RDWR | O_CREAT | O_BINARY,
342        S_MODE);
343      break;
344    }
345    default:
346    {
347      (void) ThrowWizardException(exception,GetWizardModule(),FileError,
348        "Invalid file mode `%s'",path);
349      file_info=DestroyFileInfo(file_info,exception);
350      return((FileInfo *) NULL);
351    }
352  }
353  if (file_info->file < 0)
354    {
355      file_info=DestroyFileInfo(file_info,exception);
356      return((FileInfo *) NULL);
357    }
358  (void) fstat(file_info->file,&file_info->properties);
359  return(file_info);
360}
361
362/*
363%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
364%                                                                             %
365%                                                                             %
366%                                                                             %
367%   D e s t r o y F i l e                                                     %
368%                                                                             %
369%                                                                             %
370%                                                                             %
371%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
372%
373%  DestroyFile() destroys the file on disk.
374%
375%  The format of the DestroyFile method is:
376%
377%      WizardBooleanType DestroyFile(FileInfo *file_info,
378%        Exceptioninfo *exception)
379%
380%  A description of each parameter follows:
381%
382%    o file_info: The file info.
383%
384%    o exception: Return any errors or warnings in this structure.
385%
386*/
387WizardExport WizardBooleanType DestroyFile(FileInfo *file_info,
388  ExceptionInfo *exception)
389{
390  if (file_info->file >= 0)
391    if (close(file_info->file) == -1)
392      {
393        (void) ThrowWizardException(exception,GetWizardModule(),FileError,
394          "unable to close file `%s': %s",file_info->path,strerror(errno));
395        return(WizardFalse);
396      }
397  file_info->file=(-1);
398  if (remove(file_info->path) == -1)
399    {
400      (void) ThrowWizardException(exception,GetWizardModule(),FileError,
401        "unable to close file `%s': %s",file_info->path,strerror(errno));
402      return(WizardFalse);
403    }
404  return(WizardTrue);
405}
406
407/*
408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
409%                                                                             %
410%                                                                             %
411%                                                                             %
412%   D e s t r o y F i l e I n f o                                             %
413%                                                                             %
414%                                                                             %
415%                                                                             %
416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
417%
418%  DestroyFileInfo() destroys the file info structure.
419%
420%  The format of the DestroyFileInfo method is:
421%
422%      FileInfo *DestroyFileInfo(FileInfo *file_info)
423%
424%  A description of each parameter follows:
425%
426%    o path: The file name.
427%
428*/
429WizardExport FileInfo *DestroyFileInfo(FileInfo *file_info,
430  ExceptionInfo *exception)
431{
432  assert(file_info != (FileInfo *) NULL);
433  assert(file_info->signature == WizardSignature);
434  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",file_info->path);
435  (void) LockSemaphoreInfo(file_info->semaphore);
436  if (file_info->file >= 0)
437    if (close(file_info->file) == -1)
438      (void) ThrowWizardException(exception,GetWizardModule(),FileError,
439        "unable to close file `%s': %s",file_info->path,strerror(errno));
440  file_info->file=(-1);
441  (void) RelinquishFileLock(file_info,exception);
442  if (file_info->path != (char *) NULL)
443    file_info->path=DestroyString(file_info->path);
444  file_info->signature=(~WizardSignature);
445  (void) UnlockSemaphoreInfo(file_info->semaphore);
446  DestroySemaphoreInfo(&file_info->semaphore);
447  file_info=(FileInfo *) RelinquishWizardMemory(file_info);
448  return(file_info);
449}
450
451/*
452%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453%                                                                             %
454%                                                                             %
455%                                                                             %
456%   G e t F i l e D e s c r i p t o r                                         %
457%                                                                             %
458%                                                                             %
459%                                                                             %
460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
461%
462%  GetFileDescriptor() returns the file descriptor.
463%
464%  The format of the GetFileDescriptor method is:
465%
466%      int GetFileDescriptor(const FileInfo *file_info)
467%
468%  A description of each parameter follows:
469%
470%    o file_info: The file info.
471%
472*/
473WizardExport int GetFileDescriptor(const FileInfo *file_info)
474{
475  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
476  assert(file_info != (FileInfo *) NULL);
477  assert(file_info->signature == WizardSignature);
478  return(file_info->file);
479}
480
481/*
482%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
483%                                                                             %
484%                                                                             %
485%                                                                             %
486%   G e t F i l e P a t h                                                     %
487%                                                                             %
488%                                                                             %
489%                                                                             %
490%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
491%
492%  GetFilePath() returns the file path.
493%
494%  The format of the GetFilePath method is:
495%
496%      const const char *GetFilePath(const FileInfo *file_info)
497%
498%  A description of each parameter follows:
499%
500%    o file_info: The file info.
501%
502*/
503WizardExport const char *GetFilePath(const FileInfo *file_info)
504{
505  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
506  assert(file_info != (FileInfo *) NULL);
507  assert(file_info->signature == WizardSignature);
508  return(file_info->path);
509}
510
511/*
512%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
513%                                                                             %
514%                                                                             %
515%                                                                             %
516%   G e t F i l e P r o p e r t i e s                                         %
517%                                                                             %
518%                                                                             %
519%                                                                             %
520%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
521%
522%  GetFileproperties() returns the file properties.
523%
524%  The format of the GetFileProperties method is:
525%
526%      const struct stat *GetFileProperties(const FileInfo *file_info)
527%
528%  A description of each parameter follows:
529%
530%    o file_info: The file info.
531%
532*/
533WizardExport const struct stat *GetFileProperties(const FileInfo *file_info)
534{
535  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
536  assert(file_info != (FileInfo *) NULL);
537  assert(file_info->signature == WizardSignature);
538  return(&file_info->properties);
539}
540
541/*
542%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
543%                                                                             %
544%                                                                             %
545%                                                                             %
546%  R e a d F i l e B y t e                                                    %
547%                                                                             %
548%                                                                             %
549%                                                                             %
550%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
551%
552%  ReadFileByte() returns the character read as an unsigned char cast to an
553%  integer or EOF on end of file or error.
554%
555%  The format of the ReadFileByte method is:
556%
557%      int ReadFileByte(FileInfo *file_info)
558%
559%  A description of each parameter follows.
560%
561%    o file_info: the blob info.
562%
563*/
564WizardExport int ReadFileByte(FileInfo *file_info)
565{
566  unsigned char
567    buffer[1];
568
569  assert(file_info != (FileInfo *) NULL);
570  assert(file_info->signature == WizardSignature);
571  if (ReadFileChunk(file_info,buffer,1) == WizardFalse)
572    return(EOF);
573  return((int) (*buffer));
574}
575
576/*
577%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
578%                                                                             %
579%                                                                             %
580%                                                                             %
581%   R e a d F i l e C h u n k                                                 %
582%                                                                             %
583%                                                                             %
584%                                                                             %
585%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
586%
587%  ReadFileChunk() reliably reads a chunk of data from a file.  It returns
588%  WizardTrue if all the data requested is read otherwise WizardFalse.
589%
590%  The format of the ReadFileChunk method is:
591%
592%      WizardBooleanType ReadFileChunk(FileInfo *file_info,const void *data,
593%        const size_t length)
594%
595%  A description of each parameter follows:
596%
597%    o file_info: The file info.
598%
599%    o data: The data.
600%
601%    o length: The data length in bytes.
602%
603*/
604WizardExport WizardBooleanType ReadFileChunk(FileInfo *file_info,void *data,
605  const size_t length)
606{
607  register ssize_t
608    i;
609
610  ssize_t
611    count;
612
613  assert(file_info != (FileInfo *) NULL);
614  assert(file_info->signature == WizardSignature);
615  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",file_info->path);
616  for (i=0; i < (ssize_t) length; i+=count)
617  {
618    count=read(file_info->file,(unsigned char *) data+i,Min(length-i,(size_t)
619      WizardMaxBufferExtent));
620    if (count <= 0)
621      {
622        count=0;
623        if (errno != EINTR)
624          break;
625      }
626  }
627  if (i < (ssize_t) length)
628    return(WizardFalse);
629  return(WizardTrue);
630}
631
632/*
633%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
634%                                                                             %
635%                                                                             %
636%                                                                             %
637%  R e a d F i l e 1 6 B i t s                                                %
638%                                                                             %
639%                                                                             %
640%                                                                             %
641%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
642%
643%  ReadFile16Bits() reads a 16-bit quantity in least-significant byte first
644%  order and returns it.
645%
646%  The format of the ReadFile16Bits method is:
647%
648%      WizardBooleanType ReadFile16Bits(FileInfo *file_info,
649%        unsigned short *value)
650%
651%  A description of each parameter follows.
652%
653%    o file_info: The image.
654%
655%    o value: The value.
656%
657*/
658WizardExport WizardBooleanType ReadFile16Bits(FileInfo *file_info,
659  unsigned short *value)
660{
661  WizardBooleanType
662    status;
663
664  unsigned char
665    buffer[2];
666
667  assert(file_info != (FileInfo *) NULL);
668  assert(file_info->signature == WizardSignature);
669  *buffer=(unsigned char) '\0';
670  status=ReadFileChunk(file_info,buffer,sizeof(buffer));
671  if (status == WizardFalse)
672    return(status);
673  *value=(unsigned short) (buffer[1] << 8);
674  *value|=(unsigned short) buffer[0];
675  return(status);
676}
677
678/*
679%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
680%                                                                             %
681%                                                                             %
682%                                                                             %
683%  R e a d F i l e 3 2 B i t s                                                %
684%                                                                             %
685%                                                                             %
686%                                                                             %
687%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
688%
689%  ReadFile32Bits() reads a 32-bit quantity in least-significant byte first
690%  order and returns it.
691%
692%  The format of the ReadFile32Bits method is:
693%
694%      WizardBooleanType ReadFile32Bits(FileInfo *file_info,
695%        unsigned long *value)
696%
697%  A description of each parameter follows.
698%
699%    o file_info: The image.
700%
701%    o value: The value.
702%
703*/
704WizardExport WizardBooleanType ReadFile32Bits(FileInfo *file_info,
705  unsigned long *value)
706{
707  WizardBooleanType
708    status;
709
710  unsigned char
711    buffer[4];
712
713  assert(file_info != (FileInfo *) NULL);
714  assert(file_info->signature == WizardSignature);
715  *buffer=(unsigned char) '\0';
716  status=ReadFileChunk(file_info,buffer,sizeof(buffer));
717  if (status == WizardFalse)
718    return(status);
719  *value=((unsigned long) buffer[3]) << 24;
720  *value|=((unsigned long) buffer[2]) << 16;
721  *value|=((unsigned long) buffer[1]) << 8;
722  *value|=((unsigned long) buffer[0]);
723  return(status);
724}
725
726/*
727%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
728%                                                                             %
729%                                                                             %
730%                                                                             %
731%  R e a d F i l e 6 4 B i t s                                                %
732%                                                                             %
733%                                                                             %
734%                                                                             %
735%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
736%
737%  ReadFile64Bits() reads a 64-bit quantity in least-significant byte first
738%  order and returns it.
739%
740%  The format of the ReadFile64Bits method is:
741%
742%      WizardBooleanType ReadFile64Bits(FileInfo *file_info,
743%        WizardSizeType *value)
744%
745%  A description of each parameter follows.
746%
747%    o file_info: The image.
748%
749%    o value: The value.
750%
751*/
752WizardExport WizardBooleanType ReadFile64Bits(FileInfo *file_info,
753  WizardSizeType *value)
754{
755  WizardBooleanType
756    status;
757
758  unsigned char
759    buffer[8];
760
761  assert(file_info != (FileInfo *) NULL);
762  assert(file_info->signature == WizardSignature);
763  *buffer=(unsigned char) '\0';
764  status=ReadFileChunk(file_info,buffer,sizeof(buffer));
765  if (status == WizardFalse)
766    return(status);
767  *value=((WizardSizeType) buffer[7]) << 56;
768  *value|=((WizardSizeType) buffer[6]) << 48;
769  *value|=((WizardSizeType) buffer[5]) << 40;
770  *value|=((WizardSizeType) buffer[4]) << 32;
771  *value|=((WizardSizeType) buffer[3]) << 24;
772  *value|=((WizardSizeType) buffer[2]) << 16;
773  *value|=((WizardSizeType) buffer[1]) << 8;
774  *value|=(WizardSizeType) buffer[0];
775  return(status);
776}
777
778/*
779%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
780%                                                                             %
781%                                                                             %
782%                                                                             %
783%   R e l i n q u i s h F i l e L o c k                                       %
784%                                                                             %
785%                                                                             %
786%                                                                             %
787%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
788%
789%  RelinquishFileLock() relinquishes a file lock.
790%
791%  The format of the RelinquishFileLock method is:
792%
793%      WizardBooleanType RelinquishFileLock(FileInfo *file_info,
794%        ExceptionInfo *exception)
795%
796%  A description of each parameter follows:
797%
798%    o file_info: The file info.
799%
800%    o exception: Return any errors or warnings in this structure.
801%
802*/
803static WizardBooleanType RelinquishFileLock(FileInfo *file_info,
804  ExceptionInfo *exception)
805{
806  char
807    *path;
808
809  path=AcquireString(file_info->path);
810  AppendFileExtension("lck",path);
811  if (remove(path) == -1)
812    {
813      (void) ThrowWizardException(exception,GetWizardModule(),FileError,
814        "unable to remove file `%s': %s",path,strerror(errno));
815      path=DestroyString(path);
816      return(WizardFalse);
817    }
818  path=DestroyString(path);
819  return(WizardTrue);
820}
821
822/*
823%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824%                                                                             %
825%                                                                             %
826%                                                                             %
827%   W r i t e F i l e C h u n k                                               %
828%                                                                             %
829%                                                                             %
830%                                                                             %
831%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
832%
833%  WriteFileChunk() reliably writes data to a file.
834%
835%  The format of the WriteFileChunk method is:
836%
837%      WizardBooleanType WriteFileChunk(FileInfo *file_info,const void *data,
838%        const size_t length)
839%
840%  A description of each parameter follows:
841%
842%    o file_info: The file info.
843%
844%    o data: The data.
845%
846%    o lenth: The data length in bytes.
847%
848*/
849WizardExport WizardBooleanType WriteFileChunk(FileInfo *file_info,
850  const void *data,const size_t length)
851{
852  register ssize_t
853    i;
854
855  ssize_t
856    count;
857
858  assert(file_info != (FileInfo *) NULL);
859  assert(file_info->signature == WizardSignature);
860  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"%s",file_info->path);
861  for (i=0; i < (ssize_t) length; i+=count)
862  {
863    count=write(file_info->file,(unsigned char *) data+i,length-i);
864    if (count <= 0)
865      {
866        count=0;
867        if (errno != EINTR)
868          break;
869      }
870  }
871  if (i < (ssize_t) length)
872    return(WizardFalse);
873  return(WizardTrue);
874}
875
876/*
877%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
878%                                                                             %
879%                                                                             %
880%                                                                             %
881%  W r i t e F i l e 1 6 B i t s                                              %
882%                                                                             %
883%                                                                             %
884%                                                                             %
885%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
886%
887%  WriteFile16Bits() writes a long value as a 16-bit quantity in
888%  least-significant byte first order.
889%
890%  The format of the WriteFile16Bits method is:
891%
892%      WizardBooleanType WriteFile16Bits(FileInfo *file_info,
893%        const unsigned short value)
894%
895%  A description of each parameter follows.
896%
897%    o value:  Specifies the value to write.
898%
899%    o file_info: The image.
900%
901*/
902WizardExport WizardBooleanType WriteFile16Bits(FileInfo *file_info,
903  const unsigned short value)
904{
905  unsigned char
906    buffer[2];
907
908  assert(file_info != (FileInfo *) NULL);
909  assert(file_info->signature == WizardSignature);
910  buffer[0]=(unsigned char) value;
911  buffer[1]=(unsigned char) (value >> 8);
912  return(WriteFileChunk(file_info,buffer,sizeof(buffer)));
913}
914
915/*
916%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
917%                                                                             %
918%                                                                             %
919%                                                                             %
920%  W r i t e F i l e 3 2 B i t s                                              %
921%                                                                             %
922%                                                                             %
923%                                                                             %
924%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
925%
926%  WriteFile32Bits() writes a long value as a 32-bit quantity in
927%  least-significant byte first order.
928%
929%  The format of the WriteFile32Bits method is:
930%
931%      WizardBooleanType WriteFile32Bits(FileInfo *file_info,
932%        const unsigned long value)
933%
934%  A description of each parameter follows.
935%
936%    o value:  Specifies the value to write.
937%
938%    o file_info: The image.
939%
940*/
941WizardExport WizardBooleanType WriteFile32Bits(FileInfo *file_info,
942  const unsigned long value)
943{
944  unsigned char
945    buffer[4];
946
947  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
948  assert(file_info != (FileInfo *) NULL);
949  buffer[0]=(unsigned char) value;
950  buffer[1]=(unsigned char) (value >> 8);
951  buffer[2]=(unsigned char) (value >> 16);
952  buffer[3]=(unsigned char) (value >> 24);
953  return(WriteFileChunk(file_info,buffer,sizeof(buffer)));
954}
955
956/*
957%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
958%                                                                             %
959%                                                                             %
960%                                                                             %
961%  W r i t e F i l e 6 4 B i t s                                              %
962%                                                                             %
963%                                                                             %
964%                                                                             %
965%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
966%
967%  WriteFile64Bits() writes a long value as a 64-bit quantity in
968%  least-significant byte first order.
969%
970%  The format of the WriteFile64Bits method is:
971%
972%      WizardBooleanType WriteFile64Bits(FileInfo *file_info,
973%        const WizardSizeType value)
974%
975%  A description of each parameter follows.
976%
977%    o value:  Specifies the value to write.
978%
979%    o file_info: The image.
980%
981*/
982WizardExport WizardBooleanType WriteFile64Bits(FileInfo *file_info,
983  const WizardSizeType value)
984{
985  unsigned char
986    buffer[8];
987
988  (void) LogWizardEvent(TraceEvent,GetWizardModule(),"...");
989  assert(file_info != (FileInfo *) NULL);
990  buffer[0]=(unsigned char) value;
991  buffer[1]=(unsigned char) (value >> 8);
992  buffer[2]=(unsigned char) (value >> 16);
993  buffer[3]=(unsigned char) (value >> 24);
994  buffer[4]=(unsigned char) (value >> 32);
995  buffer[5]=(unsigned char) (value >> 40);
996  buffer[6]=(unsigned char) (value >> 48);
997  buffer[7]=(unsigned char) (value >> 56);
998  return(WriteFileChunk(file_info,buffer,sizeof(buffer)));
999}
Note: See TracBrowser for help on using the browser.