Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /branches/libroutino/src/files.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1742 - (show annotations) (download) (as text)
Sat Jul 11 15:42:22 2015 UTC (9 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 24353 byte(s)
Merge change from MS-Windows branch (size_t and offset_t).

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

Properties

Name Value
cvs:description File handling functions.