diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/common/file.c | 108 |
1 files changed, 70 insertions, 38 deletions
diff --git a/firmware/common/file.c b/firmware/common/file.c index 86e1099918..41aaea570a 100644 --- a/firmware/common/file.c +++ b/firmware/common/file.c | |||
@@ -17,6 +17,7 @@ | |||
17 | * | 17 | * |
18 | ****************************************************************************/ | 18 | ****************************************************************************/ |
19 | #include <string.h> | 19 | #include <string.h> |
20 | #include <errno.h> | ||
20 | #include "file.h" | 21 | #include "file.h" |
21 | #include "fat.h" | 22 | #include "fat.h" |
22 | #include "types.h" | 23 | #include "types.h" |
@@ -26,8 +27,10 @@ | |||
26 | #define MAX_OPEN_FILES 4 | 27 | #define MAX_OPEN_FILES 4 |
27 | 28 | ||
28 | struct filedesc { | 29 | struct filedesc { |
29 | unsigned char sector[SECTOR_SIZE]; | 30 | unsigned char cache[SECTOR_SIZE]; |
30 | int offset; | 31 | int cacheoffset; |
32 | int fileoffset; | ||
33 | int size; | ||
31 | struct fat_file fatfile; | 34 | struct fat_file fatfile; |
32 | bool busy; | 35 | bool busy; |
33 | }; | 36 | }; |
@@ -45,6 +48,7 @@ int open(char* pathname, int flags) | |||
45 | if ( pathname[0] != '/' ) { | 48 | if ( pathname[0] != '/' ) { |
46 | DEBUGF("'%s' is not an absolute path.\n",pathname); | 49 | DEBUGF("'%s' is not an absolute path.\n",pathname); |
47 | DEBUGF("Only absolute pathnames supported at the moment\n"); | 50 | DEBUGF("Only absolute pathnames supported at the moment\n"); |
51 | errno = EINVAL; | ||
48 | return -1; | 52 | return -1; |
49 | } | 53 | } |
50 | 54 | ||
@@ -55,6 +59,7 @@ int open(char* pathname, int flags) | |||
55 | 59 | ||
56 | if ( fd == MAX_OPEN_FILES ) { | 60 | if ( fd == MAX_OPEN_FILES ) { |
57 | DEBUGF("Too many files open\n"); | 61 | DEBUGF("Too many files open\n"); |
62 | errno = EMFILE; | ||
58 | return -1; | 63 | return -1; |
59 | } | 64 | } |
60 | 65 | ||
@@ -72,6 +77,7 @@ int open(char* pathname, int flags) | |||
72 | } | 77 | } |
73 | if (!dir) { | 78 | if (!dir) { |
74 | DEBUGF("Failed opening dir\n"); | 79 | DEBUGF("Failed opening dir\n"); |
80 | errno = EIO; | ||
75 | return -1; | 81 | return -1; |
76 | } | 82 | } |
77 | 83 | ||
@@ -80,6 +86,7 @@ int open(char* pathname, int flags) | |||
80 | while ((entry = readdir(dir))) { | 86 | while ((entry = readdir(dir))) { |
81 | if ( !strncmp(name, entry->d_name, namelen) ) { | 87 | if ( !strncmp(name, entry->d_name, namelen) ) { |
82 | fat_open(entry->startcluster, &(openfiles[fd].fatfile)); | 88 | fat_open(entry->startcluster, &(openfiles[fd].fatfile)); |
89 | openfiles[fd].size = entry->size; | ||
83 | break; | 90 | break; |
84 | } | 91 | } |
85 | else { | 92 | else { |
@@ -89,11 +96,12 @@ int open(char* pathname, int flags) | |||
89 | closedir(dir); | 96 | closedir(dir); |
90 | if ( !entry ) { | 97 | if ( !entry ) { |
91 | DEBUGF("Couldn't find %s in %s\n",name,pathname); | 98 | DEBUGF("Couldn't find %s in %s\n",name,pathname); |
92 | /* fixme: we need to use proper error codes */ | 99 | errno = ENOENT; |
93 | return -1; | 100 | return -1; |
94 | } | 101 | } |
95 | 102 | ||
96 | openfiles[fd].offset = 0; | 103 | openfiles[fd].cacheoffset = 0; |
104 | openfiles[fd].fileoffset = 0; | ||
97 | openfiles[fd].busy = TRUE; | 105 | openfiles[fd].busy = TRUE; |
98 | return fd; | 106 | return fd; |
99 | } | 107 | } |
@@ -109,57 +117,81 @@ int read(int fd, void* buf, int count) | |||
109 | int sectors; | 117 | int sectors; |
110 | int nread=0; | 118 | int nread=0; |
111 | 119 | ||
112 | /* are we in the middle of a cached sector? */ | 120 | if ( !openfiles[fd].busy ) { |
113 | if ( openfiles[fd].offset ) { | 121 | errno = EBADF; |
114 | if ( count > (SECTOR_SIZE - openfiles[fd].offset) ) { | 122 | return -1; |
115 | memcpy( buf, openfiles[fd].sector, | 123 | } |
116 | SECTOR_SIZE - openfiles[fd].offset ); | 124 | |
117 | openfiles[fd].offset = 0; | 125 | /* attempt to read past EOF? */ |
118 | nread = SECTOR_SIZE - openfiles[fd].offset; | 126 | if ( count > openfiles[fd].size - openfiles[fd].fileoffset ) |
119 | count -= nread; | 127 | count = openfiles[fd].size - openfiles[fd].fileoffset; |
128 | |||
129 | /* any head bytes? */ | ||
130 | if ( openfiles[fd].cacheoffset ) { | ||
131 | int headbytes; | ||
132 | int offs = openfiles[fd].cacheoffset; | ||
133 | if ( count <= SECTOR_SIZE - openfiles[fd].cacheoffset ) { | ||
134 | headbytes = count; | ||
135 | openfiles[fd].cacheoffset += count; | ||
136 | if ( openfiles[fd].cacheoffset >= SECTOR_SIZE ) | ||
137 | openfiles[fd].cacheoffset = 0; | ||
120 | } | 138 | } |
121 | else { | 139 | else { |
122 | memcpy( buf, openfiles[fd].sector, count ); | 140 | headbytes = SECTOR_SIZE - openfiles[fd].cacheoffset; |
123 | openfiles[fd].offset += count; | 141 | openfiles[fd].cacheoffset = 0; |
124 | nread = count; | ||
125 | count = 0; | ||
126 | } | 142 | } |
143 | |||
144 | /* eof? */ | ||
145 | if ( openfiles[fd].fileoffset + headbytes > openfiles[fd].size ) | ||
146 | headbytes = openfiles[fd].size - openfiles[fd].fileoffset; | ||
147 | |||
148 | memcpy( buf, openfiles[fd].cache + offs, headbytes ); | ||
149 | nread = headbytes; | ||
150 | count -= headbytes; | ||
127 | } | 151 | } |
128 | 152 | ||
129 | /* read whole sectors right into the supplied buffer */ | 153 | /* read whole sectors right into the supplied buffer */ |
130 | sectors = count / SECTOR_SIZE; | 154 | sectors = count / SECTOR_SIZE; |
131 | if ( sectors ) { | 155 | if ( sectors ) { |
132 | if ( fat_read(&(openfiles[fd].fatfile), sectors, buf+nread ) < 0 ) { | 156 | int rc = fat_read(&(openfiles[fd].fatfile), sectors, buf+nread ); |
157 | if ( rc < 0 ) { | ||
133 | DEBUGF("Failed reading %d sectors\n",sectors); | 158 | DEBUGF("Failed reading %d sectors\n",sectors); |
159 | errno = EIO; | ||
134 | return -1; | 160 | return -1; |
135 | } | 161 | } |
136 | nread += sectors * SECTOR_SIZE; | 162 | else { |
137 | count -= sectors * SECTOR_SIZE; | 163 | if ( rc > 0 ) { |
138 | openfiles[fd].offset = 0; | 164 | nread += sectors * SECTOR_SIZE; |
165 | count -= sectors * SECTOR_SIZE; | ||
166 | } | ||
167 | else { | ||
168 | /* eof */ | ||
169 | count=0; | ||
170 | } | ||
171 | |||
172 | openfiles[fd].cacheoffset = 0; | ||
173 | } | ||
139 | } | 174 | } |
140 | 175 | ||
141 | /* trailing odd bytes? */ | 176 | /* any tail bytes? */ |
142 | if ( count ) { | 177 | if ( count ) { |
143 | /* do we already have the sector cached? */ | 178 | if ( fat_read(&(openfiles[fd].fatfile), 1, |
144 | if ( count < (SECTOR_SIZE - openfiles[fd].offset) ) { | 179 | &(openfiles[fd].cache)) < 0 ) { |
145 | memcpy( buf + nread, openfiles[fd].sector, count ); | 180 | DEBUGF("Failed caching sector\n"); |
146 | openfiles[fd].offset += count; | 181 | errno = EIO; |
147 | nread += count; | 182 | return -1; |
148 | count = 0; | ||
149 | } | ||
150 | else { | ||
151 | /* cache one sector and copy the trailing bytes */ | ||
152 | if ( fat_read(&(openfiles[fd].fatfile), 1, | ||
153 | &(openfiles[fd].sector)) < 0 ) { | ||
154 | DEBUGF("Failed reading odd sector\n"); | ||
155 | return -1; | ||
156 | } | ||
157 | memcpy( buf + nread, openfiles[fd].sector, count ); | ||
158 | openfiles[fd].offset = nread; | ||
159 | nread += count; | ||
160 | } | 183 | } |
184 | |||
185 | /* eof? */ | ||
186 | if ( openfiles[fd].fileoffset + count > openfiles[fd].size ) | ||
187 | count = openfiles[fd].size - openfiles[fd].fileoffset; | ||
188 | |||
189 | memcpy( buf + nread, openfiles[fd].cache, count ); | ||
190 | nread += count; | ||
191 | openfiles[fd].cacheoffset = count; | ||
161 | } | 192 | } |
162 | 193 | ||
194 | openfiles[fd].fileoffset += nread; | ||
163 | return nread; | 195 | return nread; |
164 | } | 196 | } |
165 | 197 | ||