- split fileio handling into fileio part and image handling
[openocd.git] / src / helper / fileio.c
1 /***************************************************************************
2 * Copyright (C) 2007 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "types.h"
25 #include "replacements.h"
26 #include "log.h"
27
28 #include "fileio.h"
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <errno.h>
37 #include <ctype.h>
38
39 int fileio_close(fileio_t *fileio);
40 int fileio_dispatch_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read);
41
42 int fileio_open_local(fileio_t *fileio)
43 {
44 fileio_local_t *fileio_local = malloc(sizeof(fileio_local_t));
45 char access[4];
46
47 fileio->location_private = fileio_local;
48
49 if ((fileio->access != FILEIO_WRITE) && (fileio->access != FILEIO_READWRITE))
50 {
51 if (stat(fileio->url, &fileio_local->file_stat) == -1)
52 {
53 free(fileio_local);
54 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING,
55 "couldn't stat() %s: %s", fileio->url, strerror(errno));
56 return ERROR_FILEIO_NOT_FOUND;
57 }
58
59 if (S_ISDIR(fileio_local->file_stat.st_mode))
60 {
61 free(fileio_local);
62 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "%s is a directory", fileio->url);
63 return ERROR_FILEIO_NOT_FOUND;
64 }
65 }
66
67 switch (fileio->access)
68 {
69 case FILEIO_READ:
70 strcpy(access, "r");
71 break;
72 case FILEIO_WRITE:
73 strcpy(access, "w");
74 break;
75 case FILEIO_READWRITE:
76 strcpy(access, "w+");
77 break;
78 case FILEIO_APPEND:
79 strcpy(access, "a");
80 break;
81 case FILEIO_APPENDREAD:
82 strcpy(access, "a+");
83 break;
84 default:
85 free(fileio_local);
86 ERROR("BUG: access neither read, write nor readwrite");
87 return ERROR_INVALID_ARGUMENTS;
88 }
89
90 if (fileio->access == FILEIO_READ)
91 {
92 if (fileio_local->file_stat.st_size == 0)
93 {
94 /* tried to open an empty file for reading */
95 free(fileio_local);
96 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "empty file %s", fileio->url);
97 return ERROR_FILEIO_OPERATION_FAILED;
98 }
99 }
100
101 if (fileio->type == FILEIO_BINARY)
102 strcat(access, "b");
103
104 if (!(fileio_local->file = fopen(fileio->url, access)))
105 {
106 free(fileio_local);
107 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't open %s", fileio->url);
108 return ERROR_FILEIO_OPERATION_FAILED;
109 }
110
111 if ((fileio->access != FILEIO_WRITE) || (fileio->access == FILEIO_READWRITE))
112 {
113 fileio->size = fileio_local->file_stat.st_size;
114 }
115 else
116 {
117 fileio->size = 0x0;
118 }
119
120 return ERROR_OK;
121 }
122
123 int fileio_open(fileio_t *fileio, char *url, enum fileio_access access, enum fileio_type type)
124 {
125 int retval = ERROR_OK;
126 char *resource_identifier = NULL;
127
128 /* try to identify file location */
129 if ((resource_identifier = strstr(url, "bootp://")) && (resource_identifier == url))
130 {
131 ERROR("bootp resource location isn't supported yet");
132 return ERROR_FILEIO_RESOURCE_TYPE_UNKNOWN;
133 }
134 else if ((resource_identifier = strstr(url, "tftp://")) && (resource_identifier == url))
135 {
136 ERROR("tftp resource location isn't supported yet");
137 return ERROR_FILEIO_RESOURCE_TYPE_UNKNOWN;
138 }
139 else
140 {
141 /* default to local files */
142 fileio->location = FILEIO_LOCAL;
143 }
144
145 fileio->type = type;
146 fileio->access = access;
147 fileio->url = strdup(url);
148
149 switch (fileio->location)
150 {
151 case FILEIO_LOCAL:
152 retval = fileio_open_local(fileio);
153 break;
154 default:
155 ERROR("BUG: should never get here");
156 exit(-1);
157 }
158
159 if (retval != ERROR_OK)
160 return retval;
161
162 return ERROR_OK;
163 }
164
165 int fileio_close_local(fileio_t *fileio)
166 {
167 int retval;
168 fileio_local_t *fileio_local = fileio->location_private;
169
170 if ((retval = fclose(fileio_local->file)) != 0)
171 {
172 if (retval == EBADF)
173 {
174 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "BUG: fileio_local->file not a valid file descriptor");
175 }
176 else
177 {
178 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't close %s: %s", fileio->url, strerror(errno));
179 }
180
181 return ERROR_FILEIO_OPERATION_FAILED;
182 }
183
184 free(fileio->location_private);
185
186 return ERROR_OK;
187 }
188
189 int fileio_close(fileio_t *fileio)
190 {
191 int retval;
192
193 switch (fileio->location)
194 {
195 case FILEIO_LOCAL:
196 retval = fileio_close_local(fileio);
197 break;
198 default:
199 ERROR("BUG: should never get here");
200 retval = ERROR_FILEIO_OPERATION_FAILED;
201 }
202
203 if (retval != ERROR_OK)
204 return retval;
205
206 free(fileio->url);
207
208 return ERROR_OK;
209 }
210
211 int fileio_seek_local(fileio_t *fileio, u32 position)
212 {
213 int retval;
214 fileio_local_t *fileio_local = fileio->location_private;
215
216 if ((retval = fseek(fileio_local->file, position, SEEK_SET)) != 0)
217 {
218 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't seek file %s: %s", fileio->url, strerror(errno));
219 return ERROR_FILEIO_OPERATION_FAILED;
220 }
221
222 return ERROR_OK;
223 }
224
225 int fileio_seek(fileio_t *fileio, u32 position)
226 {
227 switch (fileio->location)
228 {
229 case FILEIO_LOCAL:
230 return fileio_seek_local(fileio, position);
231 break;
232 default:
233 ERROR("BUG: should never get here");
234 }
235
236 return ERROR_OK;
237 }
238
239 int fileio_local_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
240 {
241 fileio_local_t *fileio_local = fileio->location_private;
242
243 *size_read = fread(buffer, 1, size, fileio_local->file);
244
245 return ERROR_OK;
246 }
247
248 int fileio_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
249 {
250 switch (fileio->location)
251 {
252 case FILEIO_LOCAL:
253 return fileio_local_read(fileio, size, buffer, size_read);
254 break;
255 default:
256 ERROR("BUG: should never get here");
257 exit(-1);
258 }
259 }
260
261 int fileio_local_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
262 {
263 fileio_local_t *fileio_local = fileio->location_private;
264
265 *size_written = fwrite(buffer, 1, size, fileio_local->file);
266
267 return ERROR_OK;
268 }
269
270 int fileio_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
271 {
272 switch (fileio->location)
273 {
274 case FILEIO_LOCAL:
275 return fileio_local_write(fileio, size, buffer, size_written);
276 break;
277 default:
278 ERROR("BUG: should never get here");
279 }
280
281 return ERROR_OK;
282 }