NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/56232: Unstable system with tar on /dev



The following reply was made to PR kern/56232; it has been noted by GNATS.

From: RVP <rvp%SDF.ORG@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc: Martin Husemann <martin%duskware.de@localhost>
Subject: Re: kern/56232: Unstable system with tar on /dev
Date: Fri, 4 Jun 2021 09:06:16 +0000 (UTC)

 On Fri, 4 Jun 2021, Martin Husemann wrote:
 
 > There is an option to tar (I forgot which) to not backup ACLs - and then
 > everything should be fine.
 >
 
 Not really an ACLs or extattrs issue, I think. Just doing an
 open()/fstat()/close() on each of the entries in /dev
 reliably reboots my laptop. Run the following program as root:
 
  	$ sudo ./a.out /dev
 
 --- START CODE ---
 /**
   * ic-walk.c:
   * Traverse given dir. like ``find dir'', calling iconv(3)
   * on each pathname. This causes '?' to be displayed for
   * chars. which are not valid for the currently charset.
   */
 #include <sys/stat.h>
 #include <assert.h>
 #include <dirent.h>
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <iconv.h>
 #include <langinfo.h>
 #include <locale.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
 
 static int walk(char* path, iconv_t cd);
 static char* concat(char* path, char* name);
 static char* convpath(char* path, iconv_t cd);
 
 static char* prog;
 
 int
 main(int argc, char* argv[])
 {
  	char* tc, *fc;
  	iconv_t cd;
  	int rc = EXIT_FAILURE;
 
  	prog = argv[0];
 
  	printf("Current locale: %s\n", setlocale(LC_ALL, NULL));
  	(void)setlocale(LC_ALL, "");
  	fc = nl_langinfo(CODESET);
  	tc = "UTF-8";
  	printf("from charset: %s\n", fc);
  	printf("  to charset: %s\n", tc);
  	cd = iconv_open(tc, fc);
  	if (cd == (iconv_t)-1)
  		err(rc, "iconv failed");
  	if (argc != 2)
  		rc = walk(".", cd);
  	else
  		rc = walk(argv[1], cd);
  	iconv_close(cd);
  	return rc;
 }
 
 /*
   * Walk the directory tree recursively, starting at `path'.
   */
 static int
 walk(char* path, iconv_t cd)
 {
  	struct dirent* dent;
  	DIR* dir;
 
  	if ((dir = opendir(path)) == NULL) {
  		fprintf(stderr, "%s: %s: opendir failed. ", prog, path);
  		perror(NULL);
  		return EXIT_FAILURE;
  	}
  	while ((dent = readdir(dir)) != NULL) {
  		char* name = dent->d_name;
  		char* np = concat(path, name);
  		struct stat sb;
  		int fd;
  		if ((fd = open(np, O_RDONLY)) == -1) {
  			warn("%s: open failed", np);
  			free(np);
  			continue;
  		}
  		if (fstat(fd, &sb) != 0) {
  			warn("%s: fstat failed", np);
  			free(np);
  			close(fd);
  			continue;
  		}
  		close(fd);
  		char* s = convpath(np, cd);
  		if (S_ISDIR(sb.st_mode)) {
  			/* dir, but skip `.' and `..' */
  			if (strcmp(name, ".") && strcmp(name, "..")) {
  				printf("%s/\n", s);
  				walk(np, cd);	/* recurse */
  			}
  		} else	/* file */
  			printf("%s\n", s);
  		free(np);
  		free(s);
  	}
  	closedir(dir);
  	return EXIT_SUCCESS;
 }
 
 static char*
 concat(char* path, char* name)
 {
  	assert(path && name);
 
  	size_t len = strlen(path) + strlen(name) + 2;
  	char* s = malloc(len);
  	if (s == NULL)
  		err(EXIT_FAILURE, "malloc failed");
 
  	char* end = path + strlen(path);
  	while (end > path && *(end-1) == '/')
  		--end;
  	snprintf(s, len, "%.*s/%s", (int)(end-path), path, name);
 
  	return s;
 }
 
 static char*
 convpath(char* path, iconv_t cd)
 {
  	size_t slen = strlen(path) + 1;
  	size_t dlen = slen * 2 + 1;
  	char* dest;
  	char* sp, *dp;
 
  	dest = malloc(dlen);
  	if (dest == NULL)
  		err(EXIT_FAILURE, "malloc failed");
 
  	sp = path;
  	dp = dest;
  	while (slen >= 1) {
  		errno = 0;
  		size_t rc = iconv(cd, &sp, &slen, &dp, &dlen);
  		if (rc != (size_t)-1)
  			break;
  		if (errno == EILSEQ || errno == EINVAL) {
  			*dp++ = '?';
  			sp++;
  			dlen--;
  			slen--;
  		} else {
  			warn("iconv failed");
  			free(dest);
  			return strdup(path);
  		}
  	}
  	return dest;
 }
 --- END CODE ---
 


Home | Main Index | Thread Index | Old Index