source: abuse/trunk/src/imlib/specs.cpp @ 529

Last change on this file since 529 was 529, checked in by Sam Hocevar, 11 years ago

imlib: remove unused bFILE::set_read_buffer_size.

File size: 20.2 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This software was released into the Public Domain. As with most public
7 *  domain software, no warranty is made or implied by Crack dot Com or
8 *  Jonathan Clark.
9 */
10
11#include "config.h"
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <stdint.h>
16#include <ctype.h>
17#include <fcntl.h>
18#include <math.h>
19#include <unistd.h>
20#if (defined(__MACH__) || !defined(__APPLE__))
21#   include <sys/types.h>
22#   include <sys/stat.h>
23#endif
24
25#include "common.h"
26
27#include "image.h"
28#include "palette.h"
29#include "specs.h"
30#include "dprint.h"
31
32char const *spec_types[] =
33{
34    "Invalid type", // 0
35    "Color table",  // 1
36    "Palette",      // 2
37    "Invalid Type", // 3
38    "Image",        // 4
39    "Fore Tile",
40    "Back Tile",
41    "Character",
42    "8 Morph",
43    "16 Morph",
44    "Grue objs",
45    "Extern WAV",
46    "DMX MUS",
47    "Patched morph",
48    "Normal file",
49    "Compress1 file",
50    "Vector Image",
51    "Light list",
52    "Grue fgmap",
53    "Grue bgmap",
54    "Data array",
55    "Character2",
56    "Particle",
57    "Extern lcache"
58};
59
60
61int total_files_open=0;
62char spec_main_file[100];
63
64static char *spec_prefix=NULL;
65static char *save_spec_prefix=NULL;
66
67static jFILE spec_main_jfile((FILE*)0);
68static int spec_main_fd = -1;
69static long spec_main_offset = -1;
70static spec_directory spec_main_sd;
71
72static int fast_load_fd = -1;
73static int fast_load_mode = 0;
74
75void set_filename_prefix(char const *prefix)
76{
77    if( spec_prefix )
78    {
79        free( spec_prefix );
80    }
81
82    if( prefix )
83    {
84        spec_prefix = strcpy( (char *)malloc( strlen( prefix ) + 2 ), prefix );
85        int len = strlen( prefix );
86        if( prefix[len - 1] != '\\' && prefix[len - 1] != '/')
87        {
88            spec_prefix[len] = '/';
89            spec_prefix[len + 1] = 0;
90        }
91    }
92    else
93    {
94        spec_prefix = NULL;
95    }
96}
97
98char *get_filename_prefix()
99{
100    return spec_prefix;
101}
102
103
104void set_save_filename_prefix(char const *save_prefix)
105{
106    if( save_spec_prefix )
107    {
108        free( save_spec_prefix );
109    }
110
111    if( save_prefix )
112    {
113        int len = strlen( save_prefix );
114        save_spec_prefix = (char *)malloc( len + 1 );
115        strcpy( save_spec_prefix, save_prefix );
116/* AK - Commented this out as it may cause problems
117        if( save_prefix[len - 1] != '\\' && save_prefix[len - 1] != '/' )
118        {
119            save_spec_prefix[len] = '/';
120            save_spec_prefix[len + 1] = '\0';
121        } */
122    }
123    else
124    {
125        save_spec_prefix = NULL;
126    }
127}
128
129char *get_save_filename_prefix()
130{
131  return save_spec_prefix;
132}
133
134int search_order=SPEC_SEARCH_OUTSIDE_INSIDE;
135
136static void (*no_space_handle_fun)()=NULL;
137
138void set_no_space_handler(void (*handle_fun)())
139{
140  no_space_handle_fun=handle_fun;
141}
142
143
144bFILE::bFILE()
145{
146  rbuf_size=8192;
147  rbuf=(unsigned char *)malloc(rbuf_size);
148  rbuf_start=rbuf_end=0;
149
150  wbuf_size=8192;
151  wbuf=(unsigned char *)malloc(wbuf_size);
152  wbuf_end=0;
153}
154
155bFILE::~bFILE()
156{
157  if (rbuf) free(rbuf);
158  flush_writes();
159  if (wbuf) free(wbuf);
160}
161
162int bFILE::flush_writes()
163{
164  if (wbuf_end!=0)
165  {
166    unsigned long ret=unbuffered_write(wbuf,wbuf_end);
167    if (ret!=wbuf_end && no_space_handle_fun)
168      no_space_handle_fun();
169
170    wbuf_end=0;
171    return ret;
172  }
173  return 0;
174}
175
176int bFILE::read(void *buf, size_t count)       // returns number of bytes read, calls unbuffer_read
177{
178  if (!allow_read_buffering())
179    return unbuffered_read(buf,count);
180
181  int total_read=0,error=0;
182  if (!count) return 0;
183  while (count && !error)
184  {
185    if (rbuf_start<rbuf_end)
186    {
187      unsigned int avail_size=rbuf_end-rbuf_start;
188      int copy_size=avail_size>count ? count : avail_size;
189      memcpy(buf,rbuf+rbuf_start,copy_size);
190      buf=(void *)(((unsigned char *)buf)+copy_size);
191      rbuf_start+=copy_size;
192      if (rbuf_start>=rbuf_end)
193      {
194                if (rbuf_end!=rbuf_size)  // buffer wasn't full before so there is no way we can complete read
195                  error=1;
196                rbuf_start=rbuf_end=0;
197      }
198      total_read+=copy_size;
199      count-=copy_size;
200    } else
201    {
202      rbuf_end=unbuffered_read(rbuf,rbuf_size);
203      if (rbuf_end==0) error=1;
204      rbuf_start=0;
205    }
206  }
207  return total_read;
208}
209
210
211int bFILE::write(void const *buf, size_t count)      // returns number of bytes written
212{
213  if (allow_write_buffering())
214  {
215    int total_written=0;
216    while (count)
217    {
218      int copy_size=wbuf_end+count<=wbuf_size ? count :  wbuf_size-wbuf_end;
219      memcpy(wbuf+wbuf_end,buf,copy_size);
220      wbuf_end+=copy_size;
221      count-=copy_size;
222      buf=(void *)(((char *)buf)+copy_size);
223      if (wbuf_end==wbuf_size)
224        if ((unsigned int)flush_writes()!=wbuf_size)
225      return total_written;
226
227      total_written+=copy_size;
228    }
229    return total_written;
230  } else
231  {
232    unsigned long ret=unbuffered_write(buf,count);
233    if (ret!=count && no_space_handle_fun)
234      no_space_handle_fun();
235  }
236  return 0;
237}
238
239int bFILE::seek(long offset, int whence) // whence=SEEK_SET, SEEK_CUR, SEEK_END, ret=0=success
240{
241//    rbuf_start=rbuf_end=0;
242//    unbuffered_seek(offset,SEEK_SET);
243
244  long realpos=unbuffered_tell();
245  long curpos=realpos-rbuf_end+rbuf_start;
246  if (whence==SEEK_CUR) offset+=curpos;
247  else if (whence==SEEK_END) offset=file_size()-offset;
248
249  if (offset<realpos-(long)rbuf_end || offset>=realpos)
250  {
251    rbuf_start=rbuf_end=0;
252    unbuffered_seek(offset,SEEK_SET);
253  } else
254    rbuf_start=rbuf_end-(realpos-offset);
255  return 1;
256}
257
258int bFILE::tell()
259{
260  return unbuffered_tell()-rbuf_end+rbuf_start+
261         wbuf_end;    // if this a write file, add on how much we've written
262}
263
264int bFILE::allow_read_buffering() { return 1; }
265int bFILE::allow_write_buffering() { return 1; }
266
267void set_spec_main_file(char const *filename, int Search_order)
268{
269  dprintf("Specs : main file set to %s\n",filename);
270  strcpy(spec_main_file,filename);
271  search_order=Search_order;
272
273#if (defined(__APPLE__) && !defined(__MACH__))
274  spec_main_jfile.open_external(filename,"rb",O_BINARY|O_RDONLY);
275#else
276  spec_main_jfile.open_external(filename,"rb",O_RDONLY);
277#endif
278  spec_main_fd = spec_main_jfile.get_fd();
279  if (spec_main_fd==-1)
280    return;
281  spec_main_sd.startup(&spec_main_jfile);
282}
283
284void fast_load_start_recording(char *filename)
285{
286    fast_load_fd = ::open(filename,O_CREAT|O_RDWR,S_IRWXU | S_IRWXG | S_IRWXO);
287    fast_load_mode = 1;
288}
289
290void fast_load_stop_recording()
291{
292    fast_load_mode = 0;
293}
294
295void fast_load_start_reloading(char *filename)
296{
297    fast_load_fd = ::open(filename,O_RDONLY);
298    fast_load_mode = 2;
299}
300
301void fast_load_stop_reloading()
302{
303    fast_load_mode = 0;
304}
305
306jFILE::jFILE(FILE *file_pointer)                       // assumes fp is at begining of file
307{
308  access=0;
309  fd=-1;
310  file_length=0;
311  start_offset=0;
312  flags=JFILE_CLONED;
313}
314
315void jFILE::open_external(char const *filename, char const *mode, int flags)
316{
317  int skip_size=0;
318  char tmp_name[200];
319  if (spec_prefix && filename[0] != '/')
320    sprintf(tmp_name,"%s%s",spec_prefix,filename);
321  else strcpy(tmp_name,filename);
322
323//  int old_mask=umask(S_IRWXU | S_IRWXG | S_IRWXO);
324  if (flags&O_WRONLY)
325  {
326    if ((flags&O_APPEND)==0)
327    {
328      skip_size=1;
329      //int errval = unlink(tmp_name);
330    }
331
332    flags-=O_WRONLY;
333    flags|=O_CREAT|O_RDWR;
334
335    fd=open(tmp_name,flags,S_IRWXU | S_IRWXG | S_IRWXO);
336  } else
337    fd=open(tmp_name,flags);
338
339//  umask(old_mask);
340  if (fd>=0 && !skip_size)
341  {
342    file_length=lseek(fd,0,SEEK_END);
343    if ((flags&O_APPEND)==0)
344      lseek(fd,0,SEEK_SET);
345    else
346        current_offset = file_length;
347    start_offset=0;
348  } else
349  {
350    file_length=0;
351    start_offset=0;
352  }
353}
354
355
356class null_file : public bFILE     // this file type will use virtual opens inside of a spe
357{
358  public :
359  virtual int open_failure() { return 1; }
360  virtual int unbuffered_read(void *buf, size_t count)   { return 0; }
361  virtual int unbuffered_write(void const *buf, size_t count)  { return 0; }
362  virtual int unbuffered_seek(long offset, int whence)   { return 0; }
363
364  virtual int unbuffered_tell() { return 0; }
365  virtual int file_size() { return 0; }
366  virtual ~null_file() { ; }
367} ;
368
369
370static bFILE *(*open_file_fun)(char const *,char const *)=NULL;
371int (*verify_file_fun)(char const *,char const *)=NULL;
372
373void set_file_opener(bFILE *(*open_fun)(char const *, char const *))
374{
375  open_file_fun=open_fun;
376}
377
378bFILE *open_file(char const *filename, char const *mode)
379{
380  if (!verify_file_fun || verify_file_fun(filename,mode))
381  {
382    if (open_file_fun)
383      return open_file_fun(filename,mode);
384    else return new jFILE(filename,mode);
385  } else return new null_file;
386}
387
388void jFILE::open_internal(char const *filename, char const *mode, int flags)
389{
390  int wr=0;
391  for (char const *s=mode; *s; s++)
392    if (toupper(*s)=='A' || toupper(*s)=='W')
393      wr=1;
394
395  if (wr)
396    fd=-1;                 // only allow extern file openings for writing
397  else
398  {
399       fd = spec_main_fd;
400    if (fd>=0)                    // if we were able to open the main file, see if it's in there
401    {
402      start_offset=0;
403      spec_entry *se=spec_main_sd.find(filename);
404      if (se)
405      {
406    start_offset=se->offset;
407    current_offset = 0;
408    file_length=se->size;
409    rbuf_start=rbuf_end=0;
410      } else
411      {
412    close(fd);
413    fd=-1;
414      }
415    }
416  }
417}
418
419jFILE::jFILE(char const *filename, char const *access_string)      // same as fopen parameters
420{
421 flags=access=0;
422 char const *s=access_string;
423  for (; *s; s++)
424    if (toupper(*s)=='R') access=O_RDONLY;
425
426  for (s=access_string; *s; s++)
427    if (toupper(*s)=='W')
428    {
429      if (access)
430        access=O_RDWR;
431      else access=O_WRONLY;
432    }
433
434  for (s=access_string; *s; s++)
435    if (toupper(*s)=='A')
436      access|=O_APPEND|O_WRONLY;
437
438  file_length=start_offset=-1;
439  current_offset = 0;
440
441  fd=-1;
442  if (search_order==SPEC_SEARCH_OUTSIDE_INSIDE)
443    open_external(filename,access_string,access);
444
445  if (fd<0)
446    open_internal(filename,access_string,access);
447
448  if (fd<0 && search_order==SPEC_SEARCH_INSIDE_OUTSIDE)
449    open_external(filename,access_string,access);
450
451  total_files_open++;
452}
453
454jFILE::~jFILE()
455{
456  flush_writes();
457  if (fd>=0 && !(flags&JFILE_CLONED))
458  {
459    total_files_open--;
460    if (fd != spec_main_fd)
461        close(fd);
462  }
463}
464
465int jFILE::unbuffered_tell()
466{
467//    int ret = ::lseek(fd,0,SEEK_CUR) - start_offset;
468//    if (ret != current_offset)
469//        fprintf(stderr,"Bad tell %d\n",current_offset);
470    return current_offset;
471}
472
473int jFILE::unbuffered_read(void *buf, size_t count)
474{
475    unsigned long len;
476
477    if (fd == spec_main_fd)
478    {
479        switch (fast_load_mode)
480        {
481        case 0:
482            if (current_offset+start_offset != spec_main_offset)
483                spec_main_offset = lseek(fd, start_offset+current_offset, SEEK_SET);
484
485            len = ::read(fd,(char*)buf,count);
486            break;
487        case 1:
488            if (current_offset+start_offset != spec_main_offset)
489                spec_main_offset = lseek(fd, start_offset+current_offset, SEEK_SET);
490
491            len = ::read(fd,(char*)buf,count);
492            ::write(fast_load_fd,(char*)&len,sizeof(len));
493            ::write(fast_load_fd,(char*)buf,len);
494            break;
495        case 2:
496            ::read(fast_load_fd,(char*)&len,sizeof(len));
497            len = ::read(fast_load_fd,(char*)buf,len);
498            break;
499        }
500
501        spec_main_offset += len;
502    }
503    else
504    {
505        switch (fast_load_mode)
506        {
507        case 0:
508          len = ::read(fd,(char*)buf,count);
509          break;
510        case 1:
511          len = ::read(fd,(char*)buf,count);
512            ::write(fast_load_fd,(char*)&len,sizeof(len));
513            ::write(fast_load_fd,(char*)buf,len);
514          break;
515        case 2:
516            ::read(fast_load_fd,(char*)&len,sizeof(len));
517            len = ::read(fast_load_fd,(char*)buf,len);
518            if (count != len)
519                printf("short read! %ld:%ld\n",current_offset,len);
520          break;
521      }
522    }
523    current_offset += len;
524    return len;
525}
526
527int jFILE::unbuffered_write(void const *buf, size_t count)
528{
529  long ret = ::write(fd,(char*)buf,count);
530    current_offset += ret;
531    return ret;
532}
533
534int jFILE::unbuffered_seek(long offset, int whence) // whence=SEEK_SET, SEEK_CUR, SEEK_END, ret=0=success
535{
536  long ret;
537
538  if (fast_load_mode == 2)
539  {
540    switch (whence)
541    {
542    case SEEK_SET :
543      current_offset = start_offset+offset;
544      break;
545    case SEEK_END :
546      current_offset = start_offset+file_length-offset;
547      break;
548    case SEEK_CUR :
549      current_offset += offset;
550      break;
551    default:
552      ret = -1;
553      break;
554    }
555    return current_offset;
556  }
557
558  switch (whence)
559  {
560    case SEEK_SET :
561    { ret = lseek(fd,start_offset+offset,SEEK_SET); } break;
562    case SEEK_END :
563    { ret = lseek(fd,start_offset+file_length-offset,SEEK_SET); } break;
564    case SEEK_CUR :
565    { ret = lseek(fd,offset,SEEK_CUR); } break;
566    default:
567        ret = -1;
568        break;
569  }
570  if (ret>=0)
571  {
572    current_offset = ret - start_offset;
573    if (spec_main_fd == fd)
574      spec_main_offset = ret;
575    return ret;
576  }
577  else
578    return -1;  // if a bad whence, then failure
579}
580
581
582uint8_t bFILE::read_uint8()
583{ uint8_t x;
584  read(&x,1);
585  return x;
586}
587
588uint16_t bFILE::read_uint16()
589{
590  uint16_t x;
591  read(&x,2);
592  return lstl(x);
593}
594
595
596uint32_t bFILE::read_uint32()
597{
598  uint32_t x;
599  read(&x,4);
600  return lltl(x);
601}
602
603void bFILE::write_uint8(uint8_t x)
604{
605  write(&x,1);
606}
607
608void bFILE::write_uint16(uint16_t x)
609{
610  x=lstl(x);
611  write(&x,2);
612}
613
614
615void bFILE::write_uint32(uint32_t x)
616{
617  x=lltl(x);
618  write(&x,4);
619}
620
621void bFILE::write_double(double x)
622{
623  double a;
624  write_uint32((long)(modf(x,&a)*(double)(1<<31)));
625  write_uint32((long)a);
626}
627
628double bFILE::read_double()
629{
630  long a,b;
631  a=read_uint32();
632  b=read_uint32();
633  return (double)b+a/(double)(1<<31);
634}
635
636spec_directory::~spec_directory()
637{
638
639  if (total)
640  {
641    free(data);
642    free(entries);
643  }
644}
645
646void spec_entry::print()
647{
648  printf("%15s%25s%8ld%8ld\n",spec_types[type],name,size,offset);
649}
650
651void spec_directory::calc_offsets()
652{
653  spec_entry **e;
654  int i;
655  long o=SPEC_SIG_SIZE+2;
656  if (total)
657  {
658    for (i=0,e=entries; i<total; i++,e++)          // calculate the size of directory info
659    {
660      o+=1+1+strlen((*e)->name)+1 +1 +8;
661    }
662
663    for (i=0,e=entries; i<total; i++,e++)          // calculate offset for each entry
664    {
665      (*e)->offset=o;
666      o+=(*e)->size;
667    }
668  }
669}
670
671spec_entry *spec_directory::find(char const *name, int type)
672{
673  int i;
674  spec_entry **e;
675  for (i=0,e=entries; i<total; i++,e++)
676    if (!strcmp((*e)->name,name) && (*e)->type==type)
677      return (*e);
678  return NULL;
679}
680
681spec_entry *spec_directory::find(char const *name)
682{
683  int i;
684  spec_entry **e;
685  for (i=0,e=entries; i<total; i++,e++)
686    if (!strcmp((*e)->name,name))
687      return (*e);
688  return NULL;
689}
690
691long spec_directory::find_number(char const *name)
692{
693  int i;
694  spec_entry **e;
695  for (i=0,e=entries; i<total; i++,e++)
696    if (!strcmp((*e)->name,name))
697      return i;
698  return -1;
699}
700
701spec_entry *spec_directory::find(int type)
702{
703  int i;
704  spec_entry **e;
705  for (i=0,e=entries; i<total; i++,e++)
706    if ((*e)->type==type)
707      return (*e);
708  return NULL;
709}
710
711long spec_directory::type_total(int type)
712{
713  int i,x=0;
714  spec_entry **e;
715  for (i=0,e=entries; i<total; i++,e++)
716    if ((*e)->type==type) x++;
717  return x;
718}
719
720long spec_directory::find_number(int type)
721{
722  int i;
723  spec_entry **e;
724  for (i=0,e=entries; i<total; i++,e++)
725    if ((*e)->type==type)
726      return i;
727  return -1;
728}
729
730void spec_directory::print()
731{
732  spec_entry **se;
733  int i;
734  printf("[   Entry type   ][   Entry name   ][  Size  ][ Offset ]\n");
735  for (i=0,se=entries; i<total; i++,se++)
736    (*se)->print();
737}
738
739
740void spec_directory::startup(bFILE *fp)
741{
742  char buf[256];
743  memset(buf,0,256);
744  fp->read(buf,8);
745  buf[9]=0;
746  size=0;
747  if (!strcmp(buf,SPEC_SIGNATURE))
748  {
749    total=fp->read_uint16();
750    entries=(spec_entry **)malloc(sizeof(spec_entry *)*total);
751    long start=fp->tell();
752
753    int i;
754    for (i=0; i<total; i++)
755    {
756      fp->read(buf,2);
757      long entry_size=sizeof(spec_entry)+(unsigned char)buf[1];
758      entry_size=(entry_size+3)&(~3);
759      fp->read(buf,(unsigned char)buf[1]);
760      fp->read(buf,9);
761
762      size+=entry_size;
763    }
764    data=malloc(size);
765    char *dp=(char *)data;
766    fp->seek(start,SEEK_SET);
767    for (i=0; i<total; i++)
768    {
769      spec_entry *se=(spec_entry *)dp;
770      entries[i]=se;
771
772      unsigned char len,flags,type;
773      fp->read(&type,1);
774      fp->read(&len,1);
775      se->type=type;
776      se->name=dp+sizeof(spec_entry);
777      fp->read(se->name,len);
778      fp->read(&flags,1);
779
780      se->size=fp->read_uint32();
781      se->offset=fp->read_uint32();
782      dp+=((sizeof(spec_entry)+len)+3)&(~3);
783    }
784  }
785  else
786  {
787    total=0;
788    data=NULL;
789    entries=NULL;
790  }
791}
792
793
794spec_directory::spec_directory(bFILE *fp)
795{ startup(fp); }
796
797spec_directory::spec_directory(FILE *fp)
798{
799  jFILE jfp(fp);
800  startup(&jfp);
801}
802
803spec_directory::spec_directory()
804{
805  size=0;
806  total=0;
807  data=NULL;
808  entries=NULL;
809}
810
811/*
812spec_directory::spec_directory(char *filename)
813{
814  jFILE *fp;
815  if (filename)
816  {
817    fp=new jFILE(filename,"rb");
818    if (!fp->open_failure())
819      startup(fp);
820    else
821    {
822      total=0;
823      entries=NULL;
824    }
825    delete fp;
826  } else printf("NULL filename to spec_directory::spec_directory\n");
827}*/
828
829int write_string(bFILE *fp, char const *st)
830{
831  unsigned char length=strlen(st)+1;
832  if (fp->write(&length,1)!=1) return 0;
833  if (fp->write(st,length)!=length) return 0;
834  return 1;
835}
836
837long spec_directory::data_start_offset()
838{
839    /* FIXME: no need for a for loop here! */
840    long i;
841    for(i = 0; i < total; i++)
842        return entries[i]->offset;
843
844    // If no entries, then no data, but return where it would start anyway
845    return SPEC_SIG_SIZE + 2;
846}
847
848long spec_directory::data_end_offset()
849{
850    /* FIXME: no need for a for loop here! */
851  spec_entry **e;
852  long i;
853  for (i=total-1,e=entries; i>=0; i--,e++)
854    return (*e)->offset+(*e)->size;
855
856  return SPEC_SIG_SIZE+2;
857}
858
859int spec_directory::write(bFILE *fp)
860{
861
862  char sig[SPEC_SIG_SIZE];
863  unsigned char flags=0;
864  unsigned long offset,data_size;
865  spec_entry **e;
866  strcpy(sig,SPEC_SIGNATURE);
867
868  if (fp->write(sig,sizeof(sig))!=sizeof(sig))    return 0;
869  fp->write_uint16(total);
870
871
872  int i;
873  for (i=0,e=entries; i<total; i++,e++)
874  {
875    if (fp->write(&(*e)->type,1)!=1)                 return 0;
876    if (!write_string(fp,(*e)->name))                return 0;
877    flags=0;
878    if (fp->write(&flags,1)!=1)                     return 0;
879
880    data_size=lltl((*e)->size);
881    if (fp->write((char *)&data_size,4)!=4)              return 0;
882    offset=lltl((*e)->offset);
883    if (fp->write((char *)&offset,4)!=4)                  return 0;
884
885  }
886  return 1;
887}
888
889jFILE *spec_directory::write(char const *filename)
890{
891  jFILE *fp;
892  fp=new jFILE(filename,"wb");
893  if (fp->open_failure()) { delete fp; return NULL; }
894  if (!write(fp))
895  {
896    delete fp;
897    return NULL;
898  } else return fp;
899
900}
901
902uint16_t read_uint16(FILE *fp)
903{
904  uint16_t x;
905  fread(&x,1,2,fp);
906  return lstl(x);
907}
908
909uint32_t read_uint32(FILE *fp)
910{
911  uint32_t x;
912  fread(&x,1,4,fp);
913  return lltl(x);
914}
915void write_uint16(FILE *fp, uint16_t x)
916{
917  x=lstl(x);
918  fwrite(&x,1,2,fp);
919}
920
921void write_uint32(FILE *fp, uint32_t x)
922{
923  x=lltl(x);
924  fwrite(&x,1,4,fp);
925}
926
927uint8_t read_uint8(FILE *fp) { return fgetc(fp)&0xff; }
928void write_uint8(FILE *fp, uint8_t x) { fputc((unsigned char)x,fp); }
929
930void spec_directory::remove(spec_entry *e)
931{
932  int i;
933  for (i=0; i<total && entries[i]!=e; i++);            // find the entry in the array first
934
935  if (entries[i]==e)                                 // make sre it was found
936  {
937    delete e;
938    total--;
939    for (; i<total; i++)                               // compact the pointer array
940      entries[i]=entries[i+1];
941    entries=(spec_entry **)realloc(entries,sizeof(spec_entry *)*total);
942  }
943  else
944    printf("Spec_directory::remove bad entry pointer\n");
945}
946
947
948
949void spec_directory::add_by_hand(spec_entry *e)
950{
951  total++;
952  entries=(spec_entry **)realloc(entries,sizeof(spec_entry *)*total);
953  entries[total-1]=e;
954}
955
956void spec_directory::delete_entries()   // if the directory was created by hand instead of by file
957{
958  int i;
959  for (i=0; i<total; i++)
960    delete entries[i];
961
962  if (total)
963    free(entries);
964}
965
966void note_open_fd(int fd, char const *str)
967{
968    total_files_open++;
969}
970
971void note_close_fd(int fd)
972{
973    total_files_open--;
974}
975
976void list_open_fds()
977{
978    printf("Total open file descriptors: %d\n", total_files_open);
979}
980
Note: See TracBrowser for help on using the repository browser.