soc-2008-mxcurioni: merged changes to revision 23516
[blender.git] / source / blender / blenlib / intern / BLI_bfile.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (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 Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2009 by Stichting Blender Foundation.
21  * All rights reserved.
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  * BFILE* based abstraction for file access.
25  */
26
27 #include <string.h>
28
29 #ifndef WIN32
30   #include <unistd.h>
31 #else
32   #include <io.h>
33   #include "BLI_winstuff.h"
34 #endif
35
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "BLI_bfile.h"
43
44 // This would provide config paths and their oldest viable version
45 // so if there is an uncompatible change, user's old versions are not loaded
46 //#include "bfile_tables.h"
47
48 /* Internal bfile type flags */
49 #define BTF_OPEN     (0)
50 #define BTF_FOPEN    (1<<0)
51 #define BTF_READ     (1<<1)
52 #define BTF_WRITE    (1<<2)
53 #define BTF_AT_END   (1<<3)
54 #define BTF_DISCARD  (1<<4)
55
56
57 void fill_paths(BFILE *bfile, const char *path) {
58         char* source_path = NULL;
59         int bflags = bfile->uflags;
60
61         if(bflags & BFILE_NORMAL || bflags & BFILE_RAW) {
62 //              bfile->fpath is path with // replaced
63         }
64         if(bflags & BFILE_TEMP) {
65 //              bfile->fpath is tempdir+path
66         }
67         if(bflags & BFILE_CONFIG) {
68 //              bfile->fpath is userdir+version+path
69 //              source_path is first hit in (if using fallback to older versions)
70 //                  userdir+curversion+path (... userdir+limitversion+path) sysdir+path
71 //              (limitversion is based in path, using some kind of regex or "tables")
72         }
73
74         if(bfile->type & BTF_WRITE && !(bflags & BFILE_RAW)) {
75                 /* Generate temp path */
76                 // bfile->tpath is fpath+randstring
77                 if(!(bfile->type & BTF_DISCARD)) {
78                         /* Copy data to tpath */
79                         if(source_path) {
80                                 // copy it from older version or sys version
81                         }
82                 }
83         } else {
84                 bfile->tpath = bfile->fpath;
85         }
86 }
87
88 BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags) {
89         BFILE *bfile;
90
91         bfile = MEM_mallocN(sizeof(BFILE), "bfile-fopen");
92         bfile->type = BTF_FOPEN;
93         bfile->uflags = bflags;
94
95         /* From fopen() doc, we can guess some logic:
96         r  BTF_READ
97         r+ BTF_READ | BTF_WRITE
98         w  BTF_DISCARD | BTF_WRITE
99         w+ BTF_DISCARD | BTF_WRITE | BTF_READ
100         a  BTF_AT_END | BTF_WRITE
101         a+ BTF_AT_END | BTF_WRITE | BTF_READ
102         */
103         if(strchr(mode, 'r'))
104                 bfile->type |= BTF_READ;
105         if(strchr(mode, 'w'))
106                 bfile->type |= (BTF_DISCARD | BTF_WRITE);
107         if(strchr(mode, 'a'))
108                 bfile->type |= (BTF_AT_END | BTF_WRITE);
109         if(strchr(mode, '+'))
110                 bfile->type |= (BTF_READ | BTF_WRITE);
111
112         fill_paths(bfile, path);
113
114         bfile->stream = fopen(bfile->tpath, mode);
115         // detect failed fopen
116         bfile->fd = fileno(bfile->stream);
117         return bfile;
118 }
119
120
121 BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags) {
122         BFILE *bfile;
123
124         bfile = MEM_mallocN(sizeof(BFILE), "bfile-open");
125         bfile->type = BTF_OPEN;
126         bfile->uflags = bflags;
127
128         /* Easy mapping for open() */
129         if(flags & O_RDONLY)
130                 bfile->type |= BTF_READ;
131         if(flags & O_WRONLY)
132                 bfile->type |= BTF_WRITE;
133         if(flags & O_RDWR)
134                 bfile->type |= (BTF_READ | BTF_WRITE);
135         if(flags & O_APPEND)
136                 bfile->type |= BTF_AT_END;
137         if(flags & O_TRUNC)
138                 bfile->type |= BTF_DISCARD;
139
140         fill_paths(bfile, pathname);
141
142         bfile->fd = open(bfile->tpath, flags);
143         // detect failed open
144 //      bfile->stream = fdopen(bfile->fd, XXX); /* MSWindows _fdopen? */
145         return bfile;
146 }
147
148
149 FILE *BLI_bfile_file_from_bfile(BFILE *bfile) {
150         return bfile->stream;
151 }
152
153
154 int BLI_bfile_fd_from_bfile(BFILE *bfile) {
155         return bfile->fd;
156 }
157
158
159 ssize_t BLI_bfile_write(BFILE *f, const void *buf, size_t count) {
160         ssize_t ret;
161
162         ret = write((f->fd), buf, count);
163         if (ret == -1) {
164                 f->error = 1;
165         }
166
167         return ret;
168 }
169
170
171 ssize_t BLI_bfile_read(BFILE *f, void *buf, size_t count) {
172         ssize_t ret;
173
174         ret = read((f->fd), buf, count);
175         if (ret == -1) {
176                 f->error = 1;
177         }
178
179         return ret;
180 }
181
182
183 size_t BLI_bfile_fwrite(const void *ptr, size_t size, size_t nmemb, BFILE *f) {
184         size_t ret;
185
186         ret = fwrite(ptr, size, nmemb, f->stream);
187         if (ret < 0) {
188                 f->error = 1;
189         }
190
191         return ret;
192 }
193
194
195 size_t BLI_bfile_fread(void *ptr, size_t size, size_t nmemb, BFILE *f) {
196         size_t ret;
197
198         ret = fread(ptr, size, nmemb, f->stream);
199         if ((ret < 0) && ferror(f->stream)) {
200                 f->error = 1;
201         }
202
203         return ret;
204 }
205
206
207 void BLI_bfile_close(BFILE *bfile) {
208         if((bfile->type | BTF_WRITE) &&
209            !(bfile->uflags | BFILE_RAW)) {
210                 /* Make sure data is on disk */
211                 /* Move to final name if no errors */
212         }
213
214         /* Normal close */
215
216         /* Cleanup */
217         if(bfile->fpath) {
218                 MEM_freeN(bfile->fpath);
219         }
220         if(bfile->tpath) {
221                 MEM_freeN(bfile->tpath);
222         }
223 }
224
225
226 void BLI_bfile_clear_error(BFILE *bfile) {
227         bfile->error = 0;
228 }
229
230
231 void BLI_bfile_set_error(BFILE *bfile, int error) {
232         /* No cheating, use clear_error() for 0 */
233         if (error) {
234                 bfile->error = error;
235         }
236 }