11#include <stdlib.h>
22#include <stdio.h>
3+ #include <string.h>
34
45#if defined(_WIN32 )
56 #include <windows.h>
89
910#if !defined(_WIN32 )
1011 #include <stdio.h>
12+ #include <unistd.h>
1113 #include <sys/file.h>
1214#endif
1315
1820 #include "fs/sep.h"
1921#endif
2022
23+ #if defined(_WIN32 )
24+ static DWORD * fstream_getmode (const fstream_mode_t mode , DWORD flags [2 ]) {
25+
26+ DWORD * access = & flags [0 ];
27+ DWORD * disposition = & flags [1 ];
28+
29+ switch (mode ) {
30+ case FSTREAM_WRITE :
31+ (* access ) |= GENERIC_WRITE ;
32+ (* disposition ) |= CREATE_ALWAYS ;
33+ break ;
34+ case FSTREAM_READ :
35+ (* access ) |= GENERIC_READ ;
36+ (* disposition ) |= OPEN_EXISTING ;
37+ break ;
38+ case FSTREAM_APPEND :
39+ case FSTREAM_TRUNCATE :
40+ (* access ) |= FILE_APPEND_DATA ;
41+ (* disposition ) |= OPEN_EXISTING ;
42+ break ;
43+ }
44+
45+ return flags ;
46+ }
47+ #else
48+ static const char * fstream_getmode (const fstream_mode_t mode ) {
49+
50+ const char * flags = NULL ;
51+
52+ switch (mode ) {
53+ case FSTREAM_WRITE :
54+ flags = "wb" ;
55+ break ;
56+ case FSTREAM_READ :
57+ flags = "rb" ;
58+ break ;
59+ case FSTREAM_APPEND :
60+ flags = "a" ;
61+ break ;
62+ case FSTREAM_TRUNCATE :
63+ flags = "r+" ;
64+ break ;
65+ }
66+
67+ return flags ;
68+
69+ }
70+ #endif
71+
2172fstream_t * fstream_open (const char * const filename , const fstream_mode_t mode ) {
2273 /*
2374 Opens a file on disk.
@@ -34,26 +85,18 @@ fstream_t* fstream_open(const char* const filename, const fstream_mode_t mode) {
3485 int wfilenames = 0 ;
3586 #endif
3687
88+ DWORD values [2 ] = {0 , 0 };
89+
3790 DWORD access = 0 ;
3891 DWORD disposition = 0 ;
3992 const DWORD flags = FILE_ATTRIBUTE_NORMAL ;
4093
4194 HANDLE handle = 0 ;
4295
43- switch (mode ) {
44- case FSTREAM_WRITE :
45- access |= GENERIC_WRITE ;
46- disposition |= CREATE_ALWAYS ;
47- break ;
48- case FSTREAM_READ :
49- access |= GENERIC_READ ;
50- disposition |= OPEN_EXISTING ;
51- break ;
52- case FSTREAM_APPEND :
53- access |= FILE_APPEND_DATA ;
54- disposition |= OPEN_EXISTING ;
55- break ;
56- }
96+ fstream_getmode (mode , values );
97+
98+ access = values [0 ];
99+ disposition = values [1 ];
57100
58101 #if defined(_UNICODE )
59102 /* This prefix is required to support long paths in Windows 10+ */
@@ -94,20 +137,8 @@ fstream_t* fstream_open(const char* const filename, const fstream_mode_t mode) {
94137 }
95138 }
96139 #else
97- const char * flags = NULL ;
98140 FILE * file = NULL ;
99-
100- switch (mode ) {
101- case FSTREAM_WRITE :
102- flags = "wb" ;
103- break ;
104- case FSTREAM_READ :
105- flags = "rb" ;
106- break ;
107- case FSTREAM_APPEND :
108- flags = "a" ;
109- break ;
110- }
141+ const char * flags = fstream_getmode (mode );
111142
112143 file = fopen (filename , flags );
113144
@@ -140,6 +171,54 @@ fstream_t* fstream_open(const char* const filename, const fstream_mode_t mode) {
140171
141172}
142173
174+ fstream_t * fstream_fdopen (const int fd , const fstream_mode_t mode ) {
175+ /*
176+ Opens a file descriptor.
177+
178+ Returns a null pointer on error.
179+ */
180+
181+ fstream_t * stream = NULL ;
182+
183+ stream = malloc (sizeof (* stream ));
184+
185+ if (stream == NULL ) {
186+ return NULL ;
187+ }
188+
189+ #if defined(_WIN32 )
190+ HANDLE handle = 0 ;
191+
192+ (void ) mode ;
193+
194+ handle = (HANDLE ) _get_osfhandle (fd );
195+
196+ if (handle == INVALID_HANDLE_VALUE ) {
197+ return NULL ;
198+ }
199+ #else
200+ FILE * file = NULL ;
201+ const char * flags = fstream_getmode (mode );
202+
203+ file = fdopen (fd , flags );
204+
205+ if (file == NULL ) {
206+ return NULL ;
207+ }
208+ #endif
209+
210+ #if defined(_WIN32 )
211+ stream -> stream = handle ;
212+ #else
213+ stream -> stream = file ;
214+ #endif
215+
216+ stream -> mode = mode ;
217+
218+ return stream ;
219+
220+ }
221+
143222int fstream_lock (fstream_t * const stream ) {
144223 /*
145224 Lock the file.
@@ -333,6 +412,120 @@ long int fstream_tell(fstream_t* const stream) {
333412
334413}
335414
415+ long int fsream_size (fstream_t * const stream ) {
416+ /*
417+ Returns the current file size.
418+
419+ Returns (>=0) on success, (-1) on error.
420+ */
421+
422+ const long int pos = fstream_tell (stream );
423+
424+ long int file_size = 0 ;
425+
426+ int status = 0 ;
427+
428+ status = fstream_seek (stream , 0 , FSTREAM_SEEK_END );
429+
430+ if (status == -1 ) {
431+ return FSTREAM_ERROR ;
432+ }
433+
434+ file_size = fstream_tell (stream );
435+
436+ if (file_size == FSTREAM_ERROR || file_size == FSTREAM_EOF ) {
437+ return FSTREAM_ERROR ;
438+ }
439+
440+ status = fstream_seek (stream , pos , FSTREAM_SEEK_BEGIN );
441+
442+ if (status == FSTREAM_ERROR ) {
443+ return FSTREAM_ERROR ;
444+ }
445+
446+ return file_size ;
447+
448+ }
449+
450+ int fsream_truncate (fstream_t * const stream , const long int offset ) {
451+ /*
452+ Truncates the file.
453+
454+ Returns (0) on success, (-1) on error.
455+ */
456+
457+ char zeros [1024 ];
458+
459+ int status = 0 ;
460+ const long int file_size = fsream_size (stream );
461+
462+ long int diff = 0 ;
463+ size_t write = 0 ;
464+
465+ #if !defined(_WIN32 )
466+ int fd = 0 ;
467+ #endif
468+
469+ if (offset == file_size ) {
470+ return FSTREAM_SUCCESS ;
471+ }
472+
473+ memset (zeros , 0 , sizeof (zeros ));
474+
475+ if (offset < file_size ) {
476+ fstream_seek (stream , offset , FSTREAM_SEEK_BEGIN );
477+ } else {
478+ fstream_seek (stream , 0 , FSTREAM_SEEK_END );
479+ }
480+
481+ diff = labs (offset - file_size );
482+
483+ while (diff != 0 ) {
484+ write = (diff > sizeof (zeros )) ? sizeof (zeros ) : diff ;
485+
486+ status = fstream_write (stream , zeros , write );
487+
488+ if (status != FSTREAM_SUCCESS ) {
489+ return FSTREAM_ERROR ;
490+ }
491+
492+ diff -= write ;
493+ }
494+
495+ if (offset < file_size ) {
496+ #if defined(_WIN32 )
497+ status = fstream_seek (stream , offset , FSTREAM_SEEK_BEGIN );
498+
499+ if (status != FSTREAM_SUCCESS ) {
500+ return FSTREAM_ERROR ;
501+ }
502+
503+ if (!SetEndOfFile (stream -> stream )) {
504+ return FSTREAM_ERROR ;
505+ }
506+ #else
507+ status = fstream_seek (stream , 0 , FSTREAM_SEEK_BEGIN );
508+
509+ if (status != FSTREAM_SUCCESS ) {
510+ return FSTREAM_ERROR ;
511+ }
512+
513+ fd = fileno (stream -> stream );
514+
515+ if (fd == -1 ) {
516+ return FSTREAM_ERROR ;
517+ }
518+
519+ if (ftruncate (fd , offset ) == -1 ) {
520+ return FSTREAM_ERROR ;
521+ }
522+ #endif
523+ }
524+
525+ return FSTREAM_SUCCESS ;
526+
527+ }
528+
336529int fstream_close (fstream_t * const stream ) {
337530 /*
338531 Closes the stream.
0 commit comments