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