opendir(3): on success, don't clobber errno
The opendir(3) function was setting errno to ENOTDIR even when the directory existed and was opened successfully. This caused git to falsely detect an error. This change moves the errno assignment into the failure code block. It also adds a test to test24 to check for errno changing when opendir(3) returns success.
This commit is contained in:
parent
82932c0d6b
commit
66b369c62c
|
@ -32,12 +32,13 @@ DIR *opendir(const char *name)
|
||||||
|
|
||||||
/* Check the type again, mark close-on-exec, get a buffer. */
|
/* Check the type again, mark close-on-exec, get a buffer. */
|
||||||
if (fstat(d, &st) < 0
|
if (fstat(d, &st) < 0
|
||||||
|| (errno= ENOTDIR, !S_ISDIR(st.st_mode))
|
|| !S_ISDIR(st.st_mode)
|
||||||
|| (f= fcntl(d, F_GETFD)) < 0
|
|| (f= fcntl(d, F_GETFD)) < 0
|
||||||
|| fcntl(d, F_SETFD, f | FD_CLOEXEC) < 0
|
|| fcntl(d, F_SETFD, f | FD_CLOEXEC) < 0
|
||||||
|| (dp= (DIR *) malloc(sizeof(*dp))) == nil
|
|| (dp= (DIR *) malloc(sizeof(*dp))) == nil
|
||||||
) {
|
) {
|
||||||
int err= errno;
|
int err= errno;
|
||||||
|
if (!S_ISDIR(st.st_mode)) err= ENOTDIR;
|
||||||
(void) close(d);
|
(void) close(d);
|
||||||
errno= err;
|
errno= err;
|
||||||
return nil;
|
return nil;
|
||||||
|
|
|
@ -73,18 +73,20 @@ void test24a()
|
||||||
|
|
||||||
if ((fd = dup(0)) != 3) e(1); /* dup stdin */
|
if ((fd = dup(0)) != 3) e(1); /* dup stdin */
|
||||||
close(fd); /* free the fd again */
|
close(fd); /* free the fd again */
|
||||||
|
errno= 0;
|
||||||
dirp = opendir("/"); /* open "/" */
|
dirp = opendir("/"); /* open "/" */
|
||||||
if (dirp == ((DIR *) NULL)) e(2); /* has to succseed */
|
if (dirp == ((DIR *) NULL)) e(2); /* has to succseed */
|
||||||
if ((fd = dup(0)) <= 2) e(3); /* dup stdin */
|
if (errno != 0) e(3); /* success implies errno didn't change */
|
||||||
|
if ((fd = dup(0)) <= 2) e(4); /* dup stdin */
|
||||||
if (fd > 3) { /* if opendir() uses fd 3 */
|
if (fd > 3) { /* if opendir() uses fd 3 */
|
||||||
flags = fcntl(3, F_GETFD); /* get fd fags of 3 */
|
flags = fcntl(3, F_GETFD); /* get fd fags of 3 */
|
||||||
if (!(flags & FD_CLOEXEC)) e(4); /* it should be closed on */
|
if (!(flags & FD_CLOEXEC)) e(5); /* it should be closed on */
|
||||||
} /* exec..() calls */
|
} /* exec..() calls */
|
||||||
close(fd); /* free the fd again */
|
close(fd); /* free the fd again */
|
||||||
ret = closedir(dirp); /* close, we don't need it */
|
ret = closedir(dirp); /* close, we don't need it */
|
||||||
if (ret == -1) e(5); /* closedir () unsucces full */
|
if (ret == -1) e(6); /* closedir () unsucces full */
|
||||||
if (ret != 0) e(6); /* should be 0 or -1 */
|
if (ret != 0) e(7); /* should be 0 or -1 */
|
||||||
if ((fd = dup(0)) != 3) e(7); /* see if next fd is same */
|
if ((fd = dup(0)) != 3) e(8); /* see if next fd is same */
|
||||||
close(fd); /* free the fd again */
|
close(fd); /* free the fd again */
|
||||||
|
|
||||||
System("rm -rf foo; mkdir foo");
|
System("rm -rf foo; mkdir foo");
|
||||||
|
@ -93,71 +95,71 @@ void test24a()
|
||||||
System("rm f[24]"); /* creat `holes' in entrys */
|
System("rm f[24]"); /* creat `holes' in entrys */
|
||||||
Chdir("..");
|
Chdir("..");
|
||||||
|
|
||||||
if ((dirp = opendir("foo")) == ((DIR *) NULL)) e(8); /* open foo */
|
if ((dirp = opendir("foo")) == ((DIR *) NULL)) e(9); /* open foo */
|
||||||
chk_dir(dirp); /* test if foo's ok */
|
chk_dir(dirp); /* test if foo's ok */
|
||||||
for (j = 0; j < 10; j++) {
|
for (j = 0; j < 10; j++) {
|
||||||
errno = j * 47 % 7; /* there should */
|
errno = j * 47 % 7; /* there should */
|
||||||
if (readdir(dirp) != DIRENT0) e(9); /* be nomore dir */
|
if (readdir(dirp) != DIRENT0) e(10); /* be nomore dir */
|
||||||
if (errno != j * 47 % 7) e(10); /* entrys */
|
if (errno != j * 47 % 7) e(11); /* entrys */
|
||||||
}
|
}
|
||||||
rewinddir(dirp); /* rewind foo */
|
rewinddir(dirp); /* rewind foo */
|
||||||
chk_dir(dirp); /* test foosok */
|
chk_dir(dirp); /* test foosok */
|
||||||
for (j = 0; j < 10; j++) {
|
for (j = 0; j < 10; j++) {
|
||||||
errno = j * 23 % 7; /* there should */
|
errno = j * 23 % 7; /* there should */
|
||||||
if (readdir(dirp) != DIRENT0) e(11); /* be nomore dir */
|
if (readdir(dirp) != DIRENT0) e(12); /* be nomore dir */
|
||||||
if (errno != j * 23 % 7) e(12); /* entrys */
|
if (errno != j * 23 % 7) e(13); /* entrys */
|
||||||
}
|
}
|
||||||
if ((fd4 = creat("foo/f4", 0666)) <= 2) e(13); /* Open a file. */
|
if ((fd4 = creat("foo/f4", 0666)) <= 2) e(14); /* Open a file. */
|
||||||
System("rm foo/f4"); /* Kill entry. */
|
System("rm foo/f4"); /* Kill entry. */
|
||||||
rewinddir(dirp); /* Rewind foo. */
|
rewinddir(dirp); /* Rewind foo. */
|
||||||
if ((fd3 = open("foo/f3", O_WRONLY)) <= 2) e(14); /* Open more files. */
|
if ((fd3 = open("foo/f3", O_WRONLY)) <= 2) e(15); /* Open more files. */
|
||||||
if ((fd5 = open("foo/f5", O_WRONLY)) <= 2) e(15);
|
if ((fd5 = open("foo/f5", O_WRONLY)) <= 2) e(16);
|
||||||
if (write(fd3, "Hello", 6) != 6) e(16);
|
if (write(fd3, "Hello", 6) != 6) e(17);
|
||||||
if (write(fd4, "Hello", 6) != 6) e(17); /* write some data */
|
if (write(fd4, "Hello", 6) != 6) e(18); /* write some data */
|
||||||
if (close(fd5) != 0) e(18);
|
if (close(fd5) != 0) e(19);
|
||||||
chk_dir(dirp);
|
chk_dir(dirp);
|
||||||
for (j = 0; j < 10; j++) {
|
for (j = 0; j < 10; j++) {
|
||||||
errno = j * 101 % 7; /* there should */
|
errno = j * 101 % 7; /* there should */
|
||||||
if (readdir(dirp) != DIRENT0) e(19); /* be nomore dir */
|
if (readdir(dirp) != DIRENT0) e(20); /* be nomore dir */
|
||||||
if (errno != j * 101 % 7) e(20); /* entrys */
|
if (errno != j * 101 % 7) e(21); /* entrys */
|
||||||
}
|
}
|
||||||
if (close(fd4) != 0) e(21); /* shouldn't matter */
|
if (close(fd4) != 0) e(22); /* shouldn't matter */
|
||||||
if (close(fd3) != 0) e(22); /* when we do this */
|
if (close(fd3) != 0) e(23); /* when we do this */
|
||||||
if (closedir(dirp) != 0) e(23); /* close foo again */
|
if (closedir(dirp) != 0) e(24); /* close foo again */
|
||||||
|
|
||||||
Chdir("foo");
|
Chdir("foo");
|
||||||
if ((dirp = opendir(".//")) == ((DIR *) NULL)) e(24); /* open foo again */
|
if ((dirp = opendir(".//")) == ((DIR *) NULL)) e(25); /* open foo again */
|
||||||
Chdir("..");
|
Chdir("..");
|
||||||
chk_dir(dirp); /* foosok? */
|
chk_dir(dirp); /* foosok? */
|
||||||
for (j = 0; j < 10; j++) {
|
for (j = 0; j < 10; j++) {
|
||||||
errno = (j * 101) % 7; /* there should */
|
errno = (j * 101) % 7; /* there should */
|
||||||
if (readdir(dirp) != DIRENT0) e(25); /* be nomore dir */
|
if (readdir(dirp) != DIRENT0) e(26); /* be nomore dir */
|
||||||
if (errno != (j * 101) % 7) e(26); /* entrys */
|
if (errno != (j * 101) % 7) e(27); /* entrys */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closedir(dirp) != 0) e(27); /* It should be closable */
|
if (closedir(dirp) != 0) e(28); /* It should be closable */
|
||||||
|
|
||||||
stat("foo", &st1); /* get stat */
|
stat("foo", &st1); /* get stat */
|
||||||
time(&time1);
|
time(&time1);
|
||||||
while (time1 >= time((time_t *)0))
|
while (time1 >= time((time_t *)0))
|
||||||
;
|
;
|
||||||
if ((dirp = opendir("foo")) == ((DIR *) NULL)) e(28); /* open, */
|
if ((dirp = opendir("foo")) == ((DIR *) NULL)) e(29); /* open, */
|
||||||
if (readdir(dirp) == DIRENT0) e(29); /* read and */
|
if (readdir(dirp) == DIRENT0) e(30); /* read and */
|
||||||
stat("foo", &st2); /* get new stat */
|
stat("foo", &st2); /* get new stat */
|
||||||
if (st1.st_atime > st2.st_atime) e(30); /* st_atime check */
|
if (st1.st_atime > st2.st_atime) e(31); /* st_atime check */
|
||||||
|
|
||||||
switch (fork()) {
|
switch (fork()) {
|
||||||
case -1: printf("Can't fork\n"); break;
|
case -1: printf("Can't fork\n"); break;
|
||||||
case 0:
|
case 0:
|
||||||
rewinddir(dirp); /* rewind childs dirp */
|
rewinddir(dirp); /* rewind childs dirp */
|
||||||
if (readdir(dirp) == DIRENT0) e(31); /* read should be ok */
|
if (readdir(dirp) == DIRENT0) e(32); /* read should be ok */
|
||||||
if (closedir(dirp) != 0) e(32); /* close child'd foo */
|
if (closedir(dirp) != 0) e(33); /* close child'd foo */
|
||||||
exit(0); /* 0 stops here */
|
exit(0); /* 0 stops here */
|
||||||
default:
|
default:
|
||||||
if (wait(&stat_loc) == -1) e(33); /* PARENT wait()'s */
|
if (wait(&stat_loc) == -1) e(34); /* PARENT wait()'s */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (closedir(dirp) != 0) e(34); /* close parent's foo */
|
if (closedir(dirp) != 0) e(35); /* close parent's foo */
|
||||||
}
|
}
|
||||||
|
|
||||||
void test24b()
|
void test24b()
|
||||||
|
|
Loading…
Reference in a new issue