1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
4  * 06/2017 modified by Xiao Yang <yangx.jy@cn.fujitsu.com>
5  */
6 
7 /*
8  * DESCRIPTION
9  * 1) lseek(2) fails and sets errno to EBADF when fd is invalid.
10  * 2) lseek(2) fails ans sets errno to EINVAL when whence is invalid.
11  * 3) lseek(2) fails and sets errno to ESPIPE when fd is associated
12  *    with a pipe or FIFO.
13  */
14 
15 #include <errno.h>
16 #include <sys/types.h>
17 #include <unistd.h>
18 #include <stdio.h>
19 #include <sys/stat.h>
20 #include "tst_test.h"
21 
22 #define TFILE "tfile"
23 #define TFIFO1 "tfifo1"
24 #define TFIFO2 "tfifo2"
25 
26 static int bad_fd = -1;
27 static int fd, pfd1, pfd2;
28 static int pfds[2];
29 
30 static struct tcase {
31 	int *fd;
32 	int whence;
33 	int exp_err;
34 } tcases[] = {
35 	{&bad_fd, SEEK_SET, EBADF},
36 	{&bad_fd, SEEK_CUR, EBADF},
37 	{&bad_fd, SEEK_END, EBADF},
38 	{&fd, 5, EINVAL},
39 	{&fd, -1, EINVAL},
40 	{&fd, 7, EINVAL},
41 	{&pfd1, SEEK_SET, ESPIPE},
42 	{&pfd1, SEEK_CUR, ESPIPE},
43 	{&pfd1, SEEK_END, ESPIPE},
44 	{&pfds[0], SEEK_SET, ESPIPE},
45 	{&pfds[0], SEEK_CUR, ESPIPE},
46 	{&pfds[0], SEEK_END, ESPIPE},
47 	{&pfd2, SEEK_SET, ESPIPE},
48 	{&pfd2, SEEK_CUR, ESPIPE},
49 	{&pfd2, SEEK_END, ESPIPE},
50 };
51 
verify_lseek(unsigned int n)52 static void verify_lseek(unsigned int n)
53 {
54 	struct tcase *tc = &tcases[n];
55 
56 	TEST(lseek(*tc->fd, (off_t) 1, tc->whence));
57 	if (TST_RET != (off_t) -1) {
58 		tst_res(TFAIL, "lseek(%d, 1, %d) succeeded unexpectedly",
59 			*tc->fd, tc->whence);
60 			return;
61 	}
62 
63 	if (TST_ERR == tc->exp_err) {
64 		tst_res(TPASS | TTERRNO, "lseek(%d, 1, %d) failed as expected",
65 			*tc->fd, tc->whence);
66 	} else {
67 		tst_res(TFAIL | TTERRNO, "lseek(%d, 1, %d) failed "
68 			"unexpectedly, expected %s", *tc->fd, tc->whence,
69 			tst_strerrno(tc->exp_err));
70 	}
71 }
72 
setup(void)73 static void setup(void)
74 {
75 	fd = SAFE_OPEN(TFILE, O_RDWR | O_CREAT, 0777);
76 	SAFE_MKFIFO(TFIFO1, 0777);
77 	pfd1 = SAFE_OPEN(TFIFO1, O_RDWR, 0777);
78 	SAFE_PIPE(pfds);
79 	SAFE_MKNOD(TFIFO2, S_IFIFO | 0777, 0);
80 	pfd2 = SAFE_OPEN(TFIFO2, O_RDWR, 0777);
81 }
82 
cleanup(void)83 static void cleanup(void)
84 {
85 	if (fd > 0)
86 		SAFE_CLOSE(fd);
87 
88 	if (pfd1 > 0)
89 		SAFE_CLOSE(pfd1);
90 
91 	if (pfds[0] > 0)
92 		SAFE_CLOSE(pfds[0]);
93 
94 	if (pfds[1] > 0)
95 		SAFE_CLOSE(pfds[1]);
96 
97 	if (pfd2 > 0)
98 		SAFE_CLOSE(pfd2);
99 }
100 
101 static struct tst_test test = {
102 	.setup = setup,
103 	.cleanup = cleanup,
104 	.tcnt = ARRAY_SIZE(tcases),
105 	.test = verify_lseek,
106 	.needs_tmpdir = 1,
107 };
108