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