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