summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/common/file.c57
-rw-r--r--firmware/common/file.h2
-rw-r--r--firmware/drivers/fat.c159
-rw-r--r--firmware/drivers/fat.h3
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
232int 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
227int ftruncate(int fd, unsigned int size) 276int 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);
58extern int creat(const char *pathname, int mode); 58extern int creat(const char *pathname, int mode);
59extern int write(int fd, void* buf, int count); 59extern int write(int fd, void* buf, int count);
60extern int remove(const char* pathname); 60extern int remove(const char* pathname);
61extern int rename(const char* oldname, const char* newname); 61extern int rename(const char* path, const char* newname);
62extern int ftruncate(int fd, unsigned int size); 62extern 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
1178static 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
1178int fat_remove(struct fat_file* file) 1240int 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++) { 1264int 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);
84extern int fat_seek(struct fat_file *ent, unsigned int sector ); 84extern int fat_seek(struct fat_file *ent, unsigned int sector );
85extern int fat_remove(struct fat_file *ent); 85extern int fat_remove(struct fat_file *ent);
86extern int fat_truncate(struct fat_file *ent); 86extern int fat_truncate(struct fat_file *ent);
87extern int fat_rename(struct fat_file* file,
88 unsigned char* newname,
89 int size);
87 90
88extern int fat_opendir(struct fat_dir *ent, unsigned int currdir); 91extern int fat_opendir(struct fat_dir *ent, unsigned int currdir);
89extern int fat_getnext(struct fat_dir *ent, struct fat_direntry *entry); 92extern int fat_getnext(struct fat_dir *ent, struct fat_direntry *entry);