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 1699 -
(show annotations)
(download)
(as text)
Tue Jun 9 18:05:06 2015 UTC (9 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 23367 byte(s)
Tue Jun 9 18:05:06 2015 UTC (9 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 23367 byte(s)
Merge the MS-Windows branch back into the trunk. Code changes and documentation for Cygwin and MinGW compilers.
1 | /*************************************** |
2 | Functions to handle files. |
3 | |
4 | Part of the Routino routing software. |
5 | ******************/ /****************** |
6 | This file Copyright 2008-2015 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 | #if defined(_MSC_VER) |
24 | #include <io.h> |
25 | typedef unsigned __int64 ssize_t; |
26 | #define read(fd,address,length) _read(fd,address,(unsigned int)(length)) |
27 | #define write(fd,address,length) _write(fd,address,(unsigned int)(length)) |
28 | #define lseek _lseeki64 |
29 | #define open _open |
30 | #define close _close |
31 | #define unlink _unlink |
32 | #else |
33 | #include <unistd.h> |
34 | #endif |
35 | |
36 | #include <stdlib.h> |
37 | #include <stdio.h> |
38 | #include <string.h> |
39 | #include <fcntl.h> |
40 | #include <errno.h> |
41 | #include <sys/stat.h> |
42 | |
43 | #if defined(_MSC_VER) || defined(__MINGW32__) |
44 | #include "mman-win32.h" |
45 | #else |
46 | #include <sys/mman.h> |
47 | #endif |
48 | |
49 | #include <sys/types.h> |
50 | |
51 | #include "files.h" |
52 | |
53 | |
54 | /*+ A structure to contain the list of memory mapped files. +*/ |
55 | struct mmapinfo |
56 | { |
57 | const char *filename; /*+ The name of the file (the index of the list). +*/ |
58 | int fd; /*+ The file descriptor used when it was opened. +*/ |
59 | char *address; /*+ The address the file was mapped to. +*/ |
60 | size_t length; /*+ The length of the file. +*/ |
61 | }; |
62 | |
63 | /*+ The list of memory mapped files. +*/ |
64 | static struct mmapinfo *mappedfiles; |
65 | |
66 | /*+ The number of mapped files. +*/ |
67 | static int nmappedfiles=0; |
68 | |
69 | |
70 | #define BUFFLEN 4096 |
71 | |
72 | /*+ A structure to contain the list of file buffers. +*/ |
73 | struct filebuffer |
74 | { |
75 | char buffer[BUFFLEN]; /*+ The data buffer. +*/ |
76 | size_t pointer; /*+ The read/write pointer for the file buffer. +*/ |
77 | size_t length; /*+ The read pointer for the file buffer. +*/ |
78 | int reading; /*+ A flag to indicate if the file is for reading. +*/ |
79 | }; |
80 | |
81 | /*+ The list of file buffers. +*/ |
82 | static struct filebuffer **filebuffers=NULL; |
83 | |
84 | /*+ The number of allocated file buffer pointers. +*/ |
85 | static int nfilebuffers=0; |
86 | |
87 | |
88 | #if defined(_MSC_VER) || defined(__MINGW32__) |
89 | |
90 | /*+ A structure to contain the list of opened files to record which are to be deleted when closed. +*/ |
91 | struct openedfile |
92 | { |
93 | const char *filename; /*+ The name of the file. +*/ |
94 | int delete; /*+ Set to non-zero value if the file is to be deleted when closed. +*/ |
95 | }; |
96 | |
97 | /*+ The list of opened files. +*/ |
98 | static struct openedfile **openedfiles=NULL; |
99 | |
100 | /*+ The number of allocated opened file buffer pointers. +*/ |
101 | static int nopenedfiles=0; |
102 | |
103 | #endif |
104 | |
105 | |
106 | /* Local functions */ |
107 | |
108 | static void CreateFileBuffer(int fd,int read_write); |
109 | |
110 | #if defined(_MSC_VER) || defined(__MINGW32__) |
111 | |
112 | static void CreateOpenedFile(int fd,const char *filename); |
113 | |
114 | #endif |
115 | |
116 | |
117 | /*++++++++++++++++++++++++++++++++++++++ |
118 | Return a filename composed of the dirname, prefix and name. |
119 | |
120 | char *FileName Returns a pointer to memory allocated to the filename. |
121 | |
122 | const char *dirname The directory name. |
123 | |
124 | const char *prefix The file prefix. |
125 | |
126 | const char *name The main part of the name. |
127 | ++++++++++++++++++++++++++++++++++++++*/ |
128 | |
129 | char *FileName(const char *dirname,const char *prefix, const char *name) |
130 | { |
131 | char *filename=(char*)malloc((dirname?strlen(dirname):0)+1+(prefix?strlen(prefix):0)+1+strlen(name)+1); |
132 | |
133 | sprintf(filename,"%s%s%s%s%s",dirname?dirname:"",dirname?"/":"",prefix?prefix:"",prefix?"-":"",name); |
134 | |
135 | return(filename); |
136 | } |
137 | |
138 | |
139 | /*++++++++++++++++++++++++++++++++++++++ |
140 | Open a file read-only and map it into memory. |
141 | |
142 | void *MapFile Returns the address of the file or exits in case of an error. |
143 | |
144 | const char *filename The name of the file to open. |
145 | ++++++++++++++++++++++++++++++++++++++*/ |
146 | |
147 | void *MapFile(const char *filename) |
148 | { |
149 | int fd; |
150 | struct stat buf; |
151 | off_t size; |
152 | void *address; |
153 | |
154 | /* Open the file */ |
155 | |
156 | #if defined(_MSC_VER) || defined(__MINGW32__) |
157 | fd=open(filename,O_RDONLY|O_BINARY); |
158 | #else |
159 | fd=open(filename,O_RDONLY); |
160 | #endif |
161 | |
162 | if(fd<0) |
163 | { |
164 | fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno)); |
165 | exit(EXIT_FAILURE); |
166 | } |
167 | |
168 | /* Get its size */ |
169 | |
170 | if(stat(filename,&buf)) |
171 | { |
172 | fprintf(stderr,"Cannot stat file '%s' [%s].\n",filename,strerror(errno)); |
173 | exit(EXIT_FAILURE); |
174 | } |
175 | |
176 | size=buf.st_size; |
177 | |
178 | /* Map the file */ |
179 | |
180 | address=mmap(NULL,size,PROT_READ,MAP_SHARED,fd,0); |
181 | |
182 | if(address==MAP_FAILED) |
183 | { |
184 | close(fd); |
185 | |
186 | fprintf(stderr,"Cannot mmap file '%s' for reading [%s].\n",filename,strerror(errno)); |
187 | exit(EXIT_FAILURE); |
188 | } |
189 | |
190 | log_mmap(size); |
191 | |
192 | /* Store the information about the mapped file */ |
193 | |
194 | mappedfiles=(struct mmapinfo*)realloc((void*)mappedfiles,(nmappedfiles+1)*sizeof(struct mmapinfo)); |
195 | |
196 | mappedfiles[nmappedfiles].filename=filename; |
197 | mappedfiles[nmappedfiles].fd=fd; |
198 | mappedfiles[nmappedfiles].address=address; |
199 | mappedfiles[nmappedfiles].length=size; |
200 | |
201 | nmappedfiles++; |
202 | |
203 | return(address); |
204 | } |
205 | |
206 | |
207 | /*++++++++++++++++++++++++++++++++++++++ |
208 | Open a file read-write and map it into memory. |
209 | |
210 | void *MapFileWriteable Returns the address of the file or exits in case of an error. |
211 | |
212 | const char *filename The name of the file to open. |
213 | ++++++++++++++++++++++++++++++++++++++*/ |
214 | |
215 | void *MapFileWriteable(const char *filename) |
216 | { |
217 | int fd; |
218 | struct stat buf; |
219 | off_t size; |
220 | void *address; |
221 | |
222 | /* Open the file */ |
223 | |
224 | #if defined(_MSC_VER) || defined(__MINGW32__) |
225 | fd=open(filename,O_RDWR|O_BINARY); |
226 | #else |
227 | fd=open(filename,O_RDWR); |
228 | #endif |
229 | |
230 | if(fd<0) |
231 | { |
232 | fprintf(stderr,"Cannot open file '%s' for reading and writing [%s].\n",filename,strerror(errno)); |
233 | exit(EXIT_FAILURE); |
234 | } |
235 | |
236 | /* Get its size */ |
237 | |
238 | if(stat(filename,&buf)) |
239 | { |
240 | fprintf(stderr,"Cannot stat file '%s' [%s].\n",filename,strerror(errno)); |
241 | exit(EXIT_FAILURE); |
242 | } |
243 | |
244 | size=buf.st_size; |
245 | |
246 | /* Map the file */ |
247 | |
248 | address=mmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); |
249 | |
250 | if(address==MAP_FAILED) |
251 | { |
252 | close(fd); |
253 | |
254 | fprintf(stderr,"Cannot mmap file '%s' for reading and writing [%s].\n",filename,strerror(errno)); |
255 | exit(EXIT_FAILURE); |
256 | } |
257 | |
258 | log_mmap(size); |
259 | |
260 | /* Store the information about the mapped file */ |
261 | |
262 | mappedfiles=(struct mmapinfo*)realloc((void*)mappedfiles,(nmappedfiles+1)*sizeof(struct mmapinfo)); |
263 | |
264 | mappedfiles[nmappedfiles].filename=filename; |
265 | mappedfiles[nmappedfiles].fd=fd; |
266 | mappedfiles[nmappedfiles].address=address; |
267 | mappedfiles[nmappedfiles].length=size; |
268 | |
269 | nmappedfiles++; |
270 | |
271 | return(address); |
272 | } |
273 | |
274 | |
275 | /*++++++++++++++++++++++++++++++++++++++ |
276 | Unmap a file and close it. |
277 | |
278 | void *UnmapFile Returns NULL (for similarity to the MapFile function). |
279 | |
280 | const void *address The address of the mapped file in memory. |
281 | ++++++++++++++++++++++++++++++++++++++*/ |
282 | |
283 | void *UnmapFile(const void *address) |
284 | { |
285 | int i; |
286 | |
287 | for(i=0;i<nmappedfiles;i++) |
288 | if(mappedfiles[i].address==address) |
289 | break; |
290 | |
291 | if(i==nmappedfiles) |
292 | { |
293 | fprintf(stderr,"The data at address %p was not mapped using MapFile().\n",address); |
294 | exit(EXIT_FAILURE); |
295 | } |
296 | |
297 | /* Close the file */ |
298 | |
299 | close(mappedfiles[i].fd); |
300 | |
301 | /* Unmap the file */ |
302 | |
303 | munmap(mappedfiles[i].address,mappedfiles[i].length); |
304 | |
305 | log_munmap(mappedfiles[i].length); |
306 | |
307 | /* Shuffle the list of files */ |
308 | |
309 | nmappedfiles--; |
310 | |
311 | if(nmappedfiles>i) |
312 | memmove(&mappedfiles[i],&mappedfiles[i+1],(nmappedfiles-i)*sizeof(struct mmapinfo)); |
313 | |
314 | return(NULL); |
315 | } |
316 | |
317 | |
318 | /*++++++++++++++++++++++++++++++++++++++ |
319 | Open an existing file on disk for reading. |
320 | |
321 | int SlimMapFile Returns the file descriptor if OK or exits in case of an error. |
322 | |
323 | const char *filename The name of the file to open. |
324 | ++++++++++++++++++++++++++++++++++++++*/ |
325 | |
326 | int SlimMapFile(const char *filename) |
327 | { |
328 | int fd; |
329 | |
330 | /* Open the file */ |
331 | |
332 | #if defined(_MSC_VER) || defined(__MINGW32__) |
333 | fd=open(filename,O_RDONLY|O_BINARY); |
334 | #else |
335 | fd=open(filename,O_RDONLY); |
336 | #endif |
337 | |
338 | if(fd<0) |
339 | { |
340 | fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno)); |
341 | exit(EXIT_FAILURE); |
342 | } |
343 | |
344 | CreateFileBuffer(fd,0); |
345 | |
346 | return(fd); |
347 | } |
348 | |
349 | |
350 | /*++++++++++++++++++++++++++++++++++++++ |
351 | Open an existing file on disk for reading or writing. |
352 | |
353 | int SlimMapFileWriteable Returns the file descriptor if OK or exits in case of an error. |
354 | |
355 | const char *filename The name of the file to open. |
356 | ++++++++++++++++++++++++++++++++++++++*/ |
357 | |
358 | int SlimMapFileWriteable(const char *filename) |
359 | { |
360 | int fd; |
361 | |
362 | /* Open the file */ |
363 | |
364 | #if defined(_MSC_VER) || defined(__MINGW32__) |
365 | fd=open(filename,O_RDWR|O_BINARY); |
366 | #else |
367 | fd=open(filename,O_RDWR); |
368 | #endif |
369 | |
370 | if(fd<0) |
371 | { |
372 | fprintf(stderr,"Cannot open file '%s' for reading and writing [%s].\n",filename,strerror(errno)); |
373 | exit(EXIT_FAILURE); |
374 | } |
375 | |
376 | CreateFileBuffer(fd,0); |
377 | |
378 | return(fd); |
379 | } |
380 | |
381 | |
382 | /*++++++++++++++++++++++++++++++++++++++ |
383 | Close a file on disk. |
384 | |
385 | int SlimUnmapFile returns -1 (for similarity to the UnmapFile function). |
386 | |
387 | int fd The file descriptor to close. |
388 | ++++++++++++++++++++++++++++++++++++++*/ |
389 | |
390 | int SlimUnmapFile(int fd) |
391 | { |
392 | close(fd); |
393 | |
394 | return(-1); |
395 | } |
396 | |
397 | |
398 | /*++++++++++++++++++++++++++++++++++++++ |
399 | Open a new file on disk for writing (with buffering). |
400 | |
401 | int OpenFileBufferedNew Returns the file descriptor if OK or exits in case of an error. |
402 | |
403 | const char *filename The name of the file to create. |
404 | ++++++++++++++++++++++++++++++++++++++*/ |
405 | |
406 | int OpenFileBufferedNew(const char *filename) |
407 | { |
408 | int fd; |
409 | |
410 | /* Open the file */ |
411 | |
412 | #if defined(_MSC_VER) |
413 | fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY); |
414 | #else |
415 | #if defined(__MINGW32__) |
416 | fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,S_IRUSR|S_IWUSR); |
417 | #else |
418 | fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC ,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); |
419 | #endif |
420 | #endif |
421 | |
422 | if(fd<0) |
423 | { |
424 | fprintf(stderr,"Cannot open file '%s' for writing [%s].\n",filename,strerror(errno)); |
425 | exit(EXIT_FAILURE); |
426 | } |
427 | |
428 | CreateFileBuffer(fd,-1); |
429 | |
430 | #if defined(_MSC_VER) || defined(__MINGW32__) |
431 | CreateOpenedFile(fd,filename); |
432 | #endif |
433 | |
434 | return(fd); |
435 | } |
436 | |
437 | |
438 | /*++++++++++++++++++++++++++++++++++++++ |
439 | Open a new or existing file on disk for appending (with buffering). |
440 | |
441 | int OpenFileBufferedAppend Returns the file descriptor if OK or exits in case of an error. |
442 | |
443 | const char *filename The name of the file to create or open. |
444 | ++++++++++++++++++++++++++++++++++++++*/ |
445 | |
446 | int OpenFileBufferedAppend(const char *filename) |
447 | { |
448 | int fd; |
449 | |
450 | /* Open the file */ |
451 | |
452 | #if defined(_MSC_VER) |
453 | fd=open(filename,O_WRONLY|O_CREAT|O_APPEND|O_BINARY); |
454 | #else |
455 | #if defined(__MINGW32__) |
456 | fd=open(filename,O_WRONLY|O_CREAT|O_APPEND|O_BINARY,S_IRUSR|S_IWUSR); |
457 | #else |
458 | fd=open(filename,O_WRONLY|O_CREAT|O_APPEND ,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); |
459 | #endif |
460 | #endif |
461 | |
462 | if(fd<0) |
463 | { |
464 | fprintf(stderr,"Cannot open file '%s' for appending [%s].\n",filename,strerror(errno)); |
465 | exit(EXIT_FAILURE); |
466 | } |
467 | |
468 | CreateFileBuffer(fd,-1); |
469 | |
470 | #if defined(_MSC_VER) || defined(__MINGW32__) |
471 | CreateOpenedFile(fd,filename); |
472 | #endif |
473 | |
474 | return(fd); |
475 | } |
476 | |
477 | |
478 | /*++++++++++++++++++++++++++++++++++++++ |
479 | Open an existing file on disk for reading (with buffering). |
480 | |
481 | int ReOpenFileBuffered Returns the file descriptor if OK or exits in case of an error. |
482 | |
483 | const char *filename The name of the file to open. |
484 | ++++++++++++++++++++++++++++++++++++++*/ |
485 | |
486 | int ReOpenFileBuffered(const char *filename) |
487 | { |
488 | int fd; |
489 | |
490 | /* Open the file */ |
491 | |
492 | #if defined(_MSC_VER) || defined(__MINGW32__) |
493 | fd=open(filename,O_RDONLY|O_BINARY); |
494 | #else |
495 | fd=open(filename,O_RDONLY); |
496 | #endif |
497 | |
498 | if(fd<0) |
499 | { |
500 | fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno)); |
501 | exit(EXIT_FAILURE); |
502 | } |
503 | |
504 | CreateFileBuffer(fd,1); |
505 | |
506 | #if defined(_MSC_VER) || defined(__MINGW32__) |
507 | CreateOpenedFile(fd,filename); |
508 | #endif |
509 | |
510 | return(fd); |
511 | } |
512 | |
513 | |
514 | /*++++++++++++++++++++++++++++++++++++++ |
515 | Open an existing file on disk for reading (with buffering), delete |
516 | it and open a new file on disk for writing (with buffering). |
517 | |
518 | int ReplaceFileBuffered Returns the file descriptor of the new writable file. |
519 | |
520 | const char *filename The name of the file to open, delete and replace. |
521 | |
522 | int *oldfd Returns the file descriptor of the old, readable file. |
523 | ++++++++++++++++++++++++++++++++++++++*/ |
524 | |
525 | int ReplaceFileBuffered(const char *filename,int *oldfd) |
526 | { |
527 | int newfd; |
528 | |
529 | #if defined(_MSC_VER) || defined(__MINGW32__) |
530 | |
531 | char *filename2; |
532 | |
533 | filename2=strcpy(malloc(strlen(filename)+2),filename); |
534 | strcat(filename2,"2"); |
535 | |
536 | RenameFile(filename,filename2); |
537 | |
538 | *oldfd=ReOpenFileBuffered(filename2); |
539 | |
540 | DeleteFile(filename2); |
541 | |
542 | #else |
543 | |
544 | *oldfd=ReOpenFileBuffered(filename); |
545 | |
546 | DeleteFile(filename); |
547 | |
548 | #endif |
549 | |
550 | newfd=OpenFileBufferedNew(filename); |
551 | |
552 | return(newfd); |
553 | } |
554 | |
555 | |
556 | /*++++++++++++++++++++++++++++++++++++++ |
557 | Write data to a file descriptor (via a buffer). |
558 | |
559 | int WriteFileBuffered Returns 0 if OK or something else in case of an error. |
560 | |
561 | int fd The file descriptor to write to. |
562 | |
563 | const void *address The address of the data to be written. |
564 | |
565 | size_t length The length of data to write. |
566 | ++++++++++++++++++++++++++++++++++++++*/ |
567 | |
568 | int WriteFileBuffered(int fd,const void *address,size_t length) |
569 | { |
570 | logassert(fd!=-1,"File descriptor is in error - report a bug"); |
571 | |
572 | logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); |
573 | |
574 | logassert(!filebuffers[fd]->reading,"File descriptor was not opened for writing - report a bug"); |
575 | |
576 | /* Write the data */ |
577 | |
578 | if((filebuffers[fd]->pointer+length)>BUFFLEN) |
579 | { |
580 | if(write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer)!=(ssize_t)filebuffers[fd]->pointer) |
581 | return(-1); |
582 | |
583 | filebuffers[fd]->pointer=0; |
584 | } |
585 | |
586 | if(length>=BUFFLEN) |
587 | { |
588 | if(write(fd,address,length)!=(ssize_t)length) |
589 | return(-1); |
590 | |
591 | return(0); |
592 | } |
593 | |
594 | memcpy(filebuffers[fd]->buffer+filebuffers[fd]->pointer,address,length); |
595 | |
596 | filebuffers[fd]->pointer+=length; |
597 | |
598 | return(0); |
599 | } |
600 | |
601 | |
602 | /*++++++++++++++++++++++++++++++++++++++ |
603 | Read data from a file descriptor (via a buffer). |
604 | |
605 | int ReadFileBuffered Returns 0 if OK or something else in case of an error. |
606 | |
607 | int fd The file descriptor to read from. |
608 | |
609 | void *address The address the data is to be read into. |
610 | |
611 | size_t length The length of data to read. |
612 | ++++++++++++++++++++++++++++++++++++++*/ |
613 | |
614 | int ReadFileBuffered(int fd,void *address,size_t length) |
615 | { |
616 | logassert(fd!=-1,"File descriptor is in error - report a bug"); |
617 | |
618 | logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); |
619 | |
620 | logassert(filebuffers[fd]->reading,"File descriptor was not opened for reading - report a bug"); |
621 | |
622 | /* Read the data */ |
623 | |
624 | if((filebuffers[fd]->pointer+length)>filebuffers[fd]->length) |
625 | if(filebuffers[fd]->pointer<filebuffers[fd]->length) |
626 | { |
627 | memcpy(address,filebuffers[fd]->buffer+filebuffers[fd]->pointer,filebuffers[fd]->length-filebuffers[fd]->pointer); |
628 | |
629 | address=(char*)address+filebuffers[fd]->length-filebuffers[fd]->pointer; |
630 | length-=filebuffers[fd]->length-filebuffers[fd]->pointer; |
631 | |
632 | filebuffers[fd]->pointer=0; |
633 | filebuffers[fd]->length=0; |
634 | } |
635 | |
636 | if(length>=BUFFLEN) |
637 | { |
638 | if(read(fd,address,length)!=(ssize_t)length) |
639 | return(-1); |
640 | |
641 | return(0); |
642 | } |
643 | |
644 | if(filebuffers[fd]->pointer==filebuffers[fd]->length) |
645 | { |
646 | ssize_t len=read(fd,filebuffers[fd]->buffer,BUFFLEN); |
647 | |
648 | if(len<=0) |
649 | return(-1); |
650 | |
651 | filebuffers[fd]->length=len; |
652 | filebuffers[fd]->pointer=0; |
653 | } |
654 | |
655 | if(filebuffers[fd]->length==0) |
656 | return(-1); |
657 | |
658 | memcpy(address,filebuffers[fd]->buffer+filebuffers[fd]->pointer,length); |
659 | |
660 | filebuffers[fd]->pointer+=length; |
661 | |
662 | return(0); |
663 | } |
664 | |
665 | |
666 | /*++++++++++++++++++++++++++++++++++++++ |
667 | Seek to a position in a file descriptor that uses a buffer. |
668 | |
669 | int SeekFileBuffered Returns 0 if OK or something else in case of an error. |
670 | |
671 | int fd The file descriptor to seek within. |
672 | |
673 | off_t position The position to seek to. |
674 | ++++++++++++++++++++++++++++++++++++++*/ |
675 | |
676 | int SeekFileBuffered(int fd,off_t position) |
677 | { |
678 | logassert(fd!=-1,"File descriptor is in error - report a bug"); |
679 | |
680 | logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); |
681 | |
682 | /* Seek the data - doesn't need to be highly optimised */ |
683 | |
684 | if(!filebuffers[fd]->reading) |
685 | if(write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer)!=(ssize_t)filebuffers[fd]->pointer) |
686 | return(-1); |
687 | |
688 | filebuffers[fd]->pointer=0; |
689 | filebuffers[fd]->length=0; |
690 | |
691 | if(lseek(fd,position,SEEK_SET)!=position) |
692 | return(-1); |
693 | |
694 | return(0); |
695 | } |
696 | |
697 | |
698 | /*++++++++++++++++++++++++++++++++++++++ |
699 | Skip forward by an offset in a file descriptor that uses a buffer. |
700 | |
701 | int SkipFileBuffered Returns 0 if OK or something else in case of an error. |
702 | |
703 | int fd The file descriptor to skip within. |
704 | |
705 | off_t skip The amount to skip forward. |
706 | ++++++++++++++++++++++++++++++++++++++*/ |
707 | |
708 | int SkipFileBuffered(int fd,off_t skip) |
709 | { |
710 | logassert(fd!=-1,"File descriptor is in error - report a bug"); |
711 | |
712 | logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); |
713 | |
714 | logassert(filebuffers[fd]->reading,"File descriptor was not opened for reading - report a bug"); |
715 | |
716 | /* Skip the data - needs to be optimised */ |
717 | |
718 | if((filebuffers[fd]->pointer+skip)>filebuffers[fd]->length) |
719 | { |
720 | skip-=(off_t)(filebuffers[fd]->length-filebuffers[fd]->pointer); |
721 | |
722 | filebuffers[fd]->pointer=0; |
723 | filebuffers[fd]->length=0; |
724 | |
725 | if(lseek(fd,skip,SEEK_CUR)==-1) |
726 | return(-1); |
727 | } |
728 | else |
729 | filebuffers[fd]->pointer+=skip; |
730 | |
731 | return(0); |
732 | } |
733 | |
734 | |
735 | /*++++++++++++++++++++++++++++++++++++++ |
736 | Get the size of a file. |
737 | |
738 | off_t SizeFile Returns the file size if OK or exits in case of an error. |
739 | |
740 | const char *filename The name of the file to check. |
741 | ++++++++++++++++++++++++++++++++++++++*/ |
742 | |
743 | off_t SizeFile(const char *filename) |
744 | { |
745 | struct stat buf; |
746 | |
747 | if(stat(filename,&buf)) |
748 | { |
749 | fprintf(stderr,"Cannot stat file '%s' [%s].\n",filename,strerror(errno)); |
750 | exit(EXIT_FAILURE); |
751 | } |
752 | |
753 | return(buf.st_size); |
754 | } |
755 | |
756 | |
757 | /*++++++++++++++++++++++++++++++++++++++ |
758 | Get the size of a file from a file descriptor. |
759 | |
760 | off_t SizeFileFD Returns the file size if OK or exits in case of an error. |
761 | |
762 | int fd The file descriptor to check. |
763 | ++++++++++++++++++++++++++++++++++++++*/ |
764 | |
765 | off_t SizeFileFD(int fd) |
766 | { |
767 | struct stat buf; |
768 | |
769 | if(fstat(fd,&buf)) |
770 | { |
771 | fprintf(stderr,"Cannot stat file descriptor '%d' [%s].\n",fd,strerror(errno)); |
772 | exit(EXIT_FAILURE); |
773 | } |
774 | |
775 | return(buf.st_size); |
776 | } |
777 | |
778 | |
779 | /*++++++++++++++++++++++++++++++++++++++ |
780 | Check if a file exists. |
781 | |
782 | int ExistsFile Returns 1 if the file exists and 0 if not. |
783 | |
784 | const char *filename The name of the file to check. |
785 | ++++++++++++++++++++++++++++++++++++++*/ |
786 | |
787 | int ExistsFile(const char *filename) |
788 | { |
789 | struct stat buf; |
790 | |
791 | if(stat(filename,&buf)) |
792 | return(0); |
793 | else |
794 | return(1); |
795 | } |
796 | |
797 | |
798 | /*++++++++++++++++++++++++++++++++++++++ |
799 | Close a file on disk (and flush the buffer). |
800 | |
801 | int CloseFileBuffered returns -1 (for similarity to the *OpenFileBuffered* functions). |
802 | |
803 | int fd The file descriptor to close. |
804 | ++++++++++++++++++++++++++++++++++++++*/ |
805 | |
806 | int CloseFileBuffered(int fd) |
807 | { |
808 | logassert(fd<nfilebuffers && filebuffers[fd],"File descriptor has no buffer - report a bug"); |
809 | |
810 | if(!filebuffers[fd]->reading) |
811 | if(write(fd,filebuffers[fd]->buffer,filebuffers[fd]->pointer)!=(ssize_t)filebuffers[fd]->pointer) |
812 | return(-1); |
813 | |
814 | close(fd); |
815 | |
816 | free(filebuffers[fd]); |
817 | filebuffers[fd]=NULL; |
818 | |
819 | #if defined(_MSC_VER) || defined(__MINGW32__) |
820 | |
821 | logassert(fd<nopenedfiles && openedfiles[fd],"File descriptor has no record of opening - report a bug"); |
822 | |
823 | if(openedfiles[fd]->delete) |
824 | unlink(openedfiles[fd]->filename); |
825 | |
826 | free(openedfiles[fd]); |
827 | openedfiles[fd]=NULL; |
828 | |
829 | #endif |
830 | |
831 | return(-1); |
832 | } |
833 | |
834 | |
835 | /*++++++++++++++++++++++++++++++++++++++ |
836 | Open an existing file on disk for reading (in a simple mode). |
837 | |
838 | int OpenFile Returns the file descriptor if OK or exits in case of an error. |
839 | |
840 | const char *filename The name of the file to open. |
841 | ++++++++++++++++++++++++++++++++++++++*/ |
842 | |
843 | int OpenFile(const char *filename) |
844 | { |
845 | int fd; |
846 | |
847 | /* Open the file */ |
848 | |
849 | #if defined(_MSC_VER) || defined(__MINGW32__) |
850 | fd=open(filename,O_RDONLY|O_BINARY); |
851 | #else |
852 | fd=open(filename,O_RDONLY); |
853 | #endif |
854 | |
855 | if(fd<0) |
856 | { |
857 | fprintf(stderr,"Cannot open file '%s' for reading [%s].\n",filename,strerror(errno)); |
858 | exit(EXIT_FAILURE); |
859 | } |
860 | |
861 | #if defined(_MSC_VER) || defined(__MINGW32__) |
862 | CreateOpenedFile(fd,filename); |
863 | #endif |
864 | |
865 | return(fd); |
866 | } |
867 | |
868 | |
869 | /*++++++++++++++++++++++++++++++++++++++ |
870 | Close a file on disk (that was opened in simple mode). |
871 | |
872 | int fd The file descriptor to close. |
873 | ++++++++++++++++++++++++++++++++++++++*/ |
874 | |
875 | void CloseFile(int fd) |
876 | { |
877 | close(fd); |
878 | |
879 | #if defined(_MSC_VER) || defined(__MINGW32__) |
880 | |
881 | logassert(fd<nopenedfiles && openedfiles[fd],"File descriptor has no record of opening - report a bug"); |
882 | |
883 | if(openedfiles[fd]->delete) |
884 | unlink(openedfiles[fd]->filename); |
885 | |
886 | free(openedfiles[fd]); |
887 | openedfiles[fd]=NULL; |
888 | |
889 | #endif |
890 | } |
891 | |
892 | |
893 | /*++++++++++++++++++++++++++++++++++++++ |
894 | Delete a file from disk. |
895 | |
896 | int DeleteFile Returns 0 if OK. |
897 | |
898 | const char *filename The name of the file to delete. |
899 | ++++++++++++++++++++++++++++++++++++++*/ |
900 | |
901 | int DeleteFile(const char *filename) |
902 | { |
903 | #if defined(_MSC_VER) || defined(__MINGW32__) |
904 | |
905 | int fd; |
906 | |
907 | for(fd=0;fd<nopenedfiles;fd++) |
908 | if(openedfiles[fd] && !strcmp(openedfiles[fd]->filename,filename)) |
909 | { |
910 | openedfiles[fd]->delete=1; |
911 | return(0); |
912 | } |
913 | |
914 | #endif |
915 | |
916 | unlink(filename); |
917 | |
918 | return(0); |
919 | } |
920 | |
921 | |
922 | /*++++++++++++++++++++++++++++++++++++++ |
923 | Rename a file on disk. |
924 | |
925 | int RenameFile Returns 0 if OK. |
926 | |
927 | const char *oldfilename The old name of the file before renaming. |
928 | |
929 | const char *newfilename The new name of the file after renaming. |
930 | ++++++++++++++++++++++++++++++++++++++*/ |
931 | |
932 | int RenameFile(const char *oldfilename,const char *newfilename) |
933 | { |
934 | rename(oldfilename,newfilename); |
935 | |
936 | return(0); |
937 | } |
938 | |
939 | |
940 | /*++++++++++++++++++++++++++++++++++++++ |
941 | Create a file buffer. |
942 | |
943 | int fd The file descriptor. |
944 | |
945 | int read_write A flag set to 1 for reading, -1 for writing and 0 for unbuffered. |
946 | ++++++++++++++++++++++++++++++++++++++*/ |
947 | |
948 | static void CreateFileBuffer(int fd,int read_write) |
949 | { |
950 | if(nfilebuffers<=fd) |
951 | { |
952 | int i; |
953 | |
954 | filebuffers=(struct filebuffer**)realloc((void*)filebuffers,(fd+1)*sizeof(struct filebuffer*)); |
955 | |
956 | for(i=nfilebuffers;i<=fd;i++) |
957 | filebuffers[i]=NULL; |
958 | |
959 | nfilebuffers=fd+1; |
960 | } |
961 | |
962 | if(read_write) |
963 | { |
964 | filebuffers[fd]=(struct filebuffer*)calloc(sizeof(struct filebuffer),1); |
965 | |
966 | filebuffers[fd]->reading=(read_write==1); |
967 | } |
968 | } |
969 | |
970 | |
971 | #if defined(_MSC_VER) || defined(__MINGW32__) |
972 | |
973 | /*++++++++++++++++++++++++++++++++++++++ |
974 | Create an opened file record. |
975 | |
976 | int fd The file descriptor. |
977 | |
978 | const char *filename The name of the file. |
979 | ++++++++++++++++++++++++++++++++++++++*/ |
980 | |
981 | static void CreateOpenedFile(int fd,const char *filename) |
982 | { |
983 | if(nopenedfiles<=fd) |
984 | { |
985 | int i; |
986 | |
987 | openedfiles=(struct openedfile**)realloc((void*)openedfiles,(fd+1)*sizeof(struct openedfile*)); |
988 | |
989 | for(i=nopenedfiles;i<=fd;i++) |
990 | openedfiles[i]=NULL; |
991 | |
992 | nopenedfiles=fd+1; |
993 | } |
994 | |
995 | openedfiles[fd]=(struct openedfile*)calloc(sizeof(struct openedfile),1); |
996 | |
997 | openedfiles[fd]->filename=strcpy(malloc(strlen(filename)+1),filename); |
998 | openedfiles[fd]->delete=0; |
999 | } |
1000 | |
1001 | #endif |
Properties
Name | Value |
---|---|
cvs:description | File handling functions. |