This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
Re: Problems with rewinddir() on RTEMS
- From: Corinna Vinschen <vinschen at redhat dot com>
- To: newlib at sourceware dot org
- Date: Mon, 5 Jul 2010 13:47:08 +0200
- Subject: Re: Problems with rewinddir() on RTEMS
- References: <4C31A4D9.8090507@embedded-brains.de>
- Reply-to: newlib at sourceware dot org
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