Prefer https to http for gnu.org and fsf.org URLs
[platform/upstream/glibc.git] / rt / tst-aio64.c
1 /* Tests for 64bit AIO in librt.
2    Copyright (C) 1998-2019 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <https://www.gnu.org/licenses/>.  */
19
20 #define _LARGEFILE_SOURCE 1
21 #include <aio.h>
22 #include <errno.h>
23 #include <error.h>
24 #include <fcntl.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <sys/stat.h>
29
30
31 /* Prototype for our test function.  */
32 extern void do_prepare (int argc, char *argv[]);
33 extern int do_test (int argc, char *argv[]);
34
35 /* We have a preparation function.  */
36 #define PREPARE do_prepare
37
38 /* This defines the `main' function and some more.  */
39 #include <test-skeleton.c>
40
41
42 /* These are for the temporary file we generate.  */
43 char *name;
44 int fd;
45
46 void
47 do_prepare (int argc, char *argv[])
48 {
49   size_t name_len;
50
51   name_len = strlen (test_dir);
52   name = xmalloc (name_len + sizeof ("/aioXXXXXX"));
53   mempcpy (mempcpy (name, test_dir, name_len),
54            "/aioXXXXXX", sizeof ("/aioXXXXXX"));
55
56   /* Open our test file.   */
57   fd = mkstemp (name);
58   if (fd == -1)
59     error (EXIT_FAILURE, errno, "cannot open test file `%s'", name);
60   add_temp_file (name);
61 }
62
63
64 static int
65 test_file (const void *buf, size_t size, int fd, const char *msg)
66 {
67   struct stat st;
68   char tmp[size];
69
70   errno = 0;
71   if (fstat (fd, &st) < 0)
72     {
73       error (0, errno, "%s: failed stat", msg);
74       return 1;
75     }
76
77   if (st.st_size != (off_t) size)
78     {
79       error (0, errno, "%s: wrong size: %lu, should be %lu",
80              msg, (unsigned long int) st.st_size, (unsigned long int) size);
81       return 1;
82     }
83
84   if (pread (fd, tmp, size, 0) != (ssize_t) size)
85     {
86       error (0, errno, "%s: failed pread", msg);
87       return 1;
88     }
89
90   if (memcmp (buf, tmp, size) != 0)
91     {
92       error (0, errno, "%s: failed comparison", msg);
93       return 1;
94     }
95
96   printf ("%s test ok\n", msg);
97
98   return 0;
99 }
100
101
102 static int
103 do_wait (struct aiocb64 **cbp, size_t nent, int allowed_err)
104 {
105   int go_on;
106   size_t cnt;
107   int result = 0;
108
109   do
110     {
111       aio_suspend64 ((const struct aiocb64 *const *) cbp, nent, NULL);
112       go_on = 0;
113       for (cnt = 0; cnt < nent; ++cnt)
114         if (cbp[cnt] != NULL)
115           {
116             if (aio_error64 (cbp[cnt]) == EINPROGRESS)
117               go_on = 1;
118             else
119               {
120                 if (aio_return64 (cbp[cnt]) == -1
121                     && (allowed_err == 0
122                         || aio_error64 (cbp[cnt]) != allowed_err))
123                   {
124                     error (0, aio_error64 (cbp[cnt]), "Operation failed\n");
125                     result = 1;
126                   }
127                 cbp[cnt] = NULL;
128               }
129           }
130     }
131   while (go_on);
132
133   return result;
134 }
135
136
137 int
138 do_test (int argc, char *argv[])
139 {
140   struct aiocb64 cbs[10];
141   struct aiocb64 cbs_fsync;
142   struct aiocb64 *cbp[10];
143   struct aiocb64 *cbp_fsync[1];
144   char buf[1000];
145   size_t cnt;
146   int result = 0;
147
148   /* Preparation.  */
149   for (cnt = 0; cnt < 10; ++cnt)
150     {
151       cbs[cnt].aio_fildes = fd;
152       cbs[cnt].aio_reqprio = 0;
153       cbs[cnt].aio_buf = memset (&buf[cnt * 100], '0' + cnt, 100);
154       cbs[cnt].aio_nbytes = 100;
155       cbs[cnt].aio_offset = cnt * 100;
156       cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE;
157
158       cbp[cnt] = &cbs[cnt];
159     }
160
161   /* First a simple test.  */
162   for (cnt = 10; cnt > 0; )
163     if (aio_write64 (cbp[--cnt]) < 0 && errno == ENOSYS)
164       {
165         error (0, 0, "no aio support in this configuration");
166         return 0;
167       }
168   /* Wait 'til the results are there.  */
169   result |= do_wait (cbp, 10, 0);
170   /* Test this.  */
171   result |= test_file (buf, sizeof (buf), fd, "aio_write");
172
173   /* Read now as we've written it.  */
174   memset (buf, '\0', sizeof (buf));
175   /* Issue the commands.  */
176   for (cnt = 10; cnt > 0; )
177     {
178       --cnt;
179       cbp[cnt] = &cbs[cnt];
180       aio_read64 (cbp[cnt]);
181     }
182   /* Wait 'til the results are there.  */
183   result |= do_wait (cbp, 10, 0);
184   /* Test this.  */
185   for (cnt = 0; cnt < 1000; ++cnt)
186     if (buf[cnt] != '0' + (cnt / 100))
187       {
188         result = 1;
189         error (0, 0, "comparison failed for aio_read test");
190         break;
191       }
192
193   if (cnt == 1000)
194     puts ("aio_read test ok");
195
196   /* Remove the test file contents.  */
197   if (ftruncate64 (fd, 0) < 0)
198     {
199       error (0, errno, "ftruncate failed\n");
200       result = 1;
201     }
202
203   /* Test lio_listio.  */
204   for (cnt = 0; cnt < 10; ++cnt)
205     {
206       cbs[cnt].aio_lio_opcode = LIO_WRITE;
207       cbp[cnt] = &cbs[cnt];
208     }
209   /* Issue the command.  */
210   lio_listio64 (LIO_WAIT, cbp, 10, NULL);
211   /* ...and immediately test it since we started it in wait mode.  */
212   result |= test_file (buf, sizeof (buf), fd, "lio_listio (write)");
213
214   /* Test aio_fsync.  */
215   cbs_fsync.aio_fildes = fd;
216   cbs_fsync.aio_sigevent.sigev_notify = SIGEV_NONE;
217   cbp_fsync[0] = &cbs_fsync;
218
219   /* Remove the test file contents first.  */
220   if (ftruncate64 (fd, 0) < 0)
221     {
222       error (0, errno, "ftruncate failed\n");
223       result = 1;
224     }
225
226   /* Write again.  */
227   for (cnt = 10; cnt > 0; )
228     aio_write64 (cbp[--cnt]);
229
230   if (aio_fsync64 (O_SYNC, &cbs_fsync) < 0)
231     {
232       error (0, errno, "aio_fsync failed\n");
233       result = 1;
234     }
235   result |= do_wait (cbp_fsync, 1, 0);
236
237   /* ...and test since all data should be on disk now.  */
238   result |= test_file (buf, sizeof (buf), fd, "aio_fsync (aio_write)");
239
240   /* Test aio_cancel.  */
241   /* Remove the test file contents first.  */
242   if (ftruncate64 (fd, 0) < 0)
243     {
244       error (0, errno, "ftruncate failed\n");
245       result = 1;
246     }
247
248   /* Write again.  */
249   for (cnt = 10; cnt > 0; )
250     aio_write64 (cbp[--cnt]);
251
252   /* Cancel all requests.  */
253   if (aio_cancel64 (fd, NULL) == -1)
254     printf ("aio_cancel64 (fd, NULL) cannot cancel anything\n");
255
256   result |= do_wait (cbp, 10, ECANCELED);
257
258   /* Another test for aio_cancel.  */
259   /* Remove the test file contents first.  */
260   if (ftruncate64 (fd, 0) < 0)
261     {
262       error (0, errno, "ftruncate failed\n");
263       result = 1;
264     }
265
266   /* Write again.  */
267   for (cnt = 10; cnt > 0; )
268     {
269       --cnt;
270       cbp[cnt] = &cbs[cnt];
271       aio_write64 (cbp[cnt]);
272     }
273   puts ("finished3");
274
275   /* Cancel all requests.  */
276   for (cnt = 10; cnt > 0; )
277     if (aio_cancel64 (fd, cbp[--cnt]) == -1)
278       /* This is not an error.  The request can simply be finished.  */
279       printf ("aio_cancel64 (fd, cbp[%Zd]) cannot be canceled\n", cnt);
280   puts ("finished2");
281
282   result |= do_wait (cbp, 10, ECANCELED);
283
284   puts ("finished");
285
286   return result;
287 }