121363Sdist /* 2*61111Sbostic * Copyright (c) 1983, 1993 3*61111Sbostic * The Regents of the University of California. All rights reserved. 434790Sbostic * 542627Sbostic * %sccs.include.redist.c% 621363Sdist */ 721363Sdist 826604Sdonn #if defined(LIBC_SCCS) && !defined(lint) 9*61111Sbostic static char sccsid[] = "@(#)telldir.c 8.1 (Berkeley) 06/04/93"; 1034790Sbostic #endif /* LIBC_SCCS and not lint */ 115929Smckusick 126370Smckusic #include <sys/param.h> 1336545Smckusick #include <dirent.h> 1446597Sdonn #include <stdlib.h> 1546597Sdonn #include <unistd.h> 165929Smckusick 175929Smckusick /* 1838442Smckusick * The option SINGLEUSE may be defined to say that a telldir 1938442Smckusick * cookie may be used only once before it is freed. This option 2038442Smckusick * is used to avoid having memory usage grow without bound. 2138442Smckusick */ 2238442Smckusick #define SINGLEUSE 2338442Smckusick 2438442Smckusick /* 2538442Smckusick * One of these structures is malloced to describe the current directory 2638442Smckusick * position each time telldir is called. It records the current magic 2738442Smckusick * cookie returned by getdirentries and the offset within the buffer 2838442Smckusick * associated with that return value. 2938442Smckusick */ 3038442Smckusick struct ddloc { 3138442Smckusick struct ddloc *loc_next;/* next structure in list */ 3238442Smckusick long loc_index; /* key associated with structure */ 3338442Smckusick long loc_seek; /* magic cookie returned by getdirentries */ 3438442Smckusick long loc_loc; /* offset of entry in buffer */ 3538442Smckusick }; 3638442Smckusick 3738442Smckusick #define NDIRHASH 32 /* Num of hash lists, must be a power of 2 */ 3838442Smckusick #define LOCHASH(i) ((i)&(NDIRHASH-1)) 3938442Smckusick 4038442Smckusick static long dd_loccnt; /* Index of entry for sequential readdir's */ 4138442Smckusick static struct ddloc *dd_hash[NDIRHASH]; /* Hash list heads for ddlocs */ 4238442Smckusick 4338442Smckusick /* 445929Smckusick * return a pointer into a directory 455929Smckusick */ 465929Smckusick long telldir(dirp)475929Smckusicktelldir(dirp) 4846597Sdonn const DIR *dirp; 495929Smckusick { 5038435Smckusick register int index; 5138435Smckusick register struct ddloc *lp; 5211827Smckusick 5338435Smckusick if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL) 5438435Smckusick return (-1); 5538442Smckusick index = dd_loccnt++; 5638435Smckusick lp->loc_index = index; 5738435Smckusick lp->loc_seek = dirp->dd_seek; 5838435Smckusick lp->loc_loc = dirp->dd_loc; 5938442Smckusick lp->loc_next = dd_hash[LOCHASH(index)]; 6038442Smckusick dd_hash[LOCHASH(index)] = lp; 6138435Smckusick return (index); 625929Smckusick } 6338442Smckusick 6438442Smckusick /* 6538442Smckusick * seek to an entry in a directory. 6638442Smckusick * Only values returned by "telldir" should be passed to seekdir. 6738442Smckusick */ 6838442Smckusick void _seekdir(dirp,loc)6938442Smckusick_seekdir(dirp, loc) 7038442Smckusick register DIR *dirp; 7138442Smckusick long loc; 7238442Smckusick { 7338442Smckusick register struct ddloc *lp; 7438442Smckusick register struct ddloc **prevlp; 7538442Smckusick struct dirent *dp; 7638442Smckusick 7738442Smckusick prevlp = &dd_hash[LOCHASH(loc)]; 7838442Smckusick lp = *prevlp; 7938442Smckusick while (lp != NULL) { 8038442Smckusick if (lp->loc_index == loc) 8138442Smckusick break; 8238442Smckusick prevlp = &lp->loc_next; 8338442Smckusick lp = lp->loc_next; 8438442Smckusick } 8538442Smckusick if (lp == NULL) 8638442Smckusick return; 8738442Smckusick if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek) 8838442Smckusick goto found; 8954370Sbostic (void) lseek(dirp->dd_fd, (off_t)lp->loc_seek, SEEK_SET); 9039959Smckusick dirp->dd_seek = lp->loc_seek; 9138442Smckusick dirp->dd_loc = 0; 9238442Smckusick while (dirp->dd_loc < lp->loc_loc) { 9338442Smckusick dp = readdir(dirp); 9438442Smckusick if (dp == NULL) 9538442Smckusick break; 9638442Smckusick } 9738442Smckusick found: 9838442Smckusick #ifdef SINGLEUSE 9938442Smckusick *prevlp = lp->loc_next; 10038442Smckusick free((caddr_t)lp); 10138442Smckusick #endif 10238442Smckusick } 103