1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /*
4 * Copyright (c) International Business Machines Corp., 2002
5 */
6
7 /* 12/03/2002 Port to LTP robbiew@us.ibm.com */
8 /* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
9
10 /*\
11 * [DOCUMENTATION]
12 * Verify that acct() returns proper errno on failure.
13 */
14
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <pwd.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <sys/mount.h>
24
25 #include "tst_test.h"
26
27 #define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \
28 S_IXGRP|S_IROTH|S_IXOTH)
29 #define FILE_EISDIR "."
30 #define FILE_EACCES "/dev/null"
31 #define FILE_ENOENT "/tmp/does/not/exist"
32 #define FILE_ENOTDIR "./tmpfile/"
33 #define TEST_TMPFILE "./tmpfile"
34 #define TEST_ELOOP "test_file_eloop1"
35 #define TEST_ENAMETOOLONG nametoolong
36 #define TEST_EROFS "mntpoint/file"
37
38 static char nametoolong[PATH_MAX+2];
39 static struct passwd *ltpuser;
40
setup_euid(void)41 static void setup_euid(void)
42 {
43 SAFE_SETEUID(ltpuser->pw_uid);
44 }
45
cleanup_euid(void)46 static void cleanup_euid(void)
47 {
48 SAFE_SETEUID(0);
49 }
50
51 static struct test_case {
52 char *filename;
53 char *exp_errval;
54 int exp_errno;
55 void (*setupfunc) ();
56 void (*cleanfunc) ();
57 } tcases[] = {
58 {FILE_EISDIR, "EISDIR", EISDIR, NULL, NULL},
59 {FILE_EACCES, "EACCES", EACCES, NULL, NULL},
60 {FILE_ENOENT, "ENOENT", ENOENT, NULL, NULL},
61 {FILE_ENOTDIR, "ENOTDIR", ENOTDIR, NULL, NULL},
62 {TEST_TMPFILE, "EPERM", EPERM, setup_euid, cleanup_euid},
63 {NULL, "EPERM", EPERM, setup_euid, cleanup_euid},
64 {TEST_ELOOP, "ELOOP", ELOOP, NULL, NULL},
65 {TEST_ENAMETOOLONG, "ENAMETOOLONG", ENAMETOOLONG, NULL, NULL},
66 {TEST_EROFS, "EROFS", EROFS, NULL, NULL},
67 };
68
setup(void)69 static void setup(void)
70 {
71 int fd;
72
73 TEST(acct(NULL));
74 if (TST_RET == -1 && TST_ERR == ENOSYS)
75 tst_brk(TCONF, "acct() system call isn't configured in kernel");
76
77 ltpuser = SAFE_GETPWNAM("nobody");
78
79 fd = SAFE_CREAT(TEST_TMPFILE, 0777);
80 SAFE_CLOSE(fd);
81
82 TEST(acct(TEST_TMPFILE));
83 if (TST_RET == -1)
84 tst_brk(TBROK | TTERRNO, "acct failed unexpectedly");
85
86 /* turn off acct, so we are in a known state */
87 TEST(acct(NULL));
88 if (TST_RET == -1)
89 tst_brk(TBROK | TTERRNO, "acct(NULL) failed");
90
91 /* ELOOP SETTING */
92 SAFE_SYMLINK(TEST_ELOOP, "test_file_eloop2");
93 SAFE_SYMLINK("test_file_eloop2", TEST_ELOOP);
94
95 /* ENAMETOOLONG SETTING */
96 memset(nametoolong, 'a', PATH_MAX+1);
97 }
98
verify_acct(unsigned int nr)99 static void verify_acct(unsigned int nr)
100 {
101 struct test_case *tcase = &tcases[nr];
102
103 if (tcase->setupfunc)
104 tcase->setupfunc();
105
106 TEST(acct(tcase->filename));
107
108 if (tcase->cleanfunc)
109 tcase->cleanfunc();
110
111 if (TST_RET != -1) {
112 tst_res(TFAIL, "acct(%s) succeeded unexpectedly",
113 tcase->filename);
114 return;
115 }
116
117 if (TST_ERR == tcase->exp_errno) {
118 tst_res(TPASS | TTERRNO, "acct() failed as expected");
119 } else {
120 tst_res(TFAIL | TTERRNO,
121 "acct() failed, expected: %s",
122 tst_strerrno(tcase->exp_errno));
123 }
124 }
125
126 static struct tst_test test = {
127 .needs_root = 1,
128 .mntpoint = "mntpoint",
129 .needs_rofs = 1,
130 .tcnt = ARRAY_SIZE(tcases),
131 .setup = setup,
132 .test = verify_acct,
133 };
134