1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
/* test29: dup() dup2() Author: Jan-Mark Wams (jms@cs.vu.nl) */
/* The definition of ``dup2()'' is realy a big mess! For:
**
** (1) if fildes2 is less than zero or greater than {OPEN_MAX}
** errno has to set to [EBADF]. But if fildes2 equals {OPEN_MAX}
** errno has to be set to [EINVAL]. And ``fcntl(F_DUPFD...)'' always
** returns [EINVAL] if fildes2 is out of range!
**
** (2) if the number of file descriptors would exceed {OPEN_MAX}, or no
** file descriptors above fildes2 are available, errno has to be set
** to [EMFILE]. But this can never occur!
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
#include <time.h>
#include <stdio.h>
int max_error = 4;
#include "common.h"
#define ITERATIONS 10
#define System(cmd) if (system(cmd) != 0) printf("``%s'' failed\n", cmd)
#define Chdir(dir) if (chdir(dir) != 0) printf("Can't goto %s\n", dir)
#define Stat(a,b) if (stat(a,b) != 0) printf("Can't stat %s\n", a)
#define IS_CLOEXEC(fd) ((fcntl(fd, F_GETFD) & FD_CLOEXEC) == FD_CLOEXEC)
#define SET_CLOEXEC(fd) fcntl(fd, F_SETFD, FD_CLOEXEC)
int superuser;
void test29a(void);
void test29b(void);
void test29c(void);
int main(int argc, char *argv[])
{
int i, m = 0xFFFF;
sync();
if (argc == 2) m = atoi(argv[1]);
start(29);
superuser = (geteuid() == 0);
for (i = 0; i < ITERATIONS; i++) {
if (m & 0001) test29a();
if (m & 0002) test29b();
if (m & 0004) test29c();
}
quit();
return(-1); /* Unreachable */
}
void test29a()
{
int fd1, fd2, fd3, fd4, fd5;
struct flock flock;
subtest = 1;
/* Basic checking. */
if ((fd1 = dup(0)) != 3) e(1);
if ((fd2 = dup(0)) != 4) e(2);
if ((fd3 = dup(0)) != 5) e(3);
if ((fd4 = dup(0)) != 6) e(4);
if ((fd5 = dup(0)) != 7) e(5);
if (close(fd2) != 0) e(6);
if (close(fd4) != 0) e(7);
if ((fd2 = dup(0)) != 4) e(8);
if ((fd4 = dup(0)) != 6) e(9);
if (close(fd1) != 0) e(10);
if (close(fd3) != 0) e(11);
if (close(fd5) != 0) e(12);
if ((fd1 = dup(0)) != 3) e(13);
if ((fd3 = dup(0)) != 5) e(14);
if ((fd5 = dup(0)) != 7) e(15);
if (close(fd1) != 0) e(16);
if (close(fd2) != 0) e(17);
if (close(fd3) != 0) e(18);
if (close(fd4) != 0) e(19);
if (close(fd5) != 0) e(20);
/* FD_CLOEXEC should be cleared. */
if ((fd1 = dup(0)) != 3) e(21);
if (SET_CLOEXEC(fd1) == -1) e(22);
if (!IS_CLOEXEC(fd1)) e(23);
if ((fd2 = dup(fd1)) != 4) e(24);
if ((fd3 = dup(fd2)) != 5) e(25);
if (IS_CLOEXEC(fd2)) e(26);
if (IS_CLOEXEC(fd3)) e(27);
if (SET_CLOEXEC(fd2) == -1) e(28);
if (!IS_CLOEXEC(fd2)) e(29);
if (IS_CLOEXEC(fd3)) e(30);
if (close(fd1) != 0) e(31);
if (close(fd2) != 0) e(32);
if (close(fd3) != 0) e(33);
/* Locks should be shared, so we can lock again. */
System("echo 'Hallo' > file");
if ((fd1 = open("file", O_RDWR)) != 3) e(34);
flock.l_whence = SEEK_SET;
flock.l_start = 0;
flock.l_len = 10;
flock.l_type = F_WRLCK;
if (fcntl(fd1, F_SETLK, &flock) == -1) e(35);
if (fcntl(fd1, F_SETLK, &flock) == -1) e(36);
if ((fd2 = dup(fd1)) != 4) e(37);
if (fcntl(fd1, F_SETLK, &flock) == -1) e(38);
if (fcntl(fd1, F_GETLK, &flock) == -1) e(39);
#if 0 /* XXX - see test7.c */
if (flock.l_type != F_WRLCK) e(40);
if (flock.l_pid != getpid()) e(41);
#endif /* 0 */
flock.l_type = F_WRLCK;
if (fcntl(fd2, F_GETLK, &flock) == -1) e(42);
#if 0 /* XXX - see test7.c */
if (flock.l_type != F_WRLCK) e(43);
if (flock.l_pid != getpid()) e(44);
#endif /* 0 */
if (close(fd1) != 0) e(45);
if (close(fd2) != 0) e(46);
System("rm -rf ../DIR_29/*");
}
void test29b()
{
int fd;
char buf[32];
subtest = 2;
/* Test file called ``file''. */
System("echo 'Hallo!' > file");
/* Check dup2() call with the same fds. Should have no effect. */
if ((fd = open("file", O_RDONLY)) != 3) e(1);
if (read(fd, buf, 2) != 2) e(2);
if (strncmp(buf, "Ha", 2) != 0) e(3);
if (dup2(fd, fd) != fd) e(4);
if (read(fd, buf, 2) != 2) e(5);
if (strncmp(buf, "ll", 2) != 0) e(6);
if (dup2(fd, fd) != fd) e(7);
if (read(fd, buf, 2) != 2) e(8);
if (strncmp(buf, "o!", 2) != 0) e(9);
if (close(fd) != 0) e(10);
/* If dup2() call fails, the fildes2 argument has to stay open. */
if ((fd = open("file", O_RDONLY)) != 3) e(11);
if (read(fd, buf, 2) != 2) e(12);
if (strncmp(buf, "Ha", 2) != 0) e(13);
if (dup2(OPEN_MAX + 3, fd) != -1) e(14);
if (errno != EBADF) e(15);
if (read(fd, buf, 2) != 2) e(16);
if (strncmp(buf, "ll", 2) != 0) e(17);
if (dup2(-4, fd) != -1) e(18);
if (errno != EBADF) e(19);
if (read(fd, buf, 2) != 2) e(20);
if (strncmp(buf, "o!", 2) != 0) e(21);
if (close(fd) != 0) e(22);
System("rm -rf ../DIR_29/*");
}
void test29c()
{
int i;
subtest = 3;
/* Check bad arguments to dup() and dup2(). */
for (i = -OPEN_MAX; i < OPEN_MAX * 2; i++) {
/* ``i'' is a valid and open fd. */
if (i >= 0 && i < 3) continue;
/* If ``i'' is a valid fd it is not open. */
if (dup(i) != -1) e(1);
if (errno != EBADF) e(2);
/* ``i'' Is OPEN_MAX. */
if (i == OPEN_MAX) {
if (dup2(0, i) != -1) e(3);
if (errno != EINVAL) e(4);
}
/* ``i'' Is out of range. */
if (i < 0 || i > OPEN_MAX) {
if (dup2(0, i) != -1) e(5);
if (errno != EBADF) e(6);
}
}
System("rm -rf ../DIR_29/*");
}
|