summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2014-07-29 00:16:33 +0000
committerjhb <jhb@FreeBSD.org>2014-07-29 00:16:33 +0000
commit3fdccc4e7a49e6b99628e68e35c6b5656981c8b8 (patch)
tree183e639360502a6667ba000509809398a5be006b /lib/libc
parent0cc7234e3bb8b89821ec791dad81b9846798da52 (diff)
downloadFreeBSD-src-3fdccc4e7a49e6b99628e68e35c6b5656981c8b8.zip
FreeBSD-src-3fdccc4e7a49e6b99628e68e35c6b5656981c8b8.tar.gz
If telldir() is called immediately after a call to seekdir(), POSIX
requires the return value of telldir() to equal the value passed to seekdir(). The current seekdir code with SINGLEUSE enabled breaks this case as each call to telldir() allocates a new cookie. Instead, remove the SINGLEUSE code and change telldir() to look for an existing cookie for the directory's current location rather than always creating a new cookie. CR: https://phabric.freebsd.org/D490 PR: 121656 Reviewed by: jilles MFC after: 1 week
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/gen/directory.313
-rw-r--r--lib/libc/gen/telldir.c41
2 files changed, 26 insertions, 28 deletions
diff --git a/lib/libc/gen/directory.3 b/lib/libc/gen/directory.3
index 4573d45..1e864f8 100644
--- a/lib/libc/gen/directory.3
+++ b/lib/libc/gen/directory.3
@@ -28,7 +28,7 @@
.\" @(#)directory.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd August 18, 2013
+.Dd July 28, 2014
.Dt DIRECTORY 3
.Os
.Sh NAME
@@ -169,6 +169,10 @@ If the directory is closed and then
reopened, prior values returned by
.Fn telldir
will no longer be valid.
+Values returned by
+.Fn telldir
+are also invalidated by a call to
+.Fn rewinddir .
.Pp
The
.Fn seekdir
@@ -182,13 +186,6 @@ The new position reverts to the one associated with the
when the
.Fn telldir
operation was performed.
-State associated with the token returned by
-.Fn telldir is freed when it is passed to
-.Fn seekdir .
-If you wish return to the same location again,
-then you must create a new token with another
-.Fn telldir
-call.
.Pp
The
.Fn rewinddir
diff --git a/lib/libc/gen/telldir.c b/lib/libc/gen/telldir.c
index 4954b97..d72b500 100644
--- a/lib/libc/gen/telldir.c
+++ b/lib/libc/gen/telldir.c
@@ -47,13 +47,6 @@ __FBSDID("$FreeBSD$");
#include "telldir.h"
/*
- * The option SINGLEUSE may be defined to say that a telldir
- * cookie may be used only once before it is freed. This option
- * is used to avoid having memory usage grow without bound.
- */
-#define SINGLEUSE
-
-/*
* return a pointer into a directory
*/
long
@@ -61,18 +54,31 @@ telldir(dirp)
DIR *dirp;
{
struct ddloc *lp;
+ long idx;
- if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL)
- return (-1);
if (__isthreaded)
_pthread_mutex_lock(&dirp->dd_lock);
- lp->loc_index = dirp->dd_td->td_loccnt++;
- lp->loc_seek = dirp->dd_seek;
- lp->loc_loc = dirp->dd_loc;
- LIST_INSERT_HEAD(&dirp->dd_td->td_locq, lp, loc_lqe);
+ LIST_FOREACH(lp, &dirp->dd_td->td_locq, loc_lqe) {
+ if (lp->loc_seek == dirp->dd_seek &&
+ lp->loc_loc == dirp->dd_loc)
+ break;
+ }
+ if (lp == NULL) {
+ lp = malloc(sizeof(struct ddloc));
+ if (lp == NULL) {
+ if (__isthreaded)
+ _pthread_mutex_unlock(&dirp->dd_lock);
+ return (-1);
+ }
+ lp->loc_index = dirp->dd_td->td_loccnt++;
+ lp->loc_seek = dirp->dd_seek;
+ lp->loc_loc = dirp->dd_loc;
+ LIST_INSERT_HEAD(&dirp->dd_td->td_locq, lp, loc_lqe);
+ }
+ idx = lp->loc_index;
if (__isthreaded)
_pthread_mutex_unlock(&dirp->dd_lock);
- return (lp->loc_index);
+ return (idx);
}
/*
@@ -94,7 +100,7 @@ _seekdir(dirp, loc)
if (lp == NULL)
return;
if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek)
- goto found;
+ return;
(void) lseek(dirp->dd_fd, (off_t)lp->loc_seek, SEEK_SET);
dirp->dd_seek = lp->loc_seek;
dirp->dd_loc = 0;
@@ -103,11 +109,6 @@ _seekdir(dirp, loc)
if (dp == NULL)
break;
}
-found:
-#ifdef SINGLEUSE
- LIST_REMOVE(lp, loc_lqe);
- free((caddr_t)lp);
-#endif
}
/*
OpenPOWER on IntegriCloud