ce595ab85ac44ec55a6f68256353e2e0a8820ac9
[routino] / src / files.c
1 /***************************************
2  $Header: /home/amb/routino/src/RCS/files.c,v 1.18 2010/03/29 18:20:06 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
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <sys/stat.h>
31 #include <sys/mman.h>
32 #include <sys/types.h>
33
34 #include "functions.h"
35
36
37 /*+ A structure to contain the list of memory mapped files. +*/
38 struct mmapinfo
39 {
40  const char  *filename;         /*+ The name of the file (the index of the list). +*/
41        int    fd;               /*+ The file descriptor used when it was opened. +*/
42        void  *address;          /*+ The address the file was mapped to. +*/
43        size_t length;           /*+ The length of the file. +*/
44 };
45
46 /*+ The list of memory mapped files. +*/
47 static struct mmapinfo *mappedfiles;
48
49 /*+ The number of mapped files. +*/
50 static int nmappedfiles=0;
51
52
53 /*++++++++++++++++++++++++++++++++++++++
54   Return a filename composed of the dirname, prefix and filename.
55
56   char *FileName Returns an allocated filename.
57
58   const char *dirname The directory name.
59
60   const char *prefix The file prefix.
61
62   const char *name The filename.
63   ++++++++++++++++++++++++++++++++++++++*/
64
65 char *FileName(const char *dirname,const char *prefix, const char *name)
66 {
67  char *filename=(char*)malloc((dirname?strlen(dirname):0)+1+(prefix?strlen(prefix):0)+1+strlen(name));
68
69  sprintf(filename,"%s%s%s%s%s",dirname?dirname:"",dirname?"/":"",prefix?prefix:"",prefix?"-":"",name);
70
71  return(filename);
72 }
73
74
75 /*++++++++++++++++++++++++++++++++++++++
76   Open a file and map it into memory.
77
78   void *MapFile Returns the address of the file or exits in case of an error.
79
80   const char *filename The name of the file to open.
81   ++++++++++++++++++++++++++++++++++++++*/
82
83 void *MapFile(const char *filename)
84 {
85  int fd;
86  off_t size;
87  void *address;
88
89  /* Open the file and get its size */
90
91  fd=ReOpenFile(filename);
92
93  size=SizeFile(filename);
94
95  /* Map the file */
96
97  address=mmap(NULL,size,PROT_READ,MAP_SHARED,fd,0);
98
99  if(address==MAP_FAILED)
100    {
101     close(fd);
102
103     fprintf(stderr,"Cannot mmap file '%s' [%s].\n",filename,strerror(errno));
104     exit(EXIT_FAILURE);
105    }
106
107  mappedfiles=(struct mmapinfo*)realloc((void*)mappedfiles,(nmappedfiles+1)*sizeof(struct mmapinfo));
108
109  mappedfiles[nmappedfiles].filename=filename;
110  mappedfiles[nmappedfiles].fd=fd;
111  mappedfiles[nmappedfiles].address=address;
112  mappedfiles[nmappedfiles].length=size;
113
114  nmappedfiles++;
115
116  return(address);
117 }
118
119
120 /*++++++++++++++++++++++++++++++++++++++
121   Unmap a file.
122
123   void *UnmapFile Returns NULL (for similarity to the MapFile function).
124
125   const char *filename The name of the file when it was opened.
126   ++++++++++++++++++++++++++++++++++++++*/
127
128 void *UnmapFile(const char *filename)
129 {
130  int i;
131
132  for(i=0;i<nmappedfiles;i++)
133     if(!strcmp(mappedfiles[i].filename,filename))
134        break;
135
136  if(i==nmappedfiles)
137    {
138     fprintf(stderr,"The file '%s' was not mapped using MapFile().\n",filename);
139     exit(EXIT_FAILURE);
140    }
141
142  /* Close the file */
143
144  close(mappedfiles[i].fd);
145
146  /* Unmap the file */
147
148  munmap(mappedfiles[i].address,mappedfiles[i].length);
149
150  /* Shuffle the list of files */
151
152  nmappedfiles--;
153
154  if(nmappedfiles>i)
155     memmove(&mappedfiles[i],&mappedfiles[i+1],(nmappedfiles-i)*sizeof(struct mmapinfo));
156
157  return(NULL);
158 }
159
160
161 /*++++++++++++++++++++++++++++++++++++++
162   Open a new file on disk for writing to.
163
164   int OpenFile Returns the file descriptor if OK or exits in case of an error.
165
166   const char *filename The name of the file to create.
167   ++++++++++++++++++++++++++++++++++++++*/
168
169 int OpenFile(const char *filename)
170 {
171  int fd;
172
173  /* Open the file */
174
175  fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
176
177  if(fd<0)
178    {
179     fprintf(stderr,"Cannot open file '%s' for writing [%s].\n",filename,strerror(errno));
180     exit(EXIT_FAILURE);
181    }
182
183  return(fd);
184 }
185
186
187 /*++++++++++++++++++++++++++++++++++++++
188   Open a new file on disk for reading and appending.
189
190   int AppendFile Returns the file descriptor if OK or exits in case of an error.
191
192   const char *filename The name of the file to create.
193   ++++++++++++++++++++++++++++++++++++++*/
194
195 int AppendFile(const char *filename)
196 {
197  int fd;
198
199  /* Open the file */
200
201  fd=open(filename,O_RDWR|O_CREAT|O_APPEND,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
202
203  if(fd<0)
204    {
205     fprintf(stderr,"Cannot open file '%s' for appending [%s].\n",filename,strerror(errno));
206     exit(EXIT_FAILURE);
207    }
208
209  return(fd);
210 }
211
212
213 /*++++++++++++++++++++++++++++++++++++++
214   Open an existing file on disk for reading from.
215
216   int ReOpenFile Returns the file descriptor if OK or exits in case of an error.
217
218   const char *filename The name of the file to open.
219   ++++++++++++++++++++++++++++++++++++++*/
220
221 int ReOpenFile(const char *filename)
222 {
223  int fd;
224
225  /* Open the file */
226
227  fd=open(filename,O_RDONLY);
228
229  if(fd<0)
230    {
231     fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno));
232     exit(EXIT_FAILURE);
233    }
234
235  return(fd);
236 }
237
238
239 /*++++++++++++++++++++++++++++++++++++++
240   Write data to a file on disk.
241
242   int WriteFile Returns 0 if OK or something else in case of an error.
243
244   int fd The file descriptor to write to.
245
246   const void *address The address of the data to be written from.
247
248   size_t length The length of data to write.
249   ++++++++++++++++++++++++++++++++++++++*/
250
251 int WriteFile(int fd,const void *address,size_t length)
252 {
253  /* Write the data */
254
255  if(write(fd,address,length)!=length)
256     return(-1);
257
258  return(0);
259 }
260
261
262 /*++++++++++++++++++++++++++++++++++++++
263   Read data from a file on disk.
264
265   int ReadFile Returns 0 if OK or something else in case of an error.
266
267   int fd The file descriptor to read from.
268
269   void *address The address of the data to be read into.
270
271   size_t length The length of data to read.
272   ++++++++++++++++++++++++++++++++++++++*/
273
274 int ReadFile(int fd,void *address,size_t length)
275 {
276  /* Read the data */
277
278  if(read(fd,address,length)!=length)
279     return(-1);
280
281  return(0);
282 }
283
284
285 /*++++++++++++++++++++++++++++++++++++++
286   Get the size of a file.
287
288   off_t SizeFile Returns the file size.
289
290   const char *filename The name of the file to check.
291   ++++++++++++++++++++++++++++++++++++++*/
292
293 off_t SizeFile(const char *filename)
294 {
295  struct stat buf;
296
297  if(stat(filename,&buf))
298    {
299     fprintf(stderr,"Cannot stat file '%s' [%s].\n",filename,strerror(errno));
300     exit(EXIT_FAILURE);
301    }
302
303  return(buf.st_size);
304 }
305
306
307 /*++++++++++++++++++++++++++++++++++++++
308   Check if a file exists.
309
310   int ExistsFile Returns 1 if the file exists and 0 if not.
311
312   const char *filename The name of the file to check.
313   ++++++++++++++++++++++++++++++++++++++*/
314
315 int ExistsFile(const char *filename)
316 {
317  struct stat buf;
318
319  if(stat(filename,&buf))
320     return(0);
321  else
322     return(1);
323 }
324
325
326 /*++++++++++++++++++++++++++++++++++++++
327   Seek to a position in a file on disk.
328
329   int SeekFile Returns 0 if OK or something else in case of an error.
330
331   int fd The file descriptor to seek within.
332
333   off_t position The position to seek to.
334   ++++++++++++++++++++++++++++++++++++++*/
335
336 int SeekFile(int fd,off_t position)
337 {
338  /* Seek the data */
339
340  if(lseek(fd,position,SEEK_SET)!=position)
341     return(-1);
342
343  return(0);
344 }
345
346
347 /*++++++++++++++++++++++++++++++++++++++
348   Close a file on disk.
349
350   int fd The file descriptor to close.
351   ++++++++++++++++++++++++++++++++++++++*/
352
353 void CloseFile(int fd)
354 {
355  close(fd);
356 }
357
358
359 /*++++++++++++++++++++++++++++++++++++++
360   Delete a file from disk.
361
362   int DeleteFile Returns 0 if OK or something else in case of an error.
363
364   char *filename The name of the file to delete.
365   ++++++++++++++++++++++++++++++++++++++*/
366
367 int DeleteFile(char *filename)
368 {
369  unlink(filename);
370
371  return(0);
372 }