121363Sdist /* 221363Sdist * Copyright (c) 1983 Regents of the University of California. 334790Sbostic * All rights reserved. 434790Sbostic * 534790Sbostic * Redistribution and use in source and binary forms are permitted 634790Sbostic * provided that the above copyright notice and this paragraph are 734790Sbostic * duplicated in all such forms and that any documentation, 834790Sbostic * advertising materials, and other materials related to such 934790Sbostic * distribution and use acknowledge that the software was developed 1034790Sbostic * by the University of California, Berkeley. The name of the 1134790Sbostic * University may not be used to endorse or promote products derived 1234790Sbostic * from this software without specific prior written permission. 1334790Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434790Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534790Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621363Sdist */ 1721363Sdist 1826604Sdonn #if defined(LIBC_SCCS) && !defined(lint) 19*38442Smckusick static char sccsid[] = "@(#)telldir.c 5.6 (Berkeley) 07/11/89"; 2034790Sbostic #endif /* LIBC_SCCS and not lint */ 215929Smckusick 226370Smckusic #include <sys/param.h> 2336545Smckusick #include <dirent.h> 245929Smckusick 255929Smckusick /* 26*38442Smckusick * The option SINGLEUSE may be defined to say that a telldir 27*38442Smckusick * cookie may be used only once before it is freed. This option 28*38442Smckusick * is used to avoid having memory usage grow without bound. 29*38442Smckusick */ 30*38442Smckusick #define SINGLEUSE 31*38442Smckusick 32*38442Smckusick /* 33*38442Smckusick * One of these structures is malloced to describe the current directory 34*38442Smckusick * position each time telldir is called. It records the current magic 35*38442Smckusick * cookie returned by getdirentries and the offset within the buffer 36*38442Smckusick * associated with that return value. 37*38442Smckusick */ 38*38442Smckusick struct ddloc { 39*38442Smckusick struct ddloc *loc_next;/* next structure in list */ 40*38442Smckusick long loc_index; /* key associated with structure */ 41*38442Smckusick long loc_seek; /* magic cookie returned by getdirentries */ 42*38442Smckusick long loc_loc; /* offset of entry in buffer */ 43*38442Smckusick }; 44*38442Smckusick 45*38442Smckusick #define NDIRHASH 32 /* Num of hash lists, must be a power of 2 */ 46*38442Smckusick #define LOCHASH(i) ((i)&(NDIRHASH-1)) 47*38442Smckusick 48*38442Smckusick static long dd_loccnt; /* Index of entry for sequential readdir's */ 49*38442Smckusick static struct ddloc *dd_hash[NDIRHASH]; /* Hash list heads for ddlocs */ 50*38442Smckusick 51*38442Smckusick /* 525929Smckusick * return a pointer into a directory 535929Smckusick */ 545929Smckusick long 555929Smckusick telldir(dirp) 565929Smckusick DIR *dirp; 575929Smckusick { 5838435Smckusick register int index; 5938435Smckusick register struct ddloc *lp; 6011827Smckusick 6138435Smckusick if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL) 6238435Smckusick return (-1); 63*38442Smckusick index = dd_loccnt++; 6438435Smckusick lp->loc_index = index; 6538435Smckusick lp->loc_seek = dirp->dd_seek; 6638435Smckusick lp->loc_loc = dirp->dd_loc; 67*38442Smckusick lp->loc_next = dd_hash[LOCHASH(index)]; 68*38442Smckusick dd_hash[LOCHASH(index)] = lp; 6938435Smckusick return (index); 705929Smckusick } 71*38442Smckusick 72*38442Smckusick /* 73*38442Smckusick * seek to an entry in a directory. 74*38442Smckusick * Only values returned by "telldir" should be passed to seekdir. 75*38442Smckusick */ 76*38442Smckusick void 77*38442Smckusick _seekdir(dirp, loc) 78*38442Smckusick register DIR *dirp; 79*38442Smckusick long loc; 80*38442Smckusick { 81*38442Smckusick register struct ddloc *lp; 82*38442Smckusick register struct ddloc **prevlp; 83*38442Smckusick struct dirent *dp; 84*38442Smckusick extern long lseek(); 85*38442Smckusick 86*38442Smckusick prevlp = &dd_hash[LOCHASH(loc)]; 87*38442Smckusick lp = *prevlp; 88*38442Smckusick while (lp != NULL) { 89*38442Smckusick if (lp->loc_index == loc) 90*38442Smckusick break; 91*38442Smckusick prevlp = &lp->loc_next; 92*38442Smckusick lp = lp->loc_next; 93*38442Smckusick } 94*38442Smckusick if (lp == NULL) 95*38442Smckusick return; 96*38442Smckusick if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek) 97*38442Smckusick goto found; 98*38442Smckusick (void) lseek(dirp->dd_fd, lp->loc_seek, 0); 99*38442Smckusick dirp->dd_loc = 0; 100*38442Smckusick while (dirp->dd_loc < lp->loc_loc) { 101*38442Smckusick dp = readdir(dirp); 102*38442Smckusick if (dp == NULL) 103*38442Smckusick break; 104*38442Smckusick } 105*38442Smckusick found: 106*38442Smckusick #ifdef SINGLEUSE 107*38442Smckusick *prevlp = lp->loc_next; 108*38442Smckusick free((caddr_t)lp); 109*38442Smckusick #endif 110*38442Smckusick } 111