From dan@dan.emsphone.com  Mon Nov  9 14:20:35 1998
Received: from dan.emsphone.com (dan.emsphone.com [199.67.51.101])
          by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id OAA29435
          for <FreeBSD-gnats-submit@freebsd.org>; Mon, 9 Nov 1998 14:20:31 -0800 (PST)
          (envelope-from dan@dan.emsphone.com)
Received: (from dan@localhost)
	by dan.emsphone.com (8.9.1/8.9.1) id QAA20439;
	Mon, 9 Nov 1998 16:20:15 -0600 (CST)
Message-Id: <199811092220.QAA20439@dan.emsphone.com>
Date: Mon, 9 Nov 1998 16:20:15 -0600 (CST)
From: dnelson@emsphone.com
To: FreeBSD-gnats-submit@freebsd.org
Subject: fgetpos()/fsetpos() don't work for >2GB filesize
X-Send-Pr-Version: 3.2

>Number:         8637
>Category:       bin
>Synopsis:       fgetpos()/fsetpos() don't work for >2GB filesize
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Nov  9 14:30:00 PST 1998
>Closed-Date:    Thu May 13 12:13:16 PDT 1999
>Last-Modified:  Thu May 13 12:14:05 PDT 1999
>Originator:     Dan Nelson
>Release:        FreeBSD 2.2.7-STABLE i386
>Organization:
Executive Marketing Services, Inc.
>Environment:

FreeBSD dan.emsphone.com 2.2.7-STABLE FreeBSD 2.2.7-STABLE #0: Sat Aug  8 15:03:34 CDT 1998     dan@dan.emsphone.com:/usr/src/sys/compile/DAN  i386

>Description:

fgetpos() and fsetpos() call fseek and ftell to do their dirty work. 
This means that all FILE* operations are limited to the 2GB limit
imposed by the "long" offset type.

>How-To-Repeat:

Create a 3GB file.  Read 2.1GB into it.  Call fsetpos(fgetpos()), and
note that you are not where you should be.

>Fix:

1. Rename ftell to ftello, and fseek to fseeko, which are X/Open standard
functions that take off_t offsets.  All that had to be changed was the
prototypes, as the internals already used fpos_t.

2. add new fseek/ftell functions.

3. change fsetpos/fgetpos to use fseeko/ftello.

4. add protptypes to stdio.h.

One thing; our errno.h doesn't have an EOVERFLOW, so I used EFBIG in
ftell() for filesizes that exceed 2GB.  This should probably get fixed.

	-Dan Nelson
	dnelson@emsphone.com

Index: fgetpos.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdio/fgetpos.c,v
retrieving revision 1.3
diff -u -r1.3 fgetpos.c
--- fgetpos.c	1996/06/22 10:33:09	1.3
+++ fgetpos.c	1998/11/09 20:12:33
@@ -57,7 +57,7 @@
 #ifdef _THREAD_SAFE
 	_thread_flockfile(fp,__FILE__,__LINE__);
 #endif
-	retval = (*pos = ftell(fp)) == (fpos_t)-1;
+	retval = (*pos = ftello(fp)) == (fpos_t)-1;
 #ifdef _THREAD_SAFE
 	_thread_funlockfile(fp);
 #endif
Index: fseek.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdio/fseek.c,v
retrieving revision 1.4
diff -u -r1.4 fseek.c
--- fseek.c	1996/06/22 10:33:22	1.4
+++ fseek.c	1998/11/09 20:21:22
@@ -56,14 +56,23 @@
 
 #define	POS_ERR	(-(fpos_t)1)
 
+int
+fseek(fp, offset, whence)
+	register FILE *fp;
+	long offset;
+	int whence;
+{
+	return (fseeko(fp, offset, whence));
+}
+
 /*
  * Seek the given file to the given offset.
  * `Whence' must be one of the three SEEK_* macros.
  */
 int
-fseek(fp, offset, whence)
+fseeko(fp, offset, whence)
 	register FILE *fp;
-	long offset;
+	off_t offset;
 	int whence;
 {
 	register fpos_t (*seekfn) __P((void *, fpos_t, int));
Index: fsetpos.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdio/fsetpos.c,v
retrieving revision 1.3
diff -u -r1.3 fsetpos.c
--- fsetpos.c	1996/06/22 10:33:23	1.3
+++ fsetpos.c	1998/11/09 20:12:47
@@ -52,5 +52,5 @@
 	FILE *iop;
 	const fpos_t *pos;
 {
-	return (fseek(iop, (long)*pos, SEEK_SET));
+	return (fseeko(iop, (off_t)*pos, SEEK_SET));
 }
Index: ftell.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdio/ftell.c,v
retrieving revision 1.5
diff -u -r1.5 ftell.c
--- ftell.c	1996/06/22 10:33:25	1.5
+++ ftell.c	1998/11/09 21:59:47
@@ -44,17 +44,32 @@
 
 #include <stdio.h>
 #include <errno.h>
+#include <limits.h>
 #include "local.h"
 #ifdef _THREAD_SAFE
 #include <pthread.h>
 #include "pthread_private.h"
 #endif
 
+/* standard ftell function.  */
+long
+ftell(fp)
+	register FILE *fp;
+{
+	register off_t rv;
+	rv = ftello(fp);
+	if (rv > LONG_MAX) {
+		errno = EFBIG; 	/* XXX should be EOVERFLOW */
+		return (-1);
+	}
+	return (rv);
+}
+
 /*
  * ftell: return current offset.
  */
-long
-ftell(fp)
+off_t
+ftello(fp)
 	register FILE *fp;
 {
 	register fpos_t pos;
Index: stdio.h
===================================================================
RCS file: /home/ncvs/src/include/stdio.h,v
retrieving revision 1.8.2.2
diff -u -r1.8.2.2 stdio.h
--- stdio.h	1998/02/17 00:48:17	1.8.2.2
+++ stdio.h	1998/11/09 20:32:03
@@ -234,8 +234,10 @@
 FILE	*freopen __P((const char *, const char *, FILE *));
 int	 fscanf __P((FILE *, const char *, ...));
 int	 fseek __P((FILE *, long, int));
+int	 fseeko __P((FILE *, off_t, int));
 int	 fsetpos __P((FILE *, const fpos_t *));
 long	 ftell __P((FILE *));
+off_t	 ftello __P((FILE *));
 size_t	 fwrite __P((const void *, size_t, size_t, FILE *));
 int	 getc __P((FILE *));
 int	 getchar __P((void));



	-Dan Nelson
	dnelson@emsphone.com
>Release-Note:
>Audit-Trail:

From: Dan Nelson <dnelson@emsphone.com>
To: FreeBSD-gnats-submit@FreeBSD.ORG
Cc:  Subject: Re: bin/8637: fgetpos()/fsetpos() don't work for >2GB filesize
Date: Tue, 10 Nov 1998 10:46:28 -0600

 And here is the documentation to go along with the code:
 
 Index: Makefile.inc
 ===================================================================
 RCS file: /home/ncvs/src/lib/libc/stdio/Makefile.inc,v
 retrieving revision 1.6.2.2
 diff -u -r1.6.2.2 Makefile.inc
 --- Makefile.inc	1998/04/13 23:20:52	1.6.2.2
 +++ Makefile.inc	1998/11/10 15:11:58
 @@ -30,6 +30,7 @@
  MLINKS+=fputs.3 puts.3
  MLINKS+=fread.3 fwrite.3
  MLINKS+=fseek.3 fgetpos.3 fseek.3 fsetpos.3 fseek.3 ftell.3 fseek.3 rewind.3
 +MLINKS+=fseek.3 fseeko.3 fseek.3 ftello.3
  MLINKS+=funopen.3 fropen.3 funopen.3 fwopen.3
  MLINKS+=getc.3 fgetc.3 getc.3 getchar.3 getc.3 getw.3
  MLINKS+=mktemp.3 mkdtemp.3 mktemp.3 mkstemp.3
 Index: fseek.3
 ===================================================================
 RCS file: /home/ncvs/src/lib/libc/stdio/fseek.3,v
 retrieving revision 1.1.1.1.8.1
 diff -u -r1.1.1.1.8.1 fseek.3
 --- fseek.3	1998/02/17 17:28:44	1.1.1.1.8.1
 +++ fseek.3	1998/11/10 16:26:54
 @@ -41,8 +41,10 @@
  .Sh NAME
  .Nm fgetpos ,
  .Nm fseek ,
 +.Nm fseeko ,
  .Nm fsetpos ,
  .Nm ftell ,
 +.Nm ftello ,
  .Nm rewind
  .Nd reposition a stream
  .Sh SYNOPSIS
 @@ -57,6 +59,10 @@
  .Fn fgetpos "FILE *stream" "fpos_t *pos"
  .Ft int
  .Fn fsetpos "FILE *stream" "const fpos_t *pos"
 +.Ft int
 +.Fn fseeko "FILE *stream" "off_t offset" "int whence"
 +.Ft off_t
 +.Fn ftello "FILE *stream"
  .Sh DESCRIPTION
  The
  .Fn fseek
 @@ -106,6 +112,19 @@
  .Xr clearerr 3 ) .
  .Pp
  The
 +.Fn fseeko
 +and
 +.Fn ftello
 +functions
 +are alternate interfaces equivalent to
 +.Fn ftell
 +and
 +.Fn fseek ,
 +but take an off_t argument instead of a long.  On systems that use a 32-bit
 +long type but support 64-bit filesizes, this is the only way to seek past the
 +2-gigabyte point.
 +.Pp
 +The
  .Fn fgetpos
  and
  .Fn fsetpos
 @@ -133,10 +152,14 @@
  Upon successful completion,
  .Fn fgetpos ,
  .Fn fseek ,
 +.Fn fseeko ,
 +and
  .Fn fsetpos
  return 0,
  and
  .Fn ftell
 +and
 +.Fn ftello
  returns the current offset.
  Otherwise, \-1 is returned and the global variable errno is set to
  indicate the error.
 @@ -157,14 +180,21 @@
  .Dv SEEK_END ,
  or
  .Dv SEEK_CUR .
 +.It Bq Er EFBIG
 +For 
 +.Fn ftello ,
 +the resulting file offset would be a value which
 +cannot be represented correctly in an object of type off_t.
  .El
  .Pp
 -The function
 +The functions
  .Fn fgetpos ,
  .Fn fseek ,
 +.Fn fseeko ,
  .Fn fsetpos ,
 -and 
 -.Fn ftell
 +.Fn ftell ,
 +and
 +.Fn ftello
  may also fail and set
  .Va errno
  for any of the errors specified for the routines
 @@ -186,3 +216,16 @@
  functions
  conform to
  .St -ansiC .
 +.Pp
 +The
 +.Fn fseeko 
 +and
 +.Fn ftello
 +functions conform to the X/Open Single UNIX Specification, Version 2.
 +.Sh BUGS
 +The 
 +.Bq Er EFBIG
 +error return should be 
 +.Bq Er EOVERFLOW 
 +according to the Single Unix specification, but FreeBSD has no
 +.Bq Er EOVERFLOW .

From: Dmitrij Tejblum <tejblum@arc.hq.cti.ru>
To: dnelson@emsphone.com
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: bin/8637: fgetpos()/fsetpos() don't work for >2GB filesize 
Date: Tue, 10 Nov 1998 23:46:54 +0300

 > One thing; our errno.h doesn't have an EOVERFLOW, so I used EFBIG in
 > ftell() for filesizes that exceed 2GB.  This should probably get fixed.
 
 And how about just add EOVERFLOW to errno.h, instead of document the bug 
 in man pages???
 
 Dima
 
 

From: Dan Nelson <dnelson@emsphone.com>
To: Dmitrij Tejblum <tejblum@arc.hq.cti.ru>
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: bin/8637: fgetpos()/fsetpos() don't work for >2GB filesize
Date: Tue, 10 Nov 1998 16:43:48 -0600

 In the last episode (Nov 10), Dmitrij Tejblum said:
 > > One thing; our errno.h doesn't have an EOVERFLOW, so I used EFBIG in
 > > ftell() for filesizes that exceed 2GB.  This should probably get fixed.
 > 
 > And how about just add EOVERFLOW to errno.h, instead of document the bug 
 > in man pages???
 
 Well, if it's that easy, sure.  I don't know all that much about the
 repercussions of adding errors to errno.h.  I suppose there's a string
 table that needs adjusting, too, for strerror()?  Anything else?

From: Dmitrij Tejblum <dima@tejblum.dnttm.rssi.ru>
To: Dan Nelson <dnelson@emsphone.com>
Cc: Dmitrij Tejblum <tejblum@arc.hq.cti.ru>, FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: bin/8637: fgetpos()/fsetpos() don't work for >2GB filesize 
Date: Wed, 11 Nov 1998 03:45:46 +0300

 Dan Nelson wrote:
 > > And how about just add EOVERFLOW to errno.h, instead of document the bug 
 > > in man pages???
 > 
 > Well, if it's that easy, sure.  I don't know all that much about the
 > repercussions of adding errors to errno.h.  I suppose there's a string
 > table that needs adjusting, too, for strerror()?  Anything else?
 
 The string table is in lib/libc/gen/errlst.c. It is already incomplete. 
 
 I don't know of anything else.
 
 Dima
 
 

From: Peter Wemm <peter@netplex.com.au>
To: Dan Nelson <dnelson@emsphone.com>
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: bin/8637: fgetpos()/fsetpos() don't work for >2GB filesize 
Date: Wed, 11 Nov 1998 13:05:38 +0800

 Dan Nelson wrote:
 >  In the last episode (Nov 10), Dmitrij Tejblum said:
 >  > > One thing; our errno.h doesn't have an EOVERFLOW, so I used EFBIG in
 >  > > ftell() for filesizes that exceed 2GB.  This should probably get fixed.
 >  > 
 >  > And how about just add EOVERFLOW to errno.h, instead of document the bug 
 >  > in man pages???
 >  
 >  Well, if it's that easy, sure.  I don't know all that much about the
 >  repercussions of adding errors to errno.h.  I suppose there's a string
 >  table that needs adjusting, too, for strerror()?  Anything else?
 
 NFS needs it added to the errno mapping tables, I suspect the binary 
 emulation (linux, ibcs2 etc) need it too.
 
 Cheers,
 -Peter
 --
 Peter Wemm <peter@netplex.com.au>   Netplex Consulting
 "No coffee, No workee!" :-)
 
 
State-Changed-From-To: open->closed 
State-Changed-By: dt 
State-Changed-When: Thu May 13 12:13:16 PDT 1999 
State-Changed-Why:  
Fixed, thanks. 
>Unformatted:
Dan Nelson
