aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/telldir.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/telldir.c')
-rw-r--r--sysdeps/unix/sysv/linux/telldir.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/telldir.c b/sysdeps/unix/sysv/linux/telldir.c
index 1e5c129e9f..1ac4fce50c 100644
--- a/sysdeps/unix/sysv/linux/telldir.c
+++ b/sysdeps/unix/sysv/linux/telldir.c
@@ -15,9 +15,12 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#include <stdio.h>
+#include <assert.h>
#include <dirent.h>
#include <dirstream.h>
+#include <telldir.h>
/* Return the current position of DIRP. */
long int
@@ -26,7 +29,40 @@ telldir (DIR *dirp)
long int ret;
__libc_lock_lock (dirp->lock);
+
+#if _DIRENT_OFFSET_TRANSLATION
+ /* If the directory position fits in the packet structure, returns it.
+ Otherwise, check if the position is already been recorded in the
+ dynamic array. If not, add the new record. */
+
+ union dirstream_packed dsp;
+
+ if (!telldir_need_dirstream (dirp->filepos))
+ {
+ dsp.p.is_packed = 1;
+ dsp.p.info = dirp->filepos;
+ }
+ else
+ {
+ dsp.l = -1;
+
+ size_t i;
+ for (i = 0; ;i++)
+ {
+ /* It should be pre-allocated on readdir. */
+ assert (i < dirstream_loc_size (&dirp->locs));
+ if (*dirstream_loc_at (&dirp->locs, i) == dirp->filepos)
+ break;
+ }
+
+ dsp.p.is_packed = 0;
+ dsp.p.info = i;
+ }
+
+ ret = dsp.l;
+#else
ret = dirp->filepos;
+#endif
__libc_lock_unlock (dirp->lock);
return ret;