[ECOS] fseek on JFFS2
Jonathan Larmour
jifl@eCosCentric.com
Wed Sep 27 15:15:00 GMT 2006
Ivan Djelic wrote:
> Hello all,
>
> I believe the problems you are discussing may be related to several bugs I
> found in Cyg_StdioStream::set_position():
>
> 1) Type 'fpos_t' of parameter 'pos' is defined as cyg_ucount32, whereas
> 'pos' is generally assumed to be signed; which triggers a few annoying bugs.
> For instance, if you do something like:
>
> fgetc(fp);
> fseek( fp, -1, SEEK_CUR );
>
> then set_position() gets called with pos = 0xffffffff (unsigned).
>
> 'fpos_t' could probably be defined as cyg_count32, at least that's
> how I fixed the problem.
Ok.
> 2) When CYGPKG_LIBC_STDIO_FILEIO is used, there is a piece of code in
> set_position() which (as was said in some earlier post):
> "calculates the new absolute position and calls cyg_stdio_lseek()".
> Unfortunately it does not work with the following example:
>
> fgetc(fp);
> fseek( fp, -1, SEEK_CUR );
>
> Assuming the stream uses buffers of 256 bytes, and using the 'sfp'/'ufp'
> notation introduced in earlier posts, we have:
>
> before fgetc() (assume we just opened the file):
> sfp = 0
> ufp = 0
>
> after fgetc():
> sfp = 1
> ufp = 0x100 (because we read a full buffer)
>
> At this point, set_position() is called with:
> whence = SEEK_CUR
> pos = -1 (or 0xffffffff is fpos_t is cyg_ucount32, it does not really change
> anything here)
>
> The following variables are computed:
> abspos = position + pos;
> posdiff = abspos - position; ( = pos )
>
> -> posdiff is equal to -1
>
> then we have:
>
> position += bytesavail;
>
> so that 'position' is now equal to ufp (0x100).
>
> Then,
>
> cyg_stdio_lseek( my_device, &newpos, whence );
>
> with newpos == -1, whence == SEEK_CUR. Remember that ufp = 0x100.
>
> and finally 'position' is updated:
>
> position = newpos; (= 0xff)
>
> Finally, we have:
>
> sfp = 0xff
> ufp = 0xff
>
> But this is *not* what we want ! We want to have sfp = 0, so that for instance
> ftell(fp) returns 0.
> The problem is that we forced sfp to be equal to ufp before seeking, whereas
> it should have been the other way around.
> Here is my fix:
>
>
> @@ -441,7 +441,9 @@ Cyg_StdioStream::set_position( fpos_t po
> } // endif (bytesavail > posdiff)
>
> if (whence == SEEK_CUR) {
> - position += bytesavail;
> + pos += position;
> + whence = SEEK_SET;
> }
> } //endif (whence != SEEK_END)
>
>
> That way, we convert 'pos' to an offset from the beginning of the stream
> (SEEK_SET), and we do not depend on the value of ufp when seeking...
I agree with your analysis, but I think I would prefer a fix like:
Index: include/stream.inl
===================================================================
RCS file:
/cvs/ecos/ecos/packages/language/c/libc/stdio/current/include/stream.inl,v
retrieving revision 1.7
diff -u -5 -p -r1.7 stream.inl
--- include/stream.inl 29 Mar 2004 11:24:38 -0000 1.7
+++ include/stream.inl 27 Sep 2006 15:14:52 -0000
@@ -440,10 +440,11 @@ Cyg_StdioStream::set_position( fpos_t po
return ENOERR;
} // endif (bytesavail > posdiff)
if (whence == SEEK_CUR) {
position += bytesavail;
+ pos -= bytesavail;
}
} //endif (whence != SEEK_END)
Cyg_ErrNo err;
What do you think?
Jifl
--
eCosCentric http://www.eCosCentric.com/ The eCos and RedBoot experts
------["The best things in life aren't things."]------ Opinions==mine
--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss
More information about the Ecos-discuss
mailing list