1 /*
2  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  *
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  *
26  * http://www.sgi.com
27  *
28  * For further information regarding this notice, see:
29  *
30  * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31  */
32 /* $Id: symlink01.c,v 1.20 2009/11/02 13:57:19 subrata_modak Exp $ */
33 /*
34  *	OS Test - Silicon Graphics, Inc.
35  *
36  *	TEST IDENTIFIER	: symlink01 (symlink)
37  *	TEST TITLE	: Make a Symbolic Link to a File
38  *	PARENT DOCUMENT	: symtds01
39  *	TEST CASE TOTAL	: 5
40  *	WALL CLOCK TIME	: 3
41  *
42  *	TEST IDENTIFIER	: readlink01 (readlink)
43  *	TEST TITLE	: Reads Value of a Symbolic Link
44  *	PARENT DOCUMENT	: symtds01
45  *	TEST CASE TOTAL	: 4
46  *	WALL CLOCK TIME	: 3
47  *
48  *	TEST IDENTIFIER	: stat04  (stat)
49  *	TEST TITLE	: Gets File Status Indirectly From a Symbolic Link File
50  *	PARENT DOCUMENT	: symtds01
51  *	TEST CASE TOTAL	: 3
52  *	WALL CLOCK TIME	: 3
53  *
54  *	TEST IDENTIFIER	: lstat01 (lstat)
55  *	TEST TITLE	: Get file Status About a Symbolic Link File
56  *	PARENT DOCUMENT	: symtds01
57  *	TEST CASE TOTAL	: 3
58  *	WALL CLOCK TIME	: 3
59  *
60  *	TEST IDENTIFIER	: mkdir05 (mkdir)
61  *	TEST TITLE	: Fail When Making a Directory File Indirectly From
62  *				a Symbolic Link File
63  *	PARENT DOCUMENT	: symtds01
64  *	TEST CASE TOTAL	: 1
65  *	WALL CLOCK TIME	: 3
66  *
67  *	TEST IDENTIFIER	: rmdir03 (rmdir)
68  *	TEST TITLE	: Fail When Removing a Directory File Indirectly
69  *				From a Symbolic Link File
70  *	PARENT DOCUMENT	: symtds01
71  *	TEST CASE TOTAL	: 1
72  *	WALL CLOCK TIME	: 3
73  *
74  *	TEST IDENTIFIER	: chdir01 (chdir)
75  *	TEST TITLE	: Changes Current Working DIrectory Location
76  *				Indirectly From a Symbolic Link File
77  *	PARENT DOCUMENT	: symtds01
78  *	TEST CASE TOTAL	: 3
79  *	WALL CLOCK TIME	: 3
80  *
81  *	TEST IDENTIFIER	: link01 (link)
82  *	TEST TITLE	: Creates a Link To a File Indirectly From a
83  *				Symbolic Link File
84  *	PARENT DOCUMENT	: symtds01
85  *	TEST CASE TOTAL	: 3
86  *	WALL CLOCK TIME	: 3
87  *
88  *	TEST IDENTIFIER	: unlink01 (unlink)
89  *	TEST TITLE	: Removes a Link To a File And Not Any Object File
90  *				Which Maybe Pointed At
91  *	PARENT DOCUMENT	: symtds01
92  *	TEST CASE TOTAL	: 1
93  *	WALL CLOCK TIME	: 3
94  *
95  *	TEST IDENTIFIER	: chmod01 (chmod)
96  *	TEST TITLE	: Change Object File Permissions Indirectly From a
97  *				Symbolic Link File
98  *	PARENT DOCUMENT	: symtds01
99  *	TEST CASE TOTAL	: 3
100  *	WALL CLOCK TIME	: 3
101  *
102  *	TEST IDENTIFIER	: utime01 (utime)
103  *	TEST TITLE	: Set File Access And Modify Object File Times
104  *				Indirectly From a Symbolic Link File
105  *	PARENT DOCUMENT	: symtds01
106  *	TEST CASE TOTAL	: 3
107  *	WALL CLOCK TIME	: 3
108  *
109  *	TEST IDENTIFIER	: rename01 (rename)
110  *	TEST TITLE	: Rename a Symbolic Link File And Not Any Object
111  *				File
112  *	PARENT DOCUMENT	: symtds01
113  *	TEST CASE TOTAL	: 3
114  *	WALL CLOCK TIME	: 3
115  *
116  *	TEST IDENTIFIER	: open01 (open)
117  *	TEST TITLE	: Create/Open a File For Reading Or Writing
118  *				Indirectly From a Symbolic Link File
119  *	PARENT DOCUMENT	: symtds01
120  *	TEST CASE TOTAL	: 5
121  *	WALL CLOCK TIME	: 3
122  *
123  *
124  *	EXECUTED BY	: whom ever
125  *	CPU TYPES		: ALL
126  *	AUTHOR		: David Fenner
127  *	CO-PILOT		: Jon Hendrickson
128  *	DATE STARTED	: 07/25/90
129  *	INITIAL RELEASE	: UNICOS 6.0
130  *
131  *	TEST CASES
132  *
133  *	For symlink
134  *	1. Create symbolic link with abnormal object name path
135  *	2. Create symbolic link with normal object name path
136  *	3. Create symbolic link with path to an existing object file
137  *	4. Receive EEXIST error when creating an already existing symbolic link file.
138  *	5. Receive ENAMETOOLONG error when creating symbolic link which exceeds PATH_MAX in length
139  *
140  *	For readlink
141  *	1. Read a symbolic link file which points at no object file
142  *	2. Read a symbolic link file which points at an object file
143  *	3. Receive ENAMETOOLONG error when reading symbolic link which exceeds PATH_MAX in length
144  *	4. Receive an EINVAL error when reading a file which is not a symbolic
145  *	link file.
146  *
147  *	For stat
148  *	1. Get object file status through symbolic link file
149  *	2. Receive ENOENT error when accessing non-existent object file through symbolic link file
150  *	3. Receive ELOOP error when nesting of symbolic links exceed maximum
151  *
152  *	For lstat
153  *	1. Get symbolic link file status when pointing at no object file
154  *	2. Get symbolic link file status when pointing at an object file
155  *	3. Get object file status when argument is not a symbolic link
156  *	file.
157  *
158  *	For mkdir
159  *	1. Receive EEXIST error when creating a directory through a symbolic link file
160  *
161  *	For rmdir
162  *	1. Receive ENOTDIR error when removing an existing directory through a symbolic link file
163  *
164  *	For chdir
165  *	1. Change current working directory through a symbolic link file
166  *	2. Receive ENOENT error when accessing non-existent directory through symbolic link file
167  *	3. Receive ELOOP error when nesting of symbolic links exceed maximum
168  *
169  *	For link
170  *	1. Link an object file to a new file through symbolic link file
171  *	2. Receive ENOENT error when accessing non-existent object file through symbolic link file
172  *	3. Receive ELOOP error when nesting of symbolic links exceed maximum
173  *
174  *	For unlink
175  *	1. Delete a symbolic link file and not the object file which it points at
176  *
177  *	For chmod
178  *	1. Change file permissions of object file through a symbolic link file
179  *	2. Receive ENOENT error when accessing non-existent directory through symbolic link file
180  *	3. Receive ELOOP error when nesting of symbolic links exceed maximum
181  *
182  *	For utime
183  *	1. Change inode times of object file through a symbolic link file
184  *	2. Receive ENOENT error when accessing non-existent directory through symbolic link file
185  *	3. Receive ELOOP error when nesting of symbolic links exceed maximum
186  *
187  *	For rename
188  *	1. Rename a symbolic link file which points at no object file
189  *	2. Rename a symbolic link file which points at an object file without any object file alterations.
190  *	3. Receive EXDEV when trying to rename a symbolic link file to an address outside of current file system
191  *
192  *	For open
193  *	1. Create an object file through a symbolic link file
194  *	2. Open an object file through a symbolic link file
195  *	3. Receive EEXIST error when exclusively creating an object file through a symbolic link file
196  *	4. Receive ENOENT error when accessing non-existent object file through symbolic link file
197  *	5. Receive ELOOP error when nesting of symbolic links exceed maximum
198  *
199  *	ENVIRONMENTAL NEEDS
200  *		None
201  *
202  *	DETAILED DESCRIPTION
203  *
204  *	Self-documenting code so see below
205  */
206 
207 #include <stdio.h>
208 #include <signal.h>
209 #include <string.h>
210 #include <fcntl.h>		/* open(2) system call */
211 #include <errno.h>
212 #include <sys/types.h>
213 #include <utime.h>		/* utime(2) system call */
214 #include <sys/param.h>
215 #include <sys/stat.h>		/* stat(2) and lstat(2) system calls */
216 #include <stdint.h>
217 #include <unistd.h>
218 
219 #include "test.h"
220 
221 void setup(void);
222 void cleanup(void);
223 void help(void);
224 void delete_files(char *path1, char *path2);
225 struct all_test_cases;
226 void do_EEXIST(struct all_test_cases *tc_ptr);
227 void do_ENOENT(struct all_test_cases *tc_ptr);
228 void do_ELOOP(struct all_test_cases *tc_ptr);
229 void do_ENOTDIR(struct all_test_cases *tc_ptr);
230 void do_EXDEV(struct all_test_cases *tc_ptr);
231 void do_ENAMETOOLONG(struct all_test_cases *tc_ptr);
232 void do_EINVAL(struct all_test_cases *tc_ptr);
233 void do_readlink(struct all_test_cases *tc_ptr);
234 void do_stat(struct all_test_cases *tc_ptr);
235 void do_chdir(struct all_test_cases *tc_ptr);
236 void do_link(struct all_test_cases *tc_ptr);
237 void do_unlink(struct all_test_cases *tc_ptr);
238 void do_chmod(struct all_test_cases *tc_ptr);
239 void do_utime(struct all_test_cases *tc_ptr);
240 void do_rename(struct all_test_cases *tc_ptr);
241 void do_open(struct all_test_cases *tc_ptr);
242 struct tcses;
243 int do_syscalltests(struct tcses *tcs);
244 struct tcses *get_tcs_info(char *ptr);
245 
246 #define S_FILE "symbolic"	/* Name of symbolic link file */
247 #define O_FILE "object"		/* Name of object file */
248 #define A_S_FILE "asymbolic"	/* Another name for a symbolic link file */
249 #define Y_A_S_FILE "/NiCkEr"	/* Yet another symbolic link file */
250 #define BIG_STRING "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
251 
252 #define DEFAULT_TCID  "symlink01"
253 
254 #define SYMLINK "symlink01"
255 #define READLINK "readlink01"
256 #define STAT "stat04"
257 #define STAT_64 "stat04_64"
258 #define LSTAT "lstat01"
259 #define LSTAT_64 "lstat01_64"
260 #define MKDIR "mkdir05"
261 #define RMDIR "rmdir03"
262 #define CHDIR "chdir01"
263 #define LINK "link01"
264 #define UNLINK "unlink01"
265 #define CHMOD "chmod01"
266 #define UTIME "utime01"
267 #define RENAME "rename01"
268 #define OPEN "open01"
269 
270 #define cktcsid(s1,s2) (!strcmp(s1,s2))
271 #define BUFMAX 512
272 #define MODE 0700
273 #define MASK 0100777		/* A regular file with r,w,x for all mask */
274 
275 /*
276  * Lets be optimistic and only define messages for passing test cases
277  */
278 const char *msgs[] = {
279 	"Creation of symbolic link file to no object file is ok",
280 	"Creation of symbolic link file and object file via symbolic link is ok",
281 	"Creating an existing symbolic link file error is caught",
282 	"Creating a symbolic link which exceeds maximum pathname error is caught",
283 	"Reading of symbolic link file contents checks out ok",
284 	"Reading a symbolic link which exceeds maximum pathname error is caught",
285 	"Getting stat info about object file through symbolic link file is ok",
286 	"Stat(2) error when accessing non-existent object through symbolic link is caught",
287 	"lstat(2) of symbolic link file which points to no object file is ok",
288 	"lstat(2) of symbolic link file which points at an object file is ok",
289 	"mkdir(2) of object file through symbolic link file failed as expected",
290 	"rmdir(2) of object file through symbolic link file failed as expected",
291 	"chdir(2) to object file location through symbolic link file is ok",
292 	"chdir(2) to non-existent object file location through symbolic link file failed as expected",
293 	"link(2) to a symbolic link, which is pointing to an existing object file worked - file created and link count adjusted",
294 	"link(2) to a symbolic link, which is pointing to a non-existing object file worked ok - file created and link count adjusted.",
295 	"unlink(2) of symbolic link file with no object file removal is ok",
296 	"chmod(2) of object file permissions through symbolic link file is ok",
297 	"chmod(2) error when accessing non-existent object through symbolic link is caught",
298 	"utime(2) change of object file access and modify times through symbolic link file is ok",
299 	"utime(2) error when accessing non-existent object through symbolic link is caught",
300 	"rename(3) of symbolic link file name which points at no object file is ok",
301 	"rename(3) of symbolic link file name which points at object file is ok",
302 	"rename(3) error of symbolic link file name across file systems is caught",
303 	"open(2) with (O_CREAT | O_RDWR) to create object file through symbolic link file and all writes, reads, and lseeks are ok",
304 	"open(2) with O_RDWR of existing  object file through symbolic link file and all writes, reads, and lseeks are ok",
305 	"open(2) with (O_CREAT | O_EXCL) error  is caught when creating object file through symbolic link file",
306 	"open(2) error with O_RDWR is caught when processing symbolic link file which points at no object file",
307 	"Nested symbolic link access condition caught.  ELOOP is returned",
308 	"Reading a nonsymbolic link file error condition is caught.  EINVAL is returned",
309 	"lstat(2) of object file returns object file inode information",
310 	"NULL"
311 };
312 
313 /*
314  * Define test object setup and validation functions
315  */
316 int creat_both(char *path1, char *path2, char *path3);
317 int creat_symlink(char *path1, char *path2, char *_path3);
318 int creat_path_max(char *path1, char *path2, char *path3);
319 int ck_symlink(char *path1, char *path2, char *path3);
320 int creat_object(char *path1, char *_path2, char *_path3);
321 int ck_object(char *path1, char *path2, char *path3);
322 int ck_both(char *path1, char *path2, char *path3);
323 int ck_path_max(char *path1, char *path2, char *path3);
324 
325 /*
326  *  Define test cases
327  */
328 struct all_test_cases {
329 	char *tcid;
330 	int test_fail;
331 	int errno_val;
332 	int pass_msg;
333 	int (*test_setup) (char *path1, char *path2, char *path3);
334 	int (*ck_test) (char *path1, char *path2, char *path3);
335 	char *fn_arg[3];
336 
337 } test_objects[] = {
338 	{
339 		SYMLINK, 0, 0, 0, creat_symlink, ck_symlink, {
340 	"%bc+eFhi!k", S_FILE, NULL}}, {
341 		SYMLINK, 0, 0, 0, creat_symlink, ck_symlink, {
342 	O_FILE, S_FILE, NULL}}, {
343 		SYMLINK, 0, 0, 1, creat_both, ck_both, {
344 	O_FILE, S_FILE, O_FILE}}, {
345 		SYMLINK, 1, EEXIST, 2, creat_symlink, ck_symlink, {
346 	O_FILE, S_FILE, NULL}}, {
347 		SYMLINK, 1, ENAMETOOLONG, 3, creat_path_max, ck_path_max, {
348 	O_FILE, S_FILE, NULL}}, {
349 		READLINK, 0, 0, 4, creat_symlink, ck_symlink, {
350 	O_FILE, S_FILE, NULL}}, {
351 		READLINK, 0, 0, 4, creat_both, ck_both, {
352 	O_FILE, S_FILE, O_FILE}}, {
353 		READLINK, 1, ENAMETOOLONG, 5, creat_path_max, ck_path_max, {
354 	O_FILE, S_FILE, NULL}}, {
355 		READLINK, 1, EINVAL, 29, creat_object, ck_object, {
356 	O_FILE, NULL, NULL}}, {
357 		STAT, 0, 0, 6, creat_both, ck_both, {
358 	O_FILE, S_FILE, O_FILE}},
359 	    /* 10 */
360 	{
361 		STAT, 1, ENOENT, 7, creat_symlink, ck_symlink, {
362 	O_FILE, S_FILE, NULL}}, {
363 		STAT, 1, ELOOP, 28, creat_symlink, ck_symlink, {
364 	S_FILE, S_FILE, NULL}}, {
365 		STAT_64, 0, 0, 6, creat_both, ck_both, {
366 	O_FILE, S_FILE, O_FILE}}, {
367 		STAT_64, 1, ENOENT, 7, creat_symlink, ck_symlink, {
368 	O_FILE, S_FILE, NULL}}, {
369 		STAT_64, 1, ELOOP, 28, creat_symlink, ck_symlink, {
370 	S_FILE, S_FILE, NULL}}, {
371 		LSTAT, 0, 0, 8, creat_symlink, ck_symlink, {
372 	O_FILE, S_FILE, NULL}}, {
373 		LSTAT, 0, 0, 9, creat_both, ck_both, {
374 	O_FILE, S_FILE, O_FILE}}, {
375 		LSTAT, 0, 0, 30, creat_object, ck_object, {
376 	O_FILE, NULL, NULL}}, {
377 		LSTAT_64, 0, 0, 8, creat_symlink, ck_symlink, {
378 	O_FILE, S_FILE, NULL}}, {
379 		LSTAT_64, 0, 0, 9, creat_both, ck_both, {
380 	O_FILE, S_FILE, O_FILE}},
381 	    /* 20 */
382 	{
383 		LSTAT_64, 0, 0, 30, creat_object, ck_object, {
384 	O_FILE, NULL, NULL}}, {
385 		MKDIR, 1, EEXIST, 10, creat_symlink, ck_symlink, {
386 	O_FILE, S_FILE, NULL}}, {
387 		RMDIR, 1, ENOTDIR, 11, creat_symlink, ck_symlink, {
388 	O_FILE, S_FILE, NULL}}, {
389 		CHDIR, 0, 0, 12, creat_symlink, ck_symlink, {
390 	O_FILE, S_FILE, O_FILE}}, {
391 		CHDIR, 1, ENOENT, 13, creat_symlink, ck_symlink, {
392 	"%bc+eFhi!k", S_FILE, NULL}}, {
393 		CHDIR, 1, ELOOP, 28, creat_symlink, ck_symlink, {
394 	S_FILE, S_FILE, NULL}}, {
395 		LINK, 0, 0, 14, creat_both, ck_both, {
396 	O_FILE, S_FILE, O_FILE}}, {
397 		LINK, 0, 0, 15, creat_symlink, ck_symlink, {
398 	O_FILE, S_FILE, NULL}},
399 	    /* The following link test case is invalid - leaving it defined so */
400 	    /* I don't have to change all the entries in the all_tcses array after link */
401 	    /* It has been disabled at the moment. */
402 	{
403 		LINK, 1, -1, -1, creat_symlink, ck_symlink, {
404 	NULL, NULL, NULL}}, {
405 		UNLINK, 0, 0, 16, creat_both, ck_both, {
406 	O_FILE, S_FILE, O_FILE}},
407 	    /* 30 */
408 	{
409 		CHMOD, 0, 0, 17, creat_both, ck_both, {
410 	O_FILE, S_FILE, O_FILE}}, {
411 		CHMOD, 1, ENOENT, 18, creat_symlink, ck_symlink, {
412 	O_FILE, S_FILE, NULL}}, {
413 		CHMOD, 1, ELOOP, 28, creat_symlink, ck_symlink, {
414 	S_FILE, S_FILE, NULL}}, {
415 		UTIME, 0, 0, 19, creat_both, ck_both, {
416 	O_FILE, S_FILE, O_FILE}}, {
417 		UTIME, 1, ENOENT, 20, creat_symlink, ck_symlink, {
418 	O_FILE, S_FILE, NULL}}, {
419 		UTIME, 1, ELOOP, 28, creat_symlink, ck_symlink, {
420 	S_FILE, S_FILE, NULL}}, {
421 		RENAME, 0, 0, 21, creat_symlink, ck_symlink, {
422 	O_FILE, S_FILE, NULL}}, {
423 		RENAME, 0, 0, 22, creat_both, ck_both, {
424 	O_FILE, S_FILE, O_FILE}},
425 	    /* The following rename test makes assumption that the link and target */
426 	    /* files are located in different filesystems, which is incorrect. */
427 	    /* It has been disabled at the moment. */
428 	{
429 		RENAME, 1, EXDEV, 23, creat_both, ck_both, {
430 	O_FILE, S_FILE, O_FILE}}, {
431 		OPEN, 0, 0, 24, creat_symlink, ck_symlink, {
432 	O_FILE, S_FILE, NULL}},
433 	    /* 40 */
434 	{
435 		OPEN, 0, 0, 25, creat_both, ck_both, {
436 	O_FILE, S_FILE, O_FILE}}, {
437 		OPEN, 1, EEXIST, 26, creat_symlink, ck_symlink, {
438 	O_FILE, S_FILE, O_FILE}}, {
439 		OPEN, 1, ENOENT, 27, creat_symlink, ck_symlink, {
440 	O_FILE, S_FILE, NULL}}, {
441 		OPEN, 1, ELOOP, 28, creat_symlink, ck_symlink, {
442 	S_FILE, S_FILE, NULL}}
443 };
444 
445 /*
446  * Define tcses
447  */
448 struct tcses {
449 	char *tcid;
450 	char *syscall;
451 	int test_cases;		/* number of entries in test_objects array */
452 	struct all_test_cases *tc_ptr;
453 	char *desc;
454 } all_tcses[] = {
455 
456 	{
457 	SYMLINK, "symlink", 5, &test_objects[0],
458 		    "Make a Symbolic Link to a File"}, {
459 	READLINK, "readlink", 4, &test_objects[5],
460 		    "Reads Value of a Symbolic Link"}, {
461 	STAT, "stat", 3, &test_objects[9],
462 		    "Gets File Status Indirectly From a Symbolic Link file"}, {
463 	STAT_64, "stat64", 3, &test_objects[12],
464 		    "Gets File Status Indirectly From a Symbolic Link file"}, {
465 	LSTAT, "lstat", 3, &test_objects[15],
466 		    "Get file Status About a Symbolic Link File"}, {
467 	LSTAT_64, "lstat64", 3, &test_objects[18],
468 		    "Get file Status About a Symbolic Link File"}, {
469 	MKDIR, "mkdir", 1, &test_objects[21],
470 		    "Fail When Making a Directory File Indirectly from a symlink"},
471 	{
472 	RMDIR, "rmdir", 1, &test_objects[22],
473 		    "Fail When Removing a Directory File Indirectly from a symlink"},
474 	{
475 	CHDIR, "chdir", 3, &test_objects[23],
476 		    "Changes CWD Location Indirectly from a symlink"}, {
477 	LINK, "link", 2, &test_objects[26],
478 		    "Creates a Link To a File Indirectly From a Symbolic"}, {
479 	UNLINK, "unlink", 1, &test_objects[29],
480 		    "Removes a Link To a File but not the Object File"}, {
481 	CHMOD, "chmod", 3, &test_objects[30],
482 		    "Change Object File Permissions Indirectly From a Symbolic"},
483 	{
484 	UTIME, "utime", 3, &test_objects[33],
485 		    "Set File Access And Modify Object File Times via symlink"},
486 	{
487 	RENAME, "rename", 2, &test_objects[36],
488 		    "Rename a Symbolic Link File And Not Any Object file"}, {
489 OPEN, "open", 5, &test_objects[39],
490 		    "Create/Open a File For Reading Or Writing via symlink"},};
491 
492 /*
493  * Define GLOBAL variables
494  */
495 
496 int TST_TOTAL;
497 int TEST_RESULT;
498 time_t a_time_value = 100;
499 char *TCID;
500 char *Selectedtests = NULL;	/* Name (tcid) of selected test cases */
501 char test_msg[BUFMAX];
502 char full_path[PATH_MAX + 1 + 1];	/* Add one for '\0' and another to exceed the PATH_MAX limit, see creat_path_max() */
503 
504 struct stat asymlink, statter;
505 char Buffer[1024];
506 char Buf[1024];
507 
508 char *Tcid = NULL;
509 
510 option_t Options[] = {
511 	{"T:", NULL, &Tcid},	/* -T tcid option */
512 	{NULL, NULL, NULL}
513 };
514 
515 /***********************************************************************
516  * MAIN
517  ***********************************************************************/
main(int argc,char * argv[])518 int main(int argc, char *argv[])
519 {
520 	struct tcses *tcs_ptr;
521 	int lc;
522 
523 	tst_parse_opts(argc, argv, Options, &help);
524 
525 	/*
526 	 * If the -T option was used, use that TCID or use the default
527 	 */
528 	if (Tcid != NULL) {
529 		TCID = Tcid;
530 		Selectedtests = Tcid;
531 
532 	}
533 #ifndef ALL
534 	else {
535 		TCID = DEFAULT_TCID;
536 		Selectedtests = DEFAULT_TCID;
537 	}
538 #endif
539 
540 	/*
541 	 * Get test case specification information and assign TST_TOTAL
542 	 */
543 	if ((tcs_ptr = get_tcs_info(Selectedtests)) == NULL) {
544 		TST_TOTAL = 1;
545 		tst_brkm(TBROK, cleanup,
546 			 "Unknown symbolic link test case specification executed");
547 	}
548 
549    /***************************************************************
550     * perform global setup for test
551     ***************************************************************/
552 
553 	setup();
554 
555     /***************************************************************
556      * check looping state if -c option given
557      ***************************************************************/
558 	for (lc = 0; TEST_LOOPING(lc); lc++) {
559 
560 		tst_count = 0;
561 
562 		/*
563 		 * Execute tcs testing function and all defined test cases
564 		 */
565 		do_syscalltests(tcs_ptr);
566 
567 	}
568 
569 	/*
570 	 * End appropriately
571 	 */
572 	cleanup();
573 	tst_exit();
574 
575 }
576 
577 /***********************************************************************
578  *  This function maps the name of the process to a test case specification
579  *  defined in the all_tcses array of tcses structures.  Either a pointer
580  *  to the mapped test case specification information is returned or a
581  *  null pointer.
582  *
583  *      Argument is path to program name.
584  ***********************************************************************/
get_tcs_info(char * ptr)585 struct tcses *get_tcs_info(char *ptr)
586 {
587 	int ctr;
588 	struct tcses *tcs_ptr;
589 
590 #if ALL
591 	if (ptr == NULL) {
592 
593 		TST_TOTAL = 0;
594 		for (ctr = 1; ctr < sizeof(all_tcses) / sizeof(struct tcses);
595 		     ctr++)
596 			TST_TOTAL += all_tcses[ctr].test_cases;
597 		return all_tcses;
598 	}
599 #endif
600 
601 	for (ctr = 0; ctr < (sizeof(all_tcses) / sizeof(struct tcses)); ctr++) {
602 		if (strcmp(ptr, all_tcses[ctr].tcid) == 0 ||
603 		    strcmp(ptr, all_tcses[ctr].syscall) == 0) {
604 			tcs_ptr = &all_tcses[ctr];
605 			TCID = all_tcses[ctr].tcid;
606 			TST_TOTAL = tcs_ptr->test_cases;
607 			return (tcs_ptr);
608 		}
609 
610 	}
611 	return NULL;
612 }
613 
614 /***********************************************************************
615  *  Determines if what path points at is a symbolic link file
616  *
617  *      Argument is path to symbolic link file.
618  *
619  *  Return status is one if a symbolic link file.  Zero if not a symbolic
620  *  link file and a minus one if the path doesn't point at a file.
621  ***********************************************************************/
see_if_a_symlink(char * path)622 static int see_if_a_symlink(char *path)
623 {
624 	if (lstat(path, &asymlink) < 0)
625 		return (-1);
626 
627 	if ((asymlink.st_mode & S_IFMT) == S_IFLNK)
628 		return 1;
629 	else
630 		return 0;
631 }
632 
633 /***********************************************************************
634  * This function performs without any hesitation, file(s) deletions
635  ***********************************************************************/
delete_files(char * path1,char * path2)636 void delete_files(char *path1, char *path2)
637 {
638 	unlink(path1);
639 	unlink(path2);
640 }
641 
642 /***********************************************************************
643  *
644  * This routine creates a symbolic link file.
645  *
646  *      Argument one is symbolic link pathname to point at.
647  *      Argument two is name of symbolic link file.
648  *
649  ***********************************************************************/
creat_symlink(char * path1,char * path2,char * _path3)650 int creat_symlink(char *path1, char *path2, char *_path3)
651 {
652 	TEST(symlink(path1, path2));
653 	errno = TEST_ERRNO;
654 	if (TEST_RETURN == -1) {
655 		TEST_RESULT = TBROK;
656 		sprintf(test_msg,
657 			"symlink(2) Failure when creating setup %s object file: errno:%d %s",
658 			path1, errno, strerror(errno));
659 		return 0;
660 	} else {
661 		sprintf(Buf, "symlink(%s, %s) was succesful.\n", path1, path2);
662 		strcat(Buffer, Buf);
663 #if DEBUG
664 		tst_resm(TPASS, "symlink(%s, %s) was succesful.", path1, path2);
665 #endif
666 	}
667 	return 1;
668 }
669 #define creat_symlink(p1, p2) creat_symlink(p1, p2, NULL)
670 
671 /***********************************************************************
672  *
673  * This routine creates a regular file.
674  *
675  *      Argument one is a pathname
676  *
677  ***********************************************************************/
creat_object(char * path1,char * _path2,char * _path3)678 int creat_object(char *path1, char *_path2, char *_path3)
679 {
680 	int fd;
681 	if ((fd = creat(path1, MODE)) == -1) {
682 		TEST_RESULT = TBROK;
683 		sprintf(test_msg,
684 			"creat(2) Failure when creating setup %s object file: errno:%d %s",
685 			path1, errno, strerror(errno));
686 		return 0;
687 	} else {
688 		sprintf(Buf, "creat(%s, %#o) was succesful.\n", path1, MODE);
689 		strcat(Buffer, Buf);
690 #if DEBUG
691 		tst_resm(TPASS, "creat(%s, %#o) was succesful.", path1, MODE);
692 #endif
693 	}
694 	if (close(fd) == -1) {
695 		TEST_RESULT = TBROK;
696 		sprintf(test_msg,
697 			"close(2) Failure when closing setup %s object file: errno:%d %s",
698 			path1, errno, strerror(errno));
699 		return 0;
700 	}
701 	return 1;
702 }
703 #define creat_object(p1) creat_object(p1, NULL, NULL)
704 
705 /***********************************************************************
706  *
707  * This routine creates a symbolic link file and a regular file.
708  *
709  *      Argument one is a pathname of object file
710  *      Argument two is symbolic link file name
711  *      Argument three is regular file name
712  *
713  ***********************************************************************/
creat_both(char * path1,char * path2,char * path3)714 int creat_both(char *path1, char *path2, char *path3)
715 {
716 	if (creat_symlink(path1, path2) == -1)
717 		return 0;
718 	else if (creat_object(path3) == -1)
719 		return 0;
720 	return 1;
721 }
722 
723 /***********************************************************************
724  *
725  * This routine checks if symbolic link file is a symbolic link file.
726  *
727  *      Argument one is a pathname of object file
728  *      Argument two is symbolic link file name
729  *      Argument three is regular file name
730  *
731  ***********************************************************************/
ck_symlink(char * path1,char * path2,char * path3)732 int ck_symlink(char *path1, char *path2, char *path3)
733 {
734 	int ret;
735 
736 	if ((ret = see_if_a_symlink(path2)) == -1) {
737 		TEST_RESULT = TBROK;
738 		sprintf(test_msg,
739 			"lstat(2) Failure when accessing %s symbolic link file which should contain %s path to %s file ",
740 			path2, path1, path3);
741 		return 0;
742 	} else if (ret == 0) {
743 		TEST_RESULT = TBROK;
744 		sprintf(test_msg,
745 			"%s is not a symbolic link file which contains %s path to %s file",
746 			path2, path1, path3);
747 		return 0;
748 	}
749 	return 1;
750 }
751 
752 /***********************************************************************
753  *
754  * This routine checks if symbolic link file points at object file.
755  *
756  *      Argument one is a pathname of object file
757  *      Argument two is symbolic link file name
758  *      Argument three is regular file name
759  *
760  ***********************************************************************/
ck_both(char * path1,char * path2,char * path3)761 int ck_both(char *path1, char *path2, char *path3)
762 {
763 	if (ck_symlink(path1, path2, path3) == 0)
764 		return 0;
765 	else if ((stat(path3, &statter) == -1) && (errno == ENOENT)) {
766 		TEST_RESULT = TBROK;
767 		sprintf(test_msg,
768 			"stat(2) Failure when accessing %s object file ",
769 			path3);
770 		return 0;
771 	} else if ((stat(path2, &asymlink) == -1) && (errno == ENOENT)) {
772 		TEST_RESULT = TBROK;
773 		sprintf(test_msg,
774 			"stat(2) Failure when accessing %s symbolic link file ",
775 			path2);
776 		return 0;
777 	} else if (statter.st_ino != asymlink.st_ino) {
778 		TEST_RESULT = TBROK;
779 		sprintf(test_msg,
780 			"stat(2) Failure when accessing %s object file through %s symbolic link file ",
781 			path3, path2);
782 		return 0;
783 	}
784 	return 1;
785 
786 }
787 
788 /***********************************************************************
789  * This routine populates full_path with a pathname whose length exceeds
790  * the PATH_MAX define value in param.h
791  *
792  *      Argument one is a pathname of object file
793  *      Argument two is symbolic link file name
794  *      Argument three is regular file name
795  ***********************************************************************/
creat_path_max(char * path1,char * path2,char * path3)796 int creat_path_max(char *path1, char *path2, char *path3)
797 {
798 	int ctr, to_go, size, whole_chunks;
799 	char *cwd;
800 
801 	if ((cwd = getcwd(NULL, 0)) == NULL) {
802 		TEST_RESULT = TBROK;
803 		sprintf(test_msg,
804 			"getcwd(3) Failure in setup of %s %s %s test case object elements",
805 			path1, path2, path3);
806 		return 0;
807 	}
808 	cwd = getcwd(NULL, 0);
809 	size = strlen(cwd);
810 
811 	to_go = PATH_MAX - size;
812 	size = strlen(path1);
813 	whole_chunks = to_go / size;
814 	strcpy(full_path, cwd);
815 	for (ctr = 0; ctr < whole_chunks; ctr++) {
816 		strcat(full_path, path1);
817 	}
818 	size = strlen(full_path);
819 	to_go = PATH_MAX - size;
820 	strcat(full_path, "/");
821 	for (ctr = 0; ctr < to_go; ctr++)
822 		strcat(full_path, "Z");
823 
824 	return 1;
825 }
826 
827 /***********************************************************************
828  * This routine checks that full_path's  length exceeds the PATH_MAX
829  * define value in param.h
830  *
831  *      Argument one is a pathname of object file
832  *      Argument two is symbolic link file name
833  *      Argument three is regular file name
834  ***********************************************************************/
ck_path_max(char * path1,char * path2,char * path3)835 int ck_path_max(char *path1, char *path2, char *path3)
836 {
837 	if (strlen(full_path) == (PATH_MAX + 1))
838 		return 1;
839 	else {
840 		TEST_RESULT = TBROK;
841 		sprintf(test_msg, "%s %d %s %s %s %s",
842 			"full_path character array length was not",
843 			(PATH_MAX + 1),
844 			"characters long for test case object elements", path1,
845 			path2, path3);
846 		return 0;
847 	}
848 }
849 
850 /***********************************************************************
851  * This routine checks if the stat(2) and lstat(2) calls return the same
852  * information when the path is not a symbolic link file
853  *
854  *      Argument one is a pathname of object file
855  *      Argument two is symbolic link file name
856  *      Argument three is regular file name
857  *
858  ***********************************************************************/
ck_object(char * path1,char * path2,char * path3)859 int ck_object(char *path1, char *path2, char *path3)
860 {
861 	int ret;
862 
863 	if ((ret = see_if_a_symlink(path1)) < 0) {
864 		TEST_RESULT = TFAIL;
865 		sprintf(test_msg,
866 			"lstat(2) failed to return inode information for a regular object file");
867 		return 0;
868 	} else if (ret == 1) {
869 		TEST_RESULT = TFAIL;
870 		sprintf(test_msg,
871 			"lstat(2) detected a regular object file as a symbolic link file");
872 		return 0;
873 	} else if (stat(path1, &statter) == -1) {
874 		TEST_RESULT = TBROK;
875 		sprintf(test_msg,
876 			"stat(2) failed to return inode information for a regular object file");
877 		return 0;
878 	} else if (memcmp((char *)&statter, (char *)&asymlink, sizeof(statter))
879 		   != 0) {
880 		TEST_RESULT = TFAIL;
881 		sprintf(test_msg,
882 			"lstat(2) and stat(2) do not return same inode information for an object file");
883 		return 0;
884 
885 	}
886 	return 1;
887 }
888 
889 /***********************************************************************
890  * Main test case processing function
891  *
892  *  Argument is a ptr into the all_tcses array of structures of type tcses
893  ***********************************************************************/
do_syscalltests(struct tcses * tcs)894 int do_syscalltests(struct tcses *tcs)
895 {
896 	int ctr, ret;
897 	struct all_test_cases *tc_ptr;
898 
899 	/*
900 	 * loop through desired number of test cases
901 	 */
902 	for (ctr = 0, tc_ptr = tcs->tc_ptr; ctr < TST_TOTAL; ctr++, tc_ptr++) {
903 
904 		Buffer[0] = '\0';
905 
906 		/*
907 		 * If running all test cases for all tcid, set the TCID if needed.
908 		 */
909 		if (Selectedtests == NULL) {
910 			if (strcmp(tcs->tcid, tc_ptr->tcid) != 0) {
911 				TCID = tc_ptr->tcid;
912 				tst_count = 0;
913 			}
914 		}
915 		/*
916 		 * Insure that we are executing the correct tcs test case
917 		 */
918 		if (strcmp(tcs->tcid, tc_ptr->tcid) != 0) {
919 			tst_resm(TBROK,
920 				 "%s TCID attempted to execute %s %d %d test case",
921 				 tcs->tcid, tc_ptr->tcid, tc_ptr->test_fail,
922 				 tc_ptr->errno_val);
923 			continue;
924 		}
925 		TEST_RESULT = TPASS;
926 		delete_files(S_FILE, O_FILE);
927 		/*
928 		 * Perform test case setup
929 		 */
930 		ret =
931 		    (tc_ptr->test_setup) (tc_ptr->fn_arg[0], tc_ptr->fn_arg[1],
932 					  tc_ptr->fn_arg[2]);
933 
934 		/* If an expected error, try it out */
935 
936 		if (tc_ptr->test_fail) {
937 			/*
938 			 * Try to perform test verification function
939 			 */
940 			if (!(tc_ptr->ck_test)
941 			    (tc_ptr->fn_arg[0], tc_ptr->fn_arg[1],
942 			     tc_ptr->fn_arg[2]))
943 				tst_resm(TEST_RESULT, "%s", test_msg);
944 			else if (tc_ptr->errno_val == EEXIST)
945 				do_EEXIST(tc_ptr);
946 			else if (tc_ptr->errno_val == ENOENT)
947 				do_ENOENT(tc_ptr);
948 			else if (tc_ptr->errno_val == ELOOP)
949 				do_ELOOP(tc_ptr);
950 			else if (tc_ptr->errno_val == ENOTDIR)
951 				do_ENOTDIR(tc_ptr);
952 			else if (tc_ptr->errno_val == EXDEV)
953 				do_EXDEV(tc_ptr);
954 			else if (tc_ptr->errno_val == ENAMETOOLONG)
955 				do_ENAMETOOLONG(tc_ptr);
956 			else if (tc_ptr->errno_val == EINVAL)
957 				do_EINVAL(tc_ptr);
958 			else
959 				tst_resm(TBROK, "Test Case Declaration Error");
960 		} else if (ret == 1) {	/*  No setup function error */
961 
962 			if (tc_ptr->errno_val != 0)
963 				tst_resm(TBROK, "Test Case Declaration Error");
964 			else {
965 				/*
966 				 * Perform test verification function
967 				 */
968 				ret =
969 				    (tc_ptr->ck_test) (tc_ptr->fn_arg[0],
970 						       tc_ptr->fn_arg[1],
971 						       tc_ptr->fn_arg[2]);
972 
973 				/* Perform requested symbolic link system call test */
974 
975 				if ((cktcsid(tc_ptr->tcid, SYMLINK)) ||
976 				    (cktcsid(tc_ptr->tcid, LSTAT)) ||
977 				    (cktcsid(tc_ptr->tcid, LSTAT_64))) {
978 					if (ret == 1)
979 						tst_resm(TEST_RESULT, "%s",
980 							 msgs[tc_ptr->
981 							      pass_msg]);
982 					else
983 						tst_resm(TEST_RESULT, "%s",
984 							 test_msg);
985 				} else if (ret == 0)
986 					tst_resm(TEST_RESULT, "%s", test_msg);
987 				else if (cktcsid(tc_ptr->tcid, READLINK))
988 					do_readlink(tc_ptr);
989 				else if (cktcsid(tc_ptr->tcid, STAT))
990 					do_stat(tc_ptr);
991 				else if (cktcsid(tc_ptr->tcid, STAT_64))
992 					do_stat(tc_ptr);
993 				else if (cktcsid(tc_ptr->tcid, CHDIR))
994 					do_chdir(tc_ptr);
995 				else if (cktcsid(tc_ptr->tcid, LINK))
996 					do_link(tc_ptr);
997 				else if (cktcsid(tc_ptr->tcid, UNLINK))
998 					do_unlink(tc_ptr);
999 				else if (cktcsid(tc_ptr->tcid, CHMOD))
1000 					do_chmod(tc_ptr);
1001 				else if (cktcsid(tc_ptr->tcid, UTIME))
1002 					do_utime(tc_ptr);
1003 				else if (cktcsid(tc_ptr->tcid, RENAME))
1004 					do_rename(tc_ptr);
1005 				else if (cktcsid(tc_ptr->tcid, OPEN))
1006 					do_open(tc_ptr);
1007 				else
1008 					tst_resm(TBROK,
1009 						 "Unknown test case processing actions declared");
1010 			}
1011 		} else
1012 			tst_resm(TBROK, "Test Case Declaration Error");
1013 	}
1014 	return 0;
1015 }
1016 
1017 /***********************************************************************
1018  * This routine checks for the return of EEXIST errno from requested
1019  * system call
1020  *
1021  *   Argument is pointer to test_objects array of structures of type
1022  *   all_test_cases
1023  ***********************************************************************/
do_EEXIST(struct all_test_cases * tc_ptr)1024 void do_EEXIST(struct all_test_cases *tc_ptr)
1025 {
1026 	if (cktcsid(tc_ptr->tcid, SYMLINK)) {
1027 
1028 		TEST(symlink(tc_ptr->fn_arg[0], tc_ptr->fn_arg[1]));
1029 		errno = TEST_ERRNO;
1030 		if ((TEST_RETURN == -1) && (errno == EEXIST))
1031 			tst_resm(TPASS, "%s", msgs[tc_ptr->pass_msg]);
1032 		else
1033 			tst_resm(TFAIL, "%s %s",
1034 				 "Expected EEXIST error when creating a symbolic link file",
1035 				 "which already existed");
1036 	} else if (cktcsid(tc_ptr->tcid, MKDIR)) {
1037 
1038 		TEST(mkdir(tc_ptr->fn_arg[1], MODE));
1039 		errno = TEST_ERRNO;
1040 		if ((TEST_RETURN == -1) && (errno == EEXIST)) {
1041 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1042 		} else {
1043 
1044 			tst_resm(TFAIL, "%s %s",
1045 				 "Expected EEXIST error when creating a directory by a symbolic",
1046 				 "link file which pointed at no object file");
1047 			rmdir(tc_ptr->fn_arg[1]);
1048 		}
1049 	} else if (cktcsid(tc_ptr->tcid, OPEN)) {
1050 
1051 		TEST(open(tc_ptr->fn_arg[1], (O_EXCL | O_CREAT), 0666));
1052 		errno = TEST_ERRNO;
1053 		if ((TEST_RETURN == -1) && (errno == EEXIST)) {
1054 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1055 		} else {
1056 			tst_resm(TFAIL, "%s %s errno:%d %s",
1057 				 "Expected EEXIST error for exclusively opening an object file",
1058 				 "through a symbolic link file was not received:",
1059 				 errno, strerror(errno));
1060 		}
1061 	} else
1062 		tst_resm(TBROK,
1063 			 "Unknown test case processing actions declared");
1064 }
1065 
1066 /***********************************************************************
1067  * This routine checks for the return of ENOENT errno from requested
1068  * system call
1069  *
1070  *   Argument is pointer to test_objects array of structures of type
1071  *   all_test_cases
1072  ***********************************************************************/
do_ENOENT(struct all_test_cases * tc_ptr)1073 void do_ENOENT(struct all_test_cases *tc_ptr)
1074 {
1075 	if ((cktcsid(tc_ptr->tcid, STAT)) || (cktcsid(tc_ptr->tcid, STAT_64))) {
1076 
1077 		if ((stat(tc_ptr->fn_arg[1], &asymlink) == -1)
1078 		    && (errno == ENOENT)) {
1079 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1080 		} else {
1081 			tst_resm(TFAIL, "%s %s errno:%d %s",
1082 				 "Expected ENOENT error for stating a non-existent directory",
1083 				 "through a symbolic link file was not received:",
1084 				 errno, strerror(errno));
1085 		}
1086 	} else if (cktcsid(tc_ptr->tcid, CHDIR)) {
1087 		if ((chdir(tc_ptr->fn_arg[1]) == -1) && (errno == ENOENT)) {
1088 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1089 		} else {
1090 			tst_resm(TFAIL, "%s %s errno:%d %s",
1091 				 "Expected ENOENT error for changing to a non-existent",
1092 				 "directory through a symbolic link file was not received:",
1093 				 errno, strerror(errno));
1094 			/* FIXME (garrcoop): memory leak */
1095 			chdir(tst_get_tmpdir());
1096 		}
1097 	} else if (cktcsid(tc_ptr->tcid, LINK)) {
1098 
1099 		if ((link(tc_ptr->fn_arg[1], "nick") == -1)
1100 		    && (errno == ENOENT)) {
1101 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1102 		} else {
1103 			tst_resm(TFAIL, "%s %s errno:%d %s",
1104 				 "Expected ENOENT error condition when link(2) a symbolic",
1105 				 "link which pointed at no object:", errno,
1106 				 strerror(errno));
1107 			delete_files("nick", NULL);
1108 		}
1109 	} else if (cktcsid(tc_ptr->tcid, CHMOD)) {
1110 
1111 		if ((chmod(tc_ptr->fn_arg[1], MODE) == -1) && (errno == ENOENT)) {
1112 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1113 		} else {
1114 			tst_resm(TFAIL, "%s %s errno:%d %s",
1115 				 "Expected ENOENT error condition when chmod(2) a symbolic",
1116 				 "link which pointed at no object,", errno,
1117 				 strerror(errno));
1118 		}
1119 	} else if (cktcsid(tc_ptr->tcid, UTIME)) {
1120 
1121 		if ((utime(tc_ptr->fn_arg[1], NULL) == -1) && (errno == ENOENT)) {
1122 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1123 		} else {
1124 			tst_resm(TFAIL, "%s %s errno:%d %s",
1125 				 "Expected ENOENT error condition when utime(2) a symbolic",
1126 				 "link which pointed at no object:", errno,
1127 				 strerror(errno));
1128 		}
1129 	} else if (cktcsid(tc_ptr->tcid, OPEN)) {
1130 
1131 		if ((open(tc_ptr->fn_arg[1], O_RDWR) == -1)
1132 		    && (errno == ENOENT)) {
1133 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1134 		} else {
1135 			tst_resm(TFAIL, "%s %s errno:%d %s",
1136 				 "Expected ENOENT error for opening a non-existent object",
1137 				 " file through a symbolic link file was not received,",
1138 				 errno, strerror(errno));
1139 		}
1140 	} else
1141 		tst_resm(TBROK,
1142 			 "Unknown test case processing actions declared");
1143 }
1144 
1145 /***********************************************************************
1146  * This routine checks for the return of ELOOP errno from requested
1147  * system call
1148  *
1149  *   Argument is pointer to test_objects array of structures of type
1150  *   all_test_cases
1151  ***********************************************************************/
do_ELOOP(struct all_test_cases * tc_ptr)1152 void do_ELOOP(struct all_test_cases *tc_ptr)
1153 {
1154 	if ((cktcsid(tc_ptr->tcid, STAT)) || (cktcsid(tc_ptr->tcid, STAT_64))) {
1155 
1156 		TEST(stat(tc_ptr->fn_arg[1], &asymlink));
1157 		errno = TEST_ERRNO;
1158 		if ((TEST_RETURN == -1) && (errno == ELOOP)) {
1159 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1160 		} else {
1161 			tst_resm(TEST_RESULT, "%s errno:%d %s",
1162 				 "Expected ELOOP errno from stat(2) (nested symb link),",
1163 				 errno, strerror(errno));
1164 		}
1165 	} else if (cktcsid(tc_ptr->tcid, CHDIR)) {
1166 
1167 		TEST(chdir(tc_ptr->fn_arg[1]));
1168 		errno = TEST_ERRNO;
1169 		if ((TEST_RETURN == -1) && (errno == ELOOP)) {
1170 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1171 		} else {
1172 
1173 			tst_resm(TFAIL, "%s errno:%d %s",
1174 				 "Expected ELOOP error condition when chdir(2) a nested symbolic link:",
1175 				 errno, strerror(errno));
1176 			/* FIXME (garrcoop): memory leak */
1177 			chdir(tst_get_tmpdir());
1178 		}
1179 	} else if (cktcsid(tc_ptr->tcid, LINK)) {
1180 
1181 		TEST(link(tc_ptr->fn_arg[1], O_FILE));
1182 		errno = TEST_ERRNO;
1183 		if ((TEST_RETURN == -1) && (errno == ELOOP)) {
1184 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1185 		} else {
1186 			tst_resm(TFAIL, "%s errno:%d %s",
1187 				 "Expected ELOOP error condition when link(2) a nested symbolic link:",
1188 				 errno, strerror(errno));
1189 		}
1190 	} else if (cktcsid(tc_ptr->tcid, CHMOD)) {
1191 
1192 		TEST(chmod(tc_ptr->fn_arg[1], MODE));
1193 		errno = TEST_ERRNO;
1194 		if ((TEST_RETURN == -1) && (errno == ELOOP)) {
1195 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1196 		} else {
1197 			tst_resm(TFAIL, "%s errno:%d %s",
1198 				 "Expected ELOOP error condition when chmod(2) a nested symbolic link:",
1199 				 errno, strerror(errno));
1200 		}
1201 		return;
1202 	} else if (cktcsid(tc_ptr->tcid, UTIME)) {
1203 
1204 		TEST(utime(tc_ptr->fn_arg[1], NULL));
1205 		errno = TEST_ERRNO;
1206 
1207 		if ((TEST_RETURN == -1) && (errno == ELOOP)) {
1208 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1209 		} else {
1210 			tst_resm(TFAIL, "%s errno:%d %s",
1211 				 "Expected ELOOP error condition when utime(2) a nested symbolic link:",
1212 				 errno, strerror(errno));
1213 		}
1214 	} else if (cktcsid(tc_ptr->tcid, OPEN)) {
1215 
1216 		int fd;
1217 		TEST(open(tc_ptr->fn_arg[1], O_CREAT, 0666));
1218 		fd = TEST_RETURN;
1219 		errno = TEST_ERRNO;
1220 		if ((fd == -1) && (errno == ELOOP)) {
1221 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1222 		} else {
1223 			tst_resm(TFAIL, "%s errno:%d %s",
1224 				 "Expected ELOOP error condition when open(2) a nested symbolic link:",
1225 				 errno, strerror(errno));
1226 		}
1227 	} else
1228 		tst_resm(TBROK,
1229 			 "Unknown test case processing actions declared");
1230 }
1231 
1232 /***********************************************************************
1233  * This routine checks for the return of ENOTDIR errno from requested
1234  * system call
1235  *
1236  *   Argument is pointer to test_objects array of structures of type
1237  *   all_test_cases
1238  ***********************************************************************/
do_ENOTDIR(struct all_test_cases * tc_ptr)1239 void do_ENOTDIR(struct all_test_cases *tc_ptr)
1240 {
1241 	if (cktcsid(tc_ptr->tcid, RMDIR)) {
1242 
1243 		TEST(mkdir(tc_ptr->fn_arg[0], MODE));
1244 		errno = TEST_ERRNO;
1245 		if (TEST_RETURN == -1)
1246 			tst_resm(TBROK, "mkdir(2) Failure when creating %s",
1247 				 tc_ptr->fn_arg[0]);
1248 		else if ((rmdir(tc_ptr->fn_arg[1]) == -1) && (errno == ENOTDIR)) {
1249 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1250 			rmdir(tc_ptr->fn_arg[0]);
1251 		} else {
1252 			tst_resm(TFAIL, "%s %s errno:%d %s",
1253 				 "Expected ENOTDIR error for removing a non-existent",
1254 				 "directory through a symbolic link file was not received,",
1255 				 errno, strerror(errno));
1256 		}
1257 	} else
1258 		tst_resm(TBROK,
1259 			 "Unknown test case processing actions declared");
1260 }
1261 
1262 /***********************************************************************
1263  * This routine checks for the return of EXDEV errno from requested
1264  * system call
1265  *
1266  *   Argument is pointer to test_objects array of structures of type
1267  *   all_test_cases
1268  ***********************************************************************/
do_EXDEV(struct all_test_cases * tc_ptr)1269 void do_EXDEV(struct all_test_cases *tc_ptr)
1270 {
1271 	if (cktcsid(tc_ptr->tcid, RENAME)) {
1272 
1273 		TEST(rename(tc_ptr->fn_arg[1], Y_A_S_FILE));
1274 		errno = TEST_ERRNO;
1275 		if ((TEST_RETURN == -1) && (errno == EXDEV)) {
1276 			if (see_if_a_symlink(Y_A_S_FILE) == -1) {
1277 				tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1278 			} else {
1279 				tst_resm(TFAIL,
1280 					 "%s %s %s file outside of current file system",
1281 					 "rename(3) returned -1 when trying to move symbolic link file",
1282 					 "outside of current file system, but created",
1283 					 Y_A_S_FILE);
1284 			}
1285 		} else {
1286 			tst_resm(TFAIL, "%s %s errno:%d %s",
1287 				 "Expected EXDEV error for renaming an existing symbolic",
1288 				 "link file to a location outside of existing file system,",
1289 				 errno, strerror(errno));
1290 			delete_files("/NiCkEr", NULL);
1291 		}
1292 	} else
1293 		tst_resm(TBROK,
1294 			 "Unknown test case processing actions declared");
1295 }
1296 
1297 /***********************************************************************
1298  * This routine checks for the return of ENAMETOOLONG errno from requested
1299  * system call
1300  *
1301  *   Argument is pointer to test_objects array of structures of type
1302  *   all_test_cases
1303  ***********************************************************************/
do_ENAMETOOLONG(struct all_test_cases * tc_ptr)1304 void do_ENAMETOOLONG(struct all_test_cases *tc_ptr)
1305 {
1306 	int ret;
1307 
1308 	if (cktcsid(tc_ptr->tcid, SYMLINK)) {
1309 
1310 		TEST(symlink(tc_ptr->fn_arg[0], full_path));
1311 		errno = TEST_ERRNO;
1312 		if ((TEST_RETURN == -1) && (errno == ENAMETOOLONG)) {
1313 			if (see_if_a_symlink(full_path) == -1) {
1314 				tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1315 			} else {
1316 				tst_resm(TFAIL, "%s %s %d %s",
1317 					 "symlink(2) returned -1 when trying to create a symbolic",
1318 					 "link file whose name exceeded",
1319 					 (PATH_MAX + 1),
1320 					 "characters, but it created the symbolic link file");
1321 			}
1322 		} else {
1323 			tst_resm(TFAIL | TERRNO,
1324 				 "Expected ENAMETOOLONG error when creating %s symbolic link file with a path exceeding %d characters",
1325 				 tc_ptr->fn_arg[1], (PATH_MAX + 1));
1326 		}
1327 	} else if (cktcsid(tc_ptr->tcid, READLINK)) {
1328 
1329 		char scratch[PATH_MAX + 1];
1330 
1331 		ret = readlink(full_path, scratch, strlen(full_path));
1332 		if ((ret == -1) && (errno == ENAMETOOLONG)) {
1333 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1334 		} else {
1335 			tst_resm(TFAIL,
1336 				 "Expected ENAMETOOLONG error when reading %s symbolic link file with a path exceeding %d characters: errno:%d %s",
1337 				 tc_ptr->fn_arg[1], (PATH_MAX + 1), errno,
1338 				 strerror(errno));
1339 		}
1340 	} else
1341 		tst_resm(TBROK,
1342 			 "Unknown test case processing actions declared");
1343 }
1344 
1345 /***********************************************************************
1346  * This routine checks for the return of EINVAL errno from requested
1347  * system call
1348  *
1349  *   Argument is pointer to test_objects array of structures of type
1350  *   all_test_cases
1351  ***********************************************************************/
do_EINVAL(struct all_test_cases * tc_ptr)1352 void do_EINVAL(struct all_test_cases *tc_ptr)
1353 {
1354 	if (cktcsid(tc_ptr->tcid, READLINK)) {
1355 		TEST(readlink(tc_ptr->fn_arg[0], test_msg, BUFMAX));
1356 		errno = TEST_ERRNO;
1357 		if (TEST_RETURN == -1) {
1358 			if (errno == EINVAL) {
1359 				tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1360 			} else {
1361 				tst_resm(TFAIL,
1362 					 "readlink(2) ret:-1, errno:%d, : Exp errno:%d",
1363 					 errno, EINVAL);
1364 			}
1365 		} else {
1366 			tst_resm(TFAIL,
1367 				 "readlink(2) did not returned -1 when reading %s",
1368 				 "a file which is not a symbolic link file");
1369 		}
1370 	} else
1371 		tst_resm(TBROK,
1372 			 "Unknown test case processing actions declared");
1373 }
1374 
1375 /***********************************************************************
1376  * This routine checks out the readlink(2) system call for a successful
1377  * invocation
1378  *
1379  *   Argument is pointer to test_objects array of structures of type
1380  *   all_test_cases
1381  ***********************************************************************/
do_readlink(struct all_test_cases * tc_ptr)1382 void do_readlink(struct all_test_cases *tc_ptr)
1383 {
1384 	char scratch[PATH_MAX];
1385 	int ret;
1386 
1387 	ret = readlink(tc_ptr->fn_arg[1], scratch, strlen(tc_ptr->fn_arg[0]));
1388 
1389      /*** the TEST macro cannot be used here for some reason ****/
1390 
1391 	if (ret == -1) {
1392 		tst_resm(TFAIL, "readlink(2) failure on %s symbolic link file",
1393 			 tc_ptr->fn_arg[1]);
1394 
1395 	} else
1396 	    if (strncmp(tc_ptr->fn_arg[0], scratch, strlen(tc_ptr->fn_arg[0]))
1397 		!= 0) {
1398 
1399 		/* Must null terminate scratch because readlink(2) doesn't */
1400 
1401 		scratch[strlen(tc_ptr->fn_arg[0])] = '\0';
1402 
1403 		tst_resm(TFAIL,
1404 			 "readlink(2) Error : Expected %s symbolic link file contents but %s actual contents were returned",
1405 			 tc_ptr->fn_arg[0], scratch);
1406 	} else {
1407 		tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1408 	}
1409 }
1410 
1411 /***********************************************************************
1412  * This routine checks out the stat(2) system call for a successful
1413  * invocation
1414  *
1415  *   Argument is pointer to test_objects array of structures of type
1416  *   all_test_cases
1417  ***********************************************************************/
do_stat(struct all_test_cases * tc_ptr)1418 void do_stat(struct all_test_cases *tc_ptr)
1419 {
1420 	if (statter.st_dev != asymlink.st_dev)
1421 		tst_resm(TFAIL,
1422 			 "stat of symbolic link reference to object device info %jd != stat of object file device info %jd",
1423 			 (intmax_t) statter.st_dev, (intmax_t) asymlink.st_dev);
1424 
1425 	else if (statter.st_mode != asymlink.st_mode)
1426 		tst_resm(TFAIL,
1427 			 "stat of symbolic link reference to object file permissions %jd != stat of object file permissions %jd",
1428 			 (intmax_t) statter.st_mode,
1429 			 (intmax_t) asymlink.st_mode);
1430 
1431 	else if (statter.st_nlink != asymlink.st_nlink)
1432 		tst_resm(TFAIL,
1433 			 "stat of symbolic link reference to object file link count %jd != stat of object file link count %jd",
1434 			 (intmax_t) statter.st_nlink,
1435 			 (intmax_t) asymlink.st_nlink);
1436 
1437 	else if (statter.st_uid != asymlink.st_uid)
1438 		tst_resm(TFAIL,
1439 			 "stat of symbolic link reference to object file uid %jd != stat of object file uid %jd",
1440 			 (intmax_t) statter.st_uid, (intmax_t) asymlink.st_uid);
1441 
1442 	else if (statter.st_gid != asymlink.st_gid)
1443 		tst_resm(TFAIL,
1444 			 "stat of symbolic link reference to object file gid %jd != stat of object file gid %jd",
1445 			 (intmax_t) statter.st_gid, (intmax_t) asymlink.st_gid);
1446 
1447 	else if (statter.st_size != asymlink.st_size)
1448 		tst_resm(TFAIL,
1449 			 "stat of symbolic link reference to object file size %ld != stat of object file size %ld",
1450 			 statter.st_size, asymlink.st_size);
1451 
1452 	else if (statter.st_atime != asymlink.st_atime)
1453 		tst_resm(TFAIL,
1454 			 "stat of symbolic link reference to object access time %ld != stat of object file access time %ld",
1455 			 statter.st_atime, asymlink.st_atime);
1456 
1457 	else if (statter.st_mtime != asymlink.st_mtime)
1458 		tst_resm(TFAIL,
1459 			 "stat of symbolic link reference to object modify time %ld != stat of object file modify time %ld",
1460 			 statter.st_atime, asymlink.st_atime);
1461 
1462 	else if (statter.st_ctime != asymlink.st_ctime)
1463 		tst_resm(TFAIL,
1464 			 "stat of symbolic link reference to object change time %ld != stat of object file change time %ld",
1465 			 statter.st_atime, asymlink.st_atime);
1466 	else
1467 		tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1468 }
1469 
1470 /***********************************************************************
1471  * This routine checks out the chdir(2) system call for a successful
1472  * invocation
1473  *
1474  *   Argument is pointer to test_objects array of structures of type
1475  *   all_test_cases
1476  ***********************************************************************/
do_chdir(struct all_test_cases * tc_ptr)1477 void do_chdir(struct all_test_cases *tc_ptr)
1478 {
1479 	if (mkdir(tc_ptr->fn_arg[2], MODE) == -1)
1480 		tst_resm(TFAIL, "Could not create a setup directory file");
1481 	else {
1482 
1483 		sprintf(Buf, "mkdir(%s, %#o) was successful\n",
1484 			tc_ptr->fn_arg[2], MODE);
1485 		strcat(Buffer, Buf);
1486 
1487 		if (chdir(tc_ptr->fn_arg[1]) == -1)
1488 			tst_resm(TFAIL,
1489 				 "%sCould not change a directory file through a %s",
1490 				 Buffer,
1491 				 "symbolic link which which pointed at object");
1492 		else {
1493 
1494 			char *cwd;
1495 			char expected_location[PATH_MAX];
1496 			/*
1497 			 *  Build expected current directory position
1498 			 */
1499 			/* FIXME (garrcoop): memory leak */
1500 			strcpy(expected_location, tst_get_tmpdir());
1501 			strcat(expected_location, "/");
1502 			strcat(expected_location, tc_ptr->fn_arg[2]);
1503 
1504 			if ((cwd = getcwd(NULL, 0)) == NULL) {
1505 				tst_resm(TFAIL, "getcwd(3) FAILURE");
1506 			} else if (strcmp(cwd, expected_location) == 0) {
1507 				tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1508 			} else {
1509 				tst_resm(TFAIL,
1510 					 "%s%s %s %s not equal to expected %s",
1511 					 Buffer,
1512 					 "chdir(2) returned successfully, but getcwd(3) indicated",
1513 					 "new current working directory location",
1514 					 cwd, expected_location);
1515 			}
1516 			/* FIXME (garrcoop): memory leak */
1517 			chdir(tst_get_tmpdir());
1518 		}
1519 		rmdir(tc_ptr->fn_arg[2]);
1520 	}
1521 }
1522 
1523 /***********************************************************************
1524  * This routine checks out the link(2) system call for a successful
1525  * invocation
1526  *
1527  *   Argument is pointer to test_objects array of structures of type
1528  *   all_test_cases
1529  ***********************************************************************/
do_link(struct all_test_cases * tc_ptr)1530 void do_link(struct all_test_cases *tc_ptr)
1531 {
1532 	struct stat stbuf;
1533 
1534 	if (link(tc_ptr->fn_arg[1], "nick") == -1) {
1535 		tst_resm(TFAIL, "%slink(%s, \"nick\") failed, errno: %d: %s %s",
1536 			 Buffer, tc_ptr->fn_arg[1], errno,
1537 			 "link of new file to object file via symbolic link file failed",
1538 			 "when expected not to");
1539 	} else {
1540 		sprintf(Buf, "link(%s, \"nick\") was successful\n",
1541 			tc_ptr->fn_arg[1]);
1542 		strcat(Buffer, Buf);
1543 
1544 		/*
1545 		 * Check that links counts were properly set
1546 		 */
1547 		if (lstat(tc_ptr->fn_arg[1], &asymlink) == -1) {
1548 			tst_resm(TBROK, "lstat(%s) failed. errno: %d",
1549 				 tc_ptr->fn_arg[1], errno);
1550 
1551 		} else if (lstat("nick", &statter) == -1) {
1552 			tst_resm(TBROK, "lstat(nick) failed, errno:%d",
1553 				 errno);
1554 		} else {
1555 			if (statter.st_ino == asymlink.st_ino) {
1556 				if ((statter.st_nlink == 2) && (asymlink.st_nlink == 2)) {
1557 					tst_resm(TEST_RESULT, "%s",
1558 					         msgs[tc_ptr->pass_msg]);
1559 				} else {
1560 					lstat(tc_ptr->fn_arg[2],
1561 					      &stbuf);
1562 
1563 					tst_resm(TFAIL,
1564 						 "%slink(%s, %s) failed to adjust link count.\n\
1565 		count for nick is %d, count for %s is %d, count for %s is %d.",
1566 						 Buffer, tc_ptr->fn_arg[1], "nick", statter.st_nlink, tc_ptr->fn_arg[1], asymlink.st_nlink, tc_ptr->fn_arg[2],
1567 						 stbuf.st_nlink);
1568 				}
1569 			} else {
1570 				tst_resm(TFAIL, "%sA lstat of %s (ino:%jd) and of\n\t\t\
1571 %s (ino:%jd), does not show them being the same ino.", Buffer,
1572 					 tc_ptr->fn_arg[1], (intmax_t) asymlink.st_ino, "nick", (intmax_t) statter.st_ino);
1573 			}
1574 		}
1575 
1576 		delete_files("nick", NULL);
1577 	}
1578 }
1579 
1580 /***********************************************************************
1581  * This routine checks out the unlink(2) system call for a successful
1582  * invocation
1583  *
1584  *   Argument is pointer to test_objects array of structures of type
1585  *   all_test_cases
1586  ***********************************************************************/
do_unlink(struct all_test_cases * tc_ptr)1587 void do_unlink(struct all_test_cases *tc_ptr)
1588 {
1589 	if (stat(tc_ptr->fn_arg[2], &asymlink) == -1)
1590 		tst_resm(TBROK, "stat(2) Failure when accessing %s object file",
1591 			 tc_ptr->fn_arg[2]);
1592 	else if (unlink(tc_ptr->fn_arg[1]) == -1)
1593 		tst_resm(TFAIL,
1594 			 "unlink(2) failed when removing symbolic link file");
1595 	else {
1596 		sprintf(Buf, "unlink(%s) was successful\n", tc_ptr->fn_arg[1]);
1597 		strcat(Buffer, Buf);
1598 		if (stat(tc_ptr->fn_arg[2], &statter) == -1) {
1599 			tst_resm(TFAIL, "%s %s",
1600 				 "unlink(2) failed because it not only removed symbolic link",
1601 				 "file which pointed at object file, but object file as well");
1602 
1603 		} else if ((statter.st_ino == asymlink.st_ino) &&
1604 			 (statter.st_dev == asymlink.st_dev) &&
1605 			 (statter.st_size == asymlink.st_size)) {
1606 
1607 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1608 		} else {
1609 			tst_resm(TFAIL, "%s%s %s %s", Buffer,
1610 				 "unlink(2) failed because it not only removed symbolic link",
1611 				 "file which pointed at object file, but it changed object",
1612 				 "file inode information");
1613 		}
1614 	}
1615 
1616 }
1617 
1618 /***********************************************************************
1619  * This routine checks out the chmod(2) system call for a successful
1620  * invocation
1621  *
1622  *   Argument is pointer to test_objects array of structures of type
1623  *   all_test_cases
1624  ***********************************************************************/
do_chmod(struct all_test_cases * tc_ptr)1625 void do_chmod(struct all_test_cases *tc_ptr)
1626 {
1627 	if (stat(tc_ptr->fn_arg[2], &asymlink) == -1)
1628 		tst_resm(TBROK, "stat(2) Failure when accessing %s object file",
1629 			 tc_ptr->fn_arg[2]);
1630 	else if (chmod(tc_ptr->fn_arg[1], (MODE | MASK)) == -1)
1631 		tst_resm(TFAIL, "%s%s %s", Buffer,
1632 			 "chmod(2) failed when changing file permission",
1633 			 "through symbolic link file");
1634 	else {
1635 		sprintf(Buf, "chmod(%s, %#o) was successful\n",
1636 			tc_ptr->fn_arg[1], (MODE | MASK));
1637 		strcat(Buffer, Buf);
1638 
1639 		if (stat(tc_ptr->fn_arg[2], &statter) == -1) {
1640 			tst_resm(TBROK,
1641 				 "stat(2) Failure when accessing %s object file",
1642 				 tc_ptr->fn_arg[2]);
1643 		} else if ((statter.st_mode == (MODE | MASK))
1644 			 && (statter.st_mode != asymlink.st_mode)) {
1645 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1646 		} else {
1647 			tst_resm(TFAIL, "%s%s %o to %o %s", Buffer,
1648 				 "chmod(2) failed to change object file permissions from",
1649 				 asymlink.st_mode, (MODE | MASK),
1650 				 "through symbolic link file");
1651 		}
1652 	}
1653 
1654 }
1655 
1656 /***********************************************************************
1657  * This routine checks out the utime(2) system call for a successful
1658  * invocation
1659  *
1660  *   Argument is pointer to test_objects array of structures of type
1661  *   all_test_cases
1662  ***********************************************************************/
do_utime(struct all_test_cases * tc_ptr)1663 void do_utime(struct all_test_cases *tc_ptr)
1664 {
1665 	struct utimbuf utimes;
1666 
1667 	if (stat(tc_ptr->fn_arg[2], &asymlink) == -1)
1668 		tst_resm(TBROK, "stat(2) Failure when accessing %s object file",
1669 			 tc_ptr->fn_arg[2]);
1670 	else {
1671 		/* Now add a few values to access and modify times */
1672 
1673 		utimes.actime = asymlink.st_atime + a_time_value;
1674 		utimes.modtime = asymlink.st_mtime + a_time_value;
1675 
1676 		/* Now hand off to utime(2) via symbolic link file */
1677 
1678 		if (utime(tc_ptr->fn_arg[1], &utimes) == -1)
1679 			tst_resm(TFAIL, "%s %s",
1680 				 "utime(2) failed to process object file access and modify",
1681 				 "time updates through symbolic link");
1682 		else {
1683 			/* Now verify changes were made */
1684 
1685 			if (stat(tc_ptr->fn_arg[2], &statter) == -1)
1686 				tst_resm(TBROK,
1687 					 "stat(2) Failure when accessing %s object file",
1688 					 tc_ptr->fn_arg[2]);
1689 			else {
1690 				time_t temp, diff;
1691 
1692 				temp = statter.st_atime - asymlink.st_atime;
1693 				diff =
1694 				    (statter.st_mtime - asymlink.st_mtime) -
1695 				    temp;
1696 
1697 				if (!diff) {
1698 					tst_resm(TEST_RESULT, "%s",
1699 					         msgs[tc_ptr->pass_msg]);
1700 				} else {
1701 					tst_resm(TFAIL,
1702 						 "%s %s %jd greater than original times",
1703 						 "utime(2) failed to change object file access and",
1704 						 "modify times through symbolic link to a value",
1705 						 (intmax_t) a_time_value);
1706 				}
1707 			}
1708 		}
1709 	}
1710 }
1711 
1712 /***********************************************************************
1713  * This routine checks out the rename(2) system call for a successful
1714  * invocation
1715  *
1716  *   Argument is pointer to test_objects array of structures of type
1717  *   all_test_cases
1718  ***********************************************************************/
do_rename(struct all_test_cases * tc_ptr)1719 void do_rename(struct all_test_cases *tc_ptr)
1720 {
1721 	int pts_at_object = 0;
1722 
1723 	if (stat(tc_ptr->fn_arg[2], &statter) != -1)
1724 		pts_at_object = 1;
1725 
1726 	TEST(rename(tc_ptr->fn_arg[1], A_S_FILE));
1727 	errno = TEST_ERRNO;
1728 	if (TEST_RETURN == -1) {
1729 		tst_resm(TFAIL,
1730 			 "rename(3) failed to rename %s symbolic link file to %s",
1731 			 tc_ptr->fn_arg[2], A_S_FILE);
1732 	} else if (pts_at_object) {
1733 		if (ck_both(tc_ptr->fn_arg[0], A_S_FILE, tc_ptr->fn_arg[2])) {
1734 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1735 		} else {
1736 			tst_resm(TFAIL, "%s", test_msg);
1737 		}
1738 	} else if (!ck_symlink(tc_ptr->fn_arg[0], A_S_FILE, NULL)) {
1739 		tst_resm(TFAIL, "%s", test_msg);
1740 	} else if (stat(tc_ptr->fn_arg[1], &asymlink) != -1) {
1741 		tst_resm(TFAIL,
1742 			 "rename(3) did not remove %s when renaming to %s",
1743 			 tc_ptr->fn_arg[1], A_S_FILE);
1744 	} else {
1745 		tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1746 	}
1747 }
1748 
1749 /***********************************************************************
1750  * This routine checks out the open(2) system call for a successful
1751  * invocation
1752  *
1753  *   Argument is pointer to test_objects array of structures of type
1754  *   all_test_cases
1755  ***********************************************************************/
do_open(struct all_test_cases * tc_ptr)1756 void do_open(struct all_test_cases *tc_ptr)
1757 {
1758 	int fd = -1;
1759 	int ret, pts_at_object = 0;
1760 	char scratch[PATH_MAX];
1761 
1762 	if (stat(tc_ptr->fn_arg[2], &statter) != -1)
1763 		pts_at_object = 1;
1764 
1765 	if (pts_at_object) {
1766 		TEST(open(tc_ptr->fn_arg[1], O_RDWR));
1767 		errno = TEST_ERRNO;
1768 		if ((fd = TEST_RETURN) == -1) {
1769 			tst_resm(TFAIL,
1770 				 "open(2) Failure when opening object file through symbolic link file");
1771 			return;
1772 		}
1773 	} else {
1774 		TEST(open(tc_ptr->fn_arg[1], (O_CREAT | O_RDWR), MODE));
1775 		errno = TEST_ERRNO;
1776 		if ((fd = TEST_RETURN) == -1) {
1777 			tst_resm(TFAIL,
1778 				 "open(2) Failure when creating object file through symbolic link file");
1779 			return;
1780 		}
1781 	}
1782 	if ((ret = write(fd, BIG_STRING, strlen(BIG_STRING))) == -1) {
1783 		tst_resm(TFAIL,
1784 			 "write(2) Failure to object file opened through a symbolic link file: errno:%d",
1785 			 errno);
1786 	} else if (ret != strlen(BIG_STRING)) {
1787 		tst_resm(TFAIL,
1788 			 "write(2) Failed to write %zu bytes to object file opened through a symbolic link file",
1789 			 strlen(BIG_STRING));
1790 	} else if (lseek(fd, 0L, 0) == -1) {
1791 		tst_resm(TFAIL,
1792 			 "lseek(2) Failed to position to beginning of object file opened through a symbolic link file: errno = %d",
1793 			 errno);
1794 	} else if ((ret = read(fd, scratch, strlen(BIG_STRING))) == -1) {
1795 		tst_resm(TFAIL,
1796 			 "read(2) Failure of object file opened through a symbolic link file: errno = %d",
1797 			 errno);
1798 	} else if (ret != strlen(BIG_STRING)) {
1799 		tst_resm(TFAIL,
1800 			 "read(2) Failed to read %zu bytes to object file opened through a symbolic link file",
1801 			 strlen(BIG_STRING));
1802 	} else if (strncmp(BIG_STRING, scratch, strlen(BIG_STRING)) != 0) {
1803 		tst_resm(TFAIL,
1804 			 "Content of write(2) and read(2) Failed to object file through symbolic link file was not as expected. Expected %s and read returned %s",
1805 			 BIG_STRING, scratch);
1806 	} else {
1807 		/*
1808 		 *  Close off symbolic link file to object file access
1809 		 */
1810 		if (close(fd) == -1) {
1811 			tst_resm(TFAIL,
1812 				 "close(2) Failure when closing object file accessed symbolic link file");
1813 		}
1814 		/*
1815 		 * Now, lets open up and read object file and compare contents
1816 		 */
1817 		else if ((fd = open(tc_ptr->fn_arg[0], O_RDONLY)) == -1) {
1818 			tst_resm(TFAIL,
1819 				 "open(2) Failure when opening %s file: errno:%d %s",
1820 				 tc_ptr->fn_arg[0], errno, strerror(errno));
1821 		} else if ((ret = read(fd, scratch, strlen(BIG_STRING))) == -1) {
1822 			tst_resm(TFAIL,
1823 				 "read(2) Failure of object file opened through a symbolic link file: errno:%d",
1824 				 errno);
1825 		} else if (ret != strlen(BIG_STRING)) {
1826 			tst_resm(TFAIL,
1827 				 "read(2) Failed to read %zu bytes to object file opened through a symbolic link file",
1828 				 strlen(BIG_STRING));
1829 		} else if (strncmp(BIG_STRING, scratch, strlen(BIG_STRING)) !=
1830 			   0) {
1831 			tst_resm(TFAIL,
1832 				 "Content of write(2) and read(2) Failed to object file through symbolic link file was not as expected. Expected %s and read returned %s",
1833 				 BIG_STRING, scratch);
1834 		} else if (pts_at_object) {
1835 			tst_resm(TEST_RESULT, "%s", msgs[tc_ptr->pass_msg]);
1836 		} else {	/* Insure newly created object file is pointed at */
1837 			if (ck_both
1838 			    (tc_ptr->fn_arg[0], tc_ptr->fn_arg[1],
1839 			     tc_ptr->fn_arg[0])) {
1840 				tst_resm(TEST_RESULT, "%s",
1841 					 msgs[tc_ptr->pass_msg]);
1842 			} else {
1843 				tst_resm(TFAIL, "%s", test_msg);
1844 			}
1845 		}
1846 		close(fd);
1847 	}
1848 }
1849 
1850 /***************************************************************
1851  * setup() - performs all ONE TIME setup for this test.
1852  ***************************************************************/
setup(void)1853 void setup(void)
1854 {
1855 
1856 	tst_sig(FORK, DEF_HANDLER, cleanup);
1857 
1858 	TEST_PAUSE;
1859 
1860 	/* create a temporary directory and go to it */
1861 	tst_tmpdir();
1862 
1863 }
1864 
1865 /***************************************************************
1866  * cleanup() - performs all ONE TIME cleanup for this test at
1867  *              completion or premature exit.
1868  ***************************************************************/
cleanup(void)1869 void cleanup(void)
1870 {
1871 
1872 	tst_rmdir();
1873 
1874 }
1875 
help(void)1876 void help(void)
1877 {
1878 	int ind;
1879 
1880 	printf("   -T id  Determines which tests cases to execute:\n");
1881 
1882 	for (ind = 0; ind < sizeof(all_tcses) / sizeof(struct tcses); ind++) {
1883 		printf("  %s/%s - %s\n", all_tcses[ind].tcid,
1884 		       all_tcses[ind].syscall, all_tcses[ind].desc);
1885 	}
1886 }
1887