libcdio  2.1.0
About: GNU libcdio is a library for CD-ROM and CD image access.
  Fossies Dox: libcdio-2.1.0.tar.bz2  ("inofficial" and yet experimental doxygen-generated source code documentation)  

_cdio_stdio.c
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003, 2004, 2005, 2008, 2011 Rocky Bernstein <rocky@gnu.org>
3  Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
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 3 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, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 # define __CDIO_CONFIG_H__ 1
22 #endif
23 
24 #ifdef HAVE_STDIO_H
25 #include <stdio.h>
26 #endif
27 #ifdef HAVE_STDLIB_H
28 #include <stdlib.h>
29 #endif
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #ifdef HAVE_SYS_STAT_H
37 #include <sys/stat.h>
38 #endif
39 #ifdef HAVE_ERRNO_H
40 #include <errno.h>
41 #endif
42 #include <ctype.h>
43 
44 #include <cdio/logging.h>
45 #include <cdio/util.h>
46 #include "_cdio_stream.h"
47 #include "_cdio_stdio.h"
48 #include "cdio_assert.h"
49 
50 /* On 32 bit platforms, fseek can only access streams of 2 GB or less.
51  Prefer fseeko/fseeko64, that take a 64 bit offset when LFS is enabled */
52 #if defined(HAVE_FSEEKO64) && defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
53 #define CDIO_FSEEK fseeko64
54 #elif defined(HAVE_FSEEKO)
55 #define CDIO_FSEEK fseeko
56 #else
57 #define CDIO_FSEEK fseek
58 #endif
59 
60 /* Windows' fopen is not UTF-8 compliant, so we use our own */
61 #if defined(_WIN32)
62 #include <cdio/utf8.h>
63 #define CDIO_FOPEN fopen_utf8
64 #else
65 #define CDIO_FOPEN fopen
66 #endif
67 
68 /* Use _stati64 if needed, on platforms that don't have transparent LFS support */
69 #if defined(HAVE__STATI64) && defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
70 #define CDIO_STAT_STRUCT _stati64
71 #if defined(_WIN32)
72 /* Once again, use our own UTF-8 compliant version */
73 static inline int _stati64_utf8(const char *path, struct _stati64 *buffer) {
74  int ret;
75  wchar_t* wpath = cdio_utf8_to_wchar(path);
76  ret = _wstati64(wpath, buffer);
77  cdio_free(wpath);
78  return ret;
79 }
80 #define CDIO_STAT_CALL _stati64_utf8
81 #else
82 #define CDIO_STAT_CALL _stati64
83 #endif
84 #else
85 #define CDIO_STAT_STRUCT stat
86 #define CDIO_STAT_CALL stat
87 #endif
88 
89 #define _STRINGIFY(a) #a
90 #define STRINGIFY(a) _STRINGIFY(a)
91 
92 #define CDIO_STDIO_BUFSIZE (128*1024)
93 
94 typedef struct {
95  char *pathname;
96  FILE *fd;
97  char *fd_buf;
98  off_t st_size; /* used only for source */
99 } _UserData;
100 
101 static int
102 _stdio_open (void *user_data)
103 {
104  _UserData *const ud = user_data;
105 
106  if ((ud->fd = CDIO_FOPEN (ud->pathname, "rb")))
107  {
108  ud->fd_buf = calloc (1, CDIO_STDIO_BUFSIZE);
109  setvbuf (ud->fd, ud->fd_buf, _IOFBF, CDIO_STDIO_BUFSIZE);
110  }
111 
112  return (ud->fd == NULL);
113 }
114 
115 static int
116 _stdio_close(void *user_data)
117 {
118  _UserData *const ud = user_data;
119 
120  if (fclose (ud->fd))
121  cdio_error ("fclose (): %s", strerror (errno));
122 
123  ud->fd = NULL;
124 
125  free (ud->fd_buf);
126  ud->fd_buf = NULL;
127 
128  return 0;
129 }
130 
131 static void
132 _stdio_free(void *user_data)
133 {
134  _UserData *const ud = user_data;
135 
136  if (ud->pathname)
137  free(ud->pathname);
138 
139  if (ud->fd) /* should be NULL anyway... */
140  _stdio_close(user_data);
141 
142  free(ud);
143 }
144 
161 static int
162 _stdio_seek(void *p_user_data, off_t i_offset, int whence)
163 {
164  _UserData *const ud = p_user_data;
165  int ret;
166 #if !defined(HAVE_FSEEKO) && !defined(HAVE_FSEEKO64)
167  /* Detect if off_t is lossy-truncated to long to avoid data corruption */
168  if ( (sizeof(off_t) > sizeof(long)) && (i_offset != (off_t)((long)i_offset)) ) {
169  cdio_error ( STRINGIFY(CDIO_FSEEK) " (): lossy truncation detected!");
170  errno = EFBIG;
171  return DRIVER_OP_ERROR;
172  }
173 #endif
174 
175  if ( (ret=CDIO_FSEEK (ud->fd, i_offset, whence)) ) {
176  cdio_error ( STRINGIFY(CDIO_FSEEK) " (): %s", strerror (errno));
177  }
178 
179  return ret;
180 }
181 
182 static off_t
183 _stdio_stat(void *p_user_data)
184 {
185  const _UserData *const ud = p_user_data;
186 
187  return ud->st_size;
188 }
189 
207 static ssize_t
208 _stdio_read(void *user_data, void *buf, size_t count)
209 {
210  _UserData *const ud = user_data;
211  long read_count;
212 
213  read_count = fread(buf, 1, count, ud->fd);
214 
215  if (read_count != count)
216  { /* fixme -- ferror/feof */
217  if (feof (ud->fd))
218  {
219  cdio_debug ("fread (): EOF encountered");
220  clearerr (ud->fd);
221  }
222  else if (ferror (ud->fd))
223  {
224  cdio_error ("fread (): %s", strerror (errno));
225  clearerr (ud->fd);
226  }
227  else
228  cdio_debug ("fread (): short read and no EOF?!?");
229  }
230 
231  return read_count;
232 }
233 
237 void
239 {
240  cdio_stream_destroy(p_obj);
241 }
242 
244 cdio_stdio_new(const char pathname[])
245 {
246  CdioDataSource_t *new_obj = NULL;
248  _UserData *ud = NULL;
249  struct CDIO_STAT_STRUCT statbuf;
250  char* pathdup;
251 
252  if (pathname == NULL)
253  return NULL;
254 
255  /* MinGW may require a translated path */
256  pathdup = _cdio_strdup_fixpath(pathname);
257  if (pathdup == NULL)
258  return NULL;
259 
260  if (CDIO_STAT_CALL (pathdup, &statbuf) == -1)
261  {
262  cdio_warn ("could not retrieve file info for `%s': %s",
263  pathdup, strerror (errno));
264  cdio_free(pathdup);
265  return NULL;
266  }
267 
268  ud = calloc (1, sizeof (_UserData));
269  cdio_assert (ud != NULL);
270 
271  ud->pathname = pathdup;
272  ud->st_size = statbuf.st_size; /* let's hope it doesn't change... */
273 
274  funcs.open = _stdio_open;
275  funcs.seek = _stdio_seek;
276  funcs.stat = _stdio_stat;
277  funcs.read = _stdio_read;
278  funcs.close = _stdio_close;
279  funcs.free = _stdio_free;
280 
281  new_obj = cdio_stream_new(ud, &funcs);
282 
283  return new_obj;
284 }
285 
286 
287 /*
288  * Local variables:
289  * c-file-style: "gnu"
290  * tab-width: 8
291  * indent-tabs-mode: nil
292  * End:
293  */
cdio_stream_io_functions::close
cdio_data_close_t close
Definition: _cdio_stream.h:54
_CdioDataSource
Definition: _cdio_stream.c:48
CDIO_STDIO_BUFSIZE
#define CDIO_STDIO_BUFSIZE
Definition: _cdio_stdio.c:92
_stdio_open
static int _stdio_open(void *user_data)
Definition: _cdio_stdio.c:102
cdio_warn
void void void void cdio_warn(const char format[],...) GNUC_PRINTF(1
cdio_stream_io_functions::open
cdio_data_open_t open
Definition: _cdio_stream.h:50
cdio_stream_destroy
void cdio_stream_destroy(CdioDataSource_t *p_obj)
Definition: _cdio_stream.c:69
cdio_stream_io_functions::seek
cdio_data_seek_t seek
Definition: _cdio_stream.h:51
_stdio_seek
static int _stdio_seek(void *p_user_data, off_t i_offset, int whence)
Definition: _cdio_stdio.c:162
_stdio_free
static void _stdio_free(void *user_data)
Definition: _cdio_stdio.c:132
CDIO_STAT_STRUCT
#define CDIO_STAT_STRUCT
Definition: _cdio_stdio.c:85
cdio_debug
void void cdio_debug(const char format[],...) GNUC_PRINTF(1
_cdio_strdup_fixpath
char * _cdio_strdup_fixpath(const char path[])
Definition: util.c:147
_cdio_stream.h
cdio_error
void void void void void cdio_error(const char format[],...) GNUC_PRINTF(1
NULL
#define NULL
Definition: types.h:184
_cdio_stdio.h
CDIO_FSEEK
#define CDIO_FSEEK
Definition: _cdio_stdio.c:57
cdio_assert
#define cdio_assert(expr)
Definition: cdio_assert.h:50
util.h
Miscellaneous utility functions.
_UserData::fd_buf
char * fd_buf
Definition: _cdio_stdio.c:97
cdio_stream_new
CdioDataSource_t * cdio_stream_new(void *user_data, const cdio_stream_io_functions *funcs)
Definition: _cdio_stream.c:97
cdio_free
void cdio_free(void *p_memory)
Definition: memory.c:37
cdio_stream_io_functions::stat
cdio_data_stat_t stat
Definition: _cdio_stream.h:52
buffer
char buffer[6][CDIO_CD_FRAMESIZE_RAW]
Definition: cdinfo-linux.c:201
_stdio_stat
static off_t _stdio_stat(void *p_user_data)
Definition: _cdio_stdio.c:183
utf8.h
UTF-8 support.
DRIVER_OP_ERROR
Definition: device.h:211
_UserData::st_size
off_t st_size
Definition: _cdio_stdio.c:98
_stdio_close
static int _stdio_close(void *user_data)
Definition: _cdio_stdio.c:116
logging.h
Header to control logging and level of detail of output.
_UserData
Definition: _cdio_stdio.c:94
config.h
_stdio_read
static ssize_t _stdio_read(void *user_data, void *buf, size_t count)
Definition: _cdio_stdio.c:208
cdio_stream_io_functions::read
cdio_data_read_t read
Definition: _cdio_stream.h:53
cdio_stdio_new
CdioDataSource_t * cdio_stdio_new(const char pathname[])
Definition: _cdio_stdio.c:244
CDIO_STAT_CALL
#define CDIO_STAT_CALL
Definition: _cdio_stdio.c:86
STRINGIFY
#define STRINGIFY(a)
Definition: _cdio_stdio.c:90
_UserData::fd
FILE * fd
Definition: _cdio_stdio.c:96
cdio_stdio_destroy
void cdio_stdio_destroy(CdioDataSource_t *p_obj)
Definition: _cdio_stdio.c:238
CDIO_FOPEN
#define CDIO_FOPEN
Definition: _cdio_stdio.c:65
cdio_assert.h
cdio_stream_io_functions::free
cdio_data_free_t free
Definition: _cdio_stream.h:55
cdio_stream_io_functions
Definition: _cdio_stream.h:49
_UserData::pathname
char * pathname
Definition: _cdio_stdio.c:95