chiark / gitweb /
eglibc (2.11.3-4+deb6u3) squeeze-lts; urgency=medium
[eglibc.git] / io / tst-fchownat.c
1 #include <dirent.h>
2 #include <fcntl.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7
8
9 static void prepare (void);
10 #define PREPARE(argc, argv) prepare ()
11
12 static int do_test (void);
13 #define TEST_FUNCTION do_test ()
14
15 #include "../test-skeleton.c"
16
17 static int dir_fd;
18
19 static void
20 prepare (void)
21 {
22 #if _POSIX_CHOWN_RESTRICTED == 0
23   if (pathconf (test_dir, _PC_CHOWN_RESTRICTED) != 0)
24 #endif
25     {
26       uid_t uid = getuid ();
27       if (uid != 0)
28         {
29           puts ("need root privileges");
30           exit (0);
31         }
32     }
33
34   size_t test_dir_len = strlen (test_dir);
35   static const char dir_name[] = "/tst-fchownat.XXXXXX";
36
37   size_t dirbuflen = test_dir_len + sizeof (dir_name);
38   char *dirbuf = malloc (dirbuflen);
39   if (dirbuf == NULL)
40     {
41       puts ("out of memory");
42       exit (1);
43     }
44
45   snprintf (dirbuf, dirbuflen, "%s%s", test_dir, dir_name);
46   if (mkdtemp (dirbuf) == NULL)
47     {
48       puts ("cannot create temporary directory");
49       exit (1);
50     }
51
52   add_temp_file (dirbuf);
53
54   dir_fd = open (dirbuf, O_RDONLY | O_DIRECTORY);
55   if (dir_fd == -1)
56     {
57       puts ("cannot open directory");
58       exit (1);
59     }
60 }
61
62
63 static int
64 do_test (void)
65 {
66   /* fdopendir takes over the descriptor, make a copy.  */
67   int dupfd = dup (dir_fd);
68   if (dupfd == -1)
69     {
70       puts ("dup failed");
71       return 1;
72     }
73   if (lseek (dupfd, 0, SEEK_SET) != 0)
74     {
75       puts ("1st lseek failed");
76       return 1;
77     }
78
79   /* The directory should be empty safe the . and .. files.  */
80   DIR *dir = fdopendir (dupfd);
81   if (dir == NULL)
82     {
83       puts ("fdopendir failed");
84       return 1;
85     }
86   struct dirent64 *d;
87   while ((d = readdir64 (dir)) != NULL)
88     if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0)
89       {
90         printf ("temp directory contains file \"%s\"\n", d->d_name);
91         return 1;
92       }
93   closedir (dir);
94
95   /* Try to create a file.  */
96   int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666);
97   if (fd == -1)
98     {
99       if (errno == ENOSYS)
100         {
101           puts ("*at functions not supported");
102           return 0;
103         }
104
105       puts ("file creation failed");
106       return 1;
107     }
108   write (fd, "hello", 5);
109   puts ("file created");
110
111   struct stat64 st1;
112   if (fstat64 (fd, &st1) != 0)
113     {
114       puts ("fstat64 failed");
115       return 1;
116     }
117
118   /* Before closing the file, try using this file descriptor to open
119      another file.  This must fail.  */
120   if (fchownat (fd, "some-file", 1, 1, 0) != -1)
121     {
122       puts ("fchownat using descriptor for normal file worked");
123       return 1;
124     }
125   if (errno != ENOTDIR)
126     {
127       puts ("\
128 error for fchownat using descriptor for normal file not ENOTDIR ");
129       return 1;
130     }
131
132   close (fd);
133
134   if (fchownat (dir_fd, "some-file", st1.st_uid + 1, st1.st_gid + 1, 0) != 0)
135     {
136       puts ("fchownat failed");
137       return 1;
138     }
139
140   struct stat64 st2;
141   if (fstatat64 (dir_fd, "some-file", &st2, 0) != 0)
142     {
143       puts ("fstatat64 failed");
144       return 1;
145     }
146
147   if (st1.st_uid + 1 != st2.st_uid || st1.st_gid + 1 != st2.st_gid)
148     {
149       puts ("owner change failed");
150       return 1;
151     }
152
153   if (unlinkat (dir_fd, "some-file", 0) != 0)
154     {
155       puts ("unlinkat failed");
156       return 1;
157     }
158
159   /* Create a file descriptor which is closed again right away.  */
160   int dir_fd2 = dup (dir_fd);
161   if (dir_fd2 == -1)
162     {
163       puts ("dup failed");
164       return 1;
165     }
166   close (dir_fd2);
167
168   if (fchownat (dir_fd2, "some-file", 1, 1, 0) != -1)
169     {
170       puts ("fchownat using closed descriptor worked");
171       return 1;
172     }
173   if (errno != EBADF)
174     {
175       puts ("error for fchownat using closed descriptor not EBADF ");
176       return 1;
177     }
178
179   close (dir_fd);
180
181   if (fchownat (-1, "some-file", 1, 1, 0) != -1)
182     {
183       puts ("fchownat using invalid descriptor worked");
184       return 1;
185     }
186   if (errno != EBADF)
187     {
188       puts ("error for fchownat using invalid descriptor not EBADF ");
189       return 1;
190     }
191
192   return 0;
193 }