Routino SVN Repository Browser

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

ViewVC logotype

Annotation of /trunk/src/files.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1401 - (hide annotations) (download) (as text)
Wed Jun 19 18:57:15 2013 UTC (11 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 15364 byte(s)
Add functions to read and write file descriptors with buffering.

1 amb 2 /***************************************
2 amb 326 Functions to handle files.
3 amb 151
4     Part of the Routino routing software.
5 amb 2 ******************/ /******************
6 amb 1401 This file Copyright 2008-2013 Andrew M. Bishop
7 amb 2
8 amb 151 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 amb 2 ***************************************/
21    
22 amb 680
23 amb 2 #include <unistd.h>
24     #include <stdlib.h>
25 amb 449 #include <stdio.h>
26 amb 162 #include <string.h>
27 amb 2 #include <fcntl.h>
28 amb 330 #include <errno.h>
29 amb 2 #include <sys/stat.h>
30     #include <sys/mman.h>
31 amb 251 #include <sys/types.h>
32 amb 2
33 amb 449 #include "files.h"
34 amb 2
35    
36 amb 289 /*+ A structure to contain the list of memory mapped files. +*/
37 amb 248 struct mmapinfo
38     {
39 amb 289 const char *filename; /*+ The name of the file (the index of the list). +*/
40     int fd; /*+ The file descriptor used when it was opened. +*/
41     void *address; /*+ The address the file was mapped to. +*/
42     size_t length; /*+ The length of the file. +*/
43 amb 248 };
44    
45 amb 289 /*+ The list of memory mapped files. +*/
46     static struct mmapinfo *mappedfiles;
47 amb 248
48 amb 289 /*+ The number of mapped files. +*/
49     static int nmappedfiles=0;
50 amb 248
51 amb 289
52 amb 1401 #define BUFFLEN 1024
53    
54     /*+ A structure to contain the list of file buffers. +*/
55     struct filebuffer
56     {
57     int fd; /*+ The file descriptor used when it was opened. +*/
58     char buffer[BUFFLEN]; /*+ The data buffer. +*/
59     size_t pointer; /*+ The read/write pointer for the file buffer. +*/
60     size_t length; /*+ The read pointer for the file buffer. +*/
61     int reading; /*+ A flag to indicate if the file is for reading. +*/
62     };
63    
64     /*+ The list of file buffers. +*/
65     static struct filebuffer **filebuffers=NULL;
66    
67     /*+ The number of allocated file buffer pointers. +*/
68     static int nfilebuffers=0;
69    
70    
71     static void CreateFileBuffer(int fd,int reading);
72    
73    
74 amb 2 /*++++++++++++++++++++++++++++++++++++++
75 amb 680 Return a filename composed of the dirname, prefix and name.
76 amb 162
77 amb 680 char *FileName Returns a pointer to memory allocated to the filename.
78 amb 162
79     const char *dirname The directory name.
80    
81     const char *prefix The file prefix.
82    
83 amb 680 const char *name The main part of the name.
84 amb 162 ++++++++++++++++++++++++++++++++++++++*/
85    
86     char *FileName(const char *dirname,const char *prefix, const char *name)
87     {
88 amb 518 char *filename=(char*)malloc((dirname?strlen(dirname):0)+1+(prefix?strlen(prefix):0)+1+strlen(name)+1);
89 amb 162
90     sprintf(filename,"%s%s%s%s%s",dirname?dirname:"",dirname?"/":"",prefix?prefix:"",prefix?"-":"",name);
91    
92     return(filename);
93     }
94    
95    
96     /*++++++++++++++++++++++++++++++++++++++
97 amb 680 Open a file read-only and map it into memory.
98 amb 2
99 amb 331 void *MapFile Returns the address of the file or exits in case of an error.
100 amb 2
101     const char *filename The name of the file to open.
102     ++++++++++++++++++++++++++++++++++++++*/
103    
104 amb 250 void *MapFile(const char *filename)
105 amb 2 {
106     int fd;
107 amb 331 off_t size;
108 amb 2 void *address;
109    
110 amb 331 /* Open the file and get its size */
111 amb 2
112 amb 331 fd=ReOpenFile(filename);
113 amb 2
114 amb 331 size=SizeFile(filename);
115 amb 2
116     /* Map the file */
117    
118 amb 331 address=mmap(NULL,size,PROT_READ,MAP_SHARED,fd,0);
119 amb 2
120 amb 245 if(address==MAP_FAILED)
121 amb 2 {
122     close(fd);
123 amb 177
124 amb 511 fprintf(stderr,"Cannot mmap file '%s' for reading [%s].\n",filename,strerror(errno));
125 amb 177 exit(EXIT_FAILURE);
126 amb 2 }
127    
128 amb 680 /* Store the information about the mapped file */
129    
130 amb 248 mappedfiles=(struct mmapinfo*)realloc((void*)mappedfiles,(nmappedfiles+1)*sizeof(struct mmapinfo));
131    
132     mappedfiles[nmappedfiles].filename=filename;
133     mappedfiles[nmappedfiles].fd=fd;
134     mappedfiles[nmappedfiles].address=address;
135 amb 331 mappedfiles[nmappedfiles].length=size;
136 amb 248
137     nmappedfiles++;
138    
139 amb 2 return(address);
140     }
141    
142    
143     /*++++++++++++++++++++++++++++++++++++++
144 amb 680 Open a file read-write and map it into memory.
145 amb 507
146 amb 513 void *MapFileWriteable Returns the address of the file or exits in case of an error.
147 amb 507
148     const char *filename The name of the file to open.
149     ++++++++++++++++++++++++++++++++++++++*/
150    
151     void *MapFileWriteable(const char *filename)
152     {
153     int fd;
154     off_t size;
155     void *address;
156    
157     /* Open the file and get its size */
158    
159 amb 511 fd=ReOpenFileWriteable(filename);
160 amb 507
161     size=SizeFile(filename);
162    
163     /* Map the file */
164    
165     address=mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
166    
167     if(address==MAP_FAILED)
168     {
169     close(fd);
170    
171 amb 511 fprintf(stderr,"Cannot mmap file '%s' for reading and writing [%s].\n",filename,strerror(errno));
172 amb 507 exit(EXIT_FAILURE);
173     }
174    
175 amb 680 /* Store the information about the mapped file */
176    
177 amb 507 mappedfiles=(struct mmapinfo*)realloc((void*)mappedfiles,(nmappedfiles+1)*sizeof(struct mmapinfo));
178    
179     mappedfiles[nmappedfiles].filename=filename;
180     mappedfiles[nmappedfiles].fd=fd;
181     mappedfiles[nmappedfiles].address=address;
182     mappedfiles[nmappedfiles].length=size;
183    
184     nmappedfiles++;
185    
186     return(address);
187     }
188    
189    
190     /*++++++++++++++++++++++++++++++++++++++
191 amb 680 Unmap a file and close it.
192 amb 2
193 amb 289 void *UnmapFile Returns NULL (for similarity to the MapFile function).
194 amb 255
195 amb 1122 const void *address The address of the mapped file in memory.
196 amb 248 ++++++++++++++++++++++++++++++++++++++*/
197    
198 amb 1122 void *UnmapFile(const void *address)
199 amb 248 {
200     int i;
201    
202     for(i=0;i<nmappedfiles;i++)
203 amb 1122 if(mappedfiles[i].address==address)
204 amb 248 break;
205    
206     if(i==nmappedfiles)
207     {
208 amb 1122 fprintf(stderr,"The data at address %p was not mapped using MapFile().\n",address);
209 amb 248 exit(EXIT_FAILURE);
210     }
211    
212     /* Close the file */
213    
214     close(mappedfiles[i].fd);
215    
216     /* Unmap the file */
217    
218     munmap(mappedfiles[i].address,mappedfiles[i].length);
219    
220     /* Shuffle the list of files */
221    
222     nmappedfiles--;
223    
224     if(nmappedfiles>i)
225     memmove(&mappedfiles[i],&mappedfiles[i+1],(nmappedfiles-i)*sizeof(struct mmapinfo));
226 amb 255
227     return(NULL);
228 amb 248 }
229    
230    
231     /*++++++++++++++++++++++++++++++++++++++
232 amb 680 Open a new file on disk for writing.
233 amb 248
234 amb 513 int OpenFileNew Returns the file descriptor if OK or exits in case of an error.
235 amb 248
236 amb 97 const char *filename The name of the file to create.
237 amb 2 ++++++++++++++++++++++++++++++++++++++*/
238    
239 amb 502 int OpenFileNew(const char *filename)
240 amb 2 {
241 amb 97 int fd;
242 amb 2
243 amb 97 /* Open the file */
244 amb 2
245 amb 448 fd=open(filename,O_RDWR|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
246 amb 2
247 amb 97 if(fd<0)
248 amb 177 {
249 amb 330 fprintf(stderr,"Cannot open file '%s' for writing [%s].\n",filename,strerror(errno));
250 amb 177 exit(EXIT_FAILURE);
251     }
252 amb 2
253 amb 97 return(fd);
254 amb 2 }
255    
256    
257     /*++++++++++++++++++++++++++++++++++++++
258 amb 1401 Open a new file on disk for writing (with buffering).
259    
260     int OpenFileBufferedNew Returns the file descriptor if OK or exits in case of an error.
261    
262     const char *filename The name of the file to create.
263     ++++++++++++++++++++++++++++++++++++++*/
264    
265     int OpenFileBufferedNew(const char *filename)
266     {
267     int fd;
268    
269     fd=OpenFileNew(filename);
270    
271     CreateFileBuffer(fd,0);
272    
273     return(fd);
274     }
275    
276    
277     /*++++++++++++++++++++++++++++++++++++++
278 amb 680 Open a new or existing file on disk for reading and appending.
279 amb 326
280 amb 502 int OpenFileAppend Returns the file descriptor if OK or exits in case of an error.
281 amb 326
282 amb 680 const char *filename The name of the file to create or open.
283 amb 326 ++++++++++++++++++++++++++++++++++++++*/
284    
285 amb 502 int OpenFileAppend(const char *filename)
286 amb 326 {
287     int fd;
288    
289     /* Open the file */
290    
291     fd=open(filename,O_RDWR|O_CREAT|O_APPEND,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
292    
293     if(fd<0)
294     {
295 amb 330 fprintf(stderr,"Cannot open file '%s' for appending [%s].\n",filename,strerror(errno));
296 amb 326 exit(EXIT_FAILURE);
297     }
298    
299     return(fd);
300     }
301    
302    
303     /*++++++++++++++++++++++++++++++++++++++
304 amb 1401 Open a new or existing file on disk for reading and appending (with buffering).
305    
306     int OpenFileBufferedAppend Returns the file descriptor if OK or exits in case of an error.
307    
308     const char *filename The name of the file to create or open.
309     ++++++++++++++++++++++++++++++++++++++*/
310    
311     int OpenFileBufferedAppend(const char *filename)
312     {
313     int fd;
314    
315     fd=OpenFileAppend(filename);
316    
317     CreateFileBuffer(fd,0);
318    
319     return(fd);
320     }
321    
322    
323     /*++++++++++++++++++++++++++++++++++++++
324 amb 511 Open an existing file on disk for reading.
325 amb 251
326 amb 331 int ReOpenFile Returns the file descriptor if OK or exits in case of an error.
327 amb 251
328     const char *filename The name of the file to open.
329     ++++++++++++++++++++++++++++++++++++++*/
330    
331     int ReOpenFile(const char *filename)
332     {
333     int fd;
334    
335     /* Open the file */
336    
337 amb 511 fd=open(filename,O_RDONLY);
338 amb 251
339     if(fd<0)
340     {
341 amb 330 fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno));
342 amb 251 exit(EXIT_FAILURE);
343     }
344    
345     return(fd);
346     }
347    
348    
349     /*++++++++++++++++++++++++++++++++++++++
350 amb 680 Open an existing file on disk for reading or writing.
351 amb 511
352     int ReOpenFileWriteable Returns the file descriptor if OK or exits in case of an error.
353    
354     const char *filename The name of the file to open.
355     ++++++++++++++++++++++++++++++++++++++*/
356    
357     int ReOpenFileWriteable(const char *filename)
358     {
359     int fd;
360    
361     /* Open the file */
362    
363     fd=open(filename,O_RDWR);
364    
365     if(fd<0)
366     {
367     fprintf(stderr,"Cannot open file '%s' for reading and writing [%s].\n",filename,strerror(errno));
368     exit(EXIT_FAILURE);
369     }
370    
371     return(fd);
372     }
373    
374    
375     /*++++++++++++++++++++++++++++++++++++++
376 amb 1401 Write data to a file descriptor (via a buffer).
377    
378     int WriteFileBuffered Returns 0 if OK or something else in case of an error.
379    
380     int fd The file descriptor to write to.
381    
382     const void *address The address of the data to be written.
383    
384     size_t length The length of data to write.
385     ++++++++++++++++++++++++++++++++++++++*/
386    
387     int WriteFileBuffered(int fd,const void *address,size_t length)
388     {
389     logassert(fd!=-1,"File descriptor is in error - report a bug");
390    
391     logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug");
392    
393     logassert(!filebuffers[fd]->reading,"File descriptor was not opened for writing - report a bug");
394    
395     /* Write the data */
396    
397     if((filebuffers[fd]->pointer+length)>BUFFLEN)
398     {
399     if(write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer)!=(ssize_t)filebuffers[fd]->pointer)
400     return(-1);
401    
402     filebuffers[fd]->pointer=0;
403     }
404    
405     while(length>BUFFLEN)
406     {
407     if(write(fd,address,BUFFLEN)!=(ssize_t)BUFFLEN)
408     return(-1);
409    
410     address+=BUFFLEN;
411     length-=BUFFLEN;
412     }
413    
414     if(length>0)
415     {
416     memcpy(filebuffers[fd]->buffer+filebuffers[fd]->pointer,address,length);
417    
418     filebuffers[fd]->pointer+=length;
419     }
420    
421     return(0);
422     }
423    
424    
425     /*++++++++++++++++++++++++++++++++++++++
426     Read data from a file descriptor (via a buffer).
427    
428     int ReadFileBuffered Returns 0 if OK or something else in case of an error.
429    
430     int fd The file descriptor to read from.
431    
432     void *address The address the data is to be read into.
433    
434     size_t length The length of data to read.
435     ++++++++++++++++++++++++++++++++++++++*/
436    
437     int ReadFileBuffered(int fd,void *address,size_t length)
438     {
439     logassert(fd!=-1,"File descriptor is in error - report a bug");
440    
441     logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug");
442    
443     logassert(filebuffers[fd]->reading,"File descriptor was not opened for reading - report a bug");
444    
445     /* Read the data */
446    
447     if(length>BUFFLEN)
448     {
449     if(filebuffers[fd]->pointer<filebuffers[fd]->length)
450     {
451     memcpy(address,filebuffers[fd]->buffer+filebuffers[fd]->pointer,filebuffers[fd]->length-filebuffers[fd]->pointer);
452    
453     address+=filebuffers[fd]->length-filebuffers[fd]->pointer;
454     length-=filebuffers[fd]->length-filebuffers[fd]->pointer;
455    
456     filebuffers[fd]->pointer=0;
457     filebuffers[fd]->length=0;
458     }
459    
460     while(length>BUFFLEN)
461     {
462     if(read(fd,address,BUFFLEN)!=(ssize_t)BUFFLEN)
463     return(-1);
464    
465     address+=BUFFLEN;
466     length-=BUFFLEN;
467     }
468    
469     if(length==0)
470     return(0);
471     }
472    
473     if((filebuffers[fd]->pointer+length)>filebuffers[fd]->length)
474     {
475     if(filebuffers[fd]->pointer<filebuffers[fd]->length)
476     memcpy(filebuffers[fd]->buffer,filebuffers[fd]->buffer+filebuffers[fd]->pointer,filebuffers[fd]->length-filebuffers[fd]->pointer);
477    
478     filebuffers[fd]->pointer=0;
479     filebuffers[fd]->length=filebuffers[fd]->length-filebuffers[fd]->pointer;
480    
481     filebuffers[fd]->length+=read(fd,filebuffers[fd]->buffer+filebuffers[fd]->length,BUFFLEN-filebuffers[fd]->length);
482     }
483    
484     if(filebuffers[fd]->length==0)
485     return(-1);
486    
487     memcpy(address,filebuffers[fd]->buffer+filebuffers[fd]->pointer,length);
488    
489     filebuffers[fd]->pointer+=length;
490    
491     return(0);
492     }
493    
494    
495     /*++++++++++++++++++++++++++++++++++++++
496 amb 331 Get the size of a file.
497    
498 amb 680 off_t SizeFile Returns the file size if OK or exits in case of an error.
499 amb 331
500     const char *filename The name of the file to check.
501     ++++++++++++++++++++++++++++++++++++++*/
502    
503     off_t SizeFile(const char *filename)
504     {
505     struct stat buf;
506    
507     if(stat(filename,&buf))
508     {
509     fprintf(stderr,"Cannot stat file '%s' [%s].\n",filename,strerror(errno));
510     exit(EXIT_FAILURE);
511     }
512    
513     return(buf.st_size);
514     }
515    
516    
517     /*++++++++++++++++++++++++++++++++++++++
518 amb 341 Check if a file exists.
519    
520     int ExistsFile Returns 1 if the file exists and 0 if not.
521    
522     const char *filename The name of the file to check.
523     ++++++++++++++++++++++++++++++++++++++*/
524    
525     int ExistsFile(const char *filename)
526     {
527     struct stat buf;
528    
529     if(stat(filename,&buf))
530     return(0);
531     else
532     return(1);
533     }
534    
535    
536     /*++++++++++++++++++++++++++++++++++++++
537 amb 97 Close a file on disk.
538 amb 87
539 amb 680 int CloseFile returns -1 (for similarity to the *OpenFile* functions).
540 amb 612
541 amb 97 int fd The file descriptor to close.
542 amb 87 ++++++++++++++++++++++++++++++++++++++*/
543    
544 amb 612 int CloseFile(int fd)
545 amb 87 {
546 amb 1401 logassert(fd>nfilebuffers || !filebuffers[fd],"File descriptor has a buffer - report a bug");
547    
548 amb 97 close(fd);
549 amb 612
550     return(-1);
551 amb 87 }
552 amb 251
553    
554     /*++++++++++++++++++++++++++++++++++++++
555 amb 1401 Close a file on disk (and flush the buffer).
556    
557     int CloseFileBuffered returns -1 (for similarity to the *OpenFile* functions).
558    
559     int fd The file descriptor to close.
560     ++++++++++++++++++++++++++++++++++++++*/
561    
562     int CloseFileBuffered(int fd)
563     {
564     logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug");
565    
566     if(!filebuffers[fd]->reading)
567     write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer);
568    
569     close(fd);
570    
571     free(filebuffers[fd]);
572    
573     filebuffers[fd]=NULL;
574    
575     return(-1);
576     }
577    
578    
579     /*++++++++++++++++++++++++++++++++++++++
580 amb 251 Delete a file from disk.
581    
582 amb 680 int DeleteFile Returns 0 if OK.
583 amb 251
584 amb 1119 const char *filename The name of the file to delete.
585 amb 251 ++++++++++++++++++++++++++++++++++++++*/
586    
587 amb 1119 int DeleteFile(const char *filename)
588 amb 251 {
589     unlink(filename);
590    
591     return(0);
592     }
593 amb 1119
594    
595     /*++++++++++++++++++++++++++++++++++++++
596     Rename a file on disk.
597    
598 amb 1162 int RenameFile Returns 0 if OK.
599 amb 1119
600     const char *oldfilename The old name of the file before renaming.
601    
602     const char *newfilename The new name of the file after renaming.
603     ++++++++++++++++++++++++++++++++++++++*/
604    
605     int RenameFile(const char *oldfilename,const char *newfilename)
606     {
607     rename(oldfilename,newfilename);
608    
609     return(0);
610     }
611 amb 1401
612    
613     /*++++++++++++++++++++++++++++++++++++++
614     Create a file buffer.
615    
616     int fd The file descriptor.
617    
618     int reading A flag set if the file descriptor is to be used for reading.
619     ++++++++++++++++++++++++++++++++++++++*/
620    
621     static void CreateFileBuffer(int fd,int reading)
622     {
623     if(nfilebuffers<=fd)
624     {
625     int i;
626    
627     filebuffers=(struct filebuffer**)realloc((void*)filebuffers,(fd+1)*sizeof(struct filebuffer*));
628    
629     for(i=nfilebuffers;i<=fd;i++)
630     filebuffers[i]=NULL;
631    
632     nfilebuffers=fd+1;
633     }
634    
635     filebuffers[fd]=(struct filebuffer*)calloc(sizeof(struct filebuffer),1);
636    
637     filebuffers[fd]->reading=reading;
638     }

Properties

Name Value
cvs:description File handling functions.