Merge branch 'upstream'
[routino] / src / files.c
1 /***************************************
2  $Header: /home/amb/routino/src/RCS/files.c,v 1.25 2010/10/31 17:52:40 amb Exp $
3
4  Functions to handle files.
5
6  Part of the Routino routing software.
7  ******************/ /******************
8  This file Copyright 2008-2010 Andrew M. Bishop
9
10  This program is free software: you can redistribute it and/or modify
11  it under the terms of the GNU Affero General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU Affero General Public License for more details.
19
20  You should have received a copy of the GNU Affero General Public License
21  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  ***************************************/
23
24 #include <assert.h>
25
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <errno.h>
32 #include <sys/stat.h>
33 #include <sys/mman.h>
34 #include <sys/types.h>
35
36 #include "files.h"
37
38
39 /*+ A structure to contain the list of memory mapped files. +*/
40 struct mmapinfo
41 {
42  const char  *filename;         /*+ The name of the file (the index of the list). +*/
43        int    fd;               /*+ The file descriptor used when it was opened. +*/
44        void  *address;          /*+ The address the file was mapped to. +*/
45        size_t length;           /*+ The length of the file. +*/
46 };
47
48 /*+ The list of memory mapped files. +*/
49 static struct mmapinfo *mappedfiles;
50
51 /*+ The number of mapped files. +*/
52 static int nmappedfiles=0;
53
54
55 /*++++++++++++++++++++++++++++++++++++++
56   Return a filename composed of the dirname, prefix and filename.
57
58   char *FileName Returns an allocated filename.
59
60   const char *dirname The directory name.
61
62   const char *prefix The file prefix.
63
64   const char *name The filename.
65   ++++++++++++++++++++++++++++++++++++++*/
66
67 char *FileName(const char *dirname,const char *prefix, const char *name)
68 {
69  char *filename=(char*)malloc((dirname?strlen(dirname):0)+1+(prefix?strlen(prefix):0)+1+strlen(name)+1);
70
71  sprintf(filename,"%s%s%s%s%s",dirname?dirname:"",dirname?"/":"",prefix?prefix:"",prefix?"-":"",name);
72
73  return(filename);
74 }
75
76
77 /*++++++++++++++++++++++++++++++++++++++
78   Open a file and map it into memory.
79
80   void *MapFile Returns the address of the file or exits in case of an error.
81
82   const char *filename The name of the file to open.
83   ++++++++++++++++++++++++++++++++++++++*/
84
85 void *MapFile(const char *filename)
86 {
87  int fd;
88  off_t size;
89  void *address;
90
91  /* Open the file and get its size */
92
93  fd=ReOpenFile(filename);
94
95  size=SizeFile(filename);
96
97  /* Map the file */
98
99  address=mmap(NULL,size,PROT_READ,MAP_SHARED,fd,0);
100
101  if(address==MAP_FAILED)
102    {
103     close(fd);
104
105     assert(0);
106
107     fprintf(stderr,"Cannot mmap file '%s' for reading [%s].\n",filename,strerror(errno));
108     exit(EXIT_FAILURE);
109    }
110
111  mappedfiles=(struct mmapinfo*)realloc((void*)mappedfiles,(nmappedfiles+1)*sizeof(struct mmapinfo));
112
113  mappedfiles[nmappedfiles].filename=filename;
114  mappedfiles[nmappedfiles].fd=fd;
115  mappedfiles[nmappedfiles].address=address;
116  mappedfiles[nmappedfiles].length=size;
117
118  nmappedfiles++;
119
120  return(address);
121 }
122
123
124 /*++++++++++++++++++++++++++++++++++++++
125   Open a file and map it into memory.
126
127   void *MapFileWriteable Returns the address of the file or exits in case of an error.
128
129   const char *filename The name of the file to open.
130   ++++++++++++++++++++++++++++++++++++++*/
131
132 void *MapFileWriteable(const char *filename)
133 {
134  int fd;
135  off_t size;
136  void *address;
137
138  /* Open the file and get its size */
139
140  fd=ReOpenFileWriteable(filename);
141
142  size=SizeFile(filename);
143
144  /* Map the file */
145
146  address=mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
147
148  if(address==MAP_FAILED)
149    {
150     close(fd);
151
152     fprintf(stderr,"Cannot mmap file '%s' for reading and writing [%s].\n",filename,strerror(errno));
153     exit(EXIT_FAILURE);
154    }
155
156  mappedfiles=(struct mmapinfo*)realloc((void*)mappedfiles,(nmappedfiles+1)*sizeof(struct mmapinfo));
157
158  mappedfiles[nmappedfiles].filename=filename;
159  mappedfiles[nmappedfiles].fd=fd;
160  mappedfiles[nmappedfiles].address=address;
161  mappedfiles[nmappedfiles].length=size;
162
163  nmappedfiles++;
164
165  return(address);
166 }
167
168
169 /*++++++++++++++++++++++++++++++++++++++
170   Unmap a file.
171
172   void *UnmapFile Returns NULL (for similarity to the MapFile function).
173
174   const char *filename The name of the file when it was opened.
175   ++++++++++++++++++++++++++++++++++++++*/
176
177 void *UnmapFile(const char *filename)
178 {
179  int i;
180
181  for(i=0;i<nmappedfiles;i++)
182     if(!strcmp(mappedfiles[i].filename,filename))
183        break;
184
185  if(i==nmappedfiles)
186    {
187     fprintf(stderr,"The file '%s' was not mapped using MapFile().\n",filename);
188     exit(EXIT_FAILURE);
189    }
190
191  /* Close the file */
192
193  close(mappedfiles[i].fd);
194
195  /* Unmap the file */
196
197  munmap(mappedfiles[i].address,mappedfiles[i].length);
198
199  /* Shuffle the list of files */
200
201  nmappedfiles--;
202
203  if(nmappedfiles>i)
204     memmove(&mappedfiles[i],&mappedfiles[i+1],(nmappedfiles-i)*sizeof(struct mmapinfo));
205
206  return(NULL);
207 }
208
209
210 /*++++++++++++++++++++++++++++++++++++++
211   Open a new file on disk for writing to.
212
213   int OpenFileNew Returns the file descriptor if OK or exits in case of an error.
214
215   const char *filename The name of the file to create.
216   ++++++++++++++++++++++++++++++++++++++*/
217
218 int OpenFileNew(const char *filename)
219 {
220  int fd;
221
222  /* Open the file */
223
224  fd=open(filename,O_RDWR|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
225
226  if(fd<0)
227    {
228     fprintf(stderr,"Cannot open file '%s' for writing [%s].\n",filename,strerror(errno));
229     exit(EXIT_FAILURE);
230    }
231
232  return(fd);
233 }
234
235
236 /*++++++++++++++++++++++++++++++++++++++
237   Open a new file on disk for reading from and appending.
238
239   int OpenFileAppend Returns the file descriptor if OK or exits in case of an error.
240
241   const char *filename The name of the file to create.
242   ++++++++++++++++++++++++++++++++++++++*/
243
244 int OpenFileAppend(const char *filename)
245 {
246  int fd;
247
248  /* Open the file */
249
250  fd=open(filename,O_RDWR|O_CREAT|O_APPEND,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
251
252  if(fd<0)
253    {
254     fprintf(stderr,"Cannot open file '%s' for appending [%s].\n",filename,strerror(errno));
255     exit(EXIT_FAILURE);
256    }
257
258  return(fd);
259 }
260
261
262 /*++++++++++++++++++++++++++++++++++++++
263   Open an existing file on disk for reading.
264
265   int ReOpenFile Returns the file descriptor if OK or exits in case of an error.
266
267   const char *filename The name of the file to open.
268   ++++++++++++++++++++++++++++++++++++++*/
269
270 int ReOpenFile(const char *filename)
271 {
272  int fd;
273
274  /* Open the file */
275
276  fd=open(filename,O_RDONLY);
277
278  if(fd<0)
279    {
280     fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno));
281     exit(EXIT_FAILURE);
282    }
283
284  return(fd);
285 }
286
287
288 /*++++++++++++++++++++++++++++++++++++++
289   Open an existing file on disk for reading from or writing to.
290
291   int ReOpenFileWriteable Returns the file descriptor if OK or exits in case of an error.
292
293   const char *filename The name of the file to open.
294   ++++++++++++++++++++++++++++++++++++++*/
295
296 int ReOpenFileWriteable(const char *filename)
297 {
298  int fd;
299
300  /* Open the file */
301
302  fd=open(filename,O_RDWR);
303
304  if(fd<0)
305    {
306     fprintf(stderr,"Cannot open file '%s' for reading and writing [%s].\n",filename,strerror(errno));
307     exit(EXIT_FAILURE);
308    }
309
310  return(fd);
311 }
312
313
314 /*++++++++++++++++++++++++++++++++++++++
315   Get the size of a file.
316
317   off_t SizeFile Returns the file size.
318
319   const char *filename The name of the file to check.
320   ++++++++++++++++++++++++++++++++++++++*/
321
322 off_t SizeFile(const char *filename)
323 {
324  struct stat buf;
325
326  if(stat(filename,&buf))
327    {
328     fprintf(stderr,"Cannot stat file '%s' [%s].\n",filename,strerror(errno));
329     exit(EXIT_FAILURE);
330    }
331
332  return(buf.st_size);
333 }
334
335
336 /*++++++++++++++++++++++++++++++++++++++
337   Check if a file exists.
338
339   int ExistsFile Returns 1 if the file exists and 0 if not.
340
341   const char *filename The name of the file to check.
342   ++++++++++++++++++++++++++++++++++++++*/
343
344 int ExistsFile(const char *filename)
345 {
346  struct stat buf;
347
348  if(stat(filename,&buf))
349     return(0);
350  else
351     return(1);
352 }
353
354
355 /*++++++++++++++++++++++++++++++++++++++
356   Close a file on disk.
357
358   int fd The file descriptor to close.
359   ++++++++++++++++++++++++++++++++++++++*/
360
361 void CloseFile(int fd)
362 {
363  close(fd);
364 }
365
366
367 /*++++++++++++++++++++++++++++++++++++++
368   Delete a file from disk.
369
370   int DeleteFile Returns 0 if OK or something else in case of an error.
371
372   char *filename The name of the file to delete.
373   ++++++++++++++++++++++++++++++++++++++*/
374
375 int DeleteFile(char *filename)
376 {
377  unlink(filename);
378
379  return(0);
380 }