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
221void setup(void);
222void cleanup(void);
223void help(void);
224void delete_files(char *path1, char *path2);
225struct all_test_cases;
226void do_EEXIST(struct all_test_cases *tc_ptr);
227void do_ENOENT(struct all_test_cases *tc_ptr);
228void do_ELOOP(struct all_test_cases *tc_ptr);
229void do_ENOTDIR(struct all_test_cases *tc_ptr);
230void do_EXDEV(struct all_test_cases *tc_ptr);
231void do_ENAMETOOLONG(struct all_test_cases *tc_ptr);
232void do_EINVAL(struct all_test_cases *tc_ptr);
233void do_readlink(struct all_test_cases *tc_ptr);
234void do_stat(struct all_test_cases *tc_ptr);
235void do_chdir(struct all_test_cases *tc_ptr);
236void do_link(struct all_test_cases *tc_ptr);
237void do_unlink(struct all_test_cases *tc_ptr);
238void do_chmod(struct all_test_cases *tc_ptr);
239void do_utime(struct all_test_cases *tc_ptr);
240void do_rename(struct all_test_cases *tc_ptr);
241void do_open(struct all_test_cases *tc_ptr);
242struct tcses;
243int do_syscalltests(struct tcses *tcs);
244struct 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 */
278const 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 */
316int creat_both(char *path1, char *path2, char *path3);
317int creat_symlink(char *path1, char *path2, char *_path3);
318int creat_path_max(char *path1, char *path2, char *path3);
319int ck_symlink(char *path1, char *path2, char *path3);
320int creat_object(char *path1, char *_path2, char *_path3);
321int ck_object(char *path1, char *path2, char *path3);
322int ck_both(char *path1, char *path2, char *path3);
323int ck_path_max(char *path1, char *path2, char *path3);
324
325/*
326 *  Define test cases
327 */
328struct 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 */
448struct 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"}, {
489OPEN, "open", 5, &test_objects[39],
490		    "Create/Open a File For Reading Or Writing via symlink"},};
491
492/*
493 * Define GLOBAL variables
494 */
495
496int TST_TOTAL;
497int TEST_RESULT;
498time_t a_time_value = 100;
499char *TCID;
500char *Selectedtests = NULL;	/* Name (tcid) of selected test cases */
501char test_msg[BUFMAX];
502char full_path[PATH_MAX + 1 + 1];	/* Add one for '\0' and another to exceed the PATH_MAX limit, see creat_path_max() */
503
504struct stat asymlink, statter;
505char Buffer[1024];
506char Buf[1024];
507
508char *Tcid = NULL;
509
510option_t Options[] = {
511	{"T:", NULL, &Tcid},	/* -T tcid option */
512	{NULL, NULL, NULL}
513};
514
515/***********************************************************************
516 * MAIN
517 ***********************************************************************/
518int 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 ***********************************************************************/
585struct 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 ***********************************************************************/
622static 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 ***********************************************************************/
636void 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 ***********************************************************************/
650int 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 ***********************************************************************/
678int 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 ***********************************************************************/
714int 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 ***********************************************************************/
732int 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 ***********************************************************************/
761int 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 ***********************************************************************/
796int 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 ***********************************************************************/
835int 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 ***********************************************************************/
859int 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 ***********************************************************************/
894int 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 ***********************************************************************/
1024void 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 ***********************************************************************/
1073void 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 ***********************************************************************/
1152void 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 ***********************************************************************/
1239void 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 ***********************************************************************/
1269void 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 ***********************************************************************/
1304void 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 ***********************************************************************/
1352void 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 ***********************************************************************/
1382void 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 ***********************************************************************/
1418void 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 ***********************************************************************/
1477void 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 ***********************************************************************/
1530void 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 ***********************************************************************/
1587void 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 ***********************************************************************/
1625void 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 ***********************************************************************/
1663void 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 ***********************************************************************/
1719void 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 ***********************************************************************/
1756void 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 ***************************************************************/
1853void 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 ***************************************************************/
1869void cleanup(void)
1870{
1871
1872	tst_rmdir();
1873
1874}
1875
1876void 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