diff options
author | Benoît Thébaudeau <benoit@wsystem.com> | 2015-09-28 15:45:32 +0200 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2015-10-11 17:12:08 -0400 |
commit | 1254b44a9f31c78ce7325eb392eaa949a2c7fc9a (patch) | |
tree | c02399fd3ce118719e0f209234747b82509102d3 /fs | |
parent | e876be4b5ccb661d68b5b83330e134ace339316c (diff) | |
download | u-boot-imx-1254b44a9f31c78ce7325eb392eaa949a2c7fc9a.zip u-boot-imx-1254b44a9f31c78ce7325eb392eaa949a2c7fc9a.tar.gz u-boot-imx-1254b44a9f31c78ce7325eb392eaa949a2c7fc9a.tar.bz2 |
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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fat/fat_write.c | 85 |
1 files changed, 64 insertions, 21 deletions
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index 2d032ee..af828d0 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -710,6 +710,14 @@ set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, debug("%llu bytes\n", filesize); + if (!curclust) { + if (filesize) { + debug("error: nonempty clusterless file!\n"); + return -1; + } + return 0; + } + actsize = bytesperclust; endclust = curclust; do { @@ -765,15 +773,24 @@ getit: } /* - * Fill dir_entry + * Set start cluster in directory entry */ -static void fill_dentry(fsdata *mydata, dir_entry *dentptr, - const char *filename, __u32 start_cluster, __u32 size, __u8 attr) +static void set_start_cluster(const fsdata *mydata, dir_entry *dentptr, + __u32 start_cluster) { if (mydata->fatsize == 32) dentptr->starthi = cpu_to_le16((start_cluster & 0xffff0000) >> 16); 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->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); start_cluster = START(retdent); - ret = check_overflow(mydata, start_cluster, size); - if (ret) { - printf("Error: %llu overflow\n", size); - goto exit; - } + if (start_cluster) { + if (size) { + ret = check_overflow(mydata, start_cluster, + size); + if (ret) { + printf("Error: %llu overflow\n", size); + goto exit; + } + } + + ret = clear_fatent(mydata, start_cluster); + if (ret) { + printf("Error: clearing FAT entries\n"); + goto exit; + } - ret = clear_fatent(mydata, start_cluster); - if (ret) { - printf("Error: clearing FAT entries\n"); - 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 { /* Set short name to set alias checksum field in dir_slot */ set_name(empty_dentptr, filename); fill_dir_slot(mydata, &empty_dentptr, filename); - ret = start_cluster = find_empty_cluster(mydata); - if (ret < 0) { - printf("Error: finding empty cluster\n"); - goto exit; - } + 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; + ret = check_overflow(mydata, start_cluster, size); + if (ret) { + printf("Error: %llu overflow\n", size); + goto exit; + } + } else { + start_cluster = 0; } /* Set attribute as archieve for regular file */ |