]> git.sur5r.net Git - openocd/blob - src/helper/fileio.c
3ee0b18bc6651f6d58abc7e3b479ca2c0319dd83
[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         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         /* win32 always opens in binary mode */
102 #ifndef _WIN32
103         if (fileio->type == FILEIO_BINARY)
104 #endif
105         {
106                 strcat(access, "b");
107         }
108         
109         if (!(fileio_local->file = fopen(fileio->url, access)))
110         {
111                 free(fileio_local);
112                 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't open %s", fileio->url);
113                 return ERROR_FILEIO_OPERATION_FAILED;
114         }
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 ((retval = fclose(fileio_local->file)) != 0)
176         {
177                 if (retval == EBADF)
178                 {
179                         snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "BUG: fileio_local->file not a valid file descriptor");
180                 }
181                 else
182                 {
183                         snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't close %s: %s", fileio->url, strerror(errno));
184                 }
185
186                 return ERROR_FILEIO_OPERATION_FAILED;
187         }
188         
189         free(fileio->location_private);
190         
191         return ERROR_OK;
192 }
193
194 int fileio_close(fileio_t *fileio)
195 {
196         int retval;
197         
198         switch (fileio->location)
199         {
200                 case FILEIO_LOCAL:
201                         retval = fileio_close_local(fileio);
202                         break;
203                 default:
204                         ERROR("BUG: should never get here");
205                         retval = ERROR_FILEIO_OPERATION_FAILED;
206         }
207         
208         if (retval != ERROR_OK)
209                 return retval;
210         
211         free(fileio->url);
212         
213         return ERROR_OK;
214 }
215
216 int fileio_seek_local(fileio_t *fileio, u32 position)
217 {
218         int retval;
219         fileio_local_t *fileio_local = fileio->location_private;
220         
221         if ((retval = fseek(fileio_local->file, position, SEEK_SET)) != 0)
222         {
223                 snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't seek file %s: %s", fileio->url, strerror(errno));
224                 return ERROR_FILEIO_OPERATION_FAILED;
225         }
226         
227         return ERROR_OK;
228 }
229
230 int fileio_seek(fileio_t *fileio, u32 position)
231 {
232         switch (fileio->location)
233         {
234                 case FILEIO_LOCAL:
235                         return fileio_seek_local(fileio, position);
236                         break;
237                 default:
238                         ERROR("BUG: should never get here");
239         }
240         
241         return ERROR_OK;
242 }
243
244 int fileio_local_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
245 {
246         fileio_local_t *fileio_local = fileio->location_private;
247         
248         *size_read = fread(buffer, 1, size, fileio_local->file);
249         
250         return ERROR_OK;
251 }
252
253 int fileio_read(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_read)
254 {
255         switch (fileio->location)
256         {
257                 case FILEIO_LOCAL:
258                         return fileio_local_read(fileio, size, buffer, size_read);
259                         break;
260                 default:
261                         ERROR("BUG: should never get here");
262                         exit(-1);
263         }
264 }
265
266 int fileio_read_u32(fileio_t *fileio, u32 *data)
267 {
268         u8 buf[4];
269         u32 size_read;
270         int retval;
271         
272         switch (fileio->location)
273         {
274                 case FILEIO_LOCAL:
275                         if ((retval = fileio_local_read(fileio, 4, buf, &size_read)) != ERROR_OK)
276                                 return retval;
277                         *data = be_to_h_u32(buf);
278                         break;
279                 default:
280                         ERROR("BUG: should never get here");
281                         exit(-1);
282         }
283         
284         return ERROR_OK;
285 }
286
287 int fileio_local_fgets(fileio_t *fileio, u32 size, u8 *buffer)
288 {
289         fileio_local_t *fileio_local = fileio->location_private;
290         
291         if( fgets(buffer, size, fileio_local->file) == NULL)
292                 return ERROR_FILEIO_OPERATION_FAILED;
293         
294         return ERROR_OK;
295 }
296
297 int fileio_fgets(fileio_t *fileio, u32 size, u8 *buffer)
298 {
299         switch (fileio->location)
300         {
301                 case FILEIO_LOCAL:
302                         return fileio_local_fgets(fileio, size, buffer);
303                         break;
304                 default:
305                         ERROR("BUG: should never get here");
306                         exit(-1);
307         }
308 }
309
310 int fileio_local_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
311 {
312         fileio_local_t *fileio_local = fileio->location_private;
313         
314         *size_written = fwrite(buffer, 1, size, fileio_local->file);
315         
316         return ERROR_OK;
317 }
318
319 int fileio_write(fileio_t *fileio, u32 size, u8 *buffer, u32 *size_written)
320 {
321         int retval;
322         
323         switch (fileio->location)
324         {
325                 case FILEIO_LOCAL:
326                         retval = fileio_local_write(fileio, size, buffer, size_written);
327                         break;
328                 default:
329                         ERROR("BUG: should never get here");
330                         exit(-1);
331         }
332         
333         if (retval == ERROR_OK)
334                 fileio->size += *size_written;
335         
336         return retval;;
337 }
338
339 int fileio_write_u32(fileio_t *fileio, u32 data)
340 {
341         u8 buf[4];
342         u32 size_written;
343         int retval;
344         
345         h_u32_to_be(buf, data);
346         
347         switch (fileio->location)
348         {
349                 case FILEIO_LOCAL:
350                         if ((retval = fileio_local_write(fileio, 4, buf, &size_written)) != ERROR_OK)
351                                 return retval;
352                         break;
353                 default:
354                         ERROR("BUG: should never get here");
355         }
356         
357         return ERROR_OK;
358 }