diff --git a/kernel/fatfs.c b/kernel/fatfs.c index 43d2d180..4c0103e7 100644 --- a/kernel/fatfs.c +++ b/kernel/fatfs.c @@ -1024,17 +1024,6 @@ COUNT map_cluster(REG f_node_ptr fnp, COUNT mode) cluster = extend(fnp); if (cluster == LONG_LAST_CLUSTER) return DE_HNDLDSKFULL; - - /* ecm: finally the right solution, only extend/modify - file size after having just appended a cluster. */ - fnp->f_dir.dir_size = - (((ULONG)fnp->f_cluster_offset + 2) - /* at 0 we will increment to 1, having allocated the second - cluster, so + 2 for the then-total size. */ - * (ULONG)fnp->f_dpb->dpb_secsize) - << - fnp->f_dpb->dpb_shftcnt; - merge_file_changes(fnp, FALSE); } fnp->f_cluster = cluster; @@ -1055,7 +1044,7 @@ COUNT map_cluster(REG f_node_ptr fnp, COUNT mode) /* #define WRITEZEROS 1 */ /* but because we want to be compatible, we don't do this by */ /* default */ -STATIC COUNT dos_extend(f_node_ptr fnp) +STATIC COUNT dos_extend(f_node_ptr fnp, BOOL emptywrite) { #ifdef WRITEZEROS struct buffer FAR *bp; @@ -1075,8 +1064,39 @@ STATIC COUNT dos_extend(f_node_ptr fnp) while (count > 0) #endif { - if (map_cluster(fnp, XFR_WRITE) != SUCCESS) + BOOL special = 0; + if (emptywrite +#ifdef WRITEZEROS + && fnp->f_offset != 0 +#else + /* f_offset != 0 always true here */ +#endif + && ((fnp->f_offset & + (((ULONG)fnp->f_dpb->dpb_secsize + << fnp->f_dpb->dpb_shftcnt) - 1) + ) + == 0) + ) { + special = 1; + -- fnp->f_offset; + } + if (map_cluster(fnp, XFR_WRITE) != SUCCESS) { + if (special) ++ fnp->f_offset; + if (fnp->f_cluster != FREE) { + /* ecm: write size if couldn't satisfy full request, + but at least one cluster is allocated. */ + fnp->f_dir.dir_size = + (((ULONG)fnp->f_cluster_offset + 1) + /* at 0 we have incremented to 1, having allocated the second + cluster, so + 1 for the then-total size. */ + * (ULONG)fnp->f_dpb->dpb_secsize) + << + fnp->f_dpb->dpb_shftcnt; + merge_file_changes(fnp, FALSE); + } return DE_HNDLDSKFULL; + } + if (special) ++ fnp->f_offset; #ifdef WRITEZEROS /* Compute the block within the cluster and the offset */ @@ -1106,6 +1126,18 @@ STATIC COUNT dos_extend(f_node_ptr fnp) } if (bp == NULL) { + if (fnp->f_cluster != FREE) { + /* ecm: write size if couldn't satisfy full request, + but at least one cluster is allocated. */ + fnp->f_dir.dir_size = + (((ULONG)fnp->f_cluster_offset + 1) + /* at 0 we have incremented to 1, having allocated the second + cluster, so + 1 for the then-total size. */ + * (ULONG)fnp->f_dpb->dpb_secsize) + << + fnp->f_dpb->dpb_shftcnt; + merge_file_changes(fnp, FALSE); + } return DE_ACCESS; } @@ -1221,7 +1253,7 @@ long rwblock(COUNT fd, VOID FAR * buffer, UCOUNT count, int mode) /* mark file as modified and set date not valid any more */ fnp->f_flags &= ~(SFT_FCLEAN|SFT_FDATE); - if (dos_extend(fnp) != SUCCESS) + if (dos_extend(fnp, count == 0) != SUCCESS) { /* ecm: control flow may end up here if CX = 0000h and the extending failed to allocate a cluster