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