Blame src/lib/libast/dir/getdents.c

Packit Service a8c26c
/***********************************************************************
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*               This software is part of the ast package               *
Packit Service a8c26c
*          Copyright (c) 1985-2011 AT&T Intellectual Property          *
Packit Service a8c26c
*                      and is licensed under the                       *
Packit Service a8c26c
*                 Eclipse Public License, Version 1.0                  *
Packit Service a8c26c
*                    by AT&T Intellectual Property                     *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                A copy of the License is available at                 *
Packit Service a8c26c
*          http://www.eclipse.org/org/documents/epl-v10.html           *
Packit Service a8c26c
*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*              Information and Software Systems Research               *
Packit Service a8c26c
*                            AT&T Research                             *
Packit Service a8c26c
*                           Florham Park NJ                            *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                 Glenn Fowler <gsf@research.att.com>                  *
Packit Service a8c26c
*                  David Korn <dgk@research.att.com>                   *
Packit Service a8c26c
*                   Phong Vo <kpv@research.att.com>                    *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
***********************************************************************/
Packit Service a8c26c
#pragma prototyped
Packit Service a8c26c
Packit Service a8c26c
#include "dirlib.h"
Packit Service a8c26c
Packit Service a8c26c
#if _dir_ok || _lib_getdents
Packit Service a8c26c
Packit Service a8c26c
NoN(getdents)
Packit Service a8c26c
Packit Service a8c26c
#else
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * getdents
Packit Service a8c26c
 *
Packit Service a8c26c
 * read directory entries into directory block
Packit Service a8c26c
 *
Packit Service a8c26c
 * NOTE: directory entries must fit within DIRBLKSIZ boundaries
Packit Service a8c26c
 */
Packit Service a8c26c
Packit Service a8c26c
#ifndef MAXNAMLEN
Packit Service a8c26c
#define MAXNAMLEN	255
Packit Service a8c26c
#endif
Packit Service a8c26c
Packit Service a8c26c
#if _lib_dirread
Packit Service a8c26c
extern int		dirread(int, char*, int);
Packit Service a8c26c
#endif
Packit Service a8c26c
#if _lib_getdirentries
Packit Service a8c26c
extern int		getdirentries(int, char*, int, long*);
Packit Service a8c26c
#endif
Packit Service a8c26c
Packit Service a8c26c
ssize_t
Packit Service a8c26c
getdents(int fd, void* buf, size_t siz)
Packit Service a8c26c
{
Packit Service a8c26c
	struct stat		st;
Packit Service a8c26c
Packit Service a8c26c
	if (siz < DIRBLKSIZ)
Packit Service a8c26c
	{
Packit Service a8c26c
		errno = EINVAL;
Packit Service a8c26c
		return(-1);
Packit Service a8c26c
	}
Packit Service a8c26c
	if (fstat(fd, &st)) return(-1);
Packit Service a8c26c
	if (!S_ISDIR(st.st_mode))
Packit Service a8c26c
	{
Packit Service a8c26c
#ifdef ENOTDIR
Packit Service a8c26c
		errno = ENOTDIR;
Packit Service a8c26c
#else
Packit Service a8c26c
		errno = EBADF;
Packit Service a8c26c
#endif
Packit Service a8c26c
		return(-1);
Packit Service a8c26c
	}
Packit Service a8c26c
#if _lib_getdirentries
Packit Service a8c26c
	{
Packit Service a8c26c
		long		off;
Packit Service a8c26c
		return(getdirentries(fd, buf, siz, &off));
Packit Service a8c26c
	}
Packit Service a8c26c
#else
Packit Service a8c26c
#if _lib_dirread
Packit Service a8c26c
	{
Packit Service a8c26c
		register char*		sp;	/* system */
Packit Service a8c26c
		register struct dirent*	up;	/* user */
Packit Service a8c26c
		char*			u;
Packit Service a8c26c
		int			n;
Packit Service a8c26c
		int			m;
Packit Service a8c26c
		int			i;
Packit Service a8c26c
Packit Service a8c26c
		m = (siz * 6) / 10;
Packit Service a8c26c
		m = roundof(m, 8);
Packit Service a8c26c
		sp = (char*)buf + siz - m - 1;
Packit Service a8c26c
		if (!(n = dirread(fd, sp, m))) return(0);
Packit Service a8c26c
		if (n > 0)
Packit Service a8c26c
		{
Packit Service a8c26c
			up = (struct dirent*)buf;
Packit Service a8c26c
			sp[n] = 0;
Packit Service a8c26c
			while (sp < (char*)buf + siz - m + n)
Packit Service a8c26c
			{
Packit Service a8c26c
				i = 0;
Packit Service a8c26c
				while (*sp >= '0' && *sp <= '9')
Packit Service a8c26c
					i = 10 * i + *sp++ - '0';
Packit Service a8c26c
				while (*sp && *sp != '\t') sp++;
Packit Service a8c26c
				if (*sp++)
Packit Service a8c26c
				{
Packit Service a8c26c
					up->d_fileno = i;
Packit Service a8c26c
					u = up->d_name;
Packit Service a8c26c
					while ((*u = *sp++) && u < up->d_name + MAXNAMLEN) u++;
Packit Service a8c26c
					*u = 0;
Packit Service a8c26c
					up->d_reclen = sizeof(struct dirent) - sizeof(up->d_name) + (up->d_namlen = u - up->d_name) + 1;
Packit Service a8c26c
					up->d_reclen = roundof(up->d_reclen, 8);
Packit Service a8c26c
					up = (struct dirent*)((char*)up + up->d_reclen);
Packit Service a8c26c
				}
Packit Service a8c26c
			}
Packit Service a8c26c
			return((char*)up - (char*)buf);
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
#else
Packit Service a8c26c
#if _mem_d_reclen_direct
Packit Service a8c26c
	return(read(fd, buf, siz));
Packit Service a8c26c
#else
Packit Service a8c26c
	{
Packit Service a8c26c
Packit Service a8c26c
#define MAXREC	roundof(sizeof(*up)-sizeof(up->d_name)+sizeof(sp->d_name)+1,8)
Packit Service a8c26c
Packit Service a8c26c
		register struct direct*	sp;	/* system */
Packit Service a8c26c
		register struct dirent*	up;	/* user */
Packit Service a8c26c
		register char*		s;
Packit Service a8c26c
		register char*		u;
Packit Service a8c26c
		int			n;
Packit Service a8c26c
		int			m;
Packit Service a8c26c
		char			tmp[sizeof(sp->d_name) + 1];
Packit Service a8c26c
Packit Service a8c26c
		/*
Packit Service a8c26c
		 * we assume sizeof(struct dirent) > sizeof(struct direct)
Packit Service a8c26c
		 */
Packit Service a8c26c
Packit Service a8c26c
		up = (struct dirent*)buf;
Packit Service a8c26c
		n = (siz / MAXREC) * sizeof(struct direct);
Packit Service a8c26c
		if ((!(m = n & ~511) || m < MAXREC) && (!(m = n & ~255) || m < MAXREC)) m = n;
Packit Service a8c26c
		do
Packit Service a8c26c
		{
Packit Service a8c26c
			if ((n = read(fd, (char*)buf + siz - m, m)) <= 0) break;
Packit Service a8c26c
			sp = (struct direct*)((char*)buf + siz - m);
Packit Service a8c26c
			while (sp < (struct direct*)((char*)buf + siz - m + n))
Packit Service a8c26c
			{
Packit Service a8c26c
				if (sp->d_ino)
Packit Service a8c26c
				{
Packit Service a8c26c
					up->d_fileno = sp->d_ino;
Packit Service a8c26c
					s = sp->d_name;
Packit Service a8c26c
					u = tmp;
Packit Service a8c26c
					while (s < sp->d_name + sizeof(sp->d_name) && *s)
Packit Service a8c26c
						*u++ = *s++;
Packit Service a8c26c
					*u = 0;
Packit Service a8c26c
					strcpy(up->d_name, tmp);
Packit Service a8c26c
					up->d_reclen = sizeof(struct dirent) - sizeof(up->d_name) + (up->d_namlen = u - tmp) + 1;
Packit Service a8c26c
					up->d_reclen = roundof(up->d_reclen, 8);
Packit Service a8c26c
					up = (struct dirent*)((char*)up + up->d_reclen);
Packit Service a8c26c
				}
Packit Service a8c26c
				sp++;
Packit Service a8c26c
			}
Packit Service a8c26c
		} while (up == (struct dirent*)buf);
Packit Service a8c26c
		return((char*)up - (char*)buf);
Packit Service a8c26c
	}
Packit Service a8c26c
#endif
Packit Service a8c26c
#endif
Packit Service a8c26c
#endif
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
#endif