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