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