Skip to content

Commit fc6a76b

Browse files
committed
Add fstream_size()/fstream_truncate()
1 parent 6c8030a commit fc6a76b

2 files changed

Lines changed: 226 additions & 28 deletions

File tree

tools/gcc-wrapper/fstream.c

Lines changed: 220 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <stdlib.h>
22
#include <stdio.h>
3+
#include <string.h>
34

45
#if defined(_WIN32)
56
#include <windows.h>
@@ -8,6 +9,7 @@
89

910
#if !defined(_WIN32)
1011
#include <stdio.h>
12+
#include <unistd.h>
1113
#include <sys/file.h>
1214
#endif
1315

@@ -18,6 +20,55 @@
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+
2172
fstream_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+
143222
int 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+
336529
int fstream_close(fstream_t* const stream) {
337530
/*
338531
Closes the stream.

tools/gcc-wrapper/fstream.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#if defined(_WIN32)
77
#include <windows.h>
8+
#include <io.h>
89
#endif
910

1011
#if !defined(_WIN32)
@@ -19,7 +20,8 @@
1920
enum FStreamMode {
2021
FSTREAM_WRITE,
2122
FSTREAM_READ,
22-
FSTREAM_APPEND
23+
FSTREAM_APPEND,
24+
FSTREAM_TRUNCATE
2325
};
2426

2527
typedef enum FStreamMode fstream_mode_t;
@@ -44,11 +46,14 @@ struct FStream {
4446
typedef struct FStream fstream_t;
4547

4648
fstream_t* fstream_open(const char* const filename, const fstream_mode_t mode);
49+
fstream_t* fstream_fdopen(const int fd, const fstream_mode_t mode);
4750
int fstream_lock(fstream_t* const stream);
4851
ssize_t fstream_read(fstream_t* const stream, char* const buffer, const size_t size);
4952
int fstream_write(fstream_t* const stream, const char* const buffer, const size_t size);
5053
int fstream_seek(fstream_t* const stream, const long int offset, const fstream_seek_t method);
54+
int fsream_truncate(fstream_t* const stream, const long int offset);
5155
long int fstream_tell(fstream_t* const stream);
56+
long int fsream_size(fstream_t* const stream);
5257
int fstream_close(fstream_t* const stream);
5358

5459
#endif

0 commit comments

Comments
 (0)