1 /***************************************
2 Functions to handle files.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2008-2015 Andrew M. Bishop
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU Affero General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ***************************************/
21
22
23 #if defined(_MSC_VER)
24 #include <io.h>
25 #include <basetsd.h>
26 #define read(fd,address,length) _read(fd,address,(unsigned int)(length))
27 #define write(fd,address,length) _write(fd,address,(unsigned int)(length))
28 #define open _open
29 #define close _close
30 #define unlink _unlink
31 #define ssize_t SSIZE_T
32 #else
33 #include <unistd.h>
34 #endif
35
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <fcntl.h>
40 #include <errno.h>
41 #include <sys/stat.h>
42
43 #if defined(_MSC_VER) || defined(__MINGW32__)
44 #undef lseek
45 #undef stat
46 #undef fstat
47 #define lseek _lseeki64
48 #define stat _stati64
49 #define fstat _fstati64
50 #endif
51
52 #if defined(_MSC_VER) || defined(__MINGW32__)
53 #include "mman-win32.h"
54 #else
55 #include <sys/mman.h>
56 #endif
57
58 #include <sys/types.h>
59
60 #include "files.h"
61
62
63 /*+ A structure to contain the list of memory mapped files. +*/
64 struct mmapinfo
65 {
66 const char *filename; /*+ The name of the file (the index of the list). +*/
67 int fd; /*+ The file descriptor used when it was opened. +*/
68 char *address; /*+ The address the file was mapped to. +*/
69 size_t length; /*+ The length of the file. +*/
70 };
71
72 /*+ The list of memory mapped files. +*/
73 static struct mmapinfo *mappedfiles;
74
75 /*+ The number of mapped files. +*/
76 static int nmappedfiles=0;
77
78
79 #define BUFFLEN 4096
80
81 /*+ A structure to contain the list of file buffers. +*/
82 struct filebuffer
83 {
84 char buffer[BUFFLEN]; /*+ The data buffer. +*/
85 size_t pointer; /*+ The read/write pointer for the file buffer. +*/
86 size_t length; /*+ The read pointer for the file buffer. +*/
87 int reading; /*+ A flag to indicate if the file is for reading. +*/
88 };
89
90 /*+ The list of file buffers. +*/
91 static struct filebuffer **filebuffers=NULL;
92
93 /*+ The number of allocated file buffer pointers. +*/
94 static int nfilebuffers=0;
95
96
97 #if defined(_MSC_VER) || defined(__MINGW32__)
98
99 /*+ A structure to contain the list of opened files to record which are to be deleted when closed. +*/
100 struct openedfile
101 {
102 const char *filename; /*+ The name of the file. +*/
103 int delete; /*+ Set to non-zero value if the file is to be deleted when closed. +*/
104 };
105
106 /*+ The list of opened files. +*/
107 static struct openedfile **openedfiles=NULL;
108
109 /*+ The number of allocated opened file buffer pointers. +*/
110 static int nopenedfiles=0;
111
112 #endif
113
114
115 /* Local functions */
116
117 static void CreateFileBuffer(int fd,int read_write);
118
119 #if defined(_MSC_VER) || defined(__MINGW32__)
120
121 static void CreateOpenedFile(int fd,const char *filename);
122
123 #endif
124
125
126 /*++++++++++++++++++++++++++++++++++++++
127 Return a filename composed of the dirname, prefix and name.
128
129 char *FileName Returns a pointer to memory allocated to the filename.
130
131 const char *dirname The directory name.
132
133 const char *prefix The file prefix.
134
135 const char *name The main part of the name.
136 ++++++++++++++++++++++++++++++++++++++*/
137
FileName(const char * dirname,const char * prefix,const char * name)138 char *FileName(const char *dirname,const char *prefix, const char *name)
139 {
140 char *filename=(char*)malloc((dirname?strlen(dirname):0)+1+(prefix?strlen(prefix):0)+1+strlen(name)+1);
141
142 sprintf(filename,"%s%s%s%s%s",dirname?dirname:"",dirname?"/":"",prefix?prefix:"",prefix?"-":"",name);
143
144 return(filename);
145 }
146
147
148 /*++++++++++++++++++++++++++++++++++++++
149 Open a file read-only and map it into memory.
150
151 void *MapFile Returns the address of the file or exits in case of an error.
152
153 const char *filename The name of the file to open.
154 ++++++++++++++++++++++++++++++++++++++*/
155
MapFile(const char * filename)156 void *MapFile(const char *filename)
157 {
158 int fd;
159 struct stat buf;
160 offset_t size;
161 void *address;
162
163 /* Open the file */
164
165 #if defined(_MSC_VER) || defined(__MINGW32__)
166 fd=open(filename,O_RDONLY|O_BINARY|O_RANDOM);
167 #else
168 fd=open(filename,O_RDONLY);
169 #endif
170
171 if(fd<0)
172 {
173 #ifdef LIBROUTINO
174 return(NULL);
175 #else
176 fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno));
177 exit(EXIT_FAILURE);
178 #endif
179 }
180
181 /* Get its size */
182
183 if(stat(filename,&buf))
184 {
185 #ifdef LIBROUTINO
186 return(NULL);
187 #else
188 fprintf(stderr,"Cannot stat file '%s' [%s].\n",filename,strerror(errno));
189 exit(EXIT_FAILURE);
190 #endif
191 }
192
193 size=buf.st_size;
194
195 /* Map the file */
196
197 address=mmap(NULL,size,PROT_READ,MAP_SHARED,fd,0);
198
199 if(address==MAP_FAILED)
200 {
201 close(fd);
202
203 #ifdef LIBROUTINO
204 return(NULL);
205 #else
206 fprintf(stderr,"Cannot mmap file '%s' for reading [%s].\n",filename,strerror(errno));
207 exit(EXIT_FAILURE);
208 #endif
209 }
210
211 #ifndef LIBROUTINO
212 log_mmap(size);
213 #endif
214
215 /* Store the information about the mapped file */
216
217 mappedfiles=(struct mmapinfo*)realloc((void*)mappedfiles,(nmappedfiles+1)*sizeof(struct mmapinfo));
218
219 mappedfiles[nmappedfiles].filename=filename;
220 mappedfiles[nmappedfiles].fd=fd;
221 mappedfiles[nmappedfiles].address=address;
222 mappedfiles[nmappedfiles].length=size;
223
224 nmappedfiles++;
225
226 return(address);
227 }
228
229
230 /*++++++++++++++++++++++++++++++++++++++
231 Open a file read-write and map it into memory.
232
233 void *MapFileWriteable Returns the address of the file or exits in case of an error.
234
235 const char *filename The name of the file to open.
236 ++++++++++++++++++++++++++++++++++++++*/
237
MapFileWriteable(const char * filename)238 void *MapFileWriteable(const char *filename)
239 {
240 int fd;
241 struct stat buf;
242 offset_t size;
243 void *address;
244
245 /* Open the file */
246
247 #if defined(_MSC_VER) || defined(__MINGW32__)
248 fd=open(filename,O_RDWR|O_BINARY|O_RANDOM);
249 #else
250 fd=open(filename,O_RDWR);
251 #endif
252
253 if(fd<0)
254 {
255 #ifdef LIBROUTINO
256 return(NULL);
257 #else
258 fprintf(stderr,"Cannot open file '%s' for reading and writing [%s].\n",filename,strerror(errno));
259 exit(EXIT_FAILURE);
260 #endif
261 }
262
263 /* Get its size */
264
265 if(stat(filename,&buf))
266 {
267 #ifdef LIBROUTINO
268 return(NULL);
269 #else
270 fprintf(stderr,"Cannot stat file '%s' [%s].\n",filename,strerror(errno));
271 exit(EXIT_FAILURE);
272 #endif
273 }
274
275 size=buf.st_size;
276
277 /* Map the file */
278
279 address=mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
280
281 if(address==MAP_FAILED)
282 {
283 close(fd);
284
285 #ifdef LIBROUTINO
286 return(NULL);
287 #else
288 fprintf(stderr,"Cannot mmap file '%s' for reading and writing [%s].\n",filename,strerror(errno));
289 exit(EXIT_FAILURE);
290 #endif
291 }
292
293 #ifndef LIBROUTINO
294 log_mmap(size);
295 #endif
296
297 /* Store the information about the mapped file */
298
299 mappedfiles=(struct mmapinfo*)realloc((void*)mappedfiles,(nmappedfiles+1)*sizeof(struct mmapinfo));
300
301 mappedfiles[nmappedfiles].filename=filename;
302 mappedfiles[nmappedfiles].fd=fd;
303 mappedfiles[nmappedfiles].address=address;
304 mappedfiles[nmappedfiles].length=size;
305
306 nmappedfiles++;
307
308 return(address);
309 }
310
311
312 /*++++++++++++++++++++++++++++++++++++++
313 Unmap a file and close it.
314
315 void *UnmapFile Returns NULL (for similarity to the MapFile function).
316
317 const void *address The address of the mapped file in memory.
318 ++++++++++++++++++++++++++++++++++++++*/
319
UnmapFile(const void * address)320 void *UnmapFile(const void *address)
321 {
322 int i;
323
324 for(i=0;i<nmappedfiles;i++)
325 if(mappedfiles[i].address==address)
326 break;
327
328 if(i==nmappedfiles)
329 {
330 #ifdef LIBROUTINO
331 return(NULL);
332 #else
333 fprintf(stderr,"The data at address %p was not mapped using MapFile().\n",address);
334 exit(EXIT_FAILURE);
335 #endif
336 }
337
338 /* Close the file */
339
340 close(mappedfiles[i].fd);
341
342 /* Unmap the file */
343
344 munmap(mappedfiles[i].address,mappedfiles[i].length);
345
346 #ifndef LIBROUTINO
347 log_munmap(mappedfiles[i].length);
348 #endif
349
350 /* Shuffle the list of files */
351
352 nmappedfiles--;
353
354 if(nmappedfiles>i)
355 memmove(&mappedfiles[i],&mappedfiles[i+1],(nmappedfiles-i)*sizeof(struct mmapinfo));
356
357 return(NULL);
358 }
359
360
361 /*++++++++++++++++++++++++++++++++++++++
362 Open an existing file on disk for reading.
363
364 int SlimMapFile Returns the file descriptor if OK or exits in case of an error.
365
366 const char *filename The name of the file to open.
367 ++++++++++++++++++++++++++++++++++++++*/
368
SlimMapFile(const char * filename)369 int SlimMapFile(const char *filename)
370 {
371 int fd;
372
373 /* Open the file */
374
375 #if defined(_MSC_VER) || defined(__MINGW32__)
376 fd=open(filename,O_RDONLY|O_BINARY|O_RANDOM);
377 #else
378 fd=open(filename,O_RDONLY);
379 #endif
380
381 if(fd<0)
382 {
383 #ifdef LIBROUTINO
384 return(-1);
385 #else
386 fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno));
387 exit(EXIT_FAILURE);
388 #endif
389 }
390
391 CreateFileBuffer(fd,0);
392
393 return(fd);
394 }
395
396
397 /*++++++++++++++++++++++++++++++++++++++
398 Open an existing file on disk for reading or writing.
399
400 int SlimMapFileWriteable Returns the file descriptor if OK or exits in case of an error.
401
402 const char *filename The name of the file to open.
403 ++++++++++++++++++++++++++++++++++++++*/
404
SlimMapFileWriteable(const char * filename)405 int SlimMapFileWriteable(const char *filename)
406 {
407 int fd;
408
409 /* Open the file */
410
411 #if defined(_MSC_VER) || defined(__MINGW32__)
412 fd=open(filename,O_RDWR|O_BINARY|O_RANDOM);
413 #else
414 fd=open(filename,O_RDWR);
415 #endif
416
417 if(fd<0)
418 {
419 #ifdef LIBROUTINO
420 return(-1);
421 #else
422 fprintf(stderr,"Cannot open file '%s' for reading and writing [%s].\n",filename,strerror(errno));
423 exit(EXIT_FAILURE);
424 #endif
425 }
426
427 CreateFileBuffer(fd,0);
428
429 return(fd);
430 }
431
432
433 /*++++++++++++++++++++++++++++++++++++++
434 Close a file on disk.
435
436 int SlimUnmapFile returns -1 (for similarity to the UnmapFile function).
437
438 int fd The file descriptor to close.
439 ++++++++++++++++++++++++++++++++++++++*/
440
SlimUnmapFile(int fd)441 int SlimUnmapFile(int fd)
442 {
443 close(fd);
444
445 return(-1);
446 }
447
448
449 /*++++++++++++++++++++++++++++++++++++++
450 Open a new file on disk for writing (with buffering).
451
452 int OpenFileBufferedNew Returns the file descriptor if OK or exits in case of an error.
453
454 const char *filename The name of the file to create.
455 ++++++++++++++++++++++++++++++++++++++*/
456
OpenFileBufferedNew(const char * filename)457 int OpenFileBufferedNew(const char *filename)
458 {
459 int fd;
460
461 /* Open the file */
462
463 #if defined(_MSC_VER) || defined(__MINGW32__)
464 fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY|O_RANDOM,S_IREAD|S_IWRITE);
465 #else
466 fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC ,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
467 #endif
468
469 if(fd<0)
470 {
471 #ifdef LIBROUTINO
472 return(-1);
473 #else
474 fprintf(stderr,"Cannot open file '%s' for writing [%s].\n",filename,strerror(errno));
475 exit(EXIT_FAILURE);
476 #endif
477 }
478
479 CreateFileBuffer(fd,-1);
480
481 #if defined(_MSC_VER) || defined(__MINGW32__)
482 CreateOpenedFile(fd,filename);
483 #endif
484
485 return(fd);
486 }
487
488
489 /*++++++++++++++++++++++++++++++++++++++
490 Open a new or existing file on disk for appending (with buffering).
491
492 int OpenFileBufferedAppend Returns the file descriptor if OK or exits in case of an error.
493
494 const char *filename The name of the file to create or open.
495 ++++++++++++++++++++++++++++++++++++++*/
496
OpenFileBufferedAppend(const char * filename)497 int OpenFileBufferedAppend(const char *filename)
498 {
499 int fd;
500
501 /* Open the file */
502
503 #if defined(_MSC_VER) || defined(__MINGW32__)
504 fd=open(filename,O_WRONLY|O_CREAT|O_APPEND|O_BINARY|O_RANDOM,S_IREAD|S_IWRITE);
505 #else
506 fd=open(filename,O_WRONLY|O_CREAT|O_APPEND ,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
507 #endif
508
509 if(fd<0)
510 {
511 #ifdef LIBROUTINO
512 return(-1);
513 #else
514 fprintf(stderr,"Cannot open file '%s' for appending [%s].\n",filename,strerror(errno));
515 exit(EXIT_FAILURE);
516 #endif
517 }
518
519 CreateFileBuffer(fd,-1);
520
521 #if defined(_MSC_VER) || defined(__MINGW32__)
522 CreateOpenedFile(fd,filename);
523 #endif
524
525 return(fd);
526 }
527
528
529 /*++++++++++++++++++++++++++++++++++++++
530 Open an existing file on disk for reading (with buffering).
531
532 int ReOpenFileBuffered Returns the file descriptor if OK or exits in case of an error.
533
534 const char *filename The name of the file to open.
535 ++++++++++++++++++++++++++++++++++++++*/
536
ReOpenFileBuffered(const char * filename)537 int ReOpenFileBuffered(const char *filename)
538 {
539 int fd;
540
541 /* Open the file */
542
543 #if defined(_MSC_VER) || defined(__MINGW32__)
544 fd=open(filename,O_RDONLY|O_BINARY|O_RANDOM);
545 #else
546 fd=open(filename,O_RDONLY);
547 #endif
548
549 if(fd<0)
550 {
551 #ifdef LIBROUTINO
552 return(-1);
553 #else
554 fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno));
555 exit(EXIT_FAILURE);
556 #endif
557 }
558
559 CreateFileBuffer(fd,1);
560
561 #if defined(_MSC_VER) || defined(__MINGW32__)
562 CreateOpenedFile(fd,filename);
563 #endif
564
565 return(fd);
566 }
567
568
569 /*++++++++++++++++++++++++++++++++++++++
570 Open an existing file on disk for reading (with buffering), delete
571 it and open a new file on disk for writing (with buffering).
572
573 int ReplaceFileBuffered Returns the file descriptor of the new writable file.
574
575 const char *filename The name of the file to open, delete and replace.
576
577 int *oldfd Returns the file descriptor of the old, readable file.
578 ++++++++++++++++++++++++++++++++++++++*/
579
ReplaceFileBuffered(const char * filename,int * oldfd)580 int ReplaceFileBuffered(const char *filename,int *oldfd)
581 {
582 int newfd;
583
584 #if defined(_MSC_VER) || defined(__MINGW32__)
585
586 char *filename2;
587
588 filename2=strcpy(malloc(strlen(filename)+2),filename);
589 strcat(filename2,"2");
590
591 RenameFile(filename,filename2);
592
593 *oldfd=ReOpenFileBuffered(filename2);
594
595 DeleteFile(filename2);
596
597 #else
598
599 *oldfd=ReOpenFileBuffered(filename);
600
601 DeleteFile(filename);
602
603 #endif
604
605 newfd=OpenFileBufferedNew(filename);
606
607 return(newfd);
608 }
609
610
611 /*++++++++++++++++++++++++++++++++++++++
612 Write data to a file descriptor (via a buffer).
613
614 int WriteFileBuffered Returns 0 if OK or something else in case of an error.
615
616 int fd The file descriptor to write to.
617
618 const void *address The address of the data to be written.
619
620 size_t length The length of data to write.
621 ++++++++++++++++++++++++++++++++++++++*/
622
WriteFileBuffered(int fd,const void * address,size_t length)623 int WriteFileBuffered(int fd,const void *address,size_t length)
624 {
625 #ifndef LIBROUTINO
626 logassert(fd!=-1,"File descriptor is in error - report a bug");
627
628 logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug");
629
630 logassert(!filebuffers[fd]->reading,"File descriptor was not opened for writing - report a bug");
631 #endif
632
633 /* Write the data */
634
635 if((filebuffers[fd]->pointer+length)>BUFFLEN)
636 {
637 if(write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer)!=(ssize_t)filebuffers[fd]->pointer)
638 return(-1);
639
640 filebuffers[fd]->pointer=0;
641 }
642
643 if(length>=BUFFLEN)
644 {
645 if(write(fd,address,length)!=(ssize_t)length)
646 return(-1);
647
648 return(0);
649 }
650
651 memcpy(filebuffers[fd]->buffer+filebuffers[fd]->pointer,address,length);
652
653 filebuffers[fd]->pointer+=length;
654
655 return(0);
656 }
657
658
659 /*++++++++++++++++++++++++++++++++++++++
660 Read data from a file descriptor (via a buffer).
661
662 int ReadFileBuffered Returns 0 if OK or something else in case of an error.
663
664 int fd The file descriptor to read from.
665
666 void *address The address the data is to be read into.
667
668 size_t length The length of data to read.
669 ++++++++++++++++++++++++++++++++++++++*/
670
ReadFileBuffered(int fd,void * address,size_t length)671 int ReadFileBuffered(int fd,void *address,size_t length)
672 {
673 #ifndef LIBROUTINO
674 logassert(fd!=-1,"File descriptor is in error - report a bug");
675
676 logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug");
677
678 logassert(filebuffers[fd]->reading,"File descriptor was not opened for reading - report a bug");
679 #endif
680
681 /* Read the data */
682
683 if((filebuffers[fd]->pointer+length)>filebuffers[fd]->length)
684 if(filebuffers[fd]->pointer<filebuffers[fd]->length)
685 {
686 memcpy(address,filebuffers[fd]->buffer+filebuffers[fd]->pointer,filebuffers[fd]->length-filebuffers[fd]->pointer);
687
688 address=(char*)address+filebuffers[fd]->length-filebuffers[fd]->pointer;
689 length-=filebuffers[fd]->length-filebuffers[fd]->pointer;
690
691 filebuffers[fd]->pointer=0;
692 filebuffers[fd]->length=0;
693 }
694
695 if(length>=BUFFLEN)
696 {
697 if(read(fd,address,length)!=(ssize_t)length)
698 return(-1);
699
700 return(0);
701 }
702
703 if(filebuffers[fd]->pointer==filebuffers[fd]->length)
704 {
705 ssize_t len=read(fd,filebuffers[fd]->buffer,BUFFLEN);
706
707 if(len<=0)
708 return(-1);
709
710 filebuffers[fd]->length=len;
711 filebuffers[fd]->pointer=0;
712 }
713
714 if(filebuffers[fd]->length==0)
715 return(-1);
716
717 memcpy(address,filebuffers[fd]->buffer+filebuffers[fd]->pointer,length);
718
719 filebuffers[fd]->pointer+=length;
720
721 return(0);
722 }
723
724
725 /*++++++++++++++++++++++++++++++++++++++
726 Seek to a position in a file descriptor that uses a buffer.
727
728 int SeekFileBuffered Returns 0 if OK or something else in case of an error.
729
730 int fd The file descriptor to seek within.
731
732 offset_t position The position to seek to.
733 ++++++++++++++++++++++++++++++++++++++*/
734
SeekFileBuffered(int fd,offset_t position)735 int SeekFileBuffered(int fd,offset_t position)
736 {
737 #ifndef LIBROUTINO
738 logassert(fd!=-1,"File descriptor is in error - report a bug");
739
740 logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug");
741 #endif
742
743 /* Seek the data - doesn't need to be highly optimised */
744
745 if(!filebuffers[fd]->reading)
746 if(write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer)!=(ssize_t)filebuffers[fd]->pointer)
747 return(-1);
748
749 filebuffers[fd]->pointer=0;
750 filebuffers[fd]->length=0;
751
752 if(lseek(fd,position,SEEK_SET)!=position)
753 return(-1);
754
755 return(0);
756 }
757
758
759 /*++++++++++++++++++++++++++++++++++++++
760 Skip forward by an offset in a file descriptor that uses a buffer.
761
762 int SkipFileBuffered Returns 0 if OK or something else in case of an error.
763
764 int fd The file descriptor to skip within.
765
766 offset_t skip The amount to skip forward.
767 ++++++++++++++++++++++++++++++++++++++*/
768
SkipFileBuffered(int fd,offset_t skip)769 int SkipFileBuffered(int fd,offset_t skip)
770 {
771 #ifndef LIBROUTINO
772 logassert(fd!=-1,"File descriptor is in error - report a bug");
773
774 logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug");
775
776 logassert(filebuffers[fd]->reading,"File descriptor was not opened for reading - report a bug");
777 #endif
778
779 /* Skip the data - needs to be optimised */
780
781 if((filebuffers[fd]->pointer+skip)>filebuffers[fd]->length)
782 {
783 skip-=(offset_t)(filebuffers[fd]->length-filebuffers[fd]->pointer);
784
785 filebuffers[fd]->pointer=0;
786 filebuffers[fd]->length=0;
787
788 if(lseek(fd,skip,SEEK_CUR)==-1)
789 return(-1);
790 }
791 else
792 filebuffers[fd]->pointer+=skip;
793
794 return(0);
795 }
796
797
798 /*++++++++++++++++++++++++++++++++++++++
799 Get the size of a file.
800
801 offset_t SizeFile Returns the file size if OK or exits in case of an error.
802
803 const char *filename The name of the file to check.
804 ++++++++++++++++++++++++++++++++++++++*/
805
SizeFile(const char * filename)806 offset_t SizeFile(const char *filename)
807 {
808 struct stat buf;
809
810 if(stat(filename,&buf))
811 {
812 #ifdef LIBROUTINO
813 return(-1);
814 #else
815 fprintf(stderr,"Cannot stat file '%s' [%s].\n",filename,strerror(errno));
816 exit(EXIT_FAILURE);
817 #endif
818 }
819
820 return(buf.st_size);
821 }
822
823
824 /*++++++++++++++++++++++++++++++++++++++
825 Get the size of a file from a file descriptor.
826
827 offset_t SizeFileFD Returns the file size if OK or exits in case of an error.
828
829 int fd The file descriptor to check.
830 ++++++++++++++++++++++++++++++++++++++*/
831
SizeFileFD(int fd)832 offset_t SizeFileFD(int fd)
833 {
834 struct stat buf;
835
836 if(fstat(fd,&buf))
837 {
838 #ifdef LIBROUTINO
839 return(-1);
840 #else
841 fprintf(stderr,"Cannot stat file descriptor '%d' [%s].\n",fd,strerror(errno));
842 exit(EXIT_FAILURE);
843 #endif
844 }
845
846 return(buf.st_size);
847 }
848
849
850 /*++++++++++++++++++++++++++++++++++++++
851 Check if a file exists.
852
853 int ExistsFile Returns 1 if the file exists and 0 if not.
854
855 const char *filename The name of the file to check.
856 ++++++++++++++++++++++++++++++++++++++*/
857
ExistsFile(const char * filename)858 int ExistsFile(const char *filename)
859 {
860 struct stat buf;
861
862 if(stat(filename,&buf))
863 return(0);
864 else
865 return(1);
866 }
867
868
869 /*++++++++++++++++++++++++++++++++++++++
870 Close a file on disk (and flush the buffer).
871
872 int CloseFileBuffered returns -1 (for similarity to the *OpenFileBuffered* functions).
873
874 int fd The file descriptor to close.
875 ++++++++++++++++++++++++++++++++++++++*/
876
CloseFileBuffered(int fd)877 int CloseFileBuffered(int fd)
878 {
879 #ifndef LIBROUTINO
880 logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug");
881 #endif
882
883 if(!filebuffers[fd]->reading)
884 if(write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer)!=(ssize_t)filebuffers[fd]->pointer)
885 return(-1);
886
887 close(fd);
888
889 free(filebuffers[fd]);
890 filebuffers[fd]=NULL;
891
892 #if defined(_MSC_VER) || defined(__MINGW32__)
893
894 #ifndef LIBROUTINO
895 logassert(fd<nopenedfiles && openedfiles[fd],"File descriptor has no record of opening - report a bug");
896 #endif
897
898 if(openedfiles[fd]->delete)
899 unlink(openedfiles[fd]->filename);
900
901 free(openedfiles[fd]);
902 openedfiles[fd]=NULL;
903
904 #endif
905
906 return(-1);
907 }
908
909
910 /*++++++++++++++++++++++++++++++++++++++
911 Open an existing file on disk for reading (in a simple mode).
912
913 int OpenFile Returns the file descriptor if OK or exits in case of an error.
914
915 const char *filename The name of the file to open.
916 ++++++++++++++++++++++++++++++++++++++*/
917
OpenFile(const char * filename)918 int OpenFile(const char *filename)
919 {
920 int fd;
921
922 /* Open the file */
923
924 #if defined(_MSC_VER) || defined(__MINGW32__)
925 fd=open(filename,O_RDONLY|O_BINARY|O_RANDOM);
926 #else
927 fd=open(filename,O_RDONLY);
928 #endif
929
930 if(fd<0)
931 {
932 #ifdef LIBROUTINO
933 return(-1);
934 #else
935 fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno));
936 exit(EXIT_FAILURE);
937 #endif
938 }
939
940 #if defined(_MSC_VER) || defined(__MINGW32__)
941 CreateOpenedFile(fd,filename);
942 #endif
943
944 return(fd);
945 }
946
947
948 /*++++++++++++++++++++++++++++++++++++++
949 Close a file on disk (that was opened in simple mode).
950
951 int fd The file descriptor to close.
952 ++++++++++++++++++++++++++++++++++++++*/
953
CloseFile(int fd)954 void CloseFile(int fd)
955 {
956 close(fd);
957
958 #if defined(_MSC_VER) || defined(__MINGW32__)
959
960 #ifndef LIBROUTINO
961 logassert(fd<nopenedfiles && openedfiles[fd],"File descriptor has no record of opening - report a bug");
962 #endif
963
964 if(openedfiles[fd]->delete)
965 unlink(openedfiles[fd]->filename);
966
967 free(openedfiles[fd]);
968 openedfiles[fd]=NULL;
969
970 #endif
971 }
972
973
974 /*++++++++++++++++++++++++++++++++++++++
975 Delete a file from disk.
976
977 int DeleteFile Returns 0 if OK.
978
979 const char *filename The name of the file to delete.
980 ++++++++++++++++++++++++++++++++++++++*/
981
DeleteFile(const char * filename)982 int DeleteFile(const char *filename)
983 {
984 #if defined(_MSC_VER) || defined(__MINGW32__)
985
986 int fd;
987
988 for(fd=0;fd<nopenedfiles;fd++)
989 if(openedfiles[fd] && !strcmp(openedfiles[fd]->filename,filename))
990 {
991 openedfiles[fd]->delete=1;
992 return(0);
993 }
994
995 #endif
996
997 unlink(filename);
998
999 return(0);
1000 }
1001
1002
1003 /*++++++++++++++++++++++++++++++++++++++
1004 Rename a file on disk.
1005
1006 int RenameFile Returns 0 if OK.
1007
1008 const char *oldfilename The old name of the file before renaming.
1009
1010 const char *newfilename The new name of the file after renaming.
1011 ++++++++++++++++++++++++++++++++++++++*/
1012
RenameFile(const char * oldfilename,const char * newfilename)1013 int RenameFile(const char *oldfilename,const char *newfilename)
1014 {
1015 rename(oldfilename,newfilename);
1016
1017 return(0);
1018 }
1019
1020
1021 /*++++++++++++++++++++++++++++++++++++++
1022 Create a file buffer.
1023
1024 int fd The file descriptor.
1025
1026 int read_write A flag set to 1 for reading, -1 for writing and 0 for unbuffered.
1027 ++++++++++++++++++++++++++++++++++++++*/
1028
CreateFileBuffer(int fd,int read_write)1029 static void CreateFileBuffer(int fd,int read_write)
1030 {
1031 if(nfilebuffers<=fd)
1032 {
1033 int i;
1034
1035 filebuffers=(struct filebuffer**)realloc((void*)filebuffers,(fd+1)*sizeof(struct filebuffer*));
1036
1037 for(i=nfilebuffers;i<=fd;i++)
1038 filebuffers[i]=NULL;
1039
1040 nfilebuffers=fd+1;
1041 }
1042
1043 if(read_write)
1044 {
1045 filebuffers[fd]=(struct filebuffer*)calloc(sizeof(struct filebuffer),1);
1046
1047 filebuffers[fd]->reading=(read_write==1);
1048 }
1049 }
1050
1051
1052 #if defined(_MSC_VER) || defined(__MINGW32__)
1053
1054 /*++++++++++++++++++++++++++++++++++++++
1055 Create an opened file record.
1056
1057 int fd The file descriptor.
1058
1059 const char *filename The name of the file.
1060 ++++++++++++++++++++++++++++++++++++++*/
1061
CreateOpenedFile(int fd,const char * filename)1062 static void CreateOpenedFile(int fd,const char *filename)
1063 {
1064 if(nopenedfiles<=fd)
1065 {
1066 int i;
1067
1068 openedfiles=(struct openedfile**)realloc((void*)openedfiles,(fd+1)*sizeof(struct openedfile*));
1069
1070 for(i=nopenedfiles;i<=fd;i++)
1071 openedfiles[i]=NULL;
1072
1073 nopenedfiles=fd+1;
1074 }
1075
1076 openedfiles[fd]=(struct openedfile*)calloc(sizeof(struct openedfile),1);
1077
1078 openedfiles[fd]->filename=strcpy(malloc(strlen(filename)+1),filename);
1079 openedfiles[fd]->delete=0;
1080 }
1081
1082 #endif
1083