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*39959Smckusick static char sccsid[] = "@(#)telldir.c 5.7 (Berkeley) 01/30/90"; 2034790Sbostic #endif /* LIBC_SCCS and not lint */ 215929Smckusick 226370Smckusic #include <sys/param.h> 2336545Smckusick #include <dirent.h> 245929Smckusick 255929Smckusick /* 2638442Smckusick * The option SINGLEUSE may be defined to say that a telldir 2738442Smckusick * cookie may be used only once before it is freed. This option 2838442Smckusick * is used to avoid having memory usage grow without bound. 2938442Smckusick */ 3038442Smckusick #define SINGLEUSE 3138442Smckusick 3238442Smckusick /* 3338442Smckusick * One of these structures is malloced to describe the current directory 3438442Smckusick * position each time telldir is called. It records the current magic 3538442Smckusick * cookie returned by getdirentries and the offset within the buffer 3638442Smckusick * associated with that return value. 3738442Smckusick */ 3838442Smckusick struct ddloc { 3938442Smckusick struct ddloc *loc_next;/* next structure in list */ 4038442Smckusick long loc_index; /* key associated with structure */ 4138442Smckusick long loc_seek; /* magic cookie returned by getdirentries */ 4238442Smckusick long loc_loc; /* offset of entry in buffer */ 4338442Smckusick }; 4438442Smckusick 4538442Smckusick #define NDIRHASH 32 /* Num of hash lists, must be a power of 2 */ 4638442Smckusick #define LOCHASH(i) ((i)&(NDIRHASH-1)) 4738442Smckusick 4838442Smckusick static long dd_loccnt; /* Index of entry for sequential readdir's */ 4938442Smckusick static struct ddloc *dd_hash[NDIRHASH]; /* Hash list heads for ddlocs */ 5038442Smckusick 5138442Smckusick /* 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); 6338442Smckusick index = dd_loccnt++; 6438435Smckusick lp->loc_index = index; 6538435Smckusick lp->loc_seek = dirp->dd_seek; 6638435Smckusick lp->loc_loc = dirp->dd_loc; 6738442Smckusick lp->loc_next = dd_hash[LOCHASH(index)]; 6838442Smckusick dd_hash[LOCHASH(index)] = lp; 6938435Smckusick return (index); 705929Smckusick } 7138442Smckusick 7238442Smckusick /* 7338442Smckusick * seek to an entry in a directory. 7438442Smckusick * Only values returned by "telldir" should be passed to seekdir. 7538442Smckusick */ 7638442Smckusick void 7738442Smckusick _seekdir(dirp, loc) 7838442Smckusick register DIR *dirp; 7938442Smckusick long loc; 8038442Smckusick { 8138442Smckusick register struct ddloc *lp; 8238442Smckusick register struct ddloc **prevlp; 8338442Smckusick struct dirent *dp; 8438442Smckusick extern long lseek(); 8538442Smckusick 8638442Smckusick prevlp = &dd_hash[LOCHASH(loc)]; 8738442Smckusick lp = *prevlp; 8838442Smckusick while (lp != NULL) { 8938442Smckusick if (lp->loc_index == loc) 9038442Smckusick break; 9138442Smckusick prevlp = &lp->loc_next; 9238442Smckusick lp = lp->loc_next; 9338442Smckusick } 9438442Smckusick if (lp == NULL) 9538442Smckusick return; 9638442Smckusick if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek) 9738442Smckusick goto found; 9838442Smckusick (void) lseek(dirp->dd_fd, lp->loc_seek, 0); 99*39959Smckusick dirp->dd_seek = lp->loc_seek; 10038442Smckusick dirp->dd_loc = 0; 10138442Smckusick while (dirp->dd_loc < lp->loc_loc) { 10238442Smckusick dp = readdir(dirp); 10338442Smckusick if (dp == NULL) 10438442Smckusick break; 10538442Smckusick } 10638442Smckusick found: 10738442Smckusick #ifdef SINGLEUSE 10838442Smckusick *prevlp = lp->loc_next; 10938442Smckusick free((caddr_t)lp); 11038442Smckusick #endif 11138442Smckusick } 112