Control: tag -1 + patch

Hi,

Quoting Johannes Schauer Marin Rodrigues (2022-05-14 08:46:48)
> the contents of index.db are unreproducible across different
> hosts/filesystems. With the same host/filesystem, it works fine:
> 
>     $ export SOURCE_DATE_EPOCH=1652473183
>     $ mmdebstrap --variant=standard unstable out1.tar
>     $ mmdebstrap --variant=standard unstable out2.tar
>     $ cmp out1.tar out2.tar
>     $ echo $?
>     0
> 
> Now lets mmdebstrap use a filesystem mounted with disorderfs as its
> TMPDIR to simulate the problem:
> 
>     $ mkdir emptydir disorder
>     $ sudo disorderfs --multi-user=yes --shuffle-dirents=yes 
> --reverse-dirents=no emptydir disorder
>     $ export TMPDIR=$(pwd)/disorder
>     $ mmdebstrap --variant=standard unstable out1.tar
>     $ mmdebstrap --variant=standard unstable out2.tar
>     $ diffoscope out1.tar out2.tar | grep ├──
>     ├── file list
>     ├── ./var/cache/man/cs/index.db
>     ├── ./var/cache/man/da/index.db
>     ├── ./var/cache/man/de/index.db
>     ├── ./var/cache/man/es/index.db
>     ├── ./var/cache/man/fr/index.db
>     ...
> 
> I attached the contents of /var/cache/man/index.db so that you can see
> that it is indeed the order that differs between individual runs.

I now have a patch (attached).

Thanks!

cheers, josch
--- a/src/check_mandirs.c
+++ b/src/check_mandirs.c
@@ -342,8 +342,8 @@ static void add_dir_entries (MYDBM_FILE
 {
 	char *manpage;
 	int len;
-	struct dirent *newdir;
-	DIR *dir;
+	int n;
+	struct dirent **namelist;
 	gl_list_t names;
 	const char *name;
 
@@ -356,8 +356,8 @@ static void add_dir_entries (MYDBM_FILE
 	 * or . files (such as current, parent dir).
 	 */
 
-	dir = opendir (infile);
-	if (!dir) {
+	n = scandir(infile, &namelist, NULL, alphasort);
+	if (n < 0) {
 		error (0, errno, _("can't search directory %s"), manpage);
 		free (manpage);
                 return;
@@ -367,13 +367,13 @@ static void add_dir_entries (MYDBM_FILE
 
         /* strlen(newdir->d_name) could be replaced by newdir->d_reclen */
 
-	while ((newdir = readdir (dir)) != NULL) {
-		if (*newdir->d_name == '.' &&
-		    strlen (newdir->d_name) < (size_t) 3)
+	while (n--) {
+		if (*namelist[n]->d_name == '.' &&
+		    strlen (namelist[n]->d_name) < (size_t) 3)
 			continue;
-		gl_list_add_last (names, xstrdup (newdir->d_name));
+		gl_list_add_last (names, xstrdup (namelist[n]->d_name));
 	}
-	closedir (dir);
+	free(namelist);
 
 	order_files (infile, &names);
 
@@ -516,8 +516,8 @@ static void fix_permissions_tree (const
 static int testmandirs (MYDBM_FILE dbf, const char *path, const char *catpath,
 			struct timespec last, bool create)
 {
-	DIR *dir;
-	struct dirent *mandir;
+	int n;
+	struct dirent **namelist;
 	int amount = 0;
 	bool created = false;
 
@@ -526,28 +526,28 @@ static int testmandirs (MYDBM_FILE dbf,
 	if (catpath)
 		fix_permissions_tree (catpath);
 
-	dir = opendir (path);
-	if (!dir) {
+	n = scandir(path, &namelist, NULL, alphasort);
+	if (n < 0) {
 		error (0, errno, _("can't search directory %s"), path);
 		return 0;
 	}
 
 	if (chdir (path) != 0) {
 		error (0, errno, _("can't change to directory %s"), path);
-		closedir (dir);
+		free(namelist);
 		return 0;
 	}
 
-	while( (mandir = readdir (dir)) ) {
+	while (n--) {
 		struct stat stbuf;
 		struct timespec mtime;
 
-		if (strncmp (mandir->d_name, "man", 3) != 0)
+		if (strncmp (namelist[n]->d_name, "man", 3) != 0)
 			continue;
 
-		debug ("Examining %s\n", mandir->d_name);
+		debug ("Examining %s\n", namelist[n]->d_name);
 
-		if (stat (mandir->d_name, &stbuf) != 0)	/* stat failed */
+		if (stat (namelist[n]->d_name, &stbuf) != 0)	/* stat failed */
 			continue;
 		if (!S_ISDIR(stbuf.st_mode))		/* not a directory */
 			continue;
@@ -556,14 +556,14 @@ static int testmandirs (MYDBM_FILE dbf,
 			/* scanned already */
 			debug ("%s modified %ld.%09ld, "
 			       "db modified %ld.%09ld\n",
-			       mandir->d_name,
+			       namelist[n]->d_name,
 			       (long) mtime.tv_sec, (long) mtime.tv_nsec,
 			       (long) last.tv_sec, (long) last.tv_nsec);
 			continue;
 		}
 
 		debug ("\tsubdirectory %s has been 'modified'\n",
-		       mandir->d_name);
+		       namelist[n]->d_name);
 
 		if (create && !created) {
 			/* We seem to have something to do, so create the
@@ -577,13 +577,13 @@ static int testmandirs (MYDBM_FILE dbf,
 				if (errno == EACCES || errno == EROFS) {
 					debug ("database %s is read-only\n",
 					       dbf->name);
-					closedir (dir);
+					free(namelist);
 					return 0;
 				} else {
 					error (0, errno,
 					       _("can't create index cache %s"),
 					       dbf->name);
-					closedir (dir);
+					free(namelist);
 					return -1;
 				}
 			}
@@ -592,7 +592,7 @@ static int testmandirs (MYDBM_FILE dbf,
 
 			created = true;
 		} else if (!ensure_db_open (dbf)) {
-			closedir (dir);
+			free(namelist);
 			return 0;
 		}
 
@@ -603,14 +603,14 @@ static int testmandirs (MYDBM_FILE dbf,
 				fprintf (stderr, "\r");
 			fprintf (stderr,
 				 _("Updating index cache for path "
-				   "`%s/%s'. Wait..."), path, mandir->d_name);
+				   "`%s/%s'. Wait..."), path, namelist[n]->d_name);
 			if (!tty)
 				fprintf (stderr, "\n");
 		}
-		add_dir_entries (dbf, path, mandir->d_name);
+		add_dir_entries (dbf, path, namelist[n]->d_name);
 		amount++;
 	}
-	closedir (dir);
+	free(namelist);
 
 	return amount;
 }

Attachment: signature.asc
Description: signature

Reply via email to