Home | History | Annotate | Download | only in symlink
      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  ***********************************************************************/
    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  ***********************************************************************/
    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  ***********************************************************************/
    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  ***********************************************************************/
    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  ***********************************************************************/
    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  ***********************************************************************/
    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  ***********************************************************************/
    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  ***********************************************************************/
    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  ***********************************************************************/
    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  ***********************************************************************/
    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  ***********************************************************************/
    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  ***********************************************************************/
    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  ***********************************************************************/
    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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***********************************************************************/
   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  ***************************************************************/
   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  ***************************************************************/
   1869 void cleanup(void)
   1870 {
   1871 
   1872 	tst_rmdir();
   1873 
   1874 }
   1875 
   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