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 1403 - (hide annotations) (download) (as text)
Thu Jun 20 17:35:36 2013 UTC (11 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 14922 byte(s)
Fix the non-buffered close function assertion and re-factor the code for
buffered reading (although not used yet).

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 amb 1403 if(length>=BUFFLEN)
406 amb 1401 {
407 amb 1403 if(write(fd,address,length)!=(ssize_t)length)
408 amb 1401 return(-1);
409    
410 amb 1403 return(0);
411 amb 1401 }
412    
413 amb 1403 memcpy(filebuffers[fd]->buffer+filebuffers[fd]->pointer,address,length);
414 amb 1401
415 amb 1403 filebuffers[fd]->pointer+=length;
416 amb 1401
417     return(0);
418     }
419    
420    
421     /*++++++++++++++++++++++++++++++++++++++
422     Read data from a file descriptor (via a buffer).
423    
424     int ReadFileBuffered Returns 0 if OK or something else in case of an error.
425    
426     int fd The file descriptor to read from.
427    
428     void *address The address the data is to be read into.
429    
430     size_t length The length of data to read.
431     ++++++++++++++++++++++++++++++++++++++*/
432    
433     int ReadFileBuffered(int fd,void *address,size_t length)
434     {
435     logassert(fd!=-1,"File descriptor is in error - report a bug");
436    
437     logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug");
438    
439     logassert(filebuffers[fd]->reading,"File descriptor was not opened for reading - report a bug");
440    
441     /* Read the data */
442    
443 amb 1403 if((filebuffers[fd]->pointer+length)>filebuffers[fd]->length)
444 amb 1401 if(filebuffers[fd]->pointer<filebuffers[fd]->length)
445     {
446     memcpy(address,filebuffers[fd]->buffer+filebuffers[fd]->pointer,filebuffers[fd]->length-filebuffers[fd]->pointer);
447    
448     address+=filebuffers[fd]->length-filebuffers[fd]->pointer;
449     length-=filebuffers[fd]->length-filebuffers[fd]->pointer;
450    
451     filebuffers[fd]->pointer=0;
452     filebuffers[fd]->length=0;
453     }
454    
455 amb 1403 if(length>=BUFFLEN)
456     {
457     if(read(fd,address,length)!=(ssize_t)length)
458     return(-1);
459 amb 1401
460 amb 1403 return(0);
461 amb 1401 }
462    
463 amb 1403 if(filebuffers[fd]->pointer==filebuffers[fd]->length)
464 amb 1401 {
465 amb 1403 filebuffers[fd]->length=read(fd,filebuffers[fd]->buffer,BUFFLEN);
466 amb 1401 filebuffers[fd]->pointer=0;
467     }
468    
469     if(filebuffers[fd]->length==0)
470     return(-1);
471    
472     memcpy(address,filebuffers[fd]->buffer+filebuffers[fd]->pointer,length);
473    
474     filebuffers[fd]->pointer+=length;
475    
476     return(0);
477     }
478    
479    
480     /*++++++++++++++++++++++++++++++++++++++
481 amb 331 Get the size of a file.
482    
483 amb 680 off_t SizeFile Returns the file size if OK or exits in case of an error.
484 amb 331
485     const char *filename The name of the file to check.
486     ++++++++++++++++++++++++++++++++++++++*/
487    
488     off_t SizeFile(const char *filename)
489     {
490     struct stat buf;
491    
492     if(stat(filename,&buf))
493     {
494     fprintf(stderr,"Cannot stat file '%s' [%s].\n",filename,strerror(errno));
495     exit(EXIT_FAILURE);
496     }
497    
498     return(buf.st_size);
499     }
500    
501    
502     /*++++++++++++++++++++++++++++++++++++++
503 amb 341 Check if a file exists.
504    
505     int ExistsFile Returns 1 if the file exists and 0 if not.
506    
507     const char *filename The name of the file to check.
508     ++++++++++++++++++++++++++++++++++++++*/
509    
510     int ExistsFile(const char *filename)
511     {
512     struct stat buf;
513    
514     if(stat(filename,&buf))
515     return(0);
516     else
517     return(1);
518     }
519    
520    
521     /*++++++++++++++++++++++++++++++++++++++
522 amb 97 Close a file on disk.
523 amb 87
524 amb 680 int CloseFile returns -1 (for similarity to the *OpenFile* functions).
525 amb 612
526 amb 97 int fd The file descriptor to close.
527 amb 87 ++++++++++++++++++++++++++++++++++++++*/
528    
529 amb 612 int CloseFile(int fd)
530 amb 87 {
531 amb 1403 logassert(fd>=nfilebuffers || !filebuffers[fd],"File descriptor has a buffer - report a bug");
532 amb 1401
533 amb 97 close(fd);
534 amb 612
535     return(-1);
536 amb 87 }
537 amb 251
538    
539     /*++++++++++++++++++++++++++++++++++++++
540 amb 1401 Close a file on disk (and flush the buffer).
541    
542 amb 1403 int CloseFileBuffered returns -1 (for similarity to the *OpenFileBuffered* functions).
543 amb 1401
544     int fd The file descriptor to close.
545     ++++++++++++++++++++++++++++++++++++++*/
546    
547     int CloseFileBuffered(int fd)
548     {
549     logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug");
550    
551     if(!filebuffers[fd]->reading)
552     write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer);
553    
554     close(fd);
555    
556     free(filebuffers[fd]);
557    
558     filebuffers[fd]=NULL;
559    
560     return(-1);
561     }
562    
563    
564     /*++++++++++++++++++++++++++++++++++++++
565 amb 251 Delete a file from disk.
566    
567 amb 680 int DeleteFile Returns 0 if OK.
568 amb 251
569 amb 1119 const char *filename The name of the file to delete.
570 amb 251 ++++++++++++++++++++++++++++++++++++++*/
571    
572 amb 1119 int DeleteFile(const char *filename)
573 amb 251 {
574     unlink(filename);
575    
576     return(0);
577     }
578 amb 1119
579    
580     /*++++++++++++++++++++++++++++++++++++++
581     Rename a file on disk.
582    
583 amb 1162 int RenameFile Returns 0 if OK.
584 amb 1119
585     const char *oldfilename The old name of the file before renaming.
586    
587     const char *newfilename The new name of the file after renaming.
588     ++++++++++++++++++++++++++++++++++++++*/
589    
590     int RenameFile(const char *oldfilename,const char *newfilename)
591     {
592     rename(oldfilename,newfilename);
593    
594     return(0);
595     }
596 amb 1401
597    
598     /*++++++++++++++++++++++++++++++++++++++
599     Create a file buffer.
600    
601     int fd The file descriptor.
602    
603     int reading A flag set if the file descriptor is to be used for reading.
604     ++++++++++++++++++++++++++++++++++++++*/
605    
606     static void CreateFileBuffer(int fd,int reading)
607     {
608     if(nfilebuffers<=fd)
609     {
610     int i;
611    
612     filebuffers=(struct filebuffer**)realloc((void*)filebuffers,(fd+1)*sizeof(struct filebuffer*));
613    
614     for(i=nfilebuffers;i<=fd;i++)
615     filebuffers[i]=NULL;
616    
617     nfilebuffers=fd+1;
618     }
619    
620     filebuffers[fd]=(struct filebuffer*)calloc(sizeof(struct filebuffer),1);
621    
622     filebuffers[fd]->reading=reading;
623     }

Properties

Name Value
cvs:description File handling functions.