]> git.draconx.ca Git - liblbx.git/blob - src/fops.c
liblbx: Always return a value in file_seek.
[liblbx.git] / src / fops.c
1 /*
2  *  2ooM: The Master of Orion II Reverse Engineering Project
3  *  Default file operations structures for liblbx.
4  *  Copyright (C) 2010 Nick Bowler
5  *
6  *  This program is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 #include <stdio.h>
20 #include <errno.h>
21
22 #include "misc.h"
23 #include "error.h"
24 #include "lbx.h"
25
26 /* Default I/O operations for ordinary files. */
27 static size_t file_read(void *buf, size_t size, void *handle)
28 {
29         size_t rc = fread(buf, 1, size, (FILE *)handle);
30
31         if (rc < size && ferror((FILE *)handle))
32                 lbx_error_raise(-errno);
33         return rc;
34 }
35
36 static int file_seek(void *handle, long offset, int whence)
37 {
38         if (fseek((FILE *)handle, offset, whence) == -1) {
39                 lbx_error_raise(-errno);
40                 return -1;
41         }
42
43         return 0;
44 }
45
46 static long file_tell(void *handle)
47 {
48         return ftell((FILE *)handle);
49 }
50
51 static int file_eof(void *handle)
52 {
53         return feof((FILE *)handle);
54 }
55
56 const struct lbx_file_ops lbx_default_fops = {
57         .read = file_read,
58         .seek = file_seek,
59         .tell = file_tell,
60         .eof  = file_eof,
61 };
62
63 /* Read function for pipes that tracks the number of bytes read. */
64 static size_t pipe_read(void *buf, size_t size, void *handle)
65 {
66         struct lbx_pipe_state *state = handle;
67         size_t rc;
68
69         rc = file_read(buf, size, state->f);
70         state->offset += rc;
71         return rc;
72 }
73
74 /* Seek function for pipes that reads data into the void. */
75 static int pipe_seek(void *handle, long offset, int whence)
76 {
77         struct lbx_pipe_state *state = handle;
78         long distance;
79
80         switch (whence) {
81         case SEEK_SET:
82                 distance = offset - state->offset;
83                 break;
84         case SEEK_CUR:
85                 distance = offset;
86                 break;
87         case SEEK_END:
88                 distance = -1;
89                 break;
90         }
91
92         if (distance < 0)
93                 return -1;
94
95         while (distance > 0) {
96                 static unsigned char oblivion[1024];
97                 size_t rc, amount = MIN(sizeof oblivion, distance);
98
99                 rc = pipe_read(oblivion, amount, handle);
100                 distance -= rc;
101
102                 if (rc < amount)
103                         return -1;
104         }
105
106         clearerr(state->f);
107         return 0;
108 }
109
110 static long pipe_tell(void *handle)
111 {
112         struct lbx_pipe_state *state = handle;
113
114         return state->offset;
115 }
116
117 static int pipe_eof(void *handle)
118 {
119         struct lbx_pipe_state *state = handle;
120
121         return feof(state->f);
122 }
123
124 const struct lbx_file_ops lbx_pipe_fops = {
125         .read = pipe_read,
126         .seek = pipe_seek,
127         .tell = pipe_tell,
128         .eof  = pipe_eof,
129 };
130
131 static size_t lbx_read(void *buf, size_t size, void *handle)
132 {
133         return lbx_file_read(handle, buf, size);
134 }
135
136 static int lbx_seek(void *handle, long offset, int whence)
137 {
138         return lbx_file_seek(handle, offset, whence);
139 }
140
141 static long lbx_tell(void *handle)
142 {
143         return lbx_file_tell(handle);
144 }
145
146 static int lbx_eof(void *handle)
147 {
148         return lbx_file_eof(handle);
149 }
150
151 const struct lbx_file_ops lbx_arch_fops = {
152         .read = lbx_read,
153         .seek = lbx_seek,
154         .tell = lbx_tell,
155         .eof  = lbx_eof,
156 };