1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
|
#include <bh/internal/file.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
static const bh_io_table_t bh_file_table = {
(int (*)(struct bh_io_s *, int)) bh_file_open_base,
(void (*)(struct bh_io_s *)) bh_file_close_base,
(int (*)(struct bh_io_s *)) bh_file_is_open_base,
(size_t (*)(struct bh_io_s *, char *, size_t)) bh_file_read_base,
(size_t (*)(struct bh_io_s *, const char *, size_t)) bh_file_write_base,
(void (*)(struct bh_io_s *)) bh_file_flush_base,
(int (*)(struct bh_io_s *, bh_off_t, int)) bh_file_seek_base,
(bh_off_t (*)(struct bh_io_s *)) bh_file_size_base,
(bh_off_t (*)(struct bh_io_s *)) bh_file_tell_base,
(bh_off_t (*)(struct bh_io_s *)) bh_file_available_base,
(void (*)(struct bh_io_s *)) bh_file_clear_base,
(void (*)(struct bh_io_s *)) bh_file_destroy
};
bh_file_t *bh_file_new(const char *path)
{
bh_file_t *result;
/* Allocate and initialize file structure */
result = malloc(sizeof(*result));
if (result && bh_file_init(result, path))
{
/* Something went wrong - free allocated memory */
free(result);
result = NULL;
}
return result;
}
void bh_file_free(bh_file_t *file)
{
bh_file_destroy(file);
free(file);
}
int bh_file_init(bh_file_t *file,
const char *path)
{
/* Ensure that path is not empty */
if (!path)
return BH_INVALID;
/* Initialize base io object */
bh_io_init(&file->base, &bh_file_table);
/* Initialize file io object */
file->handle = -1;
file->mode = 0;
file->path = strdup(path);
return BH_OK;
}
void bh_file_destroy(bh_file_t *file)
{
/* Close the file */
bh_file_close(file);
free(file->path);
}
int bh_file_open_base(bh_file_t *file,
int mode)
{
/* Set open mode for 0666 permisions */
mode_t open_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
int open_flags = 0;
/* Check if file is already opened */
if (file->handle != -1)
return BH_OK;
/* Determine read/write flags */
if (mode & BH_IO_READ_WRITE)
open_flags |= O_RDWR;
else if (mode & BH_IO_READ)
open_flags |= O_RDONLY;
else if (mode & BH_IO_WRITE)
open_flags |= O_WRONLY;
else
return BH_INVALID;
/* Determine open mode */
switch (mode & BH_IO_MASK)
{
case BH_IO_OPEN: break;
case BH_IO_CREATE: open_flags |= O_CREAT | O_EXCL; break;
case BH_IO_APPEND: open_flags |= O_CREAT | O_APPEND; break;
case BH_IO_TRUNCATE: open_flags |= O_CREAT | O_TRUNC; break;
default:
return BH_NO_IMPL;
}
/* Open file */
file->handle = open(file->path, open_flags, open_mode);
/* Check for errors */
if (file->handle == -1)
return BH_ERROR;
return BH_OK;
}
void bh_file_close_base(bh_file_t *file)
{
/* Close file if it's open */
if (file->handle != -1)
close(file->handle);
/* Set handle to invalid value */
file->handle = -1;
}
int bh_file_is_open_base(bh_file_t *file)
{
/* If handle is not -1 - then file is open */
return file->handle != -1;
}
size_t bh_file_read_base(bh_file_t *file,
char *data,
size_t size)
{
ssize_t readed;
/* Check if file is open */
if (file->handle == -1)
{
/* Error occured - set error bit */
file->base.flags |= BH_IO_ERROR;
return 0;
}
/* Read data from file */
readed = read(file->handle, data, size);
if (readed < 0)
{
/* Error occured - set error bit */
file->base.flags |= BH_IO_ERROR;
return 0;
}
/* Check for end of file */
if (!readed)
file->base.flags |= BH_IO_EOF;
else
file->base.flags &= ~BH_IO_EOF;
/* Return number of readed bytes */
return readed;
}
size_t bh_file_write_base(bh_file_t *file,
const char *data,
size_t size)
{
ssize_t written;
/* Check if file is open */
if (file->handle == -1)
{
/* Error occured - set error bit */
file->base.flags |= BH_IO_ERROR;
return 0;
}
/* Write data to file */
written = write(file->handle, data, size);
if (written < 0)
{
/* Error occured - set error bit */
file->base.flags |= BH_IO_ERROR;
return 0;
}
/* Check for end of file */
if (!written)
file->base.flags |= BH_IO_EOF;
else
file->base.flags &= ~BH_IO_EOF;
/* Return number of written bytes */
return written;
}
void bh_file_flush_base(bh_file_t *file)
{
/* Check if file is open */
if (file->handle == -1)
return;
/* Signal OS to flush data from the internal buffers */
fsync(file->handle);
}
int bh_file_seek_base(bh_file_t *file,
bh_off_t pos,
int dir)
{
/* Check if file is open */
if (file->handle == -1)
return BH_ERROR;
/* Seek to desired location */
if (lseek(file->handle, pos, dir) == -1);
return BH_ERROR;
return BH_OK;
}
bh_off_t bh_file_size_base(bh_file_t *file)
{
struct stat sb;
/* Check if file is open */
if (file->handle == -1)
return -1;
/* Get file size from the OS */
if (fstat(file->handle, &sb))
return -1;
return sb.st_size;
}
bh_off_t bh_file_tell_base(bh_file_t *file)
{
/* Check if file is open */
if (file->handle == -1)
return -1;
/* Get current file position */
return lseek(file->handle, 0, SEEK_CUR);
}
bh_off_t bh_file_available_base(bh_file_t *file)
{
/* Get available bytes for reading */
return bh_file_size_base(file) - bh_file_tell_base(file);
}
void bh_file_clear_base(bh_file_t *file)
{
file->base.flags &= ~BH_IO_ERROR;
}
|