Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/files.c
Parent Directory
|
Revision Log
Revision 1418 -
(hide annotations)
(download)
(as text)
Sat Jun 22 18:56:18 2013 UTC (11 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 18025 byte(s)
Sat Jun 22 18:56:18 2013 UTC (11 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 18025 byte(s)
Make the changes required to handle the new function names from the last few checkins.
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 | amb | 1410 | /* Local functions */ |
72 | amb | 1401 | |
73 | amb | 1410 | static void CreateFileBuffer(int fd,int read_write); |
74 | amb | 1401 | |
75 | amb | 1410 | |
76 | amb | 2 | /*++++++++++++++++++++++++++++++++++++++ |
77 | amb | 680 | Return a filename composed of the dirname, prefix and name. |
78 | amb | 162 | |
79 | amb | 680 | char *FileName Returns a pointer to memory allocated to the filename. |
80 | amb | 162 | |
81 | const char *dirname The directory name. | ||
82 | |||
83 | const char *prefix The file prefix. | ||
84 | |||
85 | amb | 680 | const char *name The main part of the name. |
86 | amb | 162 | ++++++++++++++++++++++++++++++++++++++*/ |
87 | |||
88 | char *FileName(const char *dirname,const char *prefix, const char *name) | ||
89 | { | ||
90 | amb | 518 | char *filename=(char*)malloc((dirname?strlen(dirname):0)+1+(prefix?strlen(prefix):0)+1+strlen(name)+1); |
91 | amb | 162 | |
92 | sprintf(filename,"%s%s%s%s%s",dirname?dirname:"",dirname?"/":"",prefix?prefix:"",prefix?"-":"",name); | ||
93 | |||
94 | return(filename); | ||
95 | } | ||
96 | |||
97 | |||
98 | /*++++++++++++++++++++++++++++++++++++++ | ||
99 | amb | 680 | Open a file read-only and map it into memory. |
100 | amb | 2 | |
101 | amb | 331 | void *MapFile Returns the address of the file or exits in case of an error. |
102 | amb | 2 | |
103 | const char *filename The name of the file to open. | ||
104 | ++++++++++++++++++++++++++++++++++++++*/ | ||
105 | |||
106 | amb | 250 | void *MapFile(const char *filename) |
107 | amb | 2 | { |
108 | int fd; | ||
109 | amb | 1418 | struct stat buf; |
110 | amb | 331 | off_t size; |
111 | amb | 2 | void *address; |
112 | |||
113 | amb | 1418 | /* Open the file */ |
114 | amb | 2 | |
115 | amb | 1418 | fd=open(filename,O_RDONLY); |
116 | amb | 2 | |
117 | amb | 1418 | if(fd<0) |
118 | { | ||
119 | fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno)); | ||
120 | exit(EXIT_FAILURE); | ||
121 | } | ||
122 | amb | 2 | |
123 | amb | 1418 | /* Get its size */ |
124 | |||
125 | if(stat(filename,&buf)) | ||
126 | { | ||
127 | fprintf(stderr,"Cannot stat file '%s' [%s].\n",filename,strerror(errno)); | ||
128 | exit(EXIT_FAILURE); | ||
129 | } | ||
130 | |||
131 | size=buf.st_size; | ||
132 | |||
133 | amb | 2 | /* Map the file */ |
134 | |||
135 | amb | 331 | address=mmap(NULL,size,PROT_READ,MAP_SHARED,fd,0); |
136 | amb | 2 | |
137 | amb | 245 | if(address==MAP_FAILED) |
138 | amb | 2 | { |
139 | close(fd); | ||
140 | amb | 177 | |
141 | amb | 511 | fprintf(stderr,"Cannot mmap file '%s' for reading [%s].\n",filename,strerror(errno)); |
142 | amb | 177 | exit(EXIT_FAILURE); |
143 | amb | 2 | } |
144 | |||
145 | amb | 680 | /* Store the information about the mapped file */ |
146 | |||
147 | amb | 248 | mappedfiles=(struct mmapinfo*)realloc((void*)mappedfiles,(nmappedfiles+1)*sizeof(struct mmapinfo)); |
148 | |||
149 | mappedfiles[nmappedfiles].filename=filename; | ||
150 | mappedfiles[nmappedfiles].fd=fd; | ||
151 | mappedfiles[nmappedfiles].address=address; | ||
152 | amb | 331 | mappedfiles[nmappedfiles].length=size; |
153 | amb | 248 | |
154 | nmappedfiles++; | ||
155 | |||
156 | amb | 2 | return(address); |
157 | } | ||
158 | |||
159 | |||
160 | /*++++++++++++++++++++++++++++++++++++++ | ||
161 | amb | 680 | Open a file read-write and map it into memory. |
162 | amb | 507 | |
163 | amb | 513 | void *MapFileWriteable Returns the address of the file or exits in case of an error. |
164 | amb | 507 | |
165 | const char *filename The name of the file to open. | ||
166 | ++++++++++++++++++++++++++++++++++++++*/ | ||
167 | |||
168 | void *MapFileWriteable(const char *filename) | ||
169 | { | ||
170 | int fd; | ||
171 | amb | 1418 | struct stat buf; |
172 | amb | 507 | off_t size; |
173 | void *address; | ||
174 | |||
175 | amb | 1418 | /* Open the file */ |
176 | amb | 507 | |
177 | amb | 1418 | fd=open(filename,O_RDWR); |
178 | amb | 507 | |
179 | amb | 1418 | if(fd<0) |
180 | { | ||
181 | fprintf(stderr,"Cannot open file '%s' for reading and writing [%s].\n",filename,strerror(errno)); | ||
182 | exit(EXIT_FAILURE); | ||
183 | } | ||
184 | amb | 507 | |
185 | amb | 1418 | /* Get its size */ |
186 | |||
187 | if(stat(filename,&buf)) | ||
188 | { | ||
189 | fprintf(stderr,"Cannot stat file '%s' [%s].\n",filename,strerror(errno)); | ||
190 | exit(EXIT_FAILURE); | ||
191 | } | ||
192 | |||
193 | size=buf.st_size; | ||
194 | |||
195 | amb | 507 | /* Map the file */ |
196 | |||
197 | address=mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); | ||
198 | |||
199 | if(address==MAP_FAILED) | ||
200 | { | ||
201 | close(fd); | ||
202 | |||
203 | amb | 511 | fprintf(stderr,"Cannot mmap file '%s' for reading and writing [%s].\n",filename,strerror(errno)); |
204 | amb | 507 | exit(EXIT_FAILURE); |
205 | } | ||
206 | |||
207 | amb | 680 | /* Store the information about the mapped file */ |
208 | |||
209 | amb | 507 | mappedfiles=(struct mmapinfo*)realloc((void*)mappedfiles,(nmappedfiles+1)*sizeof(struct mmapinfo)); |
210 | |||
211 | mappedfiles[nmappedfiles].filename=filename; | ||
212 | mappedfiles[nmappedfiles].fd=fd; | ||
213 | mappedfiles[nmappedfiles].address=address; | ||
214 | mappedfiles[nmappedfiles].length=size; | ||
215 | |||
216 | nmappedfiles++; | ||
217 | |||
218 | return(address); | ||
219 | } | ||
220 | |||
221 | |||
222 | /*++++++++++++++++++++++++++++++++++++++ | ||
223 | amb | 680 | Unmap a file and close it. |
224 | amb | 2 | |
225 | amb | 289 | void *UnmapFile Returns NULL (for similarity to the MapFile function). |
226 | amb | 255 | |
227 | amb | 1122 | const void *address The address of the mapped file in memory. |
228 | amb | 248 | ++++++++++++++++++++++++++++++++++++++*/ |
229 | |||
230 | amb | 1122 | void *UnmapFile(const void *address) |
231 | amb | 248 | { |
232 | int i; | ||
233 | |||
234 | for(i=0;i<nmappedfiles;i++) | ||
235 | amb | 1122 | if(mappedfiles[i].address==address) |
236 | amb | 248 | break; |
237 | |||
238 | if(i==nmappedfiles) | ||
239 | { | ||
240 | amb | 1122 | fprintf(stderr,"The data at address %p was not mapped using MapFile().\n",address); |
241 | amb | 248 | exit(EXIT_FAILURE); |
242 | } | ||
243 | |||
244 | /* Close the file */ | ||
245 | |||
246 | amb | 1418 | close(mappedfiles[i].fd); |
247 | amb | 248 | |
248 | /* Unmap the file */ | ||
249 | |||
250 | munmap(mappedfiles[i].address,mappedfiles[i].length); | ||
251 | |||
252 | /* Shuffle the list of files */ | ||
253 | |||
254 | nmappedfiles--; | ||
255 | |||
256 | if(nmappedfiles>i) | ||
257 | memmove(&mappedfiles[i],&mappedfiles[i+1],(nmappedfiles-i)*sizeof(struct mmapinfo)); | ||
258 | amb | 255 | |
259 | return(NULL); | ||
260 | amb | 248 | } |
261 | |||
262 | |||
263 | /*++++++++++++++++++++++++++++++++++++++ | ||
264 | amb | 1418 | Open an existing file on disk for reading. |
265 | amb | 248 | |
266 | amb | 1418 | int SlimMapFile Returns the file descriptor if OK or exits in case of an error. |
267 | amb | 248 | |
268 | amb | 1418 | const char *filename The name of the file to open. |
269 | amb | 2 | ++++++++++++++++++++++++++++++++++++++*/ |
270 | |||
271 | amb | 1418 | int SlimMapFile(const char *filename) |
272 | amb | 2 | { |
273 | amb | 97 | int fd; |
274 | amb | 2 | |
275 | amb | 97 | /* Open the file */ |
276 | amb | 2 | |
277 | amb | 1418 | fd=open(filename,O_RDONLY); |
278 | amb | 2 | |
279 | amb | 97 | if(fd<0) |
280 | amb | 177 | { |
281 | amb | 1418 | fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno)); |
282 | amb | 177 | exit(EXIT_FAILURE); |
283 | } | ||
284 | amb | 2 | |
285 | amb | 1410 | CreateFileBuffer(fd,0); |
286 | |||
287 | amb | 97 | return(fd); |
288 | amb | 2 | } |
289 | |||
290 | |||
291 | /*++++++++++++++++++++++++++++++++++++++ | ||
292 | amb | 1418 | Open an existing file on disk for reading or writing. |
293 | amb | 1401 | |
294 | amb | 1418 | int SlimMapFileWriteable Returns the file descriptor if OK or exits in case of an error. |
295 | amb | 1401 | |
296 | amb | 1418 | const char *filename The name of the file to open. |
297 | amb | 1401 | ++++++++++++++++++++++++++++++++++++++*/ |
298 | |||
299 | amb | 1418 | int SlimMapFileWriteable(const char *filename) |
300 | amb | 1401 | { |
301 | int fd; | ||
302 | |||
303 | amb | 326 | /* Open the file */ |
304 | |||
305 | amb | 1418 | fd=open(filename,O_RDWR); |
306 | amb | 326 | |
307 | if(fd<0) | ||
308 | { | ||
309 | amb | 1418 | fprintf(stderr,"Cannot open file '%s' for reading and writing [%s].\n",filename,strerror(errno)); |
310 | amb | 326 | exit(EXIT_FAILURE); |
311 | } | ||
312 | |||
313 | amb | 1410 | CreateFileBuffer(fd,0); |
314 | |||
315 | amb | 326 | return(fd); |
316 | } | ||
317 | |||
318 | |||
319 | /*++++++++++++++++++++++++++++++++++++++ | ||
320 | amb | 1418 | Close a file on disk. |
321 | amb | 1401 | |
322 | amb | 1418 | int SlimUnmapFile returns -1 (for similarity to the UnmapFile function). |
323 | amb | 1401 | |
324 | amb | 1418 | int fd The file descriptor to close. |
325 | amb | 1401 | ++++++++++++++++++++++++++++++++++++++*/ |
326 | |||
327 | amb | 1418 | int SlimUnmapFile(int fd) |
328 | amb | 1401 | { |
329 | amb | 1418 | close(fd); |
330 | amb | 1401 | |
331 | amb | 1418 | return(-1); |
332 | amb | 1401 | } |
333 | |||
334 | |||
335 | /*++++++++++++++++++++++++++++++++++++++ | ||
336 | amb | 1418 | Open a new file on disk for writing (with buffering). |
337 | amb | 251 | |
338 | amb | 1418 | int OpenFileBufferedNew Returns the file descriptor if OK or exits in case of an error. |
339 | amb | 251 | |
340 | amb | 1418 | const char *filename The name of the file to create. |
341 | amb | 251 | ++++++++++++++++++++++++++++++++++++++*/ |
342 | |||
343 | amb | 1418 | int OpenFileBufferedNew(const char *filename) |
344 | amb | 251 | { |
345 | int fd; | ||
346 | |||
347 | /* Open the file */ | ||
348 | |||
349 | amb | 1418 | fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); |
350 | amb | 251 | |
351 | if(fd<0) | ||
352 | { | ||
353 | amb | 1418 | fprintf(stderr,"Cannot open file '%s' for writing [%s].\n",filename,strerror(errno)); |
354 | amb | 251 | exit(EXIT_FAILURE); |
355 | } | ||
356 | |||
357 | amb | 1418 | CreateFileBuffer(fd,-1); |
358 | amb | 1410 | |
359 | amb | 251 | return(fd); |
360 | } | ||
361 | |||
362 | |||
363 | /*++++++++++++++++++++++++++++++++++++++ | ||
364 | amb | 1418 | Open a new or existing file on disk for appending (with buffering). |
365 | amb | 1404 | |
366 | amb | 1418 | int OpenFileBufferedAppend Returns the file descriptor if OK or exits in case of an error. |
367 | amb | 1404 | |
368 | amb | 1418 | const char *filename The name of the file to create or open. |
369 | amb | 1404 | ++++++++++++++++++++++++++++++++++++++*/ |
370 | |||
371 | amb | 1418 | int OpenFileBufferedAppend(const char *filename) |
372 | amb | 1404 | { |
373 | int fd; | ||
374 | |||
375 | amb | 1418 | /* Open the file */ |
376 | amb | 1404 | |
377 | amb | 1418 | fd=open(filename,O_WRONLY|O_CREAT|O_APPEND,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); |
378 | amb | 1404 | |
379 | amb | 1418 | if(fd<0) |
380 | { | ||
381 | fprintf(stderr,"Cannot open file '%s' for appending [%s].\n",filename,strerror(errno)); | ||
382 | exit(EXIT_FAILURE); | ||
383 | } | ||
384 | |||
385 | CreateFileBuffer(fd,-1); | ||
386 | |||
387 | amb | 1404 | return(fd); |
388 | } | ||
389 | |||
390 | |||
391 | /*++++++++++++++++++++++++++++++++++++++ | ||
392 | amb | 1418 | Open an existing file on disk for reading (with buffering). |
393 | amb | 511 | |
394 | amb | 1418 | int ReOpenFileBuffered Returns the file descriptor if OK or exits in case of an error. |
395 | amb | 511 | |
396 | const char *filename The name of the file to open. | ||
397 | ++++++++++++++++++++++++++++++++++++++*/ | ||
398 | |||
399 | amb | 1418 | int ReOpenFileBuffered(const char *filename) |
400 | amb | 511 | { |
401 | int fd; | ||
402 | |||
403 | /* Open the file */ | ||
404 | |||
405 | amb | 1418 | fd=open(filename,O_RDONLY); |
406 | amb | 511 | |
407 | if(fd<0) | ||
408 | { | ||
409 | amb | 1418 | fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno)); |
410 | amb | 511 | exit(EXIT_FAILURE); |
411 | } | ||
412 | |||
413 | amb | 1418 | CreateFileBuffer(fd,1); |
414 | amb | 1410 | |
415 | amb | 511 | return(fd); |
416 | } | ||
417 | |||
418 | |||
419 | /*++++++++++++++++++++++++++++++++++++++ | ||
420 | amb | 1401 | Write data to a file descriptor (via a buffer). |
421 | |||
422 | int WriteFileBuffered Returns 0 if OK or something else in case of an error. | ||
423 | |||
424 | int fd The file descriptor to write to. | ||
425 | |||
426 | const void *address The address of the data to be written. | ||
427 | |||
428 | size_t length The length of data to write. | ||
429 | ++++++++++++++++++++++++++++++++++++++*/ | ||
430 | |||
431 | int WriteFileBuffered(int fd,const void *address,size_t length) | ||
432 | { | ||
433 | logassert(fd!=-1,"File descriptor is in error - report a bug"); | ||
434 | |||
435 | logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); | ||
436 | |||
437 | logassert(!filebuffers[fd]->reading,"File descriptor was not opened for writing - report a bug"); | ||
438 | |||
439 | /* Write the data */ | ||
440 | |||
441 | if((filebuffers[fd]->pointer+length)>BUFFLEN) | ||
442 | { | ||
443 | if(write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer)!=(ssize_t)filebuffers[fd]->pointer) | ||
444 | return(-1); | ||
445 | |||
446 | filebuffers[fd]->pointer=0; | ||
447 | } | ||
448 | |||
449 | amb | 1403 | if(length>=BUFFLEN) |
450 | amb | 1401 | { |
451 | amb | 1403 | if(write(fd,address,length)!=(ssize_t)length) |
452 | amb | 1401 | return(-1); |
453 | |||
454 | amb | 1403 | return(0); |
455 | amb | 1401 | } |
456 | |||
457 | amb | 1403 | memcpy(filebuffers[fd]->buffer+filebuffers[fd]->pointer,address,length); |
458 | amb | 1401 | |
459 | amb | 1403 | filebuffers[fd]->pointer+=length; |
460 | amb | 1401 | |
461 | return(0); | ||
462 | } | ||
463 | |||
464 | |||
465 | /*++++++++++++++++++++++++++++++++++++++ | ||
466 | Read data from a file descriptor (via a buffer). | ||
467 | |||
468 | int ReadFileBuffered Returns 0 if OK or something else in case of an error. | ||
469 | |||
470 | int fd The file descriptor to read from. | ||
471 | |||
472 | void *address The address the data is to be read into. | ||
473 | |||
474 | size_t length The length of data to read. | ||
475 | ++++++++++++++++++++++++++++++++++++++*/ | ||
476 | |||
477 | int ReadFileBuffered(int fd,void *address,size_t length) | ||
478 | { | ||
479 | logassert(fd!=-1,"File descriptor is in error - report a bug"); | ||
480 | |||
481 | logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); | ||
482 | |||
483 | logassert(filebuffers[fd]->reading,"File descriptor was not opened for reading - report a bug"); | ||
484 | |||
485 | /* Read the data */ | ||
486 | |||
487 | amb | 1403 | if((filebuffers[fd]->pointer+length)>filebuffers[fd]->length) |
488 | amb | 1401 | if(filebuffers[fd]->pointer<filebuffers[fd]->length) |
489 | { | ||
490 | memcpy(address,filebuffers[fd]->buffer+filebuffers[fd]->pointer,filebuffers[fd]->length-filebuffers[fd]->pointer); | ||
491 | |||
492 | address+=filebuffers[fd]->length-filebuffers[fd]->pointer; | ||
493 | length-=filebuffers[fd]->length-filebuffers[fd]->pointer; | ||
494 | |||
495 | filebuffers[fd]->pointer=0; | ||
496 | filebuffers[fd]->length=0; | ||
497 | } | ||
498 | |||
499 | amb | 1403 | if(length>=BUFFLEN) |
500 | { | ||
501 | if(read(fd,address,length)!=(ssize_t)length) | ||
502 | return(-1); | ||
503 | amb | 1401 | |
504 | amb | 1403 | return(0); |
505 | amb | 1401 | } |
506 | |||
507 | amb | 1403 | if(filebuffers[fd]->pointer==filebuffers[fd]->length) |
508 | amb | 1401 | { |
509 | amb | 1418 | ssize_t len=read(fd,filebuffers[fd]->buffer,BUFFLEN); |
510 | |||
511 | if(len<=0) | ||
512 | return(-1); | ||
513 | |||
514 | |||
515 | filebuffers[fd]->length=len; | ||
516 | amb | 1401 | filebuffers[fd]->pointer=0; |
517 | } | ||
518 | |||
519 | if(filebuffers[fd]->length==0) | ||
520 | return(-1); | ||
521 | |||
522 | memcpy(address,filebuffers[fd]->buffer+filebuffers[fd]->pointer,length); | ||
523 | |||
524 | filebuffers[fd]->pointer+=length; | ||
525 | |||
526 | return(0); | ||
527 | } | ||
528 | |||
529 | |||
530 | /*++++++++++++++++++++++++++++++++++++++ | ||
531 | amb | 1410 | Seek to a position in a file descriptor that uses a buffer. |
532 | amb | 1407 | |
533 | amb | 1410 | int SeekFileBuffered Returns 0 if OK or something else in case of an error. |
534 | amb | 1407 | |
535 | int fd The file descriptor to seek within. | ||
536 | |||
537 | off_t position The position to seek to. | ||
538 | ++++++++++++++++++++++++++++++++++++++*/ | ||
539 | |||
540 | int SeekFileBuffered(int fd,off_t position) | ||
541 | { | ||
542 | logassert(fd!=-1,"File descriptor is in error - report a bug"); | ||
543 | |||
544 | logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); | ||
545 | |||
546 | /* Seek the data - doesn't need to be highly optimised */ | ||
547 | |||
548 | if(!filebuffers[fd]->reading) | ||
549 | if(write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer)!=(ssize_t)filebuffers[fd]->pointer) | ||
550 | return(-1); | ||
551 | |||
552 | filebuffers[fd]->pointer=0; | ||
553 | filebuffers[fd]->length=0; | ||
554 | |||
555 | if(lseek(fd,position,SEEK_SET)!=position) | ||
556 | return(-1); | ||
557 | |||
558 | return(0); | ||
559 | } | ||
560 | |||
561 | |||
562 | /*++++++++++++++++++++++++++++++++++++++ | ||
563 | amb | 1406 | Skip forward by an offset in a file descriptor that uses a buffer. |
564 | amb | 1404 | |
565 | amb | 1406 | int SkipFileBuffered Returns 0 if OK or something else in case of an error. |
566 | amb | 1404 | |
567 | amb | 1406 | int fd The file descriptor to skip within. |
568 | amb | 1404 | |
569 | amb | 1406 | off_t skip The amount to skip forward. |
570 | amb | 1404 | ++++++++++++++++++++++++++++++++++++++*/ |
571 | |||
572 | amb | 1406 | int SkipFileBuffered(int fd,off_t skip) |
573 | amb | 1404 | { |
574 | logassert(fd!=-1,"File descriptor is in error - report a bug"); | ||
575 | |||
576 | logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); | ||
577 | |||
578 | logassert(filebuffers[fd]->reading,"File descriptor was not opened for reading - report a bug"); | ||
579 | |||
580 | amb | 1407 | /* Skip the data - needs to be optimised */ |
581 | amb | 1404 | |
582 | amb | 1406 | if((filebuffers[fd]->pointer+skip)>filebuffers[fd]->length) |
583 | amb | 1404 | { |
584 | amb | 1406 | skip-=filebuffers[fd]->length-filebuffers[fd]->pointer; |
585 | amb | 1404 | |
586 | filebuffers[fd]->pointer=0; | ||
587 | filebuffers[fd]->length=0; | ||
588 | |||
589 | amb | 1406 | if(lseek(fd,skip,SEEK_CUR)==-1) |
590 | amb | 1404 | return(-1); |
591 | } | ||
592 | else | ||
593 | amb | 1406 | filebuffers[fd]->pointer+=skip; |
594 | amb | 1404 | |
595 | return(0); | ||
596 | } | ||
597 | |||
598 | |||
599 | /*++++++++++++++++++++++++++++++++++++++ | ||
600 | amb | 331 | Get the size of a file. |
601 | |||
602 | amb | 680 | off_t SizeFile Returns the file size if OK or exits in case of an error. |
603 | amb | 331 | |
604 | const char *filename The name of the file to check. | ||
605 | ++++++++++++++++++++++++++++++++++++++*/ | ||
606 | |||
607 | off_t SizeFile(const char *filename) | ||
608 | { | ||
609 | struct stat buf; | ||
610 | |||
611 | if(stat(filename,&buf)) | ||
612 | { | ||
613 | fprintf(stderr,"Cannot stat file '%s' [%s].\n",filename,strerror(errno)); | ||
614 | exit(EXIT_FAILURE); | ||
615 | } | ||
616 | |||
617 | return(buf.st_size); | ||
618 | } | ||
619 | |||
620 | |||
621 | /*++++++++++++++++++++++++++++++++++++++ | ||
622 | amb | 341 | Check if a file exists. |
623 | |||
624 | int ExistsFile Returns 1 if the file exists and 0 if not. | ||
625 | |||
626 | const char *filename The name of the file to check. | ||
627 | ++++++++++++++++++++++++++++++++++++++*/ | ||
628 | |||
629 | int ExistsFile(const char *filename) | ||
630 | { | ||
631 | struct stat buf; | ||
632 | |||
633 | if(stat(filename,&buf)) | ||
634 | return(0); | ||
635 | else | ||
636 | return(1); | ||
637 | } | ||
638 | |||
639 | |||
640 | /*++++++++++++++++++++++++++++++++++++++ | ||
641 | amb | 1418 | Close a file on disk (and flush the buffer). |
642 | amb | 87 | |
643 | amb | 1418 | int CloseFileBuffered returns -1 (for similarity to the *OpenFileBuffered* functions). |
644 | amb | 612 | |
645 | amb | 97 | int fd The file descriptor to close. |
646 | amb | 87 | ++++++++++++++++++++++++++++++++++++++*/ |
647 | |||
648 | amb | 1418 | int CloseFileBuffered(int fd) |
649 | amb | 87 | { |
650 | amb | 1418 | logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); |
651 | amb | 1401 | |
652 | amb | 1418 | if(!filebuffers[fd]->reading) |
653 | write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer); | ||
654 | |||
655 | amb | 97 | close(fd); |
656 | amb | 612 | |
657 | amb | 1418 | free(filebuffers[fd]); |
658 | |||
659 | filebuffers[fd]=NULL; | ||
660 | |||
661 | amb | 612 | return(-1); |
662 | amb | 87 | } |
663 | amb | 251 | |
664 | |||
665 | /*++++++++++++++++++++++++++++++++++++++ | ||
666 | amb | 1418 | Open an existing file on disk for reading (in a simple mode). |
667 | amb | 1401 | |
668 | amb | 1418 | int OpenFile Returns the file descriptor if OK or exits in case of an error. |
669 | amb | 1401 | |
670 | amb | 1418 | const char *filename The name of the file to open. |
671 | amb | 1401 | ++++++++++++++++++++++++++++++++++++++*/ |
672 | |||
673 | amb | 1418 | int OpenFile(const char *filename) |
674 | amb | 1401 | { |
675 | amb | 1418 | int fd; |
676 | amb | 1401 | |
677 | amb | 1418 | /* Open the file */ |
678 | amb | 1401 | |
679 | amb | 1418 | fd=open(filename,O_RDONLY); |
680 | amb | 1401 | |
681 | amb | 1418 | if(fd<0) |
682 | { | ||
683 | fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno)); | ||
684 | exit(EXIT_FAILURE); | ||
685 | } | ||
686 | amb | 1401 | |
687 | amb | 1418 | return(fd); |
688 | } | ||
689 | amb | 1401 | |
690 | amb | 1418 | |
691 | /*++++++++++++++++++++++++++++++++++++++ | ||
692 | Close a file on disk (that was opened in simple mode). | ||
693 | |||
694 | int fd The file descriptor to close. | ||
695 | ++++++++++++++++++++++++++++++++++++++*/ | ||
696 | |||
697 | void CloseFile(int fd) | ||
698 | { | ||
699 | close(fd); | ||
700 | amb | 1401 | } |
701 | |||
702 | |||
703 | /*++++++++++++++++++++++++++++++++++++++ | ||
704 | amb | 251 | Delete a file from disk. |
705 | |||
706 | amb | 680 | int DeleteFile Returns 0 if OK. |
707 | amb | 251 | |
708 | amb | 1119 | const char *filename The name of the file to delete. |
709 | amb | 251 | ++++++++++++++++++++++++++++++++++++++*/ |
710 | |||
711 | amb | 1119 | int DeleteFile(const char *filename) |
712 | amb | 251 | { |
713 | unlink(filename); | ||
714 | |||
715 | return(0); | ||
716 | } | ||
717 | amb | 1119 | |
718 | |||
719 | /*++++++++++++++++++++++++++++++++++++++ | ||
720 | Rename a file on disk. | ||
721 | |||
722 | amb | 1162 | int RenameFile Returns 0 if OK. |
723 | amb | 1119 | |
724 | const char *oldfilename The old name of the file before renaming. | ||
725 | |||
726 | const char *newfilename The new name of the file after renaming. | ||
727 | ++++++++++++++++++++++++++++++++++++++*/ | ||
728 | |||
729 | int RenameFile(const char *oldfilename,const char *newfilename) | ||
730 | { | ||
731 | rename(oldfilename,newfilename); | ||
732 | |||
733 | return(0); | ||
734 | } | ||
735 | amb | 1401 | |
736 | |||
737 | /*++++++++++++++++++++++++++++++++++++++ | ||
738 | Create a file buffer. | ||
739 | |||
740 | int fd The file descriptor. | ||
741 | |||
742 | amb | 1410 | int read_write A flag set to 1 for reading, -1 for writing and 0 for unbuffered. |
743 | amb | 1401 | ++++++++++++++++++++++++++++++++++++++*/ |
744 | |||
745 | amb | 1410 | static void CreateFileBuffer(int fd,int read_write) |
746 | amb | 1401 | { |
747 | if(nfilebuffers<=fd) | ||
748 | { | ||
749 | int i; | ||
750 | |||
751 | filebuffers=(struct filebuffer**)realloc((void*)filebuffers,(fd+1)*sizeof(struct filebuffer*)); | ||
752 | |||
753 | for(i=nfilebuffers;i<=fd;i++) | ||
754 | filebuffers[i]=NULL; | ||
755 | |||
756 | nfilebuffers=fd+1; | ||
757 | } | ||
758 | |||
759 | amb | 1410 | if(read_write) |
760 | { | ||
761 | filebuffers[fd]=(struct filebuffer*)calloc(sizeof(struct filebuffer),1); | ||
762 | amb | 1401 | |
763 | amb | 1410 | filebuffers[fd]->reading=(read_write==1); |
764 | } | ||
765 | amb | 1401 | } |
Properties
Name | Value |
---|---|
cvs:description | File handling functions. |