summaryrefslogtreecommitdiff
blob: 33f986950d7324c2bcce0d0377a5cdf77a330fe0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
From ad50ce9ae10cdd50bd620ae6ef67fe3b11896913 Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Tue, 20 Oct 2020 12:18:56 -0300
Subject: [PATCH 05/12] linux: Do not skip entries with zero d_ino values [BZ
 #12165]

According to Linux commit 2adc376c55194 (vfs: avoid creation of inode
number 0 in get_next_ino) Linux did not treat d_ino == 0 as a special
case (it is a valid inode number).

This patch fixes readdir{64} by not ignoring entried with d_ino being
0.

Checked on x86_64-linux-gnu and i686-linux-gnu.
---
 sysdeps/unix/sysv/linux/readdir.c   | 59 +++++++++++------------------
 sysdeps/unix/sysv/linux/readdir64.c | 59 +++++++++++------------------
 2 files changed, 44 insertions(+), 74 deletions(-)

diff --git a/sysdeps/unix/sysv/linux/readdir.c b/sysdeps/unix/sysv/linux/readdir.c
index c31f349639..7743f50071 100644
--- a/sysdeps/unix/sysv/linux/readdir.c
+++ b/sysdeps/unix/sysv/linux/readdir.c
@@ -25,51 +25,36 @@
 struct dirent *
 __readdir_unlocked (DIR *dirp)
 {
-  struct dirent *dp;
-  int saved_errno = errno;
+  const int saved_errno = errno;
 
-  do
+  if (dirp->offset >= dirp->size)
     {
-      size_t reclen;
-
-      if (dirp->offset >= dirp->size)
+      /* We've emptied out our buffer.  Refill it.  */
+      ssize_t bytes = __getdents (dirp->fd, dirp->data, dirp->allocation);
+      if (bytes <= 0)
 	{
-	  /* We've emptied out our buffer.  Refill it.  */
-
-	  size_t maxread = dirp->allocation;
-	  ssize_t bytes;
-
-	  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;
+	  /* 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);
+	  return NULL;
 	}
+      dirp->size = bytes;
 
-      dp = (struct dirent *) &dirp->data[dirp->offset];
-
-      reclen = dp->d_reclen;
+      /* Reset the offset into the buffer.  */
+      dirp->offset = 0;
+    }
 
-      dirp->offset += reclen;
+  struct dirent *dp = (struct dirent *) &dirp->data[dirp->offset];
 
-      dirp->filepos = dp->d_off;
+  dirp->offset += dp->d_reclen;
 
-      /* Skip deleted files.  */
-    } while (dp->d_ino == 0);
+  dirp->filepos = dp->d_off;
 
   return dp;
 }
diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c
index e876d84b02..d990a36e4e 100644
--- a/sysdeps/unix/sysv/linux/readdir64.c
+++ b/sysdeps/unix/sysv/linux/readdir64.c
@@ -30,55 +30,40 @@
 struct dirent64 *
 __readdir64 (DIR *dirp)
 {
-  struct dirent64 *dp;
-  int saved_errno = errno;
+  const int saved_errno = errno;
 
 #if IS_IN (libc)
   __libc_lock_lock (dirp->lock);
 #endif
 
-  do
+  if (dirp->offset >= dirp->size)
     {
-      size_t reclen;
-
-      if (dirp->offset >= dirp->size)
+      /* We've emptied out our buffer.  Refill it.  */
+      ssize_t bytes = __getdents64 (dirp->fd, dirp->data, dirp->allocation);
+      if (bytes <= 0)
 	{
-	  /* We've emptied out our buffer.  Refill it.  */
-
-	  size_t maxread = dirp->allocation;
-	  ssize_t bytes;
-
-	  bytes = __getdents64 (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;
+	  /* 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);
+	  return NULL;
 	}
+      dirp->size = bytes;
 
-      dp = (struct dirent64 *) &dirp->data[dirp->offset];
-
-      reclen = dp->d_reclen;
+      /* Reset the offset into the buffer.  */
+      dirp->offset = 0;
+   }
 
-      dirp->offset += reclen;
+  struct dirent64 *dp = (struct dirent64 *) &dirp->data[dirp->offset];
 
-      dirp->filepos = dp->d_off;
+  dirp->offset += dp->d_reclen;
 
-      /* Skip deleted files.  */
-    } while (dp->d_ino == 0);
+  dirp->filepos = dp->d_off;
 
 #if IS_IN (libc)
   __libc_lock_unlock (dirp->lock);
-- 
2.35.1