summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/fat.c159
-rw-r--r--firmware/drivers/fat.h3
2 files changed, 109 insertions, 53 deletions
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);