]> git.sur5r.net Git - openocd/blob - src/helper/fileio.c
- removed flash write_image - binary compare function has been moved to verify_image...
[openocd] / 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         switch (fileio->access)
48         {
49                 case FILEIO_READ:
50                         strcpy(access, "r");
51                         break;
52                 case FILEIO_WRITE:
53                         strcpy(access, "w");
54                         break;
55                 case FILEIO_READWRITE:
56                         strcpy(access, "w+");
57                         break;
58                 case FILEIO_APPEND:
59                         strcpy(access, "a");    
60                         break;
61                 case FILEIO_APPENDREAD:
62                         strcpy(access, "a+");   
63                         break;
64                 default:
65                         free(fileio_local);
66                         ERROR("BUG: access neither read, write nor readwrite");
67                         return ERROR_INVALID_ARGUMENTS;
68         }
69
70         /* win32 always opens in binary mode */
71 #ifndef _WIN32
72         if (fileio->type == FILEIO_BINARY)
73 #endif
74         {
75                 strcat(access, "b");
76         }
77         
78         if (!(fileio_local->file = fopen(fileio->url, access)))
79         {
80                 free(fileio_local);
81                 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't open %s", fileio->url);
82                 return ERROR_FILEIO_OPERATION_FAILED;
83         }
84         
85         if ((fileio->access != FILEIO_WRITE) || (fileio->access == FILEIO_READWRITE))
86         {
87                 /* NB! Here we use fseek() instead of stat(), since stat is a
88                  * more advanced operation that might not apply to e.g. a disk path
89                  * that refers to e.g. a tftp client */
90                 int result, result2;
91                 
92                 result = fseek(fileio_local->file, 0, SEEK_END);
93                 
94                 fileio->size = ftell(fileio_local->file);
95                 
96                 result2 = fseek(fileio_local->file, 0, SEEK_SET); 
97                         
98                 if ((fileio->size < 0) || (result < 0) || (result2 < 0))
99                 {
100                         fileio_close(fileio);
101                         return ERROR_FILEIO_OPERATION_FAILED;
102                 }
103         }
104         else
105         {
106                 fileio->size = 0x0;
107         }
108         
109         fileio->location_private = fileio_local;
110         
111         return ERROR_OK;
112 }
113
114 int fileio_open(fileio_t *fileio, char *url, enum fileio_access access, enum fileio_type type)
115 {
116         int retval = ERROR_OK;
117         char *resource_identifier = NULL;
118
119         /* try to identify file location. We only hijack the file paths we understand, the rest is
120          * passed on to the OS which might implement e.g. tftp via a mounted tftp device.
121          */
122         if ((resource_identifier = strstr(url, "bootp://")) && (resource_identifier == url))
123         {
124                 ERROR("bootp resource location isn't supported yet");
125                 return ERROR_FILEIO_RESOURCE_TYPE_UNKNOWN;
126         }
127         else
128         {
129                 /* default to local files */
130                 fileio->location = FILEIO_LOCAL;
131         }
132         
133         fileio->type = type;
134         fileio->access = access;
135         fileio->url = strdup(url);
136         
137         switch (fileio->location)
138         {
139                 case FILEIO_LOCAL:
140                         retval = fileio_open_local(fileio);
141                         break;
142                 default:
143                         ERROR("BUG: should never get here");
144                         exit(-1);
145         }
146         
147         if (retval != ERROR_OK)
148                 return retval;
149         
150         return ERROR_OK;
151 }
152
153 int fileio_close_local(fileio_t *fileio)
154 {
155         int retval;
156         fileio_local_t *fileio_local = fileio->location_private;
157         
158         if (fileio->location_private == NULL)
159         {
160                 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't close %s: ", fileio->url);
161                 return ERROR_FILEIO_OPERATION_FAILED;
162         }
163         
164         if ((retval = fclose(fileio_local->file)) != 0)
165         {
166                 if (retval == EBADF)
167                 {
168                         snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "BUG: fileio_local->file not a valid file descriptor");
169                 }
170                 else
171                 {
172                         snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't close %s: %s", fileio->url, strerror(errno));
173                 }
174
175                 return ERROR_FILEIO_OPERATION_FAILED;
176         }
177         
178         free(fileio->location_private);
179         fileio->location_private = NULL;
180         
181         return ERROR_OK;
182 }
183
184 int fileio_close(fileio_t *fileio)
185 {
186         int retval;
187         
188         switch (fileio->location)
189         {
190                 case FILEIO_LOCAL:
191                         retval = fileio_close_local(fileio);
192                         break;
193                 default:
194                         ERROR("BUG: should never get here");
195                         retval = ERROR_FILEIO_OPERATION_FAILED;
196         }
197         
198         if (retval != ERROR_OK)
199                 return retval;
200         
201         free(fileio->url);
202         fileio->url = NULL;
203         
204         return ERROR_OK;
205 }
206
207 int fileio_seek_local(fileio_t *fileio, u32 position)
208 {
209         int retval;
210         fileio_local_t *fileio_local = fileio->location_private;
211         
212         if ((retval = fseek(fileio_local->file, position, SEEK_SET)) != 0)
213         {
214                 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't seek file %s: %s", fileio->url, strerror(errno));
215                 return ERROR_FILEIO_OPERATION_FAILED;
216         }
217         
218         return ERROR_OK;
219 }
220
221 int fileio_seek(fileio_t *fileio, u32 position)
222 {
223         switch (fileio->location)
224         {
225                 case FILEIO_LOCAL:
226                         return fileio_seek_local(fileio, position);
227                         break;
228                 default:
229                         ERROR("BUG: should never get here");
230         }
231         
232         return ERROR_OK;
233 }
234
235 int fileio_local_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
236 {
237         fileio_local_t *fileio_local = fileio->location_private;
238         
239         *size_read = fread(buffer, 1, size, fileio_local->file);
240         
241         return ERROR_OK;
242 }
243
244 int fileio_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
245 {
246         switch (fileio->location)
247         {
248                 case FILEIO_LOCAL:
249                         return fileio_local_read(fileio, size, buffer, size_read);
250                         break;
251                 default:
252                         ERROR("BUG: should never get here");
253                         exit(-1);
254         }
255 }
256
257 int fileio_read_u32(fileio_t *fileio, u32 *data)
258 {
259         u8 buf[4];
260         u32 size_read;
261         int retval;
262         
263         switch (fileio->location)
264         {
265                 case FILEIO_LOCAL:
266                         if ((retval = fileio_local_read(fileio, 4, buf, &size_read)) != ERROR_OK)
267                                 return retval;
268                         *data = be_to_h_u32(buf);
269                         break;
270                 default:
271                         ERROR("BUG: should never get here");
272                         exit(-1);
273         }
274         
275         return ERROR_OK;
276 }
277
278 int fileio_local_fgets(fileio_t *fileio, u32 size, u8 *buffer)
279 {
280         fileio_local_t *fileio_local = fileio->location_private;
281         
282         if( fgets(buffer, size, fileio_local->file) == NULL)
283                 return ERROR_FILEIO_OPERATION_FAILED;
284         
285         return ERROR_OK;
286 }
287
288 int fileio_fgets(fileio_t *fileio, u32 size, u8 *buffer)
289 {
290         switch (fileio->location)
291         {
292                 case FILEIO_LOCAL:
293                         return fileio_local_fgets(fileio, size, buffer);
294                         break;
295                 default:
296                         ERROR("BUG: should never get here");
297                         exit(-1);
298         }
299 }
300
301 int fileio_local_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
302 {
303         fileio_local_t *fileio_local = fileio->location_private;
304         
305         *size_written = fwrite(buffer, 1, size, fileio_local->file);
306         
307         return ERROR_OK;
308 }
309
310 int fileio_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
311 {
312         int retval;
313         
314         switch (fileio->location)
315         {
316                 case FILEIO_LOCAL:
317                         retval = fileio_local_write(fileio, size, buffer, size_written);
318                         break;
319                 default:
320                         ERROR("BUG: should never get here");
321                         exit(-1);
322         }
323         
324         if (retval == ERROR_OK)
325                 fileio->size += *size_written;
326         
327         return retval;;
328 }
329
330 int fileio_write_u32(fileio_t *fileio, u32 data)
331 {
332         u8 buf[4];
333         u32 size_written;
334         int retval;
335         
336         h_u32_to_be(buf, data);
337         
338         switch (fileio->location)
339         {
340                 case FILEIO_LOCAL:
341                         if ((retval = fileio_local_write(fileio, 4, buf, &size_written)) != ERROR_OK)
342                                 return retval;
343                         break;
344                 default:
345                         ERROR("BUG: should never get here");
346         }
347         
348         return ERROR_OK;
349 }