1 /***************************************************************************
2 * Copyright (C) 2007 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2007,2008 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
8 * Copyright (C) 2008 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 ***************************************************************************/
32 #include "configuration.h"
35 struct fileio_internal
{
38 enum fileio_type type
;
39 enum fileio_access access
;
43 static inline int fileio_close_local(struct fileio_internal
*fileio
);
44 static inline int fileio_open_local(struct fileio_internal
*fileio
)
48 switch (fileio
->access
) {
50 strcpy(file_access
, "r");
53 strcpy(file_access
, "w");
55 case FILEIO_READWRITE
:
56 strcpy(file_access
, "w+");
59 strcpy(file_access
, "a");
61 case FILEIO_APPENDREAD
:
62 strcpy(file_access
, "a+");
65 LOG_ERROR("BUG: access neither read, write nor readwrite");
66 return ERROR_COMMAND_SYNTAX_ERROR
;
69 /* win32 always opens in binary mode */
71 if (fileio
->type
== FILEIO_BINARY
)
73 strcat(file_access
, "b");
75 fileio
->file
= open_file_from_path(fileio
->url
, file_access
);
77 LOG_ERROR("couldn't open %s", fileio
->url
);
78 return ERROR_FILEIO_OPERATION_FAILED
;
81 if ((fileio
->access
!= FILEIO_WRITE
) || (fileio
->access
== FILEIO_READWRITE
)) {
82 /* NB! Here we use fseek() instead of stat(), since stat is a
83 * more advanced operation that might not apply to e.g. a disk path
84 * that refers to e.g. a tftp client */
87 result
= fseek(fileio
->file
, 0, SEEK_END
);
89 fileio
->size
= ftell(fileio
->file
);
91 result2
= fseek(fileio
->file
, 0, SEEK_SET
);
93 if ((fileio
->size
< 0) || (result
< 0) || (result2
< 0)) {
94 fileio_close_local(fileio
);
95 return ERROR_FILEIO_OPERATION_FAILED
;
103 int fileio_open(struct fileio
*fileio_p
,
105 enum fileio_access access_type
,
106 enum fileio_type type
)
108 int retval
= ERROR_OK
;
110 struct fileio_internal
*fileio
= malloc(sizeof(struct fileio_internal
));
111 fileio_p
->fp
= fileio
;
114 fileio
->access
= access_type
;
115 fileio
->url
= strdup(url
);
117 retval
= fileio_open_local(fileio
);
122 static inline int fileio_close_local(struct fileio_internal
*fileio
)
124 int retval
= fclose(fileio
->file
);
127 LOG_ERROR("BUG: fileio_local->file not a valid file descriptor");
129 LOG_ERROR("couldn't close %s: %s", fileio
->url
, strerror(errno
));
131 return ERROR_FILEIO_OPERATION_FAILED
;
137 int fileio_close(struct fileio
*fileio_p
)
140 struct fileio_internal
*fileio
= fileio_p
->fp
;
142 retval
= fileio_close_local(fileio
);
144 free((void *)fileio
->url
);
153 int fileio_seek(struct fileio
*fileio_p
, size_t position
)
156 struct fileio_internal
*fileio
= fileio_p
->fp
;
157 retval
= fseek(fileio
->file
, position
, SEEK_SET
);
159 LOG_ERROR("couldn't seek file %s: %s", fileio
->url
, strerror(errno
));
160 return ERROR_FILEIO_OPERATION_FAILED
;
166 static int fileio_local_read(struct fileio_internal
*fileio
,
167 size_t size
, void *buffer
, size_t *size_read
)
169 ssize_t retval
= fread(buffer
, 1, size
, fileio
->file
);
170 *size_read
= (retval
>= 0) ? retval
: 0;
171 return (retval
< 0) ? retval
: ERROR_OK
;
174 int fileio_read(struct fileio
*fileio_p
, size_t size
, void *buffer
,
177 struct fileio_internal
*fileio
= fileio_p
->fp
;
178 return fileio_local_read(fileio
, size
, buffer
, size_read
);
181 int fileio_read_u32(struct fileio
*fileio_p
, uint32_t *data
)
185 struct fileio_internal
*fileio
= fileio_p
->fp
;
186 int retval
= fileio_local_read(fileio
, sizeof(uint32_t), buf
, &size_read
);
187 if (ERROR_OK
== retval
&& sizeof(uint32_t) != size_read
)
189 if (ERROR_OK
== retval
)
190 *data
= be_to_h_u32(buf
);
194 static int fileio_local_fgets(struct fileio_internal
*fileio
,
195 size_t size
, void *buffer
)
197 if (fgets(buffer
, size
, fileio
->file
) == NULL
)
198 return ERROR_FILEIO_OPERATION_FAILED
;
203 int fileio_fgets(struct fileio
*fileio_p
, size_t size
, void *buffer
)
205 struct fileio_internal
*fileio
= fileio_p
->fp
;
206 return fileio_local_fgets(fileio
, size
, buffer
);
209 static int fileio_local_write(struct fileio_internal
*fileio
,
210 size_t size
, const void *buffer
, size_t *size_written
)
212 ssize_t retval
= fwrite(buffer
, 1, size
, fileio
->file
);
213 *size_written
= (retval
>= 0) ? retval
: 0;
214 return (retval
< 0) ? retval
: ERROR_OK
;
217 int fileio_write(struct fileio
*fileio_p
,
218 size_t size
, const void *buffer
, size_t *size_written
)
220 struct fileio_internal
*fileio
= fileio_p
->fp
;
221 int retval
= fileio_local_write(fileio
, size
, buffer
, size_written
);
222 if (retval
== ERROR_OK
)
223 fileio
->size
+= *size_written
;
227 int fileio_write_u32(struct fileio
*fileio_p
, uint32_t data
)
230 h_u32_to_be(buf
, data
);
232 int retval
= fileio_write(fileio_p
, 4, buf
, &size_written
);
233 if (ERROR_OK
== retval
&& size_written
!= sizeof(uint32_t))
242 * For now this can not fail, but that's because a seek was executed
245 * Avoiding the seek on startup opens up for using streams.
248 int fileio_size(struct fileio
*fileio_p
, int *size
)
250 struct fileio_internal
*fileio
= fileio_p
->fp
;
251 *size
= fileio
->size
;