From a281decc878cf26cae12a5bdf5f4c6e0297303d6 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 7 Aug 2012 14:47:34 -0700 Subject: Move common dirent implementation from sysdeps/unix to sysdeps/posix. --- sysdeps/posix/closedir.c | 55 +++++++++++ sysdeps/posix/dirfd.c | 29 ++++++ sysdeps/posix/dirstream.h | 48 ++++++++++ sysdeps/posix/fdopendir.c | 51 +++++++++++ sysdeps/posix/opendir.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++ sysdeps/posix/readdir.c | 122 +++++++++++++++++++++++++ sysdeps/posix/readdir_r.c | 137 ++++++++++++++++++++++++++++ sysdeps/posix/rewinddir.c | 40 ++++++++ sysdeps/posix/seekdir.c | 37 ++++++++ sysdeps/posix/telldir.c | 27 ++++++ 10 files changed, 774 insertions(+) create mode 100644 sysdeps/posix/closedir.c create mode 100644 sysdeps/posix/dirfd.c create mode 100644 sysdeps/posix/dirstream.h create mode 100644 sysdeps/posix/fdopendir.c create mode 100644 sysdeps/posix/opendir.c create mode 100644 sysdeps/posix/readdir.c create mode 100644 sysdeps/posix/readdir_r.c create mode 100644 sysdeps/posix/rewinddir.c create mode 100644 sysdeps/posix/seekdir.c create mode 100644 sysdeps/posix/telldir.c (limited to 'sysdeps/posix') diff --git a/sysdeps/posix/closedir.c b/sysdeps/posix/closedir.c new file mode 100644 index 0000000..41abf28 --- /dev/null +++ b/sysdeps/posix/closedir.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1991,1993,1995,1996,1998,2002,2003, 2007 + 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include + + +/* Close the directory stream DIRP. + Return 0 if successful, -1 if not. */ +int +__closedir (DIR *dirp) +{ + int fd; + + if (dirp == NULL) + { + __set_errno (EINVAL); + return -1; + } + + /* We do not try to synchronize access here. If some other thread + still uses this handle it is a big mistake and that thread + deserves all the bad data it gets. */ + + fd = dirp->fd; + +#ifndef NOT_IN_libc + __libc_lock_fini (dirp->lock); +#endif + + free ((void *) dirp); + + return close_not_cancel (fd); +} +weak_alias (__closedir, closedir) diff --git a/sysdeps/posix/dirfd.c b/sysdeps/posix/dirfd.c new file mode 100644 index 0000000..536c44e --- /dev/null +++ b/sysdeps/posix/dirfd.c @@ -0,0 +1,29 @@ +/* Return the file descriptor used by a DIR stream. Unix version. + Copyright (C) 1995, 1996 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include + +#undef dirfd + +int +dirfd (dirp) + DIR *dirp; +{ + return dirp->fd; +} diff --git a/sysdeps/posix/dirstream.h b/sysdeps/posix/dirstream.h new file mode 100644 index 0000000..6ca2904 --- /dev/null +++ b/sysdeps/posix/dirstream.h @@ -0,0 +1,48 @@ +/* Copyright (C) 1993, 1995, 1996, 2007 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _DIRSTREAM_H +#define _DIRSTREAM_H 1 + +#include + +#include + +/* Directory stream type. + + The miscellaneous Unix `readdir' implementations read directory data + into a buffer and return `struct dirent *' pointers into it. */ + +struct __dirstream + { + int fd; /* File descriptor. */ + + __libc_lock_define (, lock) /* Mutex lock for this structure. */ + + size_t allocation; /* Space allocated for the block. */ + size_t size; /* Total valid data in the block. */ + size_t offset; /* Current offset into the block. */ + + off_t filepos; /* Position of next entry to read. */ + + /* Directory block. */ + char data[0] __attribute__ ((aligned (__alignof__ (void*)))); + }; + +#define _DIR_dirfd(dirp) ((dirp)->fd) + +#endif /* dirstream.h */ diff --git a/sysdeps/posix/fdopendir.c b/sysdeps/posix/fdopendir.c new file mode 100644 index 0000000..beddcbe --- /dev/null +++ b/sysdeps/posix/fdopendir.c @@ -0,0 +1,51 @@ +/* Copyright (C) 2005, 2006, 2011 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include + +#include + + +DIR * +__fdopendir (int fd) +{ + struct stat64 statbuf; + + if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &statbuf), 0) < 0) + return NULL; + if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0)) + { + __set_errno (ENOTDIR); + return NULL; + } + + /* Make sure the descriptor allows for reading. */ + int flags = __fcntl (fd, F_GETFL); + if (__builtin_expect (flags == -1, 0)) + return NULL; + if (__builtin_expect ((flags & O_ACCMODE) == O_WRONLY, 0)) + { + __set_errno (EINVAL); + return NULL; + } + + return __alloc_dir (fd, false, flags, &statbuf); +} +weak_alias (__fdopendir, fdopendir) diff --git a/sysdeps/posix/opendir.c b/sysdeps/posix/opendir.c new file mode 100644 index 0000000..e093142 --- /dev/null +++ b/sysdeps/posix/opendir.c @@ -0,0 +1,228 @@ +/* Copyright (C) 1991-1996,98,2000-2003,2005,2007,2009,2011 + 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +/* opendir() must not accidentally open something other than a directory. + Some OS's have kernel support for that, some don't. In the worst + case we have to stat() before the open() AND fstat() after. + + We have to test at runtime for kernel support since libc may have + been compiled with different headers to the kernel it's running on. + This test can't be done reliably in the general case. We'll use + /dev/null, which if it's not a device lots of stuff will break, as + a guinea pig. It may be missing in chroot environments, so we + make sure to fail safe. */ +#ifdef O_DIRECTORY +# ifdef O_DIRECTORY_WORKS +# define o_directory_works 1 +# define tryopen_o_directory() while (1) /* This must not be called. */ +# else +static int o_directory_works; + +static void +tryopen_o_directory (void) +{ + int serrno = errno; + int x = open_not_cancel_2 ("/dev/null", O_RDONLY|O_NDELAY|O_DIRECTORY); + + if (x >= 0) + { + close_not_cancel_no_status (x); + o_directory_works = -1; + } + else if (errno != ENOTDIR) + o_directory_works = -1; + else + o_directory_works = 1; + + __set_errno (serrno); +} +# endif +# define EXTRA_FLAGS O_DIRECTORY +#else +# define EXTRA_FLAGS 0 +#endif + + +DIR * +internal_function +__opendirat (int dfd, const char *name) +{ + struct stat64 statbuf; + struct stat64 *statp = NULL; + + if (__builtin_expect (name[0], '\1') == '\0') + { + /* POSIX.1-1990 says an empty name gets ENOENT; + but `open' might like it fine. */ + __set_errno (ENOENT); + return NULL; + } + +#ifdef O_DIRECTORY + /* Test whether O_DIRECTORY works. */ + if (o_directory_works == 0) + tryopen_o_directory (); + + /* We can skip the expensive `stat' call if O_DIRECTORY works. */ + if (o_directory_works < 0) +#endif + { + /* We first have to check whether the name is for a directory. We + cannot do this after the open() call since the open/close operation + performed on, say, a tape device might have undesirable effects. */ + if (__builtin_expect (__xstat64 (_STAT_VER, name, &statbuf), 0) < 0) + return NULL; + if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0)) + { + __set_errno (ENOTDIR); + return NULL; + } + } + + int flags = O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE; +#ifdef O_CLOEXEC + flags |= O_CLOEXEC; +#endif + int fd; +#ifdef IS_IN_rtld + assert (dfd == AT_FDCWD); + fd = open_not_cancel_2 (name, flags); +#else + fd = openat_not_cancel_3 (dfd, name, flags); +#endif + if (__builtin_expect (fd, 0) < 0) + return NULL; + +#ifdef O_DIRECTORY + if (o_directory_works <= 0) +#endif + { + /* Now make sure this really is a directory and nothing changed since + the `stat' call. */ + if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &statbuf), 0) < 0) + goto lose; + if (__builtin_expect (! S_ISDIR (statbuf.st_mode), 0)) + { + __set_errno (ENOTDIR); + lose: + close_not_cancel_no_status (fd); + return NULL; + } + statp = &statbuf; + } + + return __alloc_dir (fd, true, 0, statp); +} + + +/* Open a directory stream on NAME. */ +DIR * +__opendir (const char *name) +{ + return __opendirat (AT_FDCWD, name); +} +weak_alias (__opendir, opendir) + + +#ifdef __ASSUME_O_CLOEXEC +# define check_have_o_cloexec(fd) 1 +#else +static int +check_have_o_cloexec (int fd) +{ + if (__have_o_cloexec == 0) + __have_o_cloexec = (__fcntl (fd, F_GETFD, 0) & FD_CLOEXEC) == 0 ? -1 : 1; + return __have_o_cloexec > 0; +} +#endif + + +DIR * +internal_function +__alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp) +{ + /* We always have to set the close-on-exit flag if the user provided + the file descriptor. Otherwise only if we have no working + O_CLOEXEC support. */ +#ifdef O_CLOEXEC + if ((! close_fd && (flags & O_CLOEXEC) == 0) + || ! check_have_o_cloexec (fd)) +#endif + { + if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0) + goto lose; + } + + const size_t default_allocation = (4 * BUFSIZ < sizeof (struct dirent64) + ? sizeof (struct dirent64) : 4 * BUFSIZ); + const size_t small_allocation = (BUFSIZ < sizeof (struct dirent64) + ? sizeof (struct dirent64) : BUFSIZ); + size_t allocation = default_allocation; +#ifdef _STATBUF_ST_BLKSIZE + if (statp != NULL && default_allocation < statp->st_blksize) + allocation = statp->st_blksize; +#endif + + DIR *dirp = (DIR *) malloc (sizeof (DIR) + allocation); + if (dirp == NULL) + { + allocation = small_allocation; + dirp = (DIR *) malloc (sizeof (DIR) + allocation); + + if (dirp == NULL) + lose: + { + if (close_fd) + { + int save_errno = errno; + close_not_cancel_no_status (fd); + __set_errno (save_errno); + } + return NULL; + } + } + + dirp->fd = fd; +#ifndef NOT_IN_libc + __libc_lock_init (dirp->lock); +#endif + dirp->allocation = allocation; + dirp->size = 0; + dirp->offset = 0; + dirp->filepos = 0; + + return dirp; +} diff --git a/sysdeps/posix/readdir.c b/sysdeps/posix/readdir.c new file mode 100644 index 0000000..be0fcae --- /dev/null +++ b/sysdeps/posix/readdir.c @@ -0,0 +1,122 @@ +/* Copyright (C) 1991-1997,1999,2000,2002,2007 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef __READDIR +# define __READDIR __readdir +# define __GETDENTS __getdents +# define DIRENT_TYPE struct dirent +# define __READDIR_ALIAS +#endif + +/* Read a directory entry from DIRP. */ +DIRENT_TYPE * +__READDIR (DIR *dirp) +{ + DIRENT_TYPE *dp; + int saved_errno = errno; + +#ifndef NOT_IN_libc + __libc_lock_lock (dirp->lock); +#endif + + do + { + size_t reclen; + + if (dirp->offset >= dirp->size) + { + /* We've emptied out our buffer. Refill it. */ + + size_t maxread; + ssize_t bytes; + +#ifndef _DIRENT_HAVE_D_RECLEN + /* Fixed-size struct; must read one at a time (see below). */ + maxread = sizeof *dp; +#else + maxread = dirp->allocation; +#endif + + bytes = __GETDENTS (dirp->fd, dirp->data, maxread); + if (bytes <= 0) + { + /* On some systems getdents fails with ENOENT when the + open directory has been rmdir'd already. POSIX.1 + requires that we treat this condition like normal EOF. */ + if (bytes < 0 && errno == ENOENT) + bytes = 0; + + /* Don't modifiy errno when reaching EOF. */ + if (bytes == 0) + __set_errno (saved_errno); + dp = NULL; + break; + } + dirp->size = (size_t) bytes; + + /* Reset the offset into the buffer. */ + dirp->offset = 0; + } + + dp = (DIRENT_TYPE *) &dirp->data[dirp->offset]; + +#ifdef _DIRENT_HAVE_D_RECLEN + reclen = dp->d_reclen; +#else + /* The only version of `struct dirent*' that lacks `d_reclen' + is fixed-size. */ + assert (sizeof dp->d_name > 1); + reclen = sizeof *dp; + /* The name is not terminated if it is the largest possible size. + Clobber the following byte to ensure proper null termination. We + read jst one entry at a time above so we know that byte will not + be used later. */ + dp->d_name[sizeof dp->d_name] = '\0'; +#endif + + dirp->offset += reclen; + +#ifdef _DIRENT_HAVE_D_OFF + dirp->filepos = dp->d_off; +#else + dirp->filepos += reclen; +#endif + + /* Skip deleted files. */ + } while (dp->d_ino == 0); + +#ifndef NOT_IN_libc + __libc_lock_unlock (dirp->lock); +#endif + + return dp; +} + +#ifdef __READDIR_ALIAS +weak_alias (__readdir, readdir) +#endif diff --git a/sysdeps/posix/readdir_r.c b/sysdeps/posix/readdir_r.c new file mode 100644 index 0000000..bfa2c0b --- /dev/null +++ b/sysdeps/posix/readdir_r.c @@ -0,0 +1,137 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,98,99,2000,02,10 + 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef __READDIR_R +# define __READDIR_R __readdir_r +# define __GETDENTS __getdents +# define DIRENT_TYPE struct dirent +# define __READDIR_R_ALIAS +#endif + +/* Read a directory entry from DIRP. */ +int +__READDIR_R (DIR *dirp, DIRENT_TYPE *entry, DIRENT_TYPE **result) +{ + DIRENT_TYPE *dp; + size_t reclen; + const int saved_errno = errno; + + __libc_lock_lock (dirp->lock); + + do + { + if (dirp->offset >= dirp->size) + { + /* We've emptied out our buffer. Refill it. */ + + size_t maxread; + ssize_t bytes; + +#ifndef _DIRENT_HAVE_D_RECLEN + /* Fixed-size struct; must read one at a time (see below). */ + maxread = sizeof *dp; +#else + maxread = dirp->allocation; +#endif + + bytes = __GETDENTS (dirp->fd, dirp->data, maxread); + if (bytes <= 0) + { + /* On some systems getdents fails with ENOENT when the + open directory has been rmdir'd already. POSIX.1 + requires that we treat this condition like normal EOF. */ + if (bytes < 0 && errno == ENOENT) + { + bytes = 0; + __set_errno (saved_errno); + } + + dp = NULL; + /* Reclen != 0 signals that an error occurred. */ + reclen = bytes != 0; + break; + } + dirp->size = (size_t) bytes; + + /* Reset the offset into the buffer. */ + dirp->offset = 0; + } + + dp = (DIRENT_TYPE *) &dirp->data[dirp->offset]; + +#ifdef _DIRENT_HAVE_D_RECLEN + reclen = dp->d_reclen; +#else + /* The only version of `struct dirent*' that lacks `d_reclen' + is fixed-size. */ + assert (sizeof dp->d_name > 1); + reclen = sizeof *dp; + /* The name is not terminated if it is the largest possible size. + Clobber the following byte to ensure proper null termination. We + read just one entry at a time above so we know that byte will not + be used later. */ + dp->d_name[sizeof dp->d_name] = '\0'; +#endif + + dirp->offset += reclen; + +#ifdef _DIRENT_HAVE_D_OFF + dirp->filepos = dp->d_off; +#else + dirp->filepos += reclen; +#endif + + /* Skip deleted files. */ + } + while (dp->d_ino == 0); + + if (dp != NULL) + { +#ifdef GETDENTS_64BIT_ALIGNED + /* The d_reclen value might include padding which is not part of + the DIRENT_TYPE data structure. */ + reclen = MIN (reclen, + offsetof (DIRENT_TYPE, d_name) + sizeof (dp->d_name)); +#endif + *result = memcpy (entry, dp, reclen); +#ifdef GETDENTS_64BIT_ALIGNED + entry->d_reclen = reclen; +#endif + } + else + *result = NULL; + + __libc_lock_unlock (dirp->lock); + + return dp != NULL ? 0 : reclen ? errno : 0; +} + +#ifdef __READDIR_R_ALIAS +weak_alias (__readdir_r, readdir_r) +#endif diff --git a/sysdeps/posix/rewinddir.c b/sysdeps/posix/rewinddir.c new file mode 100644 index 0000000..f8eefea --- /dev/null +++ b/sysdeps/posix/rewinddir.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1991, 1995-1998, 2005, 2011 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include + +/* Rewind DIRP to the beginning of the directory. */ +void +rewinddir (dirp) + DIR *dirp; +{ +#ifndef NOT_IN_libc + __libc_lock_lock (dirp->lock); +#endif + (void) __lseek (dirp->fd, (off_t) 0, SEEK_SET); + dirp->filepos = 0; + dirp->offset = 0; + dirp->size = 0; +#ifndef NOT_IN_libc + __libc_lock_unlock (dirp->lock); +#endif +} +libc_hidden_def (rewinddir) diff --git a/sysdeps/posix/seekdir.c b/sysdeps/posix/seekdir.c new file mode 100644 index 0000000..88e34ee --- /dev/null +++ b/sysdeps/posix/seekdir.c @@ -0,0 +1,37 @@ +/* Copyright (C) 1991,1995,1996,1997,1999,2001 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include + +/* Seek to position POS in DIRP. */ +/* XXX should be __seekdir ? */ +void +seekdir (dirp, pos) + DIR *dirp; + long int pos; +{ + __libc_lock_lock (dirp->lock); + (void) __lseek (dirp->fd, pos, SEEK_SET); + dirp->size = 0; + dirp->offset = 0; + dirp->filepos = pos; + __libc_lock_unlock (dirp->lock); +} diff --git a/sysdeps/posix/telldir.c b/sysdeps/posix/telldir.c new file mode 100644 index 0000000..4a3ad25 --- /dev/null +++ b/sysdeps/posix/telldir.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 1999 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include + +#include + +/* Return the current position of DIRP. */ +long int +telldir (DIR *dirp) +{ + return dirp->filepos; +} -- cgit v1.1