xref: /onnv-gate/usr/src/lib/libast/common/dir/getdents.c (revision 4887:feebf9260c2e)
1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
18*4887Schin *                  David Korn <dgk@research.att.com>                   *
19*4887Schin *                   Phong Vo <kpv@research.att.com>                    *
20*4887Schin *                                                                      *
21*4887Schin ***********************************************************************/
22*4887Schin #pragma prototyped
23*4887Schin 
24*4887Schin #include "dirlib.h"
25*4887Schin 
26*4887Schin #if _dir_ok || _lib_getdents
27*4887Schin 
28*4887Schin NoN(getdents)
29*4887Schin 
30*4887Schin #else
31*4887Schin 
32*4887Schin /*
33*4887Schin  * getdents
34*4887Schin  *
35*4887Schin  * read directory entries into directory block
36*4887Schin  *
37*4887Schin  * NOTE: directory entries must fit within DIRBLKSIZ boundaries
38*4887Schin  */
39*4887Schin 
40*4887Schin #ifndef MAXNAMLEN
41*4887Schin #define MAXNAMLEN	255
42*4887Schin #endif
43*4887Schin 
44*4887Schin #if _lib_dirread
45*4887Schin extern int		dirread(int, char*, int);
46*4887Schin #endif
47*4887Schin #if _lib_getdirentries
48*4887Schin extern int		getdirentries(int, char*, int, long*);
49*4887Schin #endif
50*4887Schin 
51*4887Schin ssize_t
52*4887Schin getdents(int fd, void* buf, size_t siz)
53*4887Schin {
54*4887Schin 	struct stat		st;
55*4887Schin 
56*4887Schin 	if (siz < DIRBLKSIZ)
57*4887Schin 	{
58*4887Schin 		errno = EINVAL;
59*4887Schin 		return(-1);
60*4887Schin 	}
61*4887Schin 	if (fstat(fd, &st)) return(-1);
62*4887Schin 	if (!S_ISDIR(st.st_mode))
63*4887Schin 	{
64*4887Schin #ifdef ENOTDIR
65*4887Schin 		errno = ENOTDIR;
66*4887Schin #else
67*4887Schin 		errno = EBADF;
68*4887Schin #endif
69*4887Schin 		return(-1);
70*4887Schin 	}
71*4887Schin #if _lib_getdirentries
72*4887Schin 	{
73*4887Schin 		long		off;
74*4887Schin 		return(getdirentries(fd, buf, siz, &off));
75*4887Schin 	}
76*4887Schin #else
77*4887Schin #if _lib_dirread
78*4887Schin 	{
79*4887Schin 		register char*		sp;	/* system */
80*4887Schin 		register struct dirent*	up;	/* user */
81*4887Schin 		char*			u;
82*4887Schin 		int			n;
83*4887Schin 		int			m;
84*4887Schin 		int			i;
85*4887Schin 
86*4887Schin 		m = (siz * 6) / 10;
87*4887Schin 		m = roundof(m, 8);
88*4887Schin 		sp = (char*)buf + siz - m - 1;
89*4887Schin 		if (!(n = dirread(fd, sp, m))) return(0);
90*4887Schin 		if (n > 0)
91*4887Schin 		{
92*4887Schin 			up = (struct dirent*)buf;
93*4887Schin 			sp[n] = 0;
94*4887Schin 			while (sp < (char*)buf + siz - m + n)
95*4887Schin 			{
96*4887Schin 				i = 0;
97*4887Schin 				while (*sp >= '0' && *sp <= '9')
98*4887Schin 					i = 10 * i + *sp++ - '0';
99*4887Schin 				while (*sp && *sp != '\t') sp++;
100*4887Schin 				if (*sp++)
101*4887Schin 				{
102*4887Schin 					up->d_fileno = i;
103*4887Schin 					u = up->d_name;
104*4887Schin 					while ((*u = *sp++) && u < up->d_name + MAXNAMLEN) u++;
105*4887Schin 					*u = 0;
106*4887Schin 					up->d_reclen = sizeof(struct dirent) - sizeof(up->d_name) + (up->d_namlen = u - up->d_name) + 1;
107*4887Schin 					up->d_reclen = roundof(up->d_reclen, 8);
108*4887Schin 					up = (struct dirent*)((char*)up + up->d_reclen);
109*4887Schin 				}
110*4887Schin 			}
111*4887Schin 			return((char*)up - (char*)buf);
112*4887Schin 		}
113*4887Schin 	}
114*4887Schin #else
115*4887Schin #if _mem_d_reclen_direct
116*4887Schin 	return(read(fd, buf, siz));
117*4887Schin #else
118*4887Schin 	{
119*4887Schin 
120*4887Schin #define MAXREC	roundof(sizeof(*up)-sizeof(up->d_name)+sizeof(sp->d_name)+1,8)
121*4887Schin 
122*4887Schin 		register struct direct*	sp;	/* system */
123*4887Schin 		register struct dirent*	up;	/* user */
124*4887Schin 		register char*		s;
125*4887Schin 		register char*		u;
126*4887Schin 		int			n;
127*4887Schin 		int			m;
128*4887Schin 		char			tmp[sizeof(sp->d_name) + 1];
129*4887Schin 
130*4887Schin 		/*
131*4887Schin 		 * we assume sizeof(struct dirent) > sizeof(struct direct)
132*4887Schin 		 */
133*4887Schin 
134*4887Schin 		up = (struct dirent*)buf;
135*4887Schin 		n = (siz / MAXREC) * sizeof(struct direct);
136*4887Schin 		if ((!(m = n & ~511) || m < MAXREC) && (!(m = n & ~255) || m < MAXREC)) m = n;
137*4887Schin 		do
138*4887Schin 		{
139*4887Schin 			if ((n = read(fd, (char*)buf + siz - m, m)) <= 0) break;
140*4887Schin 			sp = (struct direct*)((char*)buf + siz - m);
141*4887Schin 			while (sp < (struct direct*)((char*)buf + siz - m + n))
142*4887Schin 			{
143*4887Schin 				if (sp->d_ino)
144*4887Schin 				{
145*4887Schin 					up->d_fileno = sp->d_ino;
146*4887Schin 					s = sp->d_name;
147*4887Schin 					u = tmp;
148*4887Schin 					while (s < sp->d_name + sizeof(sp->d_name) && *s)
149*4887Schin 						*u++ = *s++;
150*4887Schin 					*u = 0;
151*4887Schin 					strcpy(up->d_name, tmp);
152*4887Schin 					up->d_reclen = sizeof(struct dirent) - sizeof(up->d_name) + (up->d_namlen = u - tmp) + 1;
153*4887Schin 					up->d_reclen = roundof(up->d_reclen, 8);
154*4887Schin 					up = (struct dirent*)((char*)up + up->d_reclen);
155*4887Schin 				}
156*4887Schin 				sp++;
157*4887Schin 			}
158*4887Schin 		} while (up == (struct dirent*)buf);
159*4887Schin 		return((char*)up - (char*)buf);
160*4887Schin 	}
161*4887Schin #endif
162*4887Schin #endif
163*4887Schin #endif
164*4887Schin }
165*4887Schin 
166*4887Schin #endif
167