1: #include "global.h"
2:
3:
4: static void
5: unmap_cf(struct tagBufIO *buf)
6: {
7: if (buf)
8: munmap(buf->buf_base, buf->buf_size);
9: }
10:
11: static int
12: cf_(struct tagBufIO *buf)
13: {
14: if (!buf) {
15: io_SetErr(EINVAL, "Invalid arguments ...");
16: return -1;
17: }
18:
19: if (buf->buf_mode == BUFIO_MODE_INFINIT)
20: free(buf->buf_base);
21: else if (buf->buf_unmap)
22: buf->buf_unmap(buf);
23:
24: free(buf);
25: return 0;
26: }
27:
28: static fpos_t
29: sf_lim(struct tagBufIO *buf, fpos_t pos, int w)
30: {
31: if (!buf)
32: goto err;
33:
34: switch (w) {
35: case SEEK_SET:
36: if (buf->buf_size < pos || pos < 0)
37: goto err;
38: buf->buf_offset = pos;
39: break;
40: case SEEK_CUR:
41: if (buf->buf_size < (buf->buf_offset + pos) || (buf->buf_offset + pos) < 0)
42: goto err;
43: buf->buf_offset += pos;
44: break;
45: case SEEK_END:
46: if (buf->buf_size < (buf->buf_size + pos) || (buf->buf_size + pos) < 0)
47: goto err;
48: buf->buf_offset = buf->buf_size + pos;
49: break;
50: default:
51: goto err;
52: }
53:
54: return buf->buf_offset;
55: err:
56: io_SetErr(EINVAL, "Invalid arguments ...");
57: return -1;
58: }
59:
60: static int
61: rf_lim(struct tagBufIO *buf, char *dat, int siz)
62: {
63: if (!buf || !dat) {
64: io_SetErr(EINVAL, "Invalid arguments ...");
65: return -1;
66: }
67:
68: if (buf->buf_offset + siz > buf->buf_size)
69: siz = buf->buf_size - buf->buf_offset;
70:
71: memcpy(dat, buf->buf_base + buf->buf_offset, siz);
72: buf->buf_offset += siz;
73: return siz;
74: }
75:
76: static int
77: wf_lim(struct tagBufIO *buf, const char *dat, int siz)
78: {
79: if (!buf || !dat) {
80: io_SetErr(EINVAL, "Invalid arguments ...");
81: return -1;
82: }
83:
84: if (buf->buf_offset + siz > buf->buf_size)
85: siz = buf->buf_size - buf->buf_offset;
86:
87: memcpy(buf->buf_base + buf->buf_offset, dat, siz);
88: buf->buf_offset += siz;
89: return siz;
90: }
91:
92: static fpos_t
93: sf_inf(struct tagBufIO *buf, fpos_t pos, int w)
94: {
95: void *b;
96:
97: if (!buf)
98: goto err;
99:
100: switch (w) {
101: case SEEK_SET:
102: if (pos < 0)
103: goto err;
104: if (buf->buf_size < pos) {
105: b = realloc(buf->buf_base, pos);
106: if (!b) {
107: LOGERR;
108: return -1;
109: } else {
110: buf->buf_base = b;
111: memset(buf->buf_base + buf->buf_size, 0, pos - buf->buf_size);
112: buf->buf_size = pos;
113: }
114: }
115: buf->buf_offset = pos;
116: break;
117: case SEEK_CUR:
118: if ((buf->buf_offset + pos) < 0)
119: goto err;
120: if (buf->buf_size < (buf->buf_offset + pos)) {
121: b = realloc(buf->buf_base, buf->buf_offset + pos);
122: if (!b) {
123: LOGERR;
124: return -1;
125: } else {
126: buf->buf_base = b;
127: memset(buf->buf_base + buf->buf_size, 0,
128: buf->buf_offset + pos - buf->buf_size);
129: buf->buf_size = buf->buf_offset + pos;
130: }
131: }
132: buf->buf_offset += pos;
133: break;
134: case SEEK_END:
135: if ((buf->buf_size + pos) < 0)
136: goto err;
137: if (buf->buf_size < (buf->buf_size + pos)) {
138: b = realloc(buf->buf_base, buf->buf_size + pos);
139: if (!b) {
140: LOGERR;
141: return -1;
142: } else {
143: buf->buf_base = b;
144: memset(buf->buf_base + buf->buf_size, 0, pos);
145: buf->buf_size += pos;
146: buf->buf_offset = buf->buf_size;
147: }
148: } else
149: buf->buf_offset = buf->buf_size + pos;
150: break;
151: default:
152: goto err;
153: }
154:
155: return buf->buf_offset;
156: err:
157: io_SetErr(EINVAL, "Invalid arguments ...");
158: return -1;
159: }
160:
161: static int
162: wf_inf(struct tagBufIO *buf, const char *dat, int siz)
163: {
164: void *b;
165:
166: if (!buf || !dat) {
167: io_SetErr(EINVAL, "Invalid arguments ...");
168: return -1;
169: }
170:
171: if (buf->buf_offset + siz > buf->buf_size) {
172: b = realloc(buf->buf_base, buf->buf_offset + siz);
173: if (!b) {
174: LOGERR;
175: return -1;
176: } else {
177: buf->buf_base = b;
178: memset(buf->buf_base + buf->buf_size, 0,
179: buf->buf_offset + siz - buf->buf_size);
180: buf->buf_size = buf->buf_offset + siz;
181: }
182: }
183:
184: memcpy(buf->buf_base + buf->buf_offset, dat, siz);
185: buf->buf_offset += siz;
186: return siz;
187: }
188:
189:
190: /*
191: * io_fmemopen() File buffered stream operations over memory block
192: *
193: * @base = Base address of memory block, if =NULL Infinit length(auto-grow)
194: * @basesize = Size of memory block
195: * return: NULL error or !=NULL Opened file resource
196: */
197: FILE *
198: io_fmemopen(void ** __restrict base, off_t basesize)
199: {
200: FILE *f = NULL;
201: struct tagBufIO *buf;
202:
203: if (!base) {
204: io_SetErr(EINVAL, "Invalid base argument ...");
205: return NULL;
206: }
207:
208: buf = malloc(sizeof(struct tagBufIO));
209: if (!buf) {
210: LOGERR;
211: return NULL;
212: } else
213: memset(buf, 0, sizeof(struct tagBufIO));
214:
215: if (!*base) {
216: *base = malloc(basesize);
217: if (!*base) {
218: LOGERR;
219: free(buf);
220: return NULL;
221: } else
222: memset(*base, 0, basesize);
223:
224: buf->buf_mode = BUFIO_MODE_INFINIT;
225: } else
226: buf->buf_mode = BUFIO_MODE_LIMIT;
227:
228: buf->buf_base = *base;
229: buf->buf_size = basesize;
230:
231: if (buf->buf_mode == BUFIO_MODE_INFINIT)
232: f = funopen(buf, (int (*)(void *, char *, int)) rf_lim,
233: (int (*)(void *, char const *, int)) wf_inf,
234: (fpos_t (*)(void *, fpos_t, int)) sf_inf,
235: (int (*)(void *)) cf_);
236: else
237: f = funopen(buf, (int (*)(void *, char *, int)) rf_lim,
238: (int (*)(void *, char const *, int)) wf_lim,
239: (fpos_t (*)(void *, fpos_t, int)) sf_lim,
240: (int (*)(void *)) cf_);
241: if (!f) {
242: LOGERR;
243: if (buf->buf_mode == BUFIO_MODE_INFINIT) {
244: free(*base);
245: *base = NULL;
246: }
247: free(buf);
248: return NULL;
249: }
250:
251: return f;
252: }
253:
254: /*
255: * io_fmapopen() File buffered stream operations over MMAP block
256: *
257: * @csFile = Filename for MMAP, if =NULL private MMAP block
258: * @mode = File open mode
259: * @perm = If file not exists will be created with this access permissions
260: * @prot = MMAP protection
261: * @flags = MMAP mode flags
262: * @offset = Map from file offset, if csFile==NULL then this is size of MMAP private block
263: * return: NULL error or !=NULL Opened file resource
264: */
265: FILE *
266: io_fmapopen(const char *csFile, int mode, int perm, int prot, int flags, off_t offset)
267: {
268: FILE *f;
269: struct tagBufIO *buf;
270: void *base;
271: off_t basesize;
272: int fd = -1;
273:
274: if (csFile) {
275: fd = open(csFile, mode, perm);
276: if (fd == -1) {
277: LOGERR;
278: return NULL;
279: }
280: basesize = lseek(fd, 0, SEEK_END);
281: if (basesize == -1) {
282: LOGERR;
283: close(fd);
284: return NULL;
285: } else
286: lseek(fd, 0, SEEK_SET);
287:
288: base = mmap(NULL, basesize, prot, flags | MAP_FILE, fd, offset);
289: if (base == MAP_FAILED) {
290: LOGERR;
291: close(fd);
292: return NULL;
293: } else
294: close(fd);
295: } else if (offset) {
296: basesize = offset;
297: base = mmap(NULL, basesize, prot, MAP_ANON, -1, 0);
298: if (base == MAP_FAILED) {
299: LOGERR;
300: return NULL;
301: }
302: } else {
303: io_SetErr(EINVAL, "Invalid base argument ...");
304: return NULL;
305: }
306:
307:
308: buf = malloc(sizeof(struct tagBufIO));
309: if (!buf) {
310: LOGERR;
311: munmap(base, basesize);
312: return NULL;
313: } else
314: memset(buf, 0, sizeof(struct tagBufIO));
315:
316: buf->buf_mode = BUFIO_MODE_LIMIT;
317: buf->buf_base = base;
318: buf->buf_size = basesize;
319: buf->buf_unmap = unmap_cf;
320:
321: f = funopen(buf, (int (*)(void *, char *, int)) rf_lim,
322: (int (*)(void *, char const *, int)) wf_lim,
323: (fpos_t (*)(void *, fpos_t, int)) sf_lim,
324: (int (*)(void *)) cf_);
325: if (!f) {
326: LOGERR;
327: free(buf);
328: munmap(base, basesize);
329: return NULL;
330: }
331:
332: return f;
333: }
334:
335: /*
336: * io_dumbFile() Create empry or dumb file with fixed size
337: *
338: * @csFile = Filename for create
339: * @mode = File access permissions
340: * @size = File size
341: * return: -1 error or open file handle
342: */
343: int
344: io_dumbFile(const char *csFile, int mode, off_t size)
345: {
346: int fd;
347:
348: fd = open(csFile, O_RDWR | O_CREAT, mode);
349: if (fd == -1) {
350: LOGERR;
351: return -1;
352: }
353:
354: if (lseek(fd, size - 1, SEEK_SET) == -1)
355: goto err;
356: if (write(fd, "", 1) != 1)
357: goto err;
358: else
359: lseek(fd, 0, SEEK_SET);
360:
361: return fd;
362: err:
363: LOGERR;
364: close(fd);
365: return -1;
366: }
367:
368: /*
369: * io_fd2buf() Convert open file handle to buffered file I/O
370: *
371: * @fd = File handle
372: * @mode = Permissions for new buffered file I/O
373: * return: NULL error or open buffered file
374: */
375: inline FILE *
376: io_fd2buf(int fd, const char *mode)
377: {
378: FILE *f;
379:
380: f = fdopen(fd, mode);
381: if (!f)
382: LOGERR;
383:
384: return f;
385: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>