telldir.c revision 235647
12116Sjkh/* 22116Sjkh * Copyright (c) 1983, 1993 32116Sjkh * The Regents of the University of California. All rights reserved. 42116Sjkh * 52116Sjkh * Redistribution and use in source and binary forms, with or without 62116Sjkh * modification, are permitted provided that the following conditions 72116Sjkh * are met: 82116Sjkh * 1. Redistributions of source code must retain the above copyright 92116Sjkh * notice, this list of conditions and the following disclaimer. 102116Sjkh * 2. Redistributions in binary form must reproduce the above copyright 118870Srgrimes * notice, this list of conditions and the following disclaimer in the 122116Sjkh * documentation and/or other materials provided with the distribution. 132116Sjkh * 4. Neither the name of the University nor the names of its contributors 142116Sjkh * may be used to endorse or promote products derived from this software 152116Sjkh * without specific prior written permission. 162116Sjkh * 1750476Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 182116Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 192116Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 202116Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 212116Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 222116Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 232116Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 242116Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 252116Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 262116Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 272116Sjkh * SUCH DAMAGE. 282116Sjkh */ 292116Sjkh 30142369Sdas#if defined(LIBC_SCCS) && !defined(lint) 31142369Sdasstatic char sccsid[] = "@(#)telldir.c 8.1 (Berkeley) 6/4/93"; 32142369Sdas#endif /* LIBC_SCCS and not lint */ 33142369Sdas#include <sys/cdefs.h> 342116Sjkh__FBSDID("$FreeBSD: head/lib/libc/gen/telldir.c 235647 2012-05-19 12:44:27Z gleb $"); 352116Sjkh 362116Sjkh#include "namespace.h" 372116Sjkh#include <sys/param.h> 382116Sjkh#include <sys/queue.h> 392116Sjkh#include <dirent.h> 402116Sjkh#include <pthread.h> 4197407Salfred#include <stdlib.h> 42142369Sdas#include <unistd.h> 432116Sjkh#include "un-namespace.h" 44142369Sdas 4517141Sjkh#include "libc_private.h" 462116Sjkh#include "gen-private.h" 472116Sjkh#include "telldir.h" 482116Sjkh 492116Sjkh/* 50142369Sdas * The option SINGLEUSE may be defined to say that a telldir 512116Sjkh * cookie may be used only once before it is freed. This option 522116Sjkh * is used to avoid having memory usage grow without bound. 532116Sjkh */ 542116Sjkh#define SINGLEUSE 552116Sjkh 562116Sjkh/* 572116Sjkh * return a pointer into a directory 582116Sjkh */ 592116Sjkhlong 602116Sjkhtelldir(dirp) 612116Sjkh DIR *dirp; 622116Sjkh{ 638870Srgrimes struct ddloc *lp; 642116Sjkh 65142369Sdas if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL) 662116Sjkh return (-1); 672116Sjkh if (__isthreaded) 682116Sjkh _pthread_mutex_lock(&dirp->dd_lock); 69142369Sdas lp->loc_index = dirp->dd_td->td_loccnt++; 70142369Sdas lp->loc_seek = dirp->dd_seek; 712116Sjkh lp->loc_loc = dirp->dd_loc; 72142369Sdas LIST_INSERT_HEAD(&dirp->dd_td->td_locq, lp, loc_lqe); 738870Srgrimes if (__isthreaded) 742116Sjkh _pthread_mutex_unlock(&dirp->dd_lock); 752116Sjkh return (lp->loc_index); 762116Sjkh} 772116Sjkh 782116Sjkh/* 792116Sjkh * seek to an entry in a directory. 802116Sjkh * Only values returned by "telldir" should be passed to seekdir. 812116Sjkh */ 82142369Sdasvoid 83142369Sdas_seekdir(dirp, loc) 842116Sjkh DIR *dirp; 852116Sjkh long loc; 862116Sjkh{ 872116Sjkh struct ddloc *lp; 882116Sjkh struct dirent *dp; 892116Sjkh 902116Sjkh LIST_FOREACH(lp, &dirp->dd_td->td_locq, loc_lqe) { 912116Sjkh if (lp->loc_index == loc) 922116Sjkh break; 932116Sjkh } 942116Sjkh if (lp == NULL) 952116Sjkh return; 96 if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek) 97 goto found; 98 (void) lseek(dirp->dd_fd, (off_t)lp->loc_seek, SEEK_SET); 99 dirp->dd_seek = lp->loc_seek; 100 dirp->dd_loc = 0; 101 while (dirp->dd_loc < lp->loc_loc) { 102 dp = _readdir_unlocked(dirp, 0); 103 if (dp == NULL) 104 break; 105 } 106found: 107#ifdef SINGLEUSE 108 LIST_REMOVE(lp, loc_lqe); 109 free((caddr_t)lp); 110#endif 111} 112 113/* 114 * Reclaim memory for telldir cookies which weren't used. 115 */ 116void 117_reclaim_telldir(dirp) 118 DIR *dirp; 119{ 120 struct ddloc *lp; 121 struct ddloc *templp; 122 123 lp = LIST_FIRST(&dirp->dd_td->td_locq); 124 while (lp != NULL) { 125 templp = lp; 126 lp = LIST_NEXT(lp, loc_lqe); 127 free(templp); 128 } 129 LIST_INIT(&dirp->dd_td->td_locq); 130} 131