xref: /onnv-gate/usr/src/lib/libast/common/dir/getdents.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin 
244887Schin #include "dirlib.h"
254887Schin 
264887Schin #if _dir_ok || _lib_getdents
274887Schin 
284887Schin NoN(getdents)
294887Schin 
304887Schin #else
314887Schin 
324887Schin /*
334887Schin  * getdents
344887Schin  *
354887Schin  * read directory entries into directory block
364887Schin  *
374887Schin  * NOTE: directory entries must fit within DIRBLKSIZ boundaries
384887Schin  */
394887Schin 
404887Schin #ifndef MAXNAMLEN
414887Schin #define MAXNAMLEN	255
424887Schin #endif
434887Schin 
444887Schin #if _lib_dirread
454887Schin extern int		dirread(int, char*, int);
464887Schin #endif
474887Schin #if _lib_getdirentries
484887Schin extern int		getdirentries(int, char*, int, long*);
494887Schin #endif
504887Schin 
514887Schin ssize_t
524887Schin getdents(int fd, void* buf, size_t siz)
534887Schin {
544887Schin 	struct stat		st;
554887Schin 
564887Schin 	if (siz < DIRBLKSIZ)
574887Schin 	{
584887Schin 		errno = EINVAL;
594887Schin 		return(-1);
604887Schin 	}
614887Schin 	if (fstat(fd, &st)) return(-1);
624887Schin 	if (!S_ISDIR(st.st_mode))
634887Schin 	{
644887Schin #ifdef ENOTDIR
654887Schin 		errno = ENOTDIR;
664887Schin #else
674887Schin 		errno = EBADF;
684887Schin #endif
694887Schin 		return(-1);
704887Schin 	}
714887Schin #if _lib_getdirentries
724887Schin 	{
734887Schin 		long		off;
744887Schin 		return(getdirentries(fd, buf, siz, &off));
754887Schin 	}
764887Schin #else
774887Schin #if _lib_dirread
784887Schin 	{
794887Schin 		register char*		sp;	/* system */
804887Schin 		register struct dirent*	up;	/* user */
814887Schin 		char*			u;
824887Schin 		int			n;
834887Schin 		int			m;
844887Schin 		int			i;
854887Schin 
864887Schin 		m = (siz * 6) / 10;
874887Schin 		m = roundof(m, 8);
884887Schin 		sp = (char*)buf + siz - m - 1;
894887Schin 		if (!(n = dirread(fd, sp, m))) return(0);
904887Schin 		if (n > 0)
914887Schin 		{
924887Schin 			up = (struct dirent*)buf;
934887Schin 			sp[n] = 0;
944887Schin 			while (sp < (char*)buf + siz - m + n)
954887Schin 			{
964887Schin 				i = 0;
974887Schin 				while (*sp >= '0' && *sp <= '9')
984887Schin 					i = 10 * i + *sp++ - '0';
994887Schin 				while (*sp && *sp != '\t') sp++;
1004887Schin 				if (*sp++)
1014887Schin 				{
1024887Schin 					up->d_fileno = i;
1034887Schin 					u = up->d_name;
1044887Schin 					while ((*u = *sp++) && u < up->d_name + MAXNAMLEN) u++;
1054887Schin 					*u = 0;
1064887Schin 					up->d_reclen = sizeof(struct dirent) - sizeof(up->d_name) + (up->d_namlen = u - up->d_name) + 1;
1074887Schin 					up->d_reclen = roundof(up->d_reclen, 8);
1084887Schin 					up = (struct dirent*)((char*)up + up->d_reclen);
1094887Schin 				}
1104887Schin 			}
1114887Schin 			return((char*)up - (char*)buf);
1124887Schin 		}
1134887Schin 	}
1144887Schin #else
1154887Schin #if _mem_d_reclen_direct
1164887Schin 	return(read(fd, buf, siz));
1174887Schin #else
1184887Schin 	{
1194887Schin 
1204887Schin #define MAXREC	roundof(sizeof(*up)-sizeof(up->d_name)+sizeof(sp->d_name)+1,8)
1214887Schin 
1224887Schin 		register struct direct*	sp;	/* system */
1234887Schin 		register struct dirent*	up;	/* user */
1244887Schin 		register char*		s;
1254887Schin 		register char*		u;
1264887Schin 		int			n;
1274887Schin 		int			m;
1284887Schin 		char			tmp[sizeof(sp->d_name) + 1];
1294887Schin 
1304887Schin 		/*
1314887Schin 		 * we assume sizeof(struct dirent) > sizeof(struct direct)
1324887Schin 		 */
1334887Schin 
1344887Schin 		up = (struct dirent*)buf;
1354887Schin 		n = (siz / MAXREC) * sizeof(struct direct);
1364887Schin 		if ((!(m = n & ~511) || m < MAXREC) && (!(m = n & ~255) || m < MAXREC)) m = n;
1374887Schin 		do
1384887Schin 		{
1394887Schin 			if ((n = read(fd, (char*)buf + siz - m, m)) <= 0) break;
1404887Schin 			sp = (struct direct*)((char*)buf + siz - m);
1414887Schin 			while (sp < (struct direct*)((char*)buf + siz - m + n))
1424887Schin 			{
1434887Schin 				if (sp->d_ino)
1444887Schin 				{
1454887Schin 					up->d_fileno = sp->d_ino;
1464887Schin 					s = sp->d_name;
1474887Schin 					u = tmp;
1484887Schin 					while (s < sp->d_name + sizeof(sp->d_name) && *s)
1494887Schin 						*u++ = *s++;
1504887Schin 					*u = 0;
1514887Schin 					strcpy(up->d_name, tmp);
1524887Schin 					up->d_reclen = sizeof(struct dirent) - sizeof(up->d_name) + (up->d_namlen = u - tmp) + 1;
1534887Schin 					up->d_reclen = roundof(up->d_reclen, 8);
1544887Schin 					up = (struct dirent*)((char*)up + up->d_reclen);
1554887Schin 				}
1564887Schin 				sp++;
1574887Schin 			}
1584887Schin 		} while (up == (struct dirent*)buf);
1594887Schin 		return((char*)up - (char*)buf);
1604887Schin 	}
1614887Schin #endif
1624887Schin #endif
1634887Schin #endif
1644887Schin }
1654887Schin 
1664887Schin #endif
167