diff options
Diffstat (limited to 'firmware/drivers/fat.c')
-rw-r--r-- | firmware/drivers/fat.c | 88 |
1 files changed, 73 insertions, 15 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 02d472ceeb..55e6fa30cf 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -811,7 +811,8 @@ static int write_long_name(struct fat_file* file, | |||
811 | unsigned int firstentry, | 811 | unsigned int firstentry, |
812 | unsigned int numentries, | 812 | unsigned int numentries, |
813 | unsigned char* name, | 813 | unsigned char* name, |
814 | unsigned char* shortname) | 814 | unsigned char* shortname, |
815 | bool is_directory) | ||
815 | { | 816 | { |
816 | unsigned char buf[SECTOR_SIZE]; | 817 | unsigned char buf[SECTOR_SIZE]; |
817 | unsigned char* entry; | 818 | unsigned char* entry; |
@@ -918,7 +919,7 @@ static int write_long_name(struct fat_file* file, | |||
918 | unsigned short date=0, time=0, tenth=0; | 919 | unsigned short date=0, time=0, tenth=0; |
919 | LDEBUGF("Shortname entry: %.13s\n", shortname); | 920 | LDEBUGF("Shortname entry: %.13s\n", shortname); |
920 | strncpy(entry + FATDIR_NAME, shortname, 11); | 921 | strncpy(entry + FATDIR_NAME, shortname, 11); |
921 | entry[FATDIR_ATTR] = 0; | 922 | entry[FATDIR_ATTR] = is_directory?FAT_ATTR_DIRECTORY:0; |
922 | entry[FATDIR_NTRES] = 0; | 923 | entry[FATDIR_NTRES] = 0; |
923 | 924 | ||
924 | fat_time(&date, &time, &tenth); | 925 | fat_time(&date, &time, &tenth); |
@@ -947,7 +948,9 @@ static int write_long_name(struct fat_file* file, | |||
947 | 948 | ||
948 | static int add_dir_entry(struct fat_dir* dir, | 949 | static int add_dir_entry(struct fat_dir* dir, |
949 | struct fat_file* file, | 950 | struct fat_file* file, |
950 | char* name) | 951 | char* name, |
952 | bool is_directory, | ||
953 | bool dotdir) | ||
951 | { | 954 | { |
952 | unsigned char buf[SECTOR_SIZE]; | 955 | unsigned char buf[SECTOR_SIZE]; |
953 | unsigned char shortname[16]; | 956 | unsigned char shortname[16]; |
@@ -963,16 +966,26 @@ static int add_dir_entry(struct fat_dir* dir, | |||
963 | LDEBUGF( "add_dir_entry(%s,%x)\n", | 966 | LDEBUGF( "add_dir_entry(%s,%x)\n", |
964 | name, file->firstcluster); | 967 | name, file->firstcluster); |
965 | 968 | ||
966 | /* create dos name */ | 969 | /* The "." and ".." directory entries must not be long names */ |
967 | rc = create_dos_name(name, shortname); | 970 | if(dotdir) { |
968 | if (rc < 0) | 971 | int i; |
969 | return rc * 10 - 0; | 972 | strncpy(shortname, name, 16); |
973 | for(i = strlen(shortname);i < 12;i++) | ||
974 | shortname[i] = ' '; | ||
975 | |||
976 | entries_needed = 1; | ||
977 | } else { | ||
978 | /* create dos name */ | ||
979 | rc = create_dos_name(name, shortname); | ||
980 | if (rc < 0) | ||
981 | return rc * 10 - 0; | ||
970 | 982 | ||
971 | /* one dir entry needed for every 13 bytes of filename, | 983 | /* one dir entry needed for every 13 bytes of filename, |
972 | plus one entry for the short name */ | 984 | plus one entry for the short name */ |
973 | entries_needed = namelen / NAME_BYTES_PER_ENTRY + 1; | 985 | entries_needed = namelen / NAME_BYTES_PER_ENTRY + 1; |
974 | if (namelen % NAME_BYTES_PER_ENTRY) | 986 | if (namelen % NAME_BYTES_PER_ENTRY) |
975 | entries_needed++; | 987 | entries_needed++; |
988 | } | ||
976 | 989 | ||
977 | restart: | 990 | restart: |
978 | firstentry = 0; | 991 | firstentry = 0; |
@@ -1065,7 +1078,7 @@ static int add_dir_entry(struct fat_dir* dir, | |||
1065 | firstentry, sector); | 1078 | firstentry, sector); |
1066 | 1079 | ||
1067 | rc = write_long_name(&dir->file, firstentry, | 1080 | rc = write_long_name(&dir->file, firstentry, |
1068 | entries_needed, name, shortname); | 1081 | entries_needed, name, shortname, is_directory); |
1069 | if (rc < 0) | 1082 | if (rc < 0) |
1070 | return rc * 10 - 5; | 1083 | return rc * 10 - 5; |
1071 | 1084 | ||
@@ -1304,7 +1317,7 @@ int fat_create_file(char* name, | |||
1304 | int rc; | 1317 | int rc; |
1305 | 1318 | ||
1306 | LDEBUGF("fat_create_file(\"%s\",%x,%x)\n",name,file,dir); | 1319 | LDEBUGF("fat_create_file(\"%s\",%x,%x)\n",name,file,dir); |
1307 | rc = add_dir_entry(dir, file, name); | 1320 | rc = add_dir_entry(dir, file, name, false, false); |
1308 | if (!rc) { | 1321 | if (!rc) { |
1309 | file->firstcluster = 0; | 1322 | file->firstcluster = 0; |
1310 | file->lastcluster = 0; | 1323 | file->lastcluster = 0; |
@@ -1317,6 +1330,51 @@ int fat_create_file(char* name, | |||
1317 | return rc; | 1330 | return rc; |
1318 | } | 1331 | } |
1319 | 1332 | ||
1333 | int fat_create_dir(char* name, | ||
1334 | struct fat_dir* newdir, | ||
1335 | struct fat_dir* dir) | ||
1336 | { | ||
1337 | int rc; | ||
1338 | struct fat_file dummyfile; | ||
1339 | |||
1340 | LDEBUGF("fat_create_dir(\"%s\",%x,%x)\n",name,newdir,dir); | ||
1341 | |||
1342 | memset(newdir, sizeof(struct fat_dir), 0); | ||
1343 | |||
1344 | /* First, add the entry in the parent directory */ | ||
1345 | rc = add_dir_entry(dir, &newdir->file, name, true, false); | ||
1346 | if (rc < 0) | ||
1347 | return rc * 10 - 1; | ||
1348 | |||
1349 | /* Then add the "." entry */ | ||
1350 | rc = add_dir_entry(newdir, &dummyfile, ".", true, true); | ||
1351 | if (rc < 0) | ||
1352 | return rc * 10 - 2; | ||
1353 | dummyfile.firstcluster = newdir->file.firstcluster; | ||
1354 | update_short_entry(&dummyfile, 0, FAT_ATTR_DIRECTORY); | ||
1355 | |||
1356 | /* and the ".." entry */ | ||
1357 | rc = add_dir_entry(newdir, &dummyfile, "..", true, true); | ||
1358 | if (rc < 0) | ||
1359 | return rc * 10 - 3; | ||
1360 | |||
1361 | /* The root cluster is cluster 0 in the ".." entry */ | ||
1362 | if(dir->file.firstcluster == fat_bpb.bpb_rootclus) | ||
1363 | dummyfile.firstcluster = 0; | ||
1364 | else | ||
1365 | dummyfile.firstcluster = dir->file.firstcluster; | ||
1366 | update_short_entry(&dummyfile, 0, FAT_ATTR_DIRECTORY); | ||
1367 | |||
1368 | /* Set the firstcluster field in the direntry */ | ||
1369 | update_short_entry(&newdir->file, 0, FAT_ATTR_DIRECTORY); | ||
1370 | |||
1371 | rc = flush_fat(); | ||
1372 | if (rc < 0) | ||
1373 | return rc * 10 - 4; | ||
1374 | |||
1375 | return rc; | ||
1376 | } | ||
1377 | |||
1320 | int fat_truncate(struct fat_file *file) | 1378 | int fat_truncate(struct fat_file *file) |
1321 | { | 1379 | { |
1322 | /* truncate trailing clusters */ | 1380 | /* truncate trailing clusters */ |
@@ -1487,7 +1545,7 @@ int fat_rename(struct fat_file* file, | |||
1487 | return rc * 10 - 2; | 1545 | return rc * 10 - 2; |
1488 | 1546 | ||
1489 | /* create new name */ | 1547 | /* create new name */ |
1490 | rc = add_dir_entry(&dir, &newfile, newname); | 1548 | rc = add_dir_entry(&dir, &newfile, newname, false, false); |
1491 | if (rc < 0) | 1549 | if (rc < 0) |
1492 | return rc * 10 - 3; | 1550 | return rc * 10 - 3; |
1493 | 1551 | ||