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