1 /*
2  * Copyright (c) 2004, Bull SA. All rights reserved.
3  * Created by:  Laurent.Vivier@bull.net
4  * This file is licensed under the GPL license.  For the full content
5  * of this license, see the COPYING file at the top level of this
6  * source tree.
7  */
8 
9 /*
10  * assertion:
11  *
12  *	aio_cancel() shall return AIO_CANCELED if the requested operations
13  *	were canceled.
14  *
15  * method:
16  *
17  *	queue a lot of aio_write() to a given fildes.
18  *	try to cancel the last one submited
19  *	if aio_error() is ECANCELED and aio_cancel() is AIO_CANCELED
20  *	test is passed
21  *	if aio_error() is ECANCELED and aio_cancel() is NOT AIO_CANCELED
22  *	test is failed
23  *	if there is no aio_error() with ECANCELED and
24  *	aio_cancel() is AIO_CANCELED
25  *	test is failed
26  *	otherwise test is unresolved
27  *
28  */
29 
30 #define _XOPEN_SOURCE 600
31 #include <stdio.h>
32 #include <sys/types.h>
33 #include <unistd.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <string.h>
37 #include <errno.h>
38 #include <stdlib.h>
39 #include <malloc.h>
40 #include <aio.h>
41 
42 #include "posixtest.h"
43 
44 #define TNAME "aio_cancel/6-1.c"
45 
46 #define BUF_NB		128
47 #define BUF_SIZE	1024
48 
main()49 int main()
50 {
51 	char tmpfname[256];
52 	int fd;
53 	struct aiocb *aiocb[BUF_NB];
54 	int i;
55 	int in_progress;
56 	int gret;
57 
58 #if _POSIX_ASYNCHRONOUS_IO != 200112L
59 	return PTS_UNSUPPORTED;
60 #endif
61 
62 	snprintf(tmpfname, sizeof(tmpfname), "/tmp/pts_aio_cancel_6_1_%d",
63 		  getpid());
64 	unlink(tmpfname);
65 	fd = open(tmpfname, O_CREAT | O_RDWR | O_EXCL,
66 		  S_IRUSR | S_IWUSR);
67 	if (fd == -1)
68 	{
69 		printf(TNAME " Error at open(): %s\n",
70 		       strerror(errno));
71 		return PTS_UNRESOLVED;
72 	}
73 
74 	unlink(tmpfname);
75 
76 	/* create AIO req */
77 
78 	for (i = 0; i < BUF_NB; i++)
79 	{
80 		aiocb[i] = malloc(sizeof(struct aiocb));
81 		if (aiocb[i] == NULL)
82 		{
83 			printf(TNAME " Error at malloc(): %s\n",
84 		       		strerror(errno));
85 			return PTS_UNRESOLVED;
86 		}
87 		aiocb[i]->aio_fildes = fd;
88 		aiocb[i]->aio_buf = malloc(BUF_SIZE);
89 		if (aiocb[i]->aio_buf == NULL)
90 		{
91 			printf(TNAME " Error at malloc(): %s\n",
92 		       		strerror(errno));
93 			return PTS_UNRESOLVED;
94 		}
95 		aiocb[i]->aio_nbytes = BUF_SIZE;
96 		aiocb[i]->aio_offset = 0;
97 		aiocb[i]->aio_sigevent.sigev_notify = SIGEV_NONE;
98 
99 		if (aio_write(aiocb[i]) == -1)
100 		{
101 			printf(TNAME " loop %d: Error at aio_write(): %s\n",
102 			       i, strerror(errno));
103 			return PTS_FAIL;
104 		}
105 	}
106 
107 	/* try to cancel the last one queued */
108 
109 	gret = aio_cancel(fd, aiocb[i-1]);
110 
111 	if (gret == -1)
112 	{
113 		printf(TNAME " Error at aio_cancel(): %s\n",
114 		       strerror(errno));
115 		return PTS_FAIL;
116 	}
117 
118 	close(fd);
119 
120 	do {
121 		in_progress = 0;
122 		for (i = 0; i < BUF_NB; i++)
123 		{
124 			int ret;
125 
126 			ret = (aio_error(aiocb[i]));
127 
128 			if (ret == -1)
129 			{
130 				printf(TNAME " Error at aio_error(): %s\n",
131 		       			strerror(errno));
132 				return PTS_FAIL;
133 			}
134 			else if (ret == EINPROGRESS)
135 				in_progress = 1;
136 			else if (ret == ECANCELED)
137 			{
138 				if (gret == AIO_CANCELED)
139 				{
140 					printf ("Test PASSED\n");
141 					return PTS_PASS;
142 				}
143 
144 				printf(TNAME " aio_cancel() is not AIO_CANCELED\n");
145 				return PTS_FAIL;
146 			}
147 		}
148 	} while (in_progress);
149 
150 	if (gret == AIO_CANCELED)
151 	{
152 		printf(TNAME " aio_cancel() is AIO_CANCELED without ECANCELED\n");
153 		return PTS_FAIL;
154 	}
155 
156 	return PTS_UNRESOLVED;
157 }
158