Browse Source

Move the dirent stuff. I suppose it is system dependant, but then
it really should be grouped together too. And it needed to be grouped
more then it needed to be in sysdeps/linux/common

Eric Andersen 23 years ago
parent
commit
8bdc62b089

+ 1 - 1
libc/misc/Makefile

@@ -25,7 +25,7 @@ include $(TOPDIR)Rules.mak
 LIBC=$(TOPDIR)libc.a
 
 
-DIRS = assert crypt ctype fnmatch glob internals lsearch mntent syslog \
+DIRS = assert crypt ctype dirent fnmatch glob internals lsearch mntent syslog \
 	time utmp tsearch locale sysvipc
 
 all: libc.a

+ 44 - 0
libc/misc/dirent/Makefile

@@ -0,0 +1,44 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2001 by Lineo, inc.
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Library General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Library General Public License
+# along with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Derived in part from the Linux-8086 C library, the GNU C Library, and several
+# other sundry sources.  Files within this library are copyright by their
+# respective copyright holders.
+
+TOPDIR=../../
+include $(TOPDIR)Rules.mak
+LIBC=$(TOPDIR)libc.a
+
+CSRC=closedir.c dirfd.c opendir.c readdir.c rewinddir.c seekdir.c telldir.c
+COBJS=$(patsubst %.c,%.o, $(CSRC))
+OBJS=$(COBJS)
+
+all: $(OBJS) $(LIBC)
+
+$(LIBC): ar-target
+
+ar-target: $(OBJS)
+	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
+
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
+	$(STRIPTOOL) -x -R .note -R .comment $*.o
+
+clean:
+	rm -f *.[oa] *~ core
+

+ 26 - 0
libc/misc/dirent/closedir.c

@@ -0,0 +1,26 @@
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "dirstream.h"
+
+
+int closedir(DIR * dir)
+{
+	int fd;
+
+	if (!dir) {
+		errno = EBADF;
+		return -1;
+	}
+
+	/* We need to check dd_fd. */
+	if (dir->dd_fd == -1) {
+		errno = EBADF;
+		return -1;
+	}
+	fd = dir->dd_fd;
+	dir->dd_fd = -1;
+	free(dir->dd_buf);
+	free(dir);
+	return close(fd);
+}

+ 12 - 0
libc/misc/dirent/dirfd.c

@@ -0,0 +1,12 @@
+#include <errno.h>
+#include "dirstream.h"
+
+int dirfd(DIR * dir)
+{
+	if (!dir || dir->dd_fd == -1) {
+		errno = EBADF;
+		return -1;
+	}
+
+	return dir->dd_fd;
+}

+ 75 - 0
libc/misc/dirent/dirstream.h

@@ -0,0 +1,75 @@
+/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the, 1992 Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/*
+ *	POSIX Standard: 5.1.2 Directory Operations	<dirent.h>
+ */
+
+#ifndef	_DIRSTREAM_H
+
+#define	_DIRSTREAM_H	1
+
+#include <sys/types.h>
+#include <dirent.h>
+#ifdef _POSIX_THREADS
+#include <pthread.h>
+#endif
+
+/* For now, syscall readdir () only supports one entry at a time. It
+ * will be changed in the future.
+#define NUMENT		3
+*/
+#ifndef NUMENT
+#define NUMENT		1
+#endif
+
+#define SINGLE_READDIR	11
+#define MULTI_READDIR	12
+#define NEW_READDIR	13
+
+/* Directory stream type.  */
+struct __dirstream {
+  /* file descriptor */
+  int dd_fd;
+
+  /* offset of the next dir entry in buffer */
+  off_t dd_nextloc;
+
+  /* bytes of valid entries in buffer */
+  size_t dd_size;
+
+  /* -> directory buffer */
+  struct dirent *dd_buf;
+
+  /* offset of the next dir entry in directory. */
+  off_t dd_nextoff;
+
+  /* total size of buffer */
+  size_t dd_max;
+ 
+  enum {unknown, have_getdents, no_getdents} dd_getdents;
+
+  /* lock */
+#ifdef _POSIX_THREADS
+  pthread_mutex_t *dd_lock;
+#else
+  void *dd_lock;
+#endif
+};				/* stream data from opendir() */
+
+#endif /* dirent.h  */

+ 55 - 0
libc/misc/dirent/opendir.c

@@ -0,0 +1,55 @@
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/dir.h>
+#include <sys/stat.h>
+#include "dirstream.h"
+
+
+/* opendir just makes an open() call - it return NULL if it fails
+ * (open sets errno), otherwise it returns a DIR * pointer.
+ */
+DIR *opendir(const char *name)
+{
+	int fd;
+	struct stat statbuf;
+	struct dirent *buf;
+	DIR *ptr;
+
+	if (stat(name, &statbuf))
+		return NULL;
+	if (!S_ISDIR(statbuf.st_mode)) {
+		errno = ENOTDIR;
+		return NULL;
+	}
+	if ((fd = open(name, O_RDONLY)) < 0)
+		return NULL;
+	/* According to POSIX, directory streams should be closed when
+	 * exec. From "Anna Pluzhnikov" <besp@midway.uchicago.edu>.
+	 */
+	if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
+		return NULL;
+	if (!(ptr = malloc(sizeof(*ptr)))) {
+		close(fd);
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	ptr->dd_max = statbuf.st_blksize;
+	if (ptr->dd_max < 512)
+		ptr->dd_max = 512;
+
+	if (!(buf = malloc(ptr->dd_max))) {
+		close(fd);
+		free(ptr);
+		errno = ENOMEM;
+		return NULL;
+	}
+	ptr->dd_fd = fd;
+	ptr->dd_nextoff = ptr->dd_nextloc = ptr->dd_size = 0;
+	ptr->dd_buf = buf;
+	ptr->dd_getdents = unknown;
+	return ptr;
+}

+ 69 - 0
libc/misc/dirent/readdir.c

@@ -0,0 +1,69 @@
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <dirent.h>
+#include "dirstream.h"
+
+extern int getdents __P ((unsigned int fd, struct dirent *dirp, unsigned int count));
+
+
+struct dirent *readdir(DIR * dir)
+{
+	int result;
+	struct dirent *de;
+
+	if (!dir) {
+		errno = EBADF;
+		return NULL;
+	}
+
+	/* Are we running an old kernel? */
+	if (dir->dd_getdents == no_getdents) {
+		abort();
+	}
+
+	if (dir->dd_size <= dir->dd_nextloc) {
+		/* read dir->dd_max bytes of directory entries. */
+		result = getdents(dir->dd_fd, dir->dd_buf, dir->dd_max);
+
+		/* We assume we have getdents (). */
+		dir->dd_getdents = have_getdents;
+		if (result <= 0) {
+			result = -result;
+			if (result > 0) {
+				/* Are we right? */
+				if (result == ENOSYS) {
+					dir->dd_getdents = no_getdents;
+					abort();
+				}
+				errno = result;
+			}
+
+			return NULL;
+		}
+
+		dir->dd_size = result;
+		dir->dd_nextloc = 0;
+	}
+
+	de = (struct dirent *) (((char *) dir->dd_buf) + dir->dd_nextloc);
+
+	/* Am I right? H.J. */
+	dir->dd_nextloc += de->d_reclen;
+
+	/* We have to save the next offset here. */
+	dir->dd_nextoff = de->d_off;
+
+	/* convert */
+	dir->dd_buf->d_ino = de->d_ino;
+	dir->dd_buf->d_off = de->d_off;
+	dir->dd_buf->d_reclen = de->d_reclen;
+	dir->dd_buf->d_type = 0;
+	if (strlen((char *) &de->d_type) > 10)
+		de->d_name[10] = 0;
+	strcpy(dir->dd_buf->d_name, (char *) &de->d_name);
+	errno = 0;
+
+	return dir->dd_buf;
+}

+ 15 - 0
libc/misc/dirent/rewinddir.c

@@ -0,0 +1,15 @@
+#include <errno.h>
+#include <unistd.h>
+#include "dirstream.h"
+
+
+/* rewinddir() just does an lseek(fd,0,0) - see close for comments */
+void rewinddir(DIR * dir)
+{
+	if (!dir) {
+		errno = EBADF;
+		return;
+	}
+	lseek(dir->dd_fd, 0, SEEK_SET);
+	dir->dd_nextoff = dir->dd_nextloc = dir->dd_size = 0;
+}

+ 14 - 0
libc/misc/dirent/seekdir.c

@@ -0,0 +1,14 @@
+#include <errno.h>
+#include <unistd.h>
+#include "dirstream.h"
+
+
+void seekdir(DIR * dir, off_t offset)
+{
+	if (!dir) {
+		errno = EBADF;
+		return;
+	}
+	dir->dd_nextoff = lseek(dir->dd_fd, offset, SEEK_SET);
+	dir->dd_size = dir->dd_nextloc = 0;
+}

+ 35 - 0
libc/misc/dirent/telldir.c

@@ -0,0 +1,35 @@
+#include <errno.h>
+#include <unistd.h>
+#include "dirstream.h"
+
+
+off_t telldir(DIR * dir)
+{
+	off_t offset;
+
+	if (!dir) {
+		errno = EBADF;
+		return -1;
+	}
+
+	switch (dir->dd_getdents) {
+	case no_getdents:
+		/* We are running the old kernel. This is the starting offset
+		   of the next readdir(). */
+		offset = lseek(dir->dd_fd, 0, SEEK_CUR);
+		break;
+
+	case unknown:
+		/* readdir () is not called yet. but seekdir () may be called. */
+	case have_getdents:
+		/* The next entry. */
+		offset = dir->dd_nextoff;
+		break;
+
+	default:
+		errno = EBADF;
+		offset = -1;
+	}
+
+	return offset;
+}

+ 2 - 5
libc/sysdeps/linux/common/Makefile

@@ -25,12 +25,9 @@ TOPDIR=../../../
 include $(TOPDIR)Rules.mak
 LIBC=$(TOPDIR)libc.a
 
-CSRC=	waitpid.c getdents.c kernel_version.c rewinddir.c \
-	statfix.c getdnnm.c seekdir.c telldir.c tell.c gethstnm.c \
-	mkfifo.c setegid.c wait.c errno.c closedir.c getpagesize.c \
-	opendir.c seteuid.c wait3.c dirfd.c readdir.c setpgrp.c \
+CSRC=	waitpid.c getdents.c kernel_version.c statfix.c getdnnm.c tell.c gethstnm.c \
+	mkfifo.c setegid.c wait.c errno.c getpagesize.c  seteuid.c wait3.c setpgrp.c \
 	getdtablesize.c
-
 COBJS=$(patsubst %.c,%.o, $(CSRC))
 
 MSRC=syscalls.c