This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Problems with rewinddir() on RTEMS


On Jul  5 11:24, Sebastian Huber wrote:
> Hi,
> 
> on some platforms RTEMS uses a 64-bit type for off_t (in particular PowerPC).
> The function rewinddir() is implemented (libc/posix/rewinddir.c) in terms of:
> 
> _seekdir((dirp), (off_t)0);
> 
> For _seekdir() no prototype is present.  GCC chooses to pass (off_t) 0 as a
> 64-bit parameter (on PowerPC r5 and r6).  On the other hand we have
> (libc/posix/telldir.c):
> 
> void
> _DEFUN(_seekdir, (dirp, loc),
> 	register DIR *dirp _AND
> 	long loc)
> 
> Which has a different signature compared to above (on PowerPC r4 will contain
> loc).  We must declare _seekdir() somewhere.

Not only _seekdir is wrongly defined taking a long type, seekdir is,
too, and telldir is wrongly defined returning a long.  Both functions
should use off_t per POSIX.

The prototypes from dirent.h are not available in newlib in a generic
way.  dirent.h includes sys/dirent.h and sys/dirent.h is a dummy which
is supposed to be overloaded by a systems-specific file.

Two system-specific files are available in newlib,
sys/rtems/sys/dirent.h and sys/linux/sys/dirent.h.
Both files wrongly define seekdir and telldir with long types.

So there's not just a problem under the hood with _seekdir, even
the offical API is broken.

Unfortunately this will break backward compatibility in environments
with sizeof(long) != sizeof(off_t).

However, I propose the below patch.  Following the standards is most
important, IMHO.


Corinna


	* libc/posix/seekdir.c (seekdir): Change loc parameter to off_t
	per POSIX.
	* libc/posix/telldir.c (struct ddloc): Change loc_index and
	loc_seek members to off_t to make sure they correspond to the types
	used by telldir and lseek.
	(telldir): Return off_t per POSIX.
	(_seekdir): Change loc parameter to off_t.
	* libc/sys/linux/sys/dirent.h (DIR): Change dd_seek member to
	off_t as expected by lseek.
	(telldir): Fix prototype per POSIX.
	* libc/sys/rtems/sys/dirent.h (DIR): Change dd_seek member to
	off_t as expected by lseek.
	(seekdir): Fix prototype per POSIX.
	(telldir): Ditto.
	(_seekdir): Add prototype.


Index: libc/posix/seekdir.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/posix/seekdir.c,v
retrieving revision 1.3
diff -u -p -r1.3 seekdir.c
--- libc/posix/seekdir.c	6 Jun 2003 19:57:51 -0000	1.3
+++ libc/posix/seekdir.c	5 Jul 2010 11:43:03 -0000
@@ -48,7 +48,7 @@ static char sccsid[] = "@(#)seekdir.c	5.
 void
 _DEFUN(seekdir, (dirp, loc),
 	DIR *dirp _AND
-	long loc)
+	off_t loc)
 {
 #ifdef HAVE_DD_LOCK
 	__lock_acquire_recursive(dirp->dd_lock);
Index: libc/posix/telldir.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/posix/telldir.c,v
retrieving revision 1.9
diff -u -p -r1.9 telldir.c
--- libc/posix/telldir.c	9 Mar 2010 20:38:18 -0000	1.9
+++ libc/posix/telldir.c	5 Jul 2010 11:43:03 -0000
@@ -58,8 +58,8 @@ static char sccsid[] = "@(#)telldir.c	5.
  */
 struct ddloc {
 	struct	ddloc *loc_next;/* next structure in list */
-	long	loc_index;	/* key associated with structure */
-	long	loc_seek;	/* magic cookie returned by getdirentries */
+	off_t	loc_index;	/* key associated with structure */
+	off_t	loc_seek;	/* magic cookie returned by getdirentries */
 	long	loc_loc;	/* offset of entry in buffer */
 	DIR    *loc_dirp;       /* DIR pointer */
 };
@@ -77,11 +77,11 @@ __LOCK_INIT(static, dd_hash_lock);
 
 #if !defined(_ELIX_LEVEL) || (_ELIX_LEVEL >= 2)
 
-long
+off_t
 _DEFUN(telldir, (dirp),
        DIR *dirp)
 {
-	register int index;
+	register off_t index;
 	register struct ddloc *lp;
 
 	if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL)
@@ -114,7 +114,7 @@ _DEFUN(telldir, (dirp),
 void
 _DEFUN(_seekdir, (dirp, loc),
 	register DIR *dirp _AND
-	long loc)
+	off_t loc)
 {
 	register struct ddloc *lp;
 	register struct ddloc **prevlp;
Index: libc/sys/linux/sys/dirent.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/sys/linux/sys/dirent.h,v
retrieving revision 1.6
diff -u -p -r1.6 dirent.h
--- libc/sys/linux/sys/dirent.h	19 Nov 2008 20:55:52 -0000	1.6
+++ libc/sys/linux/sys/dirent.h	5 Jul 2010 11:43:03 -0000
@@ -22,7 +22,7 @@
 typedef struct {
     int dd_fd;		/* directory file */
     int dd_loc;		/* position in buffer */
-    int dd_seek;
+    off_t dd_seek;
     char *dd_buf;	/* buffer */
     int dd_len;		/* buffer length */
     int dd_size;	/* amount of data in buffer */
@@ -44,7 +44,7 @@ void _seekdir(DIR *dir,off_t offset);
 DIR *_opendir(const char *);
 
 #ifndef _POSIX_SOURCE
-long telldir (DIR *);
+off_t telldir (DIR *);
 void seekdir (DIR *, off_t loc);
 
 int scandir (const char *__dir,
Index: libc/sys/rtems/sys/dirent.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/sys/rtems/sys/dirent.h,v
retrieving revision 1.2
diff -u -p -r1.2 dirent.h
--- libc/sys/rtems/sys/dirent.h	8 Jan 2004 19:25:21 -0000	1.2
+++ libc/sys/rtems/sys/dirent.h	5 Jul 2010 11:43:03 -0000
@@ -19,7 +19,7 @@ typedef struct _dirdesc {
 	long	dd_size;
 	char	*dd_buf;
 	int	dd_len;
-	long	dd_seek;
+	off_t	dd_seek;
 } DIR;
 
 # define __dirfd(dp)	((dp)->dd_fd)
@@ -28,8 +28,10 @@ DIR *opendir(const char *);
 struct dirent *readdir(DIR *);
 void rewinddir(DIR *);
 int closedir(DIR *);
-void seekdir(DIR *dir, long loc);
-long telldir(DIR *dir);
+void seekdir(DIR *dir, off_t loc);
+off_t telldir(DIR *dir);
+/* internal prototype */
+void _seekdir(DIR *dir, off_t loc);
 
 #include <sys/types.h>
 



-- 
Corinna Vinschen
Cygwin Project Co-Leader
Red Hat


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]