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