(fhandler_base::lseek): Include high order bits in return.

Corinna Vinschen vinschen@redhat.com
Tue Nov 18 17:33:00 GMT 2003

On Mon, Nov 17, 2003 at 08:58:42PM -0500, J. Johnston wrote:
> IIRC, Cygwin redirects your calls to the appropriate 64-bit I/O code and 
> thus, should not be allowing you to call lseek and should instead redirect 
> your call to lseek64.

Yes, any application call to lseek is redirected automatically to lseek64.

>   Now, there isn't currently an lseek64 in the 
> libc/syscalls directory which contains syscall wrappers used by Cygwin.  
> Corinna, if I add the appropriate wrappers, would that help or does Cygwin 
> provide its own wrappers?

These wrappers in libc/syscalls aren't used by Cygwin.  Cygwin provides
its own functions.  See winsup/cygwin/cygwin.din.  E. g.  the close call
is exported as

  _close = close

which means, the close call is also exported as _close.

I debugged Brian's testcase and it turned out that the following happened
to the offset value:

  fseeko64    calls  _lseek64_r, offset is 0x12a05f200.
  _lseek64_r  calls  _lseek64,   offset is 0x12a05f200.

_lseek64 is implemented in Cygwin.

  _lseek64    calls  SetFilePointer, pos returned is 0x12a05f200.
  _lseek64    explicitely returns 0x12a05f200.

Now we're back in newlib.

  _lseek64_r stores the return value of _lseek64 in the local variable
  `ret'.  Looking into ret right after the call to _lseek64 shows that
  ret has lost its upper bits:

  (gdb) p/x ret
  $1 = 0x2a05f200

The cause for that behaviour is, that newlib is missing prototypes for
all 64 bit syscalls (_open64, _fstat64, _lseek64) it uses.

This doesn't lead to problems for all the other functions.  Only _lseek64
is affected, because it's the only function returning a value which is
bigger than int.  That means, due to the missing prototype, the returned
value is taken from only one register, instead of from two registers as
would be necessary for the 8 byte type _off64_t.

For the sake of testing I added an extern declaration of _lseek64 to
_lseek64_r like this:

  extern _off64_t _lseek64 (int, _off64_t, int);

which solved the above problem.  fseeko returned the expected value of

However, the correct solution would be to declare all syscalls used by
newlib at one point.

I propose the below patch which matches the already existing layout. 
It might be a good idea, though, to move all syscall declarations
into a special file.  They could be declared in _syslist.h, for instance.
BSD has a header file called sys/sysproto.h, which would be fine, too.


	* libc/include/sys/fcntl.h: Declare _open64.
	* libc/include/sys/stat.h: Declare _fstat64.
	* libc/include/sys/unistd.h: Declare _lseek64.

Index: libc/include/sys/fcntl.h
RCS file: /cvs/src/src/newlib/libc/include/sys/fcntl.h,v
retrieving revision 1.2
diff -u -p -r1.2 fcntl.h
--- libc/include/sys/fcntl.h	5 Sep 2000 18:29:53 -0000	1.2
+++ libc/include/sys/fcntl.h	18 Nov 2003 12:49:47 -0000
@@ -171,6 +171,9 @@ extern int fcntl _PARAMS ((int, int, ...
    of newlib.  */
 extern int _open _PARAMS ((const char *, int, ...));
 extern int _fcntl _PARAMS ((int, int, ...));
+#ifdef __LARGE64_FILES
+extern int _open64 _PARAMS ((const char *, int, ...));
 #ifdef __cplusplus
Index: libc/include/sys/stat.h
RCS file: /cvs/src/src/newlib/libc/include/sys/stat.h,v
retrieving revision 1.13
diff -u -p -r1.13 stat.h
--- libc/include/sys/stat.h	26 Aug 2003 20:54:04 -0000	1.13
+++ libc/include/sys/stat.h	18 Nov 2003 12:49:48 -0000
@@ -140,6 +140,9 @@ int	_EXFUN(mknod,( const char *__path, m
 #ifndef __INSIDE_CYGWIN__
 int	_EXFUN(_fstat,( int __fd, struct stat *__sbuf ));
 int	_EXFUN(_stat,( const char *__path, struct stat *__sbuf ));
+#ifdef __LARGE64_FILES
+int	_EXFUN(_fstat64,( int __fd, struct stat64 *__sbuf ));
 #endif /* !_STAT_H_ */
Index: libc/include/sys/unistd.h
RCS file: /cvs/src/src/newlib/libc/include/sys/unistd.h,v
retrieving revision 1.45
diff -u -p -r1.45 unistd.h
--- libc/include/sys/unistd.h	10 Sep 2003 15:53:44 -0000	1.45
+++ libc/include/sys/unistd.h	18 Nov 2003 12:49:48 -0000
@@ -177,6 +177,9 @@ void *  _EXFUN(_sbrk,  (ptrdiff_t __incr
 int     _EXFUN(_unlink, (const char *__path ));
 _READ_WRITE_RETURN_TYPE _EXFUN(_write, (int __fd, const void *__buf, size_t __nbyte ));
 int     _EXFUN(_execve, (const char *__path, char * const __argv[], char * const __envp[] ));
+#ifdef __LARGE64_FILES
+_off64_t _EXFUN(_lseek64, (int, _off64_t, int));
 #if defined(__CYGWIN__) || defined(__rtems__) || defined(__sh__)
 #if !defined(__INSIDE_CYGWIN__)

Corinna Vinschen
Cygwin Developer
Red Hat, Inc.

More information about the Newlib mailing list