svn commit: r269204 - head/lib/libc/gen

John Baldwin jhb at FreeBSD.org
Tue Jul 29 00:16:34 UTC 2014


Author: jhb
Date: Tue Jul 29 00:16:33 2014
New Revision: 269204
URL: http://svnweb.freebsd.org/changeset/base/269204

Log:
  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

Modified:
  head/lib/libc/gen/directory.3
  head/lib/libc/gen/telldir.c

Modified: head/lib/libc/gen/directory.3
==============================================================================
--- head/lib/libc/gen/directory.3	Mon Jul 28 23:36:21 2014	(r269203)
+++ head/lib/libc/gen/directory.3	Tue Jul 29 00:16:33 2014	(r269204)
@@ -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 asso
 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

Modified: head/lib/libc/gen/telldir.c
==============================================================================
--- head/lib/libc/gen/telldir.c	Mon Jul 28 23:36:21 2014	(r269203)
+++ head/lib/libc/gen/telldir.c	Tue Jul 29 00:16:33 2014	(r269204)
@@ -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
 }
 
 /*


More information about the svn-src-head mailing list