Browse code

Add support for dirent->d_type.

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...

Xavier G authored on05/04/2020 21:52:52
Showing4 changed files

1 1
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+readdir
... ...
@@ -1,8 +1,12 @@
1 1
 # Not exactly an advanceed Makefile...
2 2
 
3 3
 PREFIX = /usr/local
4
+CC = gcc
4 5
 
5 6
 all:
6 7
 
8
+readdir: readdir.c
9
+	$(CC) readdir.c -o readdir
10
+
7 11
 install: combinedfs.py
8 12
 	install -C combinedfs.py "$(PREFIX)/sbin/combinedfs"
... ...
@@ -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
+}