diff options
Diffstat (limited to 'firmware/common')
-rw-r--r-- | firmware/common/dir.c | 3 | ||||
-rw-r--r-- | firmware/common/file.c | 178 | ||||
-rw-r--r-- | firmware/common/file.h | 16 |
3 files changed, 140 insertions, 57 deletions
diff --git a/firmware/common/dir.c b/firmware/common/dir.c index 70aa4946dc..6bf9a53cad 100644 --- a/firmware/common/dir.c +++ b/firmware/common/dir.c | |||
@@ -105,8 +105,7 @@ struct dirent* readdir(DIR* dir) | |||
105 | return NULL; | 105 | return NULL; |
106 | 106 | ||
107 | if ( !entry.name[0] ) | 107 | if ( !entry.name[0] ) |
108 | return NULL; | 108 | return NULL; |
109 | |||
110 | 109 | ||
111 | strncpy(theent->d_name, entry.name, sizeof( theent->d_name ) ); | 110 | strncpy(theent->d_name, entry.name, sizeof( theent->d_name ) ); |
112 | theent->attribute = entry.attr; | 111 | theent->attribute = entry.attr; |
diff --git a/firmware/common/file.c b/firmware/common/file.c index 2c00c3e3f6..27258e4603 100644 --- a/firmware/common/file.c +++ b/firmware/common/file.c | |||
@@ -42,23 +42,25 @@ struct filedesc { | |||
42 | int size; | 42 | int size; |
43 | struct fat_file fatfile; | 43 | struct fat_file fatfile; |
44 | bool busy; | 44 | bool busy; |
45 | bool write; | ||
45 | }; | 46 | }; |
46 | 47 | ||
47 | static struct filedesc openfiles[MAX_OPEN_FILES]; | 48 | static struct filedesc openfiles[MAX_OPEN_FILES]; |
48 | 49 | ||
49 | int open(char* pathname, int flags) | 50 | int creat(const char *pathname, int mode) |
51 | { | ||
52 | (void)mode; | ||
53 | return open(pathname, O_WRONLY); | ||
54 | } | ||
55 | |||
56 | int open(const char* pathname, int flags) | ||
50 | { | 57 | { |
51 | DIR* dir; | 58 | DIR* dir; |
52 | struct dirent* entry; | 59 | struct dirent* entry; |
53 | int fd; | 60 | int fd; |
54 | char* name; | 61 | char* name; |
55 | 62 | ||
56 | /* For now, we don't support writing */ | 63 | LDEBUGF("open(\"%s\",%d)\n",pathname,flags); |
57 | if(flags & (O_WRONLY | O_RDWR)) | ||
58 | { | ||
59 | errno = EROFS; | ||
60 | return -1; | ||
61 | } | ||
62 | 64 | ||
63 | if ( pathname[0] != '/' ) { | 65 | if ( pathname[0] != '/' ) { |
64 | DEBUGF("'%s' is not an absolute path.\n",pathname); | 66 | DEBUGF("'%s' is not an absolute path.\n",pathname); |
@@ -75,44 +77,74 @@ int open(char* pathname, int flags) | |||
75 | if ( fd == MAX_OPEN_FILES ) { | 77 | if ( fd == MAX_OPEN_FILES ) { |
76 | DEBUGF("Too many files open\n"); | 78 | DEBUGF("Too many files open\n"); |
77 | errno = EMFILE; | 79 | errno = EMFILE; |
78 | return -1; | 80 | return -2; |
79 | } | 81 | } |
80 | 82 | ||
83 | switch ( flags ) { | ||
84 | case O_RDONLY: | ||
85 | openfiles[fd].write = false; | ||
86 | break; | ||
87 | |||
88 | case O_WRONLY: | ||
89 | openfiles[fd].write = true; | ||
90 | break; | ||
91 | |||
92 | default: | ||
93 | DEBUGF("Only O_RDONLY and O_WRONLY is supported\n"); | ||
94 | errno = EROFS; | ||
95 | return -3; | ||
96 | } | ||
81 | openfiles[fd].busy = true; | 97 | openfiles[fd].busy = true; |
82 | 98 | ||
83 | /* locate filename */ | 99 | /* locate filename */ |
84 | name=strrchr(pathname+1,'/'); | 100 | name=strrchr(pathname+1,'/'); |
85 | if ( name ) { | 101 | if ( name ) { |
86 | *name = 0; | 102 | *name = 0; |
87 | dir = opendir(pathname); | 103 | dir = opendir((char*)pathname); |
88 | *name = '/'; | 104 | *name = '/'; |
89 | name++; | 105 | name++; |
90 | } | 106 | } |
91 | else { | 107 | else { |
92 | dir = opendir("/"); | 108 | dir = opendir("/"); |
93 | name = pathname+1; | 109 | name = (char*)pathname+1; |
94 | } | 110 | } |
95 | if (!dir) { | 111 | if (!dir) { |
96 | DEBUGF("Failed opening dir\n"); | 112 | DEBUGF("Failed opening dir\n"); |
97 | errno = EIO; | 113 | errno = EIO; |
98 | openfiles[fd].busy = false; | 114 | openfiles[fd].busy = false; |
99 | return -1; | 115 | return -4; |
100 | } | 116 | } |
101 | 117 | ||
102 | /* scan dir for name */ | 118 | /* scan dir for name */ |
103 | while ((entry = readdir(dir))) { | 119 | while ((entry = readdir(dir))) { |
104 | if ( !strcasecmp(name, entry->d_name) ) { | 120 | if ( !strcasecmp(name, entry->d_name) ) { |
105 | fat_open(entry->startcluster, &(openfiles[fd].fatfile)); | 121 | fat_open(entry->startcluster, |
122 | &(openfiles[fd].fatfile), | ||
123 | &(dir->fatdir)); | ||
106 | openfiles[fd].size = entry->size; | 124 | openfiles[fd].size = entry->size; |
107 | break; | 125 | break; |
108 | } | 126 | } |
109 | } | 127 | } |
110 | closedir(dir); | 128 | closedir(dir); |
111 | if ( !entry ) { | 129 | if ( !entry ) { |
112 | DEBUGF("Couldn't find %s in %s\n",name,pathname); | 130 | LDEBUGF("Didn't find file %s\n",name); |
113 | errno = ENOENT; | 131 | if ( openfiles[fd].write ) { |
114 | openfiles[fd].busy = false; | 132 | if (fat_create_file(name, |
115 | return -1; | 133 | &(openfiles[fd].fatfile), |
134 | &(dir->fatdir)) < 0) { | ||
135 | DEBUGF("Couldn't create %s in %s\n",name,pathname); | ||
136 | errno = EIO; | ||
137 | openfiles[fd].busy = false; | ||
138 | return -5; | ||
139 | } | ||
140 | openfiles[fd].size = 0; | ||
141 | } | ||
142 | else { | ||
143 | DEBUGF("Couldn't find %s in %s\n",name,pathname); | ||
144 | errno = ENOENT; | ||
145 | openfiles[fd].busy = false; | ||
146 | return -6; | ||
147 | } | ||
116 | } | 148 | } |
117 | 149 | ||
118 | openfiles[fd].cacheoffset = -1; | 150 | openfiles[fd].cacheoffset = -1; |
@@ -122,19 +154,37 @@ int open(char* pathname, int flags) | |||
122 | 154 | ||
123 | int close(int fd) | 155 | int close(int fd) |
124 | { | 156 | { |
157 | int rc = 0; | ||
158 | |||
159 | LDEBUGF("close(%d)\n",fd); | ||
160 | |||
125 | if (fd < 0 || fd > MAX_OPEN_FILES-1) { | 161 | if (fd < 0 || fd > MAX_OPEN_FILES-1) { |
126 | errno = EINVAL; | 162 | errno = EINVAL; |
127 | return -1; | 163 | return -1; |
128 | } | 164 | } |
129 | if (!openfiles[fd].busy) { | 165 | if (!openfiles[fd].busy) { |
130 | errno = EBADF; | 166 | errno = EBADF; |
131 | return -1; | 167 | return -2; |
168 | } | ||
169 | if (openfiles[fd].write) { | ||
170 | /* flush sector cache */ | ||
171 | if ( openfiles[fd].cacheoffset != -1 ) { | ||
172 | if ( fat_readwrite(&(openfiles[fd].fatfile), 1, | ||
173 | &(openfiles[fd].cache),true) < 0 ) { | ||
174 | DEBUGF("Failed flushing cache\n"); | ||
175 | errno = EIO; | ||
176 | rc = -1; | ||
177 | } | ||
178 | } | ||
179 | |||
180 | /* tie up all loose ends */ | ||
181 | fat_closewrite(&(openfiles[fd].fatfile), openfiles[fd].size); | ||
132 | } | 182 | } |
133 | openfiles[fd].busy = false; | 183 | openfiles[fd].busy = false; |
134 | return 0; | 184 | return rc; |
135 | } | 185 | } |
136 | 186 | ||
137 | int read(int fd, void* buf, int count) | 187 | static int readwrite(int fd, void* buf, int count, bool write) |
138 | { | 188 | { |
139 | int sectors; | 189 | int sectors; |
140 | int nread=0; | 190 | int nread=0; |
@@ -144,9 +194,16 @@ int read(int fd, void* buf, int count) | |||
144 | return -1; | 194 | return -1; |
145 | } | 195 | } |
146 | 196 | ||
147 | /* attempt to read past EOF? */ | 197 | LDEBUGF( "readwrite(%d,%x,%d,%s)\n", |
148 | if ( count > openfiles[fd].size - openfiles[fd].fileoffset ) | 198 | fd,buf,count,write?"write":"read"); |
149 | count = openfiles[fd].size - openfiles[fd].fileoffset; | 199 | |
200 | /* attempt to access past EOF? */ | ||
201 | if (count > openfiles[fd].size - openfiles[fd].fileoffset) { | ||
202 | if ( write ) | ||
203 | openfiles[fd].size = openfiles[fd].fileoffset + count; | ||
204 | else | ||
205 | count = openfiles[fd].size - openfiles[fd].fileoffset; | ||
206 | } | ||
150 | 207 | ||
151 | /* any head bytes? */ | 208 | /* any head bytes? */ |
152 | if ( openfiles[fd].cacheoffset != -1 ) { | 209 | if ( openfiles[fd].cacheoffset != -1 ) { |
@@ -163,23 +220,38 @@ int read(int fd, void* buf, int count) | |||
163 | openfiles[fd].cacheoffset = -1; | 220 | openfiles[fd].cacheoffset = -1; |
164 | } | 221 | } |
165 | 222 | ||
166 | /* eof? */ | 223 | if (write) { |
167 | if ( openfiles[fd].fileoffset + headbytes > openfiles[fd].size ) | 224 | memcpy( openfiles[fd].cache + offs, buf, headbytes ); |
168 | headbytes = openfiles[fd].size - openfiles[fd].fileoffset; | 225 | if (offs+headbytes == SECTOR_SIZE) { |
226 | int rc = fat_readwrite(&(openfiles[fd].fatfile), 1, | ||
227 | openfiles[fd].cache, true ); | ||
228 | if ( rc < 0 ) { | ||
229 | DEBUGF("Failed read/writing %d sectors\n",sectors); | ||
230 | errno = EIO; | ||
231 | return -2; | ||
232 | } | ||
233 | openfiles[fd].cacheoffset = -1; | ||
234 | } | ||
235 | } | ||
236 | else { | ||
237 | memcpy( buf, openfiles[fd].cache + offs, headbytes ); | ||
238 | } | ||
169 | 239 | ||
170 | memcpy( buf, openfiles[fd].cache + offs, headbytes ); | ||
171 | nread = headbytes; | 240 | nread = headbytes; |
172 | count -= headbytes; | 241 | count -= headbytes; |
242 | |||
243 | LDEBUGF("readwrite incache: offs=%d\n",openfiles[fd].cacheoffset); | ||
173 | } | 244 | } |
174 | 245 | ||
175 | /* read whole sectors right into the supplied buffer */ | 246 | /* read whole sectors right into the supplied buffer */ |
176 | sectors = count / SECTOR_SIZE; | 247 | sectors = count / SECTOR_SIZE; |
177 | if ( sectors ) { | 248 | if ( sectors ) { |
178 | int rc = fat_read(&(openfiles[fd].fatfile), sectors, buf+nread ); | 249 | int rc = fat_readwrite(&(openfiles[fd].fatfile), sectors, |
250 | buf+nread, write ); | ||
179 | if ( rc < 0 ) { | 251 | if ( rc < 0 ) { |
180 | DEBUGF("Failed reading %d sectors\n",sectors); | 252 | DEBUGF("Failed read/writing %d sectors\n",sectors); |
181 | errno = EIO; | 253 | errno = EIO; |
182 | return -1; | 254 | return -2; |
183 | } | 255 | } |
184 | else { | 256 | else { |
185 | if ( rc > 0 ) { | 257 | if ( rc > 0 ) { |
@@ -197,18 +269,19 @@ int read(int fd, void* buf, int count) | |||
197 | 269 | ||
198 | /* any tail bytes? */ | 270 | /* any tail bytes? */ |
199 | if ( count ) { | 271 | if ( count ) { |
200 | if ( fat_read(&(openfiles[fd].fatfile), 1, | 272 | if (write) { |
201 | &(openfiles[fd].cache)) < 0 ) { | 273 | memcpy( openfiles[fd].cache, buf + nread, count ); |
202 | DEBUGF("Failed caching sector\n"); | ||
203 | errno = EIO; | ||
204 | return -1; | ||
205 | } | 274 | } |
206 | 275 | else { | |
207 | /* eof? */ | 276 | if ( fat_readwrite(&(openfiles[fd].fatfile), 1, |
208 | if ( openfiles[fd].fileoffset + count > openfiles[fd].size ) | 277 | &(openfiles[fd].cache),false) < 0 ) { |
209 | count = openfiles[fd].size - openfiles[fd].fileoffset; | 278 | DEBUGF("Failed caching sector\n"); |
210 | 279 | errno = EIO; | |
211 | memcpy( buf + nread, openfiles[fd].cache, count ); | 280 | return -1; |
281 | } | ||
282 | memcpy( buf + nread, openfiles[fd].cache, count ); | ||
283 | } | ||
284 | |||
212 | nread += count; | 285 | nread += count; |
213 | openfiles[fd].cacheoffset = count; | 286 | openfiles[fd].cacheoffset = count; |
214 | } | 287 | } |
@@ -217,6 +290,17 @@ int read(int fd, void* buf, int count) | |||
217 | return nread; | 290 | return nread; |
218 | } | 291 | } |
219 | 292 | ||
293 | int write(int fd, void* buf, int count) | ||
294 | { | ||
295 | return readwrite(fd, buf, count, true); | ||
296 | } | ||
297 | |||
298 | int read(int fd, void* buf, int count) | ||
299 | { | ||
300 | return readwrite(fd, buf, count, false); | ||
301 | } | ||
302 | |||
303 | |||
220 | int lseek(int fd, int offset, int whence) | 304 | int lseek(int fd, int offset, int whence) |
221 | { | 305 | { |
222 | int pos; | 306 | int pos; |
@@ -225,6 +309,8 @@ int lseek(int fd, int offset, int whence) | |||
225 | int sectoroffset; | 309 | int sectoroffset; |
226 | int rc; | 310 | int rc; |
227 | 311 | ||
312 | LDEBUGF("lseek(%d,%d,%d)\n",fd,offset,whence); | ||
313 | |||
228 | if ( !openfiles[fd].busy ) { | 314 | if ( !openfiles[fd].busy ) { |
229 | errno = EBADF; | 315 | errno = EBADF; |
230 | return -1; | 316 | return -1; |
@@ -245,11 +331,11 @@ int lseek(int fd, int offset, int whence) | |||
245 | 331 | ||
246 | default: | 332 | default: |
247 | errno = EINVAL; | 333 | errno = EINVAL; |
248 | return -1; | 334 | return -2; |
249 | } | 335 | } |
250 | if ((pos < 0) || (pos > openfiles[fd].size)) { | 336 | if ((pos < 0) || (pos > openfiles[fd].size)) { |
251 | errno = EINVAL; | 337 | errno = EINVAL; |
252 | return -1; | 338 | return -3; |
253 | } | 339 | } |
254 | 340 | ||
255 | /* new sector? */ | 341 | /* new sector? */ |
@@ -263,14 +349,14 @@ int lseek(int fd, int offset, int whence) | |||
263 | rc = fat_seek(&(openfiles[fd].fatfile), newsector); | 349 | rc = fat_seek(&(openfiles[fd].fatfile), newsector); |
264 | if ( rc < 0 ) { | 350 | if ( rc < 0 ) { |
265 | errno = EIO; | 351 | errno = EIO; |
266 | return -1; | 352 | return -4; |
267 | } | 353 | } |
268 | } | 354 | } |
269 | rc = fat_read(&(openfiles[fd].fatfile), 1, | 355 | rc = fat_readwrite(&(openfiles[fd].fatfile), 1, |
270 | &(openfiles[fd].cache)); | 356 | &(openfiles[fd].cache),false); |
271 | if ( rc < 0 ) { | 357 | if ( rc < 0 ) { |
272 | errno = EIO; | 358 | errno = EIO; |
273 | return -1; | 359 | return -5; |
274 | } | 360 | } |
275 | openfiles[fd].cacheoffset = sectoroffset; | 361 | openfiles[fd].cacheoffset = sectoroffset; |
276 | } | 362 | } |
diff --git a/firmware/common/file.h b/firmware/common/file.h index c95811fc55..7a7c63d665 100644 --- a/firmware/common/file.h +++ b/firmware/common/file.h | |||
@@ -40,24 +40,22 @@ | |||
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | #if defined(__MINGW32__) && defined(SIMULATOR) | 42 | #if defined(__MINGW32__) && defined(SIMULATOR) |
43 | int open (const char*, int, ...); | 43 | extern int open(const char*, int, ...); |
44 | extern int close(int fd); | 44 | extern int close(int fd); |
45 | int read (int, void*, unsigned int); | 45 | extern int read(int, void*, unsigned int); |
46 | long lseek (int, long, int); | 46 | extern long lseek(int, long, int); |
47 | 47 | ||
48 | #else | 48 | #else |
49 | 49 | ||
50 | #ifndef SIMULATOR | 50 | #ifndef SIMULATOR |
51 | extern int open(char* pathname, int flags); | 51 | extern int open(const char* pathname, int flags); |
52 | extern int close(int fd); | 52 | extern int close(int fd); |
53 | extern int read(int fd, void* buf, int count); | 53 | extern int read(int fd, void* buf, int count); |
54 | extern int lseek(int fd, int offset, int whence); | 54 | extern int lseek(int fd, int offset, int whence); |
55 | 55 | extern int creat(const char *pathname, int mode); | |
56 | #ifdef DISK_WRITE | ||
57 | extern int write(int fd, void* buf, int count); | 56 | extern int write(int fd, void* buf, int count); |
58 | extern int remove(char* pathname); | 57 | extern int remove(const char* pathname); |
59 | extern int rename(char* oldname, char* newname); | 58 | extern int rename(const char* oldname, const char* newname); |
60 | #endif | ||
61 | 59 | ||
62 | #else | 60 | #else |
63 | #ifdef WIN32 | 61 | #ifdef WIN32 |