1 /* $Id$ */
2 /*
3  * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4  * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include <pj/file_io.h>
21 #include <pj/assert.h>
22 #include <pj/errno.h>
23 #include <stdio.h>
24 #include <errno.h>
25 
pj_file_open(pj_pool_t * pool,const char * pathname,unsigned flags,pj_oshandle_t * fd)26 PJ_DEF(pj_status_t) pj_file_open( pj_pool_t *pool,
27                                   const char *pathname,
28                                   unsigned flags,
29                                   pj_oshandle_t *fd)
30 {
31     char mode[8];
32     char *p = mode;
33 
34     PJ_ASSERT_RETURN(pathname && fd, PJ_EINVAL);
35     PJ_UNUSED_ARG(pool);
36 
37     if ((flags & PJ_O_APPEND) == PJ_O_APPEND) {
38         if ((flags & PJ_O_WRONLY) == PJ_O_WRONLY) {
39             *p++ = 'a';
40             if ((flags & PJ_O_RDONLY) == PJ_O_RDONLY)
41                 *p++ = '+';
42         } else {
43             /* This is invalid.
44              * Can not specify PJ_O_RDONLY with PJ_O_APPEND!
45              */
46         }
47     } else {
48         if ((flags & PJ_O_RDONLY) == PJ_O_RDONLY) {
49             *p++ = 'r';
50             if ((flags & PJ_O_WRONLY) == PJ_O_WRONLY)
51                 *p++ = '+';
52         } else {
53             *p++ = 'w';
54         }
55     }
56 
57     if (p==mode)
58         return PJ_EINVAL;
59 
60     *p++ = 'b';
61     *p++ = '\0';
62 
63     *fd = fopen(pathname, mode);
64     if (*fd == NULL)
65         return PJ_RETURN_OS_ERROR(errno);
66 
67     return PJ_SUCCESS;
68 }
69 
pj_file_close(pj_oshandle_t fd)70 PJ_DEF(pj_status_t) pj_file_close(pj_oshandle_t fd)
71 {
72     PJ_ASSERT_RETURN(fd, PJ_EINVAL);
73     if (fclose((FILE*)fd) != 0)
74         return PJ_RETURN_OS_ERROR(errno);
75 
76     return PJ_SUCCESS;
77 }
78 
pj_file_write(pj_oshandle_t fd,const void * data,pj_ssize_t * size)79 PJ_DEF(pj_status_t) pj_file_write( pj_oshandle_t fd,
80                                    const void *data,
81                                    pj_ssize_t *size)
82 {
83     size_t written;
84 
85     clearerr((FILE*)fd);
86     written = fwrite(data, 1, *size, (FILE*)fd);
87     if (ferror((FILE*)fd)) {
88         *size = -1;
89         return PJ_RETURN_OS_ERROR(errno);
90     }
91 
92     *size = written;
93     return PJ_SUCCESS;
94 }
95 
pj_file_read(pj_oshandle_t fd,void * data,pj_ssize_t * size)96 PJ_DEF(pj_status_t) pj_file_read( pj_oshandle_t fd,
97                                   void *data,
98                                   pj_ssize_t *size)
99 {
100     size_t bytes;
101 
102     clearerr((FILE*)fd);
103     bytes = fread(data, 1, *size, (FILE*)fd);
104     if (ferror((FILE*)fd)) {
105         *size = -1;
106         return PJ_RETURN_OS_ERROR(errno);
107     }
108 
109     *size = bytes;
110     return PJ_SUCCESS;
111 }
112 
113 /*
114 PJ_DEF(pj_bool_t) pj_file_eof(pj_oshandle_t fd, enum pj_file_access access)
115 {
116     PJ_UNUSED_ARG(access);
117     return feof((FILE*)fd) ? PJ_TRUE : 0;
118 }
119 */
120 
pj_file_setpos(pj_oshandle_t fd,pj_off_t offset,enum pj_file_seek_type whence)121 PJ_DEF(pj_status_t) pj_file_setpos( pj_oshandle_t fd,
122                                     pj_off_t offset,
123                                     enum pj_file_seek_type whence)
124 {
125     int mode;
126 
127     switch (whence) {
128     case PJ_SEEK_SET:
129         mode = SEEK_SET; break;
130     case PJ_SEEK_CUR:
131         mode = SEEK_CUR; break;
132     case PJ_SEEK_END:
133         mode = SEEK_END; break;
134     default:
135         pj_assert(!"Invalid whence in file_setpos");
136         return PJ_EINVAL;
137     }
138 
139     if (fseek((FILE*)fd, (long)offset, mode) != 0)
140         return PJ_RETURN_OS_ERROR(errno);
141 
142     return PJ_SUCCESS;
143 }
144 
pj_file_getpos(pj_oshandle_t fd,pj_off_t * pos)145 PJ_DEF(pj_status_t) pj_file_getpos( pj_oshandle_t fd,
146                                     pj_off_t *pos)
147 {
148     long offset;
149 
150     offset = ftell((FILE*)fd);
151     if (offset == -1) {
152         *pos = -1;
153         return PJ_RETURN_OS_ERROR(errno);
154     }
155 
156     *pos = offset;
157     return PJ_SUCCESS;
158 }
159 
pj_file_flush(pj_oshandle_t fd)160 PJ_DEF(pj_status_t) pj_file_flush(pj_oshandle_t fd)
161 {
162     int rc;
163 
164     rc = fflush((FILE*)fd);
165     if (rc == EOF) {
166 	return PJ_RETURN_OS_ERROR(errno);
167     }
168 
169     return PJ_SUCCESS;
170 }
171