It turns out that a certain TLS frontend, the name of which starts with "Hit"
and ends with "ch", leverages dirent->d_type without handling DT_UNKNOWN...
... | ... |
@@ -223,22 +223,25 @@ class CombinedFS(Operations): |
223 | 223 |
# Deal only with directories: |
224 | 224 |
if filename: |
225 | 225 |
raise FuseOSError(errno.ENOTDIR) |
226 |
+ # Extra attributes, just what it takes to support dirent->d_type: |
|
227 |
+ dir_attrs = {'st_mode': stat.S_IFDIR } |
|
228 |
+ reg_attrs = {'st_mode': stat.S_IFREG } |
|
226 | 229 |
# Yield common directory entries: |
227 |
- yield '.' |
|
228 |
- yield '..' |
|
230 |
+ yield '.', dir_attrs, 0 |
|
231 |
+ yield '..', dir_attrs, 0 |
|
229 | 232 |
if not cert: |
230 | 233 |
# Top-level directory |
231 | 234 |
flat_mode = self.separator != '/' |
232 | 235 |
for cert in (d for d in os.listdir(self.root) if self.filter_cert(d)): |
233 | 236 |
if flat_mode: |
234 | 237 |
for filename in self.files: |
235 |
- yield cert + self.separator + filename |
|
238 |
+ yield cert + self.separator + filename, reg_attrs, 0 |
|
236 | 239 |
else: |
237 |
- yield cert |
|
240 |
+ yield cert, dir_attrs, 0 |
|
238 | 241 |
else: |
239 | 242 |
# Second-level directory |
240 | 243 |
for filename in self.files: |
241 |
- yield filename |
|
244 |
+ yield filename, reg_attrs, 0 |
|
242 | 245 |
|
243 | 246 |
def open(self, path, flags): |
244 | 247 |
cert, filename, file_spec = self.analyse_path(path) |
245 | 248 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,47 @@ |
1 |
+// Dummy program to test whether dirent->d_type was set by the underlying filesystem. |
|
2 |
+ |
|
3 |
+#include <dirent.h> |
|
4 |
+#include <errno.h> |
|
5 |
+#include <stdio.h> |
|
6 |
+#include <string.h> |
|
7 |
+ |
|
8 |
+const char *pr_d_type(unsigned char d_type) { |
|
9 |
+ switch (d_type) { |
|
10 |
+ case DT_BLK: return "DT_BLK"; |
|
11 |
+ case DT_CHR: return "DT_CHR"; |
|
12 |
+ case DT_DIR: return "DT_DIR"; |
|
13 |
+ case DT_FIFO: return "DT_FIFO"; |
|
14 |
+ case DT_LNK: return "DT_LNK"; |
|
15 |
+ case DT_REG: return "DT_REG"; |
|
16 |
+ case DT_SOCK: return "DT_SOCK"; |
|
17 |
+ case DT_UNKNOWN: return "DT_UNKNOWN"; |
|
18 |
+ } |
|
19 |
+ return "DT_UNKNOWN?"; |
|
20 |
+} |
|
21 |
+ |
|
22 |
+int main(int argc, char **argv) { |
|
23 |
+ DIR *directory; |
|
24 |
+ struct dirent *entry; |
|
25 |
+ |
|
26 |
+ if (argc != 2) return 0; |
|
27 |
+ |
|
28 |
+ directory = opendir(argv[1]); |
|
29 |
+ if (!directory) { |
|
30 |
+ fprintf(stderr, "Error opening directory %s: %s\n", argv[1], strerror(errno)); |
|
31 |
+ return 2; |
|
32 |
+ } |
|
33 |
+ |
|
34 |
+ for (;;) { |
|
35 |
+ errno = 0; |
|
36 |
+ entry = readdir(directory); |
|
37 |
+ if (!entry && errno) { |
|
38 |
+ fprintf(stderr, "Error listing directory %s: %s\n", argv[1], strerror(errno)); |
|
39 |
+ return 1; |
|
40 |
+ } |
|
41 |
+ if (!entry) { |
|
42 |
+ break; |
|
43 |
+ } |
|
44 |
+ printf("%d %d %d=%s %s\n", entry->d_ino, entry->d_off, entry->d_type, pr_d_type(entry->d_type), entry->d_name); |
|
45 |
+ } |
|
46 |
+ return 0; |
|
47 |
+} |