mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-09-28 23:50:26 +09:00
fs/fat/fat_write: Fix management of empty files
Overwriting an empty file not created by U-Boot did not work, and it could even corrupt the FAT. Moreover, creating empty files or emptying existing files allocated a cluster, which is not standard. Fix this by always keeping empty files clusterless as specified by Microsoft (the start cluster must be set to 0 in the directory entry in that case), and by supporting overwriting such files. Signed-off-by: Benoît Thébaudeau <benoit@wsystem.com>
This commit is contained in:
parent
e876be4b5c
commit
1254b44a9f
@ -710,6 +710,14 @@ set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
|
|||||||
|
|
||||||
debug("%llu bytes\n", filesize);
|
debug("%llu bytes\n", filesize);
|
||||||
|
|
||||||
|
if (!curclust) {
|
||||||
|
if (filesize) {
|
||||||
|
debug("error: nonempty clusterless file!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
actsize = bytesperclust;
|
actsize = bytesperclust;
|
||||||
endclust = curclust;
|
endclust = curclust;
|
||||||
do {
|
do {
|
||||||
@ -765,15 +773,24 @@ getit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill dir_entry
|
* Set start cluster in directory entry
|
||||||
*/
|
*/
|
||||||
static void fill_dentry(fsdata *mydata, dir_entry *dentptr,
|
static void set_start_cluster(const fsdata *mydata, dir_entry *dentptr,
|
||||||
const char *filename, __u32 start_cluster, __u32 size, __u8 attr)
|
__u32 start_cluster)
|
||||||
{
|
{
|
||||||
if (mydata->fatsize == 32)
|
if (mydata->fatsize == 32)
|
||||||
dentptr->starthi =
|
dentptr->starthi =
|
||||||
cpu_to_le16((start_cluster & 0xffff0000) >> 16);
|
cpu_to_le16((start_cluster & 0xffff0000) >> 16);
|
||||||
dentptr->start = cpu_to_le16(start_cluster & 0xffff);
|
dentptr->start = cpu_to_le16(start_cluster & 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill dir_entry
|
||||||
|
*/
|
||||||
|
static void fill_dentry(fsdata *mydata, dir_entry *dentptr,
|
||||||
|
const char *filename, __u32 start_cluster, __u32 size, __u8 attr)
|
||||||
|
{
|
||||||
|
set_start_cluster(mydata, dentptr, start_cluster);
|
||||||
dentptr->size = cpu_to_le32(size);
|
dentptr->size = cpu_to_le32(size);
|
||||||
|
|
||||||
dentptr->attr = attr;
|
dentptr->attr = attr;
|
||||||
@ -1030,32 +1047,58 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size,
|
|||||||
retdent->size = cpu_to_le32(size);
|
retdent->size = cpu_to_le32(size);
|
||||||
start_cluster = START(retdent);
|
start_cluster = START(retdent);
|
||||||
|
|
||||||
ret = check_overflow(mydata, start_cluster, size);
|
if (start_cluster) {
|
||||||
if (ret) {
|
if (size) {
|
||||||
printf("Error: %llu overflow\n", size);
|
ret = check_overflow(mydata, start_cluster,
|
||||||
goto exit;
|
size);
|
||||||
}
|
if (ret) {
|
||||||
|
printf("Error: %llu overflow\n", size);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = clear_fatent(mydata, start_cluster);
|
ret = clear_fatent(mydata, start_cluster);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printf("Error: clearing FAT entries\n");
|
printf("Error: clearing FAT entries\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!size)
|
||||||
|
set_start_cluster(mydata, retdent, 0);
|
||||||
|
} else if (size) {
|
||||||
|
ret = start_cluster = find_empty_cluster(mydata);
|
||||||
|
if (ret < 0) {
|
||||||
|
printf("Error: finding empty cluster\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = check_overflow(mydata, start_cluster, size);
|
||||||
|
if (ret) {
|
||||||
|
printf("Error: %llu overflow\n", size);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_start_cluster(mydata, retdent, start_cluster);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Set short name to set alias checksum field in dir_slot */
|
/* Set short name to set alias checksum field in dir_slot */
|
||||||
set_name(empty_dentptr, filename);
|
set_name(empty_dentptr, filename);
|
||||||
fill_dir_slot(mydata, &empty_dentptr, filename);
|
fill_dir_slot(mydata, &empty_dentptr, filename);
|
||||||
|
|
||||||
ret = start_cluster = find_empty_cluster(mydata);
|
if (size) {
|
||||||
if (ret < 0) {
|
ret = start_cluster = find_empty_cluster(mydata);
|
||||||
printf("Error: finding empty cluster\n");
|
if (ret < 0) {
|
||||||
goto exit;
|
printf("Error: finding empty cluster\n");
|
||||||
}
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
ret = check_overflow(mydata, start_cluster, size);
|
ret = check_overflow(mydata, start_cluster, size);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printf("Error: %llu overflow\n", size);
|
printf("Error: %llu overflow\n", size);
|
||||||
goto exit;
|
goto exit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
start_cluster = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set attribute as archieve for regular file */
|
/* Set attribute as archieve for regular file */
|
||||||
|
Loading…
Reference in New Issue
Block a user