diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/common/file.c | 57 | ||||
-rw-r--r-- | firmware/common/file.h | 2 | ||||
-rw-r--r-- | firmware/drivers/fat.c | 159 | ||||
-rw-r--r-- | firmware/drivers/fat.h | 3 |
4 files changed, 163 insertions, 58 deletions
diff --git a/firmware/common/file.c b/firmware/common/file.c index 01a0ebf890..1d78dcb456 100644 --- a/firmware/common/file.c +++ b/firmware/common/file.c | |||
@@ -125,7 +125,7 @@ int open(const char* pathname, int flags) | |||
125 | break; | 125 | break; |
126 | } | 126 | } |
127 | } | 127 | } |
128 | closedir(dir); | 128 | |
129 | if ( !entry ) { | 129 | if ( !entry ) { |
130 | LDEBUGF("Didn't find file %s\n",name); | 130 | LDEBUGF("Didn't find file %s\n",name); |
131 | if ( file->write && (flags & O_CREAT) ) { | 131 | if ( file->write && (flags & O_CREAT) ) { |
@@ -135,6 +135,7 @@ int open(const char* pathname, int flags) | |||
135 | DEBUGF("Couldn't create %s in %s\n",name,pathname); | 135 | DEBUGF("Couldn't create %s in %s\n",name,pathname); |
136 | errno = EIO; | 136 | errno = EIO; |
137 | file->busy = false; | 137 | file->busy = false; |
138 | closedir(dir); | ||
138 | return -5; | 139 | return -5; |
139 | } | 140 | } |
140 | file->size = 0; | 141 | file->size = 0; |
@@ -143,9 +144,11 @@ int open(const char* pathname, int flags) | |||
143 | DEBUGF("Couldn't find %s in %s\n",name,pathname); | 144 | DEBUGF("Couldn't find %s in %s\n",name,pathname); |
144 | errno = ENOENT; | 145 | errno = ENOENT; |
145 | file->busy = false; | 146 | file->busy = false; |
147 | closedir(dir); | ||
146 | return -6; | 148 | return -6; |
147 | } | 149 | } |
148 | } | 150 | } |
151 | closedir(dir); | ||
149 | 152 | ||
150 | file->cacheoffset = -1; | 153 | file->cacheoffset = -1; |
151 | file->fileoffset = 0; | 154 | file->fileoffset = 0; |
@@ -205,23 +208,69 @@ int remove(const char* name) | |||
205 | file = &openfiles[fd]; | 208 | file = &openfiles[fd]; |
206 | rc = fat_truncate(&(file->fatfile)); | 209 | rc = fat_truncate(&(file->fatfile)); |
207 | if ( rc < 0 ) { | 210 | if ( rc < 0 ) { |
208 | DEBUGF("Failed truncating file\n"); | 211 | DEBUGF("Failed truncating file: %d\n", rc); |
209 | errno = EIO; | 212 | errno = EIO; |
210 | return -1; | 213 | return -1; |
211 | } | 214 | } |
212 | 215 | ||
213 | rc = fat_remove(&(file->fatfile)); | 216 | rc = fat_remove(&(file->fatfile)); |
214 | if ( rc < 0 ) { | 217 | if ( rc < 0 ) { |
215 | DEBUGF("Failed removing file\n"); | 218 | DEBUGF("Failed removing file: %d\n", rc); |
216 | errno = EIO; | 219 | errno = EIO; |
217 | return -2; | 220 | return -2; |
218 | } | 221 | } |
219 | 222 | ||
220 | file->size = 0; | 223 | file->size = 0; |
221 | 224 | ||
225 | rc = close(fd); | ||
226 | if (rc<0) | ||
227 | return -3; | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | int rename(const char* path, const char* newpath) | ||
233 | { | ||
234 | int rc, fd; | ||
235 | char* nameptr; | ||
236 | struct filedesc* file; | ||
237 | |||
238 | /* verify new path does not already exist */ | ||
239 | fd = open(newpath, O_RDONLY); | ||
240 | if ( fd >= 0 ) { | ||
241 | errno = EBUSY; | ||
242 | return fd; | ||
243 | } | ||
222 | close(fd); | 244 | close(fd); |
223 | 245 | ||
224 | return rc; | 246 | fd = open(path, O_RDONLY); |
247 | if ( fd < 0 ) { | ||
248 | errno = EIO; | ||
249 | return fd; | ||
250 | } | ||
251 | |||
252 | /* strip path */ | ||
253 | nameptr = strrchr(newpath,'/'); | ||
254 | if (nameptr) | ||
255 | nameptr++; | ||
256 | else | ||
257 | nameptr = (char*)newpath; | ||
258 | |||
259 | file = &openfiles[fd]; | ||
260 | rc = fat_rename(&file->fatfile, nameptr, file->size); | ||
261 | if ( rc < 0 ) { | ||
262 | DEBUGF("Failed renaming file: %d\n", rc); | ||
263 | errno = EIO; | ||
264 | return -1; | ||
265 | } | ||
266 | |||
267 | rc = close(fd); | ||
268 | if (rc<0) { | ||
269 | errno = EIO; | ||
270 | return -2; | ||
271 | } | ||
272 | |||
273 | return 0; | ||
225 | } | 274 | } |
226 | 275 | ||
227 | int ftruncate(int fd, unsigned int size) | 276 | int ftruncate(int fd, unsigned int size) |
diff --git a/firmware/common/file.h b/firmware/common/file.h index bf7ad82ff7..bf8dc38ae9 100644 --- a/firmware/common/file.h +++ b/firmware/common/file.h | |||
@@ -58,7 +58,7 @@ extern int lseek(int fd, int offset, int whence); | |||
58 | extern int creat(const char *pathname, int mode); | 58 | extern int creat(const char *pathname, int mode); |
59 | extern int write(int fd, void* buf, int count); | 59 | extern int write(int fd, void* buf, int count); |
60 | extern int remove(const char* pathname); | 60 | extern int remove(const char* pathname); |
61 | extern int rename(const char* oldname, const char* newname); | 61 | extern int rename(const char* path, const char* newname); |
62 | extern int ftruncate(int fd, unsigned int size); | 62 | extern int ftruncate(int fd, unsigned int size); |
63 | 63 | ||
64 | #else | 64 | #else |
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 2ff36e2595..b6bedc1d26 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -1175,6 +1175,68 @@ int fat_closewrite(struct fat_file *file, int size) | |||
1175 | return 0; | 1175 | return 0; |
1176 | } | 1176 | } |
1177 | 1177 | ||
1178 | static int free_direntries(int dircluster, int startentry, int numentries) | ||
1179 | { | ||
1180 | unsigned char buf[SECTOR_SIZE]; | ||
1181 | struct fat_file dir; | ||
1182 | unsigned int entry = startentry - numentries + 1; | ||
1183 | unsigned int sector = entry / DIR_ENTRIES_PER_SECTOR; | ||
1184 | int i; | ||
1185 | int err; | ||
1186 | |||
1187 | /* create a temporary file handle for the dir holding this file */ | ||
1188 | err = fat_open(dircluster, &dir, NULL); | ||
1189 | if (err<0) | ||
1190 | return -1; | ||
1191 | |||
1192 | err = fat_seek( &dir, sector ); | ||
1193 | if (err<0) | ||
1194 | return -2; | ||
1195 | |||
1196 | err = fat_readwrite(&dir, 1, buf, false); | ||
1197 | if (err<1) | ||
1198 | return -3; | ||
1199 | |||
1200 | for (i=0; i < numentries; i++) { | ||
1201 | LDEBUGF("Clearing dir entry %d (%d/%d)\n", | ||
1202 | entry, i+1, numentries); | ||
1203 | buf[(entry % DIR_ENTRIES_PER_SECTOR) * DIR_ENTRY_SIZE] = 0xe5; | ||
1204 | entry++; | ||
1205 | |||
1206 | if ( (entry % DIR_ENTRIES_PER_SECTOR) == 0 ) { | ||
1207 | /* flush this sector */ | ||
1208 | err = fat_seek(&dir, sector); | ||
1209 | if (err<0) | ||
1210 | return -4; | ||
1211 | |||
1212 | err = fat_readwrite(&dir, 1, buf, true); | ||
1213 | if (err<1) | ||
1214 | return -5; | ||
1215 | |||
1216 | if ( i+1 < numentries ) { | ||
1217 | /* read next sector */ | ||
1218 | err = fat_readwrite(&dir, 1, buf, false); | ||
1219 | if (err<1) | ||
1220 | return -6; | ||
1221 | } | ||
1222 | sector++; | ||
1223 | } | ||
1224 | } | ||
1225 | |||
1226 | if ( entry % DIR_ENTRIES_PER_SECTOR ) { | ||
1227 | /* flush this sector */ | ||
1228 | err = fat_seek(&dir, sector); | ||
1229 | if (err<0) | ||
1230 | return -7; | ||
1231 | |||
1232 | err = fat_readwrite(&dir, 1, buf, true); | ||
1233 | if (err<1) | ||
1234 | return -8; | ||
1235 | } | ||
1236 | |||
1237 | return 0; | ||
1238 | } | ||
1239 | |||
1178 | int fat_remove(struct fat_file* file) | 1240 | int fat_remove(struct fat_file* file) |
1179 | { | 1241 | { |
1180 | int next, last = file->firstcluster; | 1242 | int next, last = file->firstcluster; |
@@ -1187,68 +1249,59 @@ int fat_remove(struct fat_file* file) | |||
1187 | last = next; | 1249 | last = next; |
1188 | } | 1250 | } |
1189 | 1251 | ||
1190 | /* free all dir entries */ | 1252 | if ( file->dircluster ) |
1191 | if ( file->dircluster ) { | 1253 | if ( free_direntries(file->dircluster, |
1192 | unsigned char buf[SECTOR_SIZE]; | 1254 | file->direntry, |
1193 | struct fat_file dir; | 1255 | file->direntries) < 0 ) |
1194 | unsigned int entry = file->direntry - file->direntries + 1; | ||
1195 | unsigned int sector = entry / DIR_ENTRIES_PER_SECTOR; | ||
1196 | unsigned int i; | ||
1197 | int err; | ||
1198 | |||
1199 | /* create a temporary file handle for the dir holding this file */ | ||
1200 | err = fat_open(file->dircluster, &dir, NULL); | ||
1201 | if (err<0) | ||
1202 | return -1; | 1256 | return -1; |
1203 | 1257 | ||
1204 | err = fat_seek( &dir, sector ); | 1258 | file->firstcluster = 0; |
1205 | if (err<0) | 1259 | file->dircluster = 0; |
1206 | return -2; | ||
1207 | 1260 | ||
1208 | err = fat_readwrite(&dir, 1, buf, false); | 1261 | return 0; |
1209 | if (err<1) | 1262 | } |
1210 | return -3; | ||
1211 | 1263 | ||
1212 | for (i=0; i < file->direntries; i++) { | 1264 | int fat_rename(struct fat_file* file, |
1213 | LDEBUGF("Clearing dir entry %d (%d/%d)\n", | 1265 | unsigned char* newname, |
1214 | entry, i+1, file->direntries); | 1266 | int size) |
1215 | buf[(entry % DIR_ENTRIES_PER_SECTOR) * DIR_ENTRY_SIZE] = 0xe5; | 1267 | { |
1216 | entry++; | 1268 | int err; |
1269 | struct fat_dir dir; | ||
1270 | struct fat_file newfile = *file; | ||
1217 | 1271 | ||
1218 | if ( (entry % DIR_ENTRIES_PER_SECTOR) == 0 ) { | 1272 | if ( !file->dircluster ) { |
1219 | /* flush this sector */ | 1273 | LDEBUGF("File has no dir cluster!\n"); |
1220 | err = fat_seek(&dir, sector); | 1274 | return -1; |
1221 | if (err<0) | 1275 | } |
1222 | return -4; | ||
1223 | 1276 | ||
1224 | err = fat_readwrite(&dir, 1, buf, true); | 1277 | /* create a temporary file handle */ |
1225 | if (err<1) | 1278 | LDEBUGF("create a temporary file handle: fat_opendir(%x,%x)\n", |
1226 | return -5; | 1279 | &dir, file->dircluster); |
1280 | err = fat_opendir(&dir, file->dircluster); | ||
1281 | if (err<0) | ||
1282 | return -2; | ||
1227 | 1283 | ||
1228 | if ( i+1 < file->direntries ) { | 1284 | /* create new name */ |
1229 | /* read next sector */ | 1285 | LDEBUGF("create new name\n"); |
1230 | err = fat_readwrite(&dir, 1, buf, false); | 1286 | err = add_dir_entry(&dir, &newfile, newname); |
1231 | if (err<1) | 1287 | if (err<0) |
1232 | return -6; | 1288 | return -3; |
1233 | } | ||
1234 | sector++; | ||
1235 | } | ||
1236 | } | ||
1237 | 1289 | ||
1238 | if ( entry % DIR_ENTRIES_PER_SECTOR ) { | 1290 | /* write size and cluster link */ |
1239 | /* flush this sector */ | 1291 | LDEBUGF("write size and cluster link\n"); |
1240 | err = fat_seek(&dir, sector); | 1292 | err = update_file_size(&newfile, size); |
1241 | if (err<0) | 1293 | if (err<0) |
1242 | return -7; | 1294 | return -4; |
1243 | |||
1244 | err = fat_readwrite(&dir, 1, buf, true); | ||
1245 | if (err<1) | ||
1246 | return -8; | ||
1247 | } | ||
1248 | } | ||
1249 | 1295 | ||
1250 | file->firstcluster = 0; | 1296 | /* remove old name */ |
1251 | file->dircluster = 0; | 1297 | LDEBUGF("remove old name\n"); |
1298 | err = free_direntries(file->dircluster, file->direntry, file->direntries); | ||
1299 | if (err<0) | ||
1300 | return -5; | ||
1301 | |||
1302 | err = flush_fat(); | ||
1303 | if (err<0) | ||
1304 | return -6; | ||
1252 | 1305 | ||
1253 | return 0; | 1306 | return 0; |
1254 | } | 1307 | } |
diff --git a/firmware/drivers/fat.h b/firmware/drivers/fat.h index a5abfd5214..d81ec65363 100644 --- a/firmware/drivers/fat.h +++ b/firmware/drivers/fat.h | |||
@@ -84,6 +84,9 @@ extern int fat_closewrite(struct fat_file *ent, int size); | |||
84 | extern int fat_seek(struct fat_file *ent, unsigned int sector ); | 84 | extern int fat_seek(struct fat_file *ent, unsigned int sector ); |
85 | extern int fat_remove(struct fat_file *ent); | 85 | extern int fat_remove(struct fat_file *ent); |
86 | extern int fat_truncate(struct fat_file *ent); | 86 | extern int fat_truncate(struct fat_file *ent); |
87 | extern int fat_rename(struct fat_file* file, | ||
88 | unsigned char* newname, | ||
89 | int size); | ||
87 | 90 | ||
88 | extern int fat_opendir(struct fat_dir *ent, unsigned int currdir); | 91 | extern int fat_opendir(struct fat_dir *ent, unsigned int currdir); |
89 | extern int fat_getnext(struct fat_dir *ent, struct fat_direntry *entry); | 92 | extern int fat_getnext(struct fat_dir *ent, struct fat_direntry *entry); |