Re: [U-Boot] [PATCH 1/1] fs: fat: write with non-zero offset

This relates to a patch in https://git.linaro.org/people/takahiro.akashi/u-boot.git branch efi/for_sct.
On 06/13/2018 08:32 AM, AKASHI Takahiro wrote:
fs/fat/fat_write.c | 385 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 299 insertions(+), 86 deletions(-)
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index a930b66f28..7e63646655 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -445,6 +445,119 @@ set_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, return 0; }
+static __u8 tmpbuf_cluster[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN);
+/*
- Read and modify data on existing and consecutive cluster blocks
- */
+static int +get_set_cluster(fsdata *mydata, __u32 clustnum, loff_t pos, __u8 *buffer,
loff_t size, loff_t *gotsize)
+{
- unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
- __u32 startsect;
- loff_t wsize;
- int clustcount, i, ret;
- *gotsize = 0;
- if (!size)
return 0;
- assert(pos < bytesperclust);
- startsect = clust_to_sect(mydata, clustnum);
- debug("clustnum: %d, startsect: %d, pos: %lld\n", clustnum, startsect,
pos);
- /* partial write at begining */
- if (pos) {
wsize = min(bytesperclust - pos, size);
ret = disk_read(startsect, mydata->clust_size, tmpbuf_cluster);
if (ret != mydata->clust_size) {
debug("Error reading data (got %d)\n", ret);
return -1;
}
memcpy(tmpbuf_cluster + pos, buffer, wsize);
ret = disk_write(startsect, mydata->clust_size, tmpbuf_cluster);
if (ret != mydata->clust_size) {
debug("Error writing data (got %d)\n", ret);
return -1;
}
size -= wsize;
buffer += wsize;
*gotsize += wsize;
startsect += mydata->clust_size;
if (!size)
return 0;
- }
- /* full-cluster write */
- if (size >= bytesperclust) {
clustcount = size / bytesperclust;
Hello Takahiro,
the line above should read + clustcount = lldiv(size, bytesperclust);
Otherwise I get an error
undefined reference to `__divdi3'
with qemu_x86_defconfig and gcc 7.3.0.
Best regards
Heinrich
if (!((unsigned long)buffer & (ARCH_DMA_MINALIGN - 1))) {
wsize = clustcount * bytesperclust;
ret = disk_write(startsect,
clustcount * mydata->clust_size,
buffer);
if (ret != clustcount * mydata->clust_size) {
debug("Error writing data (got %d)\n", ret);
return -1;
}
size -= wsize;
buffer += wsize;
*gotsize += wsize;
startsect += clustcount * mydata->clust_size;
} else {
for (i = 0; i < clustcount; i++) {
memcpy(tmpbuf_cluster, buffer, bytesperclust);
ret = disk_write(startsect, mydata->clust_size,
tmpbuf_cluster);
if (ret != mydata->clust_size) {
debug("Error writing data (got %d)\n", ret);
return -1;
}
size -= bytesperclust;
buffer += bytesperclust;
*gotsize += bytesperclust;
startsect += mydata->clust_size;
}
}
- }
- /* partial write at end */
- if (size) {
wsize = size;
ret = disk_read(startsect, mydata->clust_size, tmpbuf_cluster);
if (ret != mydata->clust_size) {
debug("Error reading data (got %d)\n", ret);
return -1;
}
memcpy(tmpbuf_cluster, buffer, wsize);
ret = disk_write(startsect, mydata->clust_size, tmpbuf_cluster);
if (ret != mydata->clust_size) {
debug("Error writing data (got %d)\n", ret);
return -1;
}
size -= wsize;
buffer += wsize;
*gotsize += wsize;
- }
- assert(!size);
- return 0;
+}
/*
- Find the first empty cluster
*/ @@ -523,6 +636,18 @@ static int clear_fatent(fsdata *mydata, __u32 entry) return 0; }
+/*
- Set start cluster in directory entry
- */
+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);
+}
/*
- Write at most 'maxsize' bytes from 'buffer' into
- the file associated with 'dentptr'
@@ -530,31 +655,164 @@ static int clear_fatent(fsdata *mydata, __u32 entry)
- or return -1 on fatal errors.
*/ static int -set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, +set_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, __u8 *buffer, loff_t maxsize, loff_t *gotsize) {
- loff_t filesize = FAT2CPU32(dentptr->size);
- loff_t filesize; unsigned int bytesperclust = mydata->clust_size * mydata->sect_size; __u32 curclust = START(dentptr); __u32 endclust = 0, newclust = 0;
- loff_t actsize;
loff_t cur_pos, offset, actsize, wsize;
*gotsize = 0;
- debug("Filesize: %llu bytes\n", filesize);
- if (maxsize > 0 && filesize > maxsize)
filesize = maxsize;
filesize = pos + maxsize;
debug("%llu bytes\n", filesize);
if (!filesize) {
if (!curclust)
return 0;
if (!CHECK_CLUST(curclust, mydata->fatsize) ||
IS_LAST_CLUST(curclust, mydata->fatsize)) {
clear_fatent(mydata, curclust);
set_start_cluster(mydata, dentptr, 0);
return 0;
}
debug("curclust: 0x%x\n", curclust);
debug("Invalid FAT entry\n");
return -1;
}
if (!curclust) {
if (filesize) {
debug("error: nonempty clusterless file!\n");
assert(pos == 0);
goto set_clusters;
}
/* go to cluster at pos */
cur_pos = bytesperclust;
while (1) {
if (pos <= cur_pos)
break;
if (IS_LAST_CLUST(curclust, mydata->fatsize))
break;
newclust = get_fatent(mydata, curclust);
if (!IS_LAST_CLUST(newclust, mydata->fatsize) &&
CHECK_CLUST(newclust, mydata->fatsize)) {
debug("curclust: 0x%x\n", curclust);
debug("Invalid FAT entry\n"); return -1;
}
cur_pos += bytesperclust;
curclust = newclust;
}
if (IS_LAST_CLUST(curclust, mydata->fatsize)) {
assert(pos == cur_pos);
goto set_clusters;
}
assert(pos < cur_pos);
cur_pos -= bytesperclust;
/* overwrite */
assert(IS_LAST_CLUST(curclust, mydata->fatsize) ||
!CHECK_CLUST(curclust, mydata->fatsize));
while (1) {
/* search for allocated consecutive clusters */
actsize = bytesperclust;
endclust = curclust;
while (1) {
if (filesize <= (cur_pos + actsize))
break;
newclust = get_fatent(mydata, endclust);
if (IS_LAST_CLUST(newclust, mydata->fatsize))
break;
if (CHECK_CLUST(newclust, mydata->fatsize)) {
debug("curclust: 0x%x\n", curclust);
debug("Invalid FAT entry\n");
return -1;
}
actsize += bytesperclust;
endclust = newclust;
}
/* overwrite to <curclust..endclust> */
if (pos < cur_pos)
offset = 0;
else
offset = pos - cur_pos;
wsize = min(cur_pos + actsize, filesize) - pos;
if (get_set_cluster(mydata, curclust, offset, buffer, wsize,
&actsize)) {
printf("Error get-and-setting cluster\n");
return -1;
}
buffer += wsize;
*gotsize += wsize;
cur_pos += offset + wsize;
if (filesize <= cur_pos)
break;
/* CHECK: newclust = get_fatent(mydata, endclust); */
if (IS_LAST_CLUST(newclust, mydata->fatsize))
/* no more clusters */
break;
curclust = newclust;
}
if (filesize <= cur_pos) {
/* no more write */
newclust = get_fatent(mydata, endclust);
if (!IS_LAST_CLUST(newclust, mydata->fatsize)) {
/* truncate the rest */
clear_fatent(mydata, newclust);
/* Mark end of file in FAT */
if (mydata->fatsize == 12)
newclust = 0xfff;
else if (mydata->fatsize == 16)
newclust = 0xffff;
else if (mydata->fatsize == 32)
newclust = 0xfffffff;
set_fatent_value(mydata, endclust, newclust);
}
return 0; }
curclust = endclust;
filesize -= cur_pos;
assert (!(cur_pos % bytesperclust));
+set_clusters:
- /* allocate and write */
- assert(!pos);
- /* Assure that curclust is valid */
- if (!curclust) {
curclust = find_empty_cluster(mydata);
set_start_cluster(mydata, dentptr, curclust);
- } else {
newclust = get_fatent(mydata, curclust);
if (IS_LAST_CLUST(newclust, mydata->fatsize)) {
newclust = determine_fatent(mydata, curclust);
set_fatent_value(mydata, curclust, newclust);
curclust = newclust;
} else {
debug("error: something wrong\n");
return -1;
}
- }
- actsize = bytesperclust; endclust = curclust; do {
@@ -563,6 +821,7 @@ set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, newclust = determine_fatent(mydata, endclust);
if ((newclust - 1) != endclust)
/* write to <curclust..endclust> */ goto getit; if (CHECK_CLUST(newclust, mydata->fatsize)) {
@@ -609,18 +868,8 @@ getit: actsize = bytesperclust; curclust = endclust = newclust; } while (1); -}
-/*
- Set start cluster in directory entry
- */
-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);
- return 0;
}
/* @@ -637,6 +886,7 @@ static void fill_dentry(fsdata *mydata, dir_entry *dentptr, set_name(dentptr, filename); }
+#if 0 /* TODO: need re-work */ /*
- Check whether adding a file makes the file system to
- exceed the size of the block device
@@ -661,6 +911,7 @@ static int check_overflow(fsdata *mydata, __u32 clustnum, loff_t size) return -1; return 0; } +#endif
/*
- Find a directory entry based on filename or start cluster number
@@ -792,11 +1043,10 @@ again: return 0; }
-static int do_fat_write(const char *filename, void *buffer, loff_t size,
loff_t *actwrite)
+int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
loff_t size, loff_t *actwrite)
{ dir_entry *retdent;
- __u32 start_cluster; fsdata datablock = { .fatbuf = NULL, }; fsdata *mydata = &datablock; fat_itr *itr = NULL;
@@ -807,11 +1057,12 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size, char bad[2] = " "; const char illegal[] = "<>:"/\|?*";
- debug("writing %s\n", filename);
- filename_copy = strdup(filename); if (!filename_copy) goto exit; split_filename(filename_copy, &dirname, &basename);
-printf(">>> %s -> "%s" + "%s"\n", filename, dirname, basename); filename = basename;
/* Check that the filename is valid */ @@ -853,45 +1104,24 @@ printf(">>> %s -> "%s" + "%s"\n", filename, dirname, basename); retdent = find_directory_entry(itr, l_filename);
if (retdent) {
/* Update file size and start_cluster in a directory entry */
retdent->size = cpu_to_le32(size);
start_cluster = START(retdent);
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;
}
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);
/* A file exists */
if (pos == -1)
/* Append to the end */
pos = FAT2CPU32(retdent->size);
if (pos > retdent->size) {
/* No hole allowed */
}goto exit;
/* Update file size in a directory entry */
} else {retdent->size = cpu_to_le32(pos + size);
-/* FIXME: empty_dentptr */
/* Create a new file */
if (pos) {
/* No hole allowed */
ret = -EINVAL;
goto exit;
}
memset(itr->dent, 0, sizeof(*itr->dent));
/* Set short name to set alias checksum field in dir_slot */
@@ -901,30 +1131,13 @@ printf(">>> %s -> "%s" + "%s"\n", filename, dirname, basename); 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;
}
} else {
start_cluster = 0;
}
- /* Set attribute as archieve for regular file */
fill_dentry(itr->fsdata, itr->dent, filename,
start_cluster, size, 0x20);
fill_dentry(itr->fsdata, itr->dent, filename, 0, size, 0x20);
retdent = itr->dent; }
- ret = set_contents(mydata, retdent, buffer, size, actwrite);
- ret = set_contents(mydata, retdent, pos, buffer, size, actwrite); if (ret < 0) { printf("Error: writing contents\n"); goto exit;
@@ -954,11 +1167,11 @@ exit: int file_fat_write(const char *filename, void *buffer, loff_t offset, loff_t maxsize, loff_t *actwrite) {
- if (offset != 0) {
printf("Error: non zero offset is currently not supported.\n");
return -1;
- }
- int ret;
- printf("writing %s\n", filename);
- return do_fat_write(filename, buffer, maxsize, actwrite);
- ret = file_fat_write_at(filename, offset, buffer, maxsize, actwrite);
- if (ret)
printf("** Unable to write file %s **\n", filename);
- return ret;
}

Hey Heinrich,
On Thu, Jun 28, 2018 at 08:14:17PM +0200, Heinrich Schuchardt wrote:
This relates to a patch in https://git.linaro.org/people/takahiro.akashi/u-boot.git branch efi/for_sct.
Thanks for your comment, but please don't cite and post my changes from this branch *in any form*. It's just not intended to do so. I wanna submit it as several separate series once I finish major re-work. For the meantime, I dropped the branch.
-Takahiro AKASHI
On 06/13/2018 08:32 AM, AKASHI Takahiro wrote:
fs/fat/fat_write.c | 385 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 299 insertions(+), 86 deletions(-)
diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index a930b66f28..7e63646655 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -445,6 +445,119 @@ set_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, return 0; }
+static __u8 tmpbuf_cluster[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN);
+/*
- Read and modify data on existing and consecutive cluster blocks
- */
+static int +get_set_cluster(fsdata *mydata, __u32 clustnum, loff_t pos, __u8 *buffer,
loff_t size, loff_t *gotsize)
+{
- unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
- __u32 startsect;
- loff_t wsize;
- int clustcount, i, ret;
- *gotsize = 0;
- if (!size)
return 0;
- assert(pos < bytesperclust);
- startsect = clust_to_sect(mydata, clustnum);
- debug("clustnum: %d, startsect: %d, pos: %lld\n", clustnum, startsect,
pos);
- /* partial write at begining */
- if (pos) {
wsize = min(bytesperclust - pos, size);
ret = disk_read(startsect, mydata->clust_size, tmpbuf_cluster);
if (ret != mydata->clust_size) {
debug("Error reading data (got %d)\n", ret);
return -1;
}
memcpy(tmpbuf_cluster + pos, buffer, wsize);
ret = disk_write(startsect, mydata->clust_size, tmpbuf_cluster);
if (ret != mydata->clust_size) {
debug("Error writing data (got %d)\n", ret);
return -1;
}
size -= wsize;
buffer += wsize;
*gotsize += wsize;
startsect += mydata->clust_size;
if (!size)
return 0;
- }
- /* full-cluster write */
- if (size >= bytesperclust) {
clustcount = size / bytesperclust;
Hello Takahiro,
the line above should read
clustcount = lldiv(size, bytesperclust);
Otherwise I get an error
undefined reference to `__divdi3'
with qemu_x86_defconfig and gcc 7.3.0.
Best regards
Heinrich
if (!((unsigned long)buffer & (ARCH_DMA_MINALIGN - 1))) {
wsize = clustcount * bytesperclust;
ret = disk_write(startsect,
clustcount * mydata->clust_size,
buffer);
if (ret != clustcount * mydata->clust_size) {
debug("Error writing data (got %d)\n", ret);
return -1;
}
size -= wsize;
buffer += wsize;
*gotsize += wsize;
startsect += clustcount * mydata->clust_size;
} else {
for (i = 0; i < clustcount; i++) {
memcpy(tmpbuf_cluster, buffer, bytesperclust);
ret = disk_write(startsect, mydata->clust_size,
tmpbuf_cluster);
if (ret != mydata->clust_size) {
debug("Error writing data (got %d)\n", ret);
return -1;
}
size -= bytesperclust;
buffer += bytesperclust;
*gotsize += bytesperclust;
startsect += mydata->clust_size;
}
}
- }
- /* partial write at end */
- if (size) {
wsize = size;
ret = disk_read(startsect, mydata->clust_size, tmpbuf_cluster);
if (ret != mydata->clust_size) {
debug("Error reading data (got %d)\n", ret);
return -1;
}
memcpy(tmpbuf_cluster, buffer, wsize);
ret = disk_write(startsect, mydata->clust_size, tmpbuf_cluster);
if (ret != mydata->clust_size) {
debug("Error writing data (got %d)\n", ret);
return -1;
}
size -= wsize;
buffer += wsize;
*gotsize += wsize;
- }
- assert(!size);
- return 0;
+}
/*
- Find the first empty cluster
*/ @@ -523,6 +636,18 @@ static int clear_fatent(fsdata *mydata, __u32 entry) return 0; }
+/*
- Set start cluster in directory entry
- */
+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);
+}
/*
- Write at most 'maxsize' bytes from 'buffer' into
- the file associated with 'dentptr'
@@ -530,31 +655,164 @@ static int clear_fatent(fsdata *mydata, __u32 entry)
- or return -1 on fatal errors.
*/ static int -set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, +set_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, __u8 *buffer, loff_t maxsize, loff_t *gotsize) {
- loff_t filesize = FAT2CPU32(dentptr->size);
- loff_t filesize; unsigned int bytesperclust = mydata->clust_size * mydata->sect_size; __u32 curclust = START(dentptr); __u32 endclust = 0, newclust = 0;
- loff_t actsize;
loff_t cur_pos, offset, actsize, wsize;
*gotsize = 0;
- debug("Filesize: %llu bytes\n", filesize);
- if (maxsize > 0 && filesize > maxsize)
filesize = maxsize;
filesize = pos + maxsize;
debug("%llu bytes\n", filesize);
if (!filesize) {
if (!curclust)
return 0;
if (!CHECK_CLUST(curclust, mydata->fatsize) ||
IS_LAST_CLUST(curclust, mydata->fatsize)) {
clear_fatent(mydata, curclust);
set_start_cluster(mydata, dentptr, 0);
return 0;
}
debug("curclust: 0x%x\n", curclust);
debug("Invalid FAT entry\n");
return -1;
}
if (!curclust) {
if (filesize) {
debug("error: nonempty clusterless file!\n");
assert(pos == 0);
goto set_clusters;
}
/* go to cluster at pos */
cur_pos = bytesperclust;
while (1) {
if (pos <= cur_pos)
break;
if (IS_LAST_CLUST(curclust, mydata->fatsize))
break;
newclust = get_fatent(mydata, curclust);
if (!IS_LAST_CLUST(newclust, mydata->fatsize) &&
CHECK_CLUST(newclust, mydata->fatsize)) {
debug("curclust: 0x%x\n", curclust);
debug("Invalid FAT entry\n"); return -1;
}
cur_pos += bytesperclust;
curclust = newclust;
}
if (IS_LAST_CLUST(curclust, mydata->fatsize)) {
assert(pos == cur_pos);
goto set_clusters;
}
assert(pos < cur_pos);
cur_pos -= bytesperclust;
/* overwrite */
assert(IS_LAST_CLUST(curclust, mydata->fatsize) ||
!CHECK_CLUST(curclust, mydata->fatsize));
while (1) {
/* search for allocated consecutive clusters */
actsize = bytesperclust;
endclust = curclust;
while (1) {
if (filesize <= (cur_pos + actsize))
break;
newclust = get_fatent(mydata, endclust);
if (IS_LAST_CLUST(newclust, mydata->fatsize))
break;
if (CHECK_CLUST(newclust, mydata->fatsize)) {
debug("curclust: 0x%x\n", curclust);
debug("Invalid FAT entry\n");
return -1;
}
actsize += bytesperclust;
endclust = newclust;
}
/* overwrite to <curclust..endclust> */
if (pos < cur_pos)
offset = 0;
else
offset = pos - cur_pos;
wsize = min(cur_pos + actsize, filesize) - pos;
if (get_set_cluster(mydata, curclust, offset, buffer, wsize,
&actsize)) {
printf("Error get-and-setting cluster\n");
return -1;
}
buffer += wsize;
*gotsize += wsize;
cur_pos += offset + wsize;
if (filesize <= cur_pos)
break;
/* CHECK: newclust = get_fatent(mydata, endclust); */
if (IS_LAST_CLUST(newclust, mydata->fatsize))
/* no more clusters */
break;
curclust = newclust;
}
if (filesize <= cur_pos) {
/* no more write */
newclust = get_fatent(mydata, endclust);
if (!IS_LAST_CLUST(newclust, mydata->fatsize)) {
/* truncate the rest */
clear_fatent(mydata, newclust);
/* Mark end of file in FAT */
if (mydata->fatsize == 12)
newclust = 0xfff;
else if (mydata->fatsize == 16)
newclust = 0xffff;
else if (mydata->fatsize == 32)
newclust = 0xfffffff;
set_fatent_value(mydata, endclust, newclust);
}
return 0; }
curclust = endclust;
filesize -= cur_pos;
assert (!(cur_pos % bytesperclust));
+set_clusters:
- /* allocate and write */
- assert(!pos);
- /* Assure that curclust is valid */
- if (!curclust) {
curclust = find_empty_cluster(mydata);
set_start_cluster(mydata, dentptr, curclust);
- } else {
newclust = get_fatent(mydata, curclust);
if (IS_LAST_CLUST(newclust, mydata->fatsize)) {
newclust = determine_fatent(mydata, curclust);
set_fatent_value(mydata, curclust, newclust);
curclust = newclust;
} else {
debug("error: something wrong\n");
return -1;
}
- }
- actsize = bytesperclust; endclust = curclust; do {
@@ -563,6 +821,7 @@ set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, newclust = determine_fatent(mydata, endclust);
if ((newclust - 1) != endclust)
/* write to <curclust..endclust> */ goto getit; if (CHECK_CLUST(newclust, mydata->fatsize)) {
@@ -609,18 +868,8 @@ getit: actsize = bytesperclust; curclust = endclust = newclust; } while (1); -}
-/*
- Set start cluster in directory entry
- */
-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);
- return 0;
}
/* @@ -637,6 +886,7 @@ static void fill_dentry(fsdata *mydata, dir_entry *dentptr, set_name(dentptr, filename); }
+#if 0 /* TODO: need re-work */ /*
- Check whether adding a file makes the file system to
- exceed the size of the block device
@@ -661,6 +911,7 @@ static int check_overflow(fsdata *mydata, __u32 clustnum, loff_t size) return -1; return 0; } +#endif
/*
- Find a directory entry based on filename or start cluster number
@@ -792,11 +1043,10 @@ again: return 0; }
-static int do_fat_write(const char *filename, void *buffer, loff_t size,
loff_t *actwrite)
+int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
loff_t size, loff_t *actwrite)
{ dir_entry *retdent;
- __u32 start_cluster; fsdata datablock = { .fatbuf = NULL, }; fsdata *mydata = &datablock; fat_itr *itr = NULL;
@@ -807,11 +1057,12 @@ static int do_fat_write(const char *filename, void *buffer, loff_t size, char bad[2] = " "; const char illegal[] = "<>:"/\|?*";
- debug("writing %s\n", filename);
- filename_copy = strdup(filename); if (!filename_copy) goto exit; split_filename(filename_copy, &dirname, &basename);
-printf(">>> %s -> "%s" + "%s"\n", filename, dirname, basename); filename = basename;
/* Check that the filename is valid */ @@ -853,45 +1104,24 @@ printf(">>> %s -> "%s" + "%s"\n", filename, dirname, basename); retdent = find_directory_entry(itr, l_filename);
if (retdent) {
/* Update file size and start_cluster in a directory entry */
retdent->size = cpu_to_le32(size);
start_cluster = START(retdent);
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;
}
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);
/* A file exists */
if (pos == -1)
/* Append to the end */
pos = FAT2CPU32(retdent->size);
if (pos > retdent->size) {
/* No hole allowed */
}goto exit;
/* Update file size in a directory entry */
} else {retdent->size = cpu_to_le32(pos + size);
-/* FIXME: empty_dentptr */
/* Create a new file */
if (pos) {
/* No hole allowed */
ret = -EINVAL;
goto exit;
}
memset(itr->dent, 0, sizeof(*itr->dent));
/* Set short name to set alias checksum field in dir_slot */
@@ -901,30 +1131,13 @@ printf(">>> %s -> "%s" + "%s"\n", filename, dirname, basename); 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;
}
} else {
start_cluster = 0;
}
- /* Set attribute as archieve for regular file */
fill_dentry(itr->fsdata, itr->dent, filename,
start_cluster, size, 0x20);
fill_dentry(itr->fsdata, itr->dent, filename, 0, size, 0x20);
retdent = itr->dent; }
- ret = set_contents(mydata, retdent, buffer, size, actwrite);
- ret = set_contents(mydata, retdent, pos, buffer, size, actwrite); if (ret < 0) { printf("Error: writing contents\n"); goto exit;
@@ -954,11 +1167,11 @@ exit: int file_fat_write(const char *filename, void *buffer, loff_t offset, loff_t maxsize, loff_t *actwrite) {
- if (offset != 0) {
printf("Error: non zero offset is currently not supported.\n");
return -1;
- }
- int ret;
- printf("writing %s\n", filename);
- return do_fat_write(filename, buffer, maxsize, actwrite);
- ret = file_fat_write_at(filename, offset, buffer, maxsize, actwrite);
- if (ret)
printf("** Unable to write file %s **\n", filename);
- return ret;
}
participants (2)
-
AKASHI Takahiro
-
Heinrich Schuchardt