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