1 /*
2 *
3 * Copyright (c) International Business Machines Corp., 2002
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /* 12/03/2002 Port to LTP robbiew@us.ibm.com */
21 /* 06/30/2001 Port to Linux nsharoff@us.ibm.com */
22
23 /*
24 * ALGORITHM
25 * issue calls to acct and test the returned values against
26 * expected results
27 */
28
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <pwd.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <sys/mount.h>
38
39 #include "test.h"
40 #include "safe_macros.h"
41
42 #define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \
43 S_IXGRP|S_IROTH|S_IXOTH)
44 #define TEST_FILE1 "/"
45 #define TEST_FILE2 "/dev/null"
46 #define TEST_FILE3 "/tmp/does/not/exist"
47 #define TEST_FILE4 "/etc/fstab/"
48 #define TEST_FILE5 "./tmpfile"
49 #define TEST_FILE6 "test_file_eloop1"
50 #define TEST_FILE7 nametoolong
51 #define TEST_FILE8 "mntpoint/tmp"
52
53 static char nametoolong[PATH_MAX+2];
54 static const char *fs_type;
55 static const char *device;
56 static int mount_flag;
57
58 static void setup(void);
59 static void cleanup(void);
60 static void setup2(void);
61 static void cleanup2(void);
62 static void acct_verify(int);
63
64 static struct test_case_t {
65 char *filename;
66 char *exp_errval;
67 int exp_errno;
68 void (*setupfunc) ();
69 void (*cleanfunc) ();
70 } test_cases[] = {
71 {TEST_FILE1, "EISDIR", EISDIR, NULL, NULL},
72 {TEST_FILE2, "EACCES", EACCES, NULL, NULL},
73 {TEST_FILE3, "ENOENT", ENOENT, NULL, NULL},
74 {TEST_FILE4, "ENOTDIR", ENOTDIR, NULL, NULL},
75 {TEST_FILE5, "EPERM", EPERM, setup2, cleanup2},
76 {NULL, "EPERM", EPERM, setup2, cleanup2},
77 {TEST_FILE6, "ELOOP", ELOOP, NULL, NULL},
78 {TEST_FILE7, "ENAMETOOLONG", ENAMETOOLONG, NULL, NULL},
79 {TEST_FILE8, "EROFS", EROFS, NULL, NULL},
80 };
81
82 char *TCID = "acct01";
83 int TST_TOTAL = ARRAY_SIZE(test_cases);
84 static struct passwd *ltpuser;
85
main(int argc,char * argv[])86 int main(int argc, char *argv[])
87 {
88 int lc;
89 int i;
90
91 tst_parse_opts(argc, argv, NULL, NULL);
92
93 setup();
94
95 for (lc = 0; TEST_LOOPING(lc); lc++) {
96 tst_count = 0;
97 for (i = 0; i < TST_TOTAL; i++)
98 acct_verify(i);
99 }
100
101 cleanup();
102 tst_exit();
103 }
104
check_acct_in_kernel(void)105 static void check_acct_in_kernel(void)
106 {
107 /* check if acct is implemented in kernel */
108 if (acct(NULL) == -1) {
109 if (errno == ENOSYS) {
110 tst_brkm(TCONF,
111 NULL, "BSD process accounting is not configured in "
112 "this kernel");
113 }
114 }
115 }
116
setup(void)117 static void setup(void)
118 {
119 int fd;
120
121 tst_require_root();
122
123 check_acct_in_kernel();
124
125 tst_tmpdir();
126
127 ltpuser = SAFE_GETPWNAM(cleanup, "nobody");
128
129 fd = SAFE_CREAT(cleanup, TEST_FILE5, 0777);
130 SAFE_CLOSE(cleanup, fd);
131
132 if (acct(TEST_FILE5) == -1)
133 tst_brkm(TBROK | TERRNO, cleanup, "acct failed unexpectedly");
134
135 /* turn off acct, so we are in a known state */
136 if (acct(NULL) == -1)
137 tst_brkm(TBROK | TERRNO, cleanup, "acct(NULL) failed");
138
139 /* ELOOP SETTING */
140 SAFE_SYMLINK(cleanup, TEST_FILE6, "test_file_eloop2");
141 SAFE_SYMLINK(cleanup, "test_file_eloop2", TEST_FILE6);
142
143 /* ENAMETOOLONG SETTING */
144 memset(nametoolong, 'a', PATH_MAX+1);
145
146 /* EROFS SETTING */
147 fs_type = tst_dev_fs_type();
148 device = tst_acquire_device(cleanup);
149
150 if (!device)
151 tst_brkm(TCONF, cleanup, "Failed to obtain block device");
152
153 tst_mkfs(cleanup, device, fs_type, NULL, NULL);
154 SAFE_MKDIR(cleanup, "mntpoint", DIR_MODE);
155 SAFE_MOUNT(cleanup, device, "mntpoint", fs_type, 0, NULL);
156 mount_flag = 1;
157
158 /* Create a file in the file system, then remount it as read-only */
159 fd = SAFE_CREAT(cleanup, TEST_FILE8, 0644);
160 SAFE_CLOSE(cleanup, fd);
161 SAFE_MOUNT(cleanup, device, "mntpoint", fs_type,
162 MS_REMOUNT | MS_RDONLY, NULL);
163 }
164
acct_verify(int i)165 static void acct_verify(int i)
166 {
167
168 if (test_cases[i].setupfunc)
169 test_cases[i].setupfunc();
170
171 TEST(acct(test_cases[i].filename));
172
173 if (test_cases[i].cleanfunc)
174 test_cases[i].cleanfunc();
175
176 if (TEST_RETURN != -1) {
177 tst_resm(TFAIL, "acct(%s) succeeded unexpectedly",
178 test_cases[i].filename);
179 return;
180 }
181
182 if (TEST_ERRNO == test_cases[i].exp_errno) {
183 tst_resm(TPASS | TTERRNO, "acct failed as expected");
184 } else {
185 tst_resm(TFAIL | TTERRNO,
186 "acct failed unexpectedly; expected: %d - %s",
187 test_cases[i].exp_errno,
188 strerror(test_cases[i].exp_errno));
189 }
190 }
191
setup2(void)192 static void setup2(void)
193 {
194 SAFE_SETEUID(cleanup, ltpuser->pw_uid);
195 }
196
cleanup2(void)197 static void cleanup2(void)
198 {
199 SAFE_SETEUID(cleanup, 0);
200 }
201
cleanup(void)202 static void cleanup(void)
203 {
204 if (acct(NULL) == -1)
205 tst_resm(TWARN | TERRNO, "acct(NULL) failed");
206
207 if (mount_flag && tst_umount("mntpoint") < 0) {
208 tst_resm(TWARN | TERRNO,
209 "umount device:%s failed", device);
210 }
211
212 if (device)
213 tst_release_device(device);
214
215 tst_rmdir();
216 }
217