664b2d68eb
* libltp/lib/tst_sig.c (tst_sig): Don't attempt to cleanup on fatal errors. * libltp/lib/parse_opts.c (parse_opts): Initialize allocated string to prevent heap corruption.
2025 lines
66 KiB
C
2025 lines
66 KiB
C
/*
|
|
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it would be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* Further, this software is distributed without any warranty that it is
|
|
* free of the rightful claim of any third person regarding infringement
|
|
* or the like. Any license provided herein, whether implied or
|
|
* otherwise, applies only to this software file. Patent licenses, if
|
|
* any, provided herein do not apply to combinations of this program with
|
|
* other software, or any other product whatsoever.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write the Free Software Foundation, Inc., 59
|
|
* Temple Place - Suite 330, Boston MA 02111-1307, USA.
|
|
*
|
|
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
|
* Mountain View, CA 94043, or:
|
|
*
|
|
* http://www.sgi.com
|
|
*
|
|
* For further information regarding this notice, see:
|
|
*
|
|
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
|
*/
|
|
/* $Id$ */
|
|
/**********************************************************
|
|
*
|
|
* OS Test - Silicon Graphics, Inc.
|
|
*
|
|
* TEST IDENTIFIER : symlink01 (symlink)
|
|
*
|
|
* TEST TITLE : Make a Symbolic Link to a File
|
|
*
|
|
* PARENT DOCUMENT : symtds01
|
|
*
|
|
* TEST CASE TOTAL : 5
|
|
*
|
|
* WALL CLOCK TIME : 3
|
|
*
|
|
* TEST IDENTIFIER : readlink01 (readlink)
|
|
*
|
|
* TEST TITLE : Reads Value of a Symbolic Link
|
|
*
|
|
* PARENT DOCUMENT : symtds01
|
|
*
|
|
* TEST CASE TOTAL : 4
|
|
*
|
|
* WALL CLOCK TIME : 3
|
|
*
|
|
* TEST IDENTIFIER : stat04 (stat)
|
|
*
|
|
* TEST TITLE : Gets File Status Indirectly From a Symbolic Link
|
|
* File
|
|
*
|
|
* PARENT DOCUMENT : symtds01
|
|
*
|
|
* TEST CASE TOTAL : 3
|
|
*
|
|
* WALL CLOCK TIME : 3
|
|
*
|
|
* TEST IDENTIFIER : lstat01 (lstat)
|
|
*
|
|
* TEST TITLE : Get file Status About a Symbolic Link File
|
|
*
|
|
* PARENT DOCUMENT : symtds01
|
|
*
|
|
* TEST CASE TOTAL : 3
|
|
*
|
|
* WALL CLOCK TIME : 3
|
|
*
|
|
* TEST IDENTIFIER : mkdir05 (mkdir)
|
|
*
|
|
* TEST TITLE : Fail When Making a Directory File Indirectly From
|
|
* a Symbolic Link File
|
|
*
|
|
* PARENT DOCUMENT : symtds01
|
|
*
|
|
* TEST CASE TOTAL : 1
|
|
*
|
|
* WALL CLOCK TIME : 3
|
|
*
|
|
* TEST IDENTIFIER : rmdir03 (rmdir)
|
|
*
|
|
* TEST TITLE : Fail When Removing a Directory File Indirectly
|
|
* From a Symbolic Link File
|
|
*
|
|
* PARENT DOCUMENT : symtds01
|
|
*
|
|
* TEST CASE TOTAL : 1
|
|
*
|
|
* WALL CLOCK TIME : 3
|
|
*
|
|
* TEST IDENTIFIER : chdir01 (chdir)
|
|
*
|
|
* TEST TITLE : Changes Current Working DIrectory Location
|
|
* Indirectly From a Symbolic Link File
|
|
*
|
|
* PARENT DOCUMENT : symtds01
|
|
*
|
|
* TEST CASE TOTAL : 3
|
|
*
|
|
* WALL CLOCK TIME : 3
|
|
*
|
|
* TEST IDENTIFIER : link01 (link)
|
|
*
|
|
* TEST TITLE : Creates a Link To a File Indirectly From a
|
|
* Symbolic Link File
|
|
*
|
|
* PARENT DOCUMENT : symtds01
|
|
*
|
|
* TEST CASE TOTAL : 3
|
|
*
|
|
* WALL CLOCK TIME : 3
|
|
*
|
|
* TEST IDENTIFIER : unlink01 (unlink)
|
|
*
|
|
* TEST TITLE : Removes a Link To a File And Not Any Object File
|
|
* Which Maybe Pointed At
|
|
*
|
|
* PARENT DOCUMENT : symtds01
|
|
*
|
|
* TEST CASE TOTAL : 1
|
|
*
|
|
* WALL CLOCK TIME : 3
|
|
*
|
|
* TEST IDENTIFIER : chmod01 (chmod)
|
|
*
|
|
* TEST TITLE : Change Object File Permissions Indirectly From a
|
|
* Symbolic Link File
|
|
*
|
|
* PARENT DOCUMENT : symtds01
|
|
*
|
|
* TEST CASE TOTAL : 3
|
|
*
|
|
* WALL CLOCK TIME : 3
|
|
*
|
|
* TEST IDENTIFIER : utime01 (utime)
|
|
*
|
|
* TEST TITLE : Set File Access And Modify Object File Times
|
|
* Indirectly From a Symbolic Link File
|
|
*
|
|
* PARENT DOCUMENT : symtds01
|
|
*
|
|
* TEST CASE TOTAL : 3
|
|
*
|
|
* WALL CLOCK TIME : 3
|
|
*
|
|
* TEST IDENTIFIER : rename01 (rename)
|
|
*
|
|
* TEST TITLE : Rename a Symbolic Link File And Not Any Object
|
|
* File
|
|
*
|
|
* PARENT DOCUMENT : symtds01
|
|
*
|
|
* TEST CASE TOTAL : 3
|
|
*
|
|
* WALL CLOCK TIME : 3
|
|
*
|
|
* TEST IDENTIFIER : open01 (open)
|
|
*
|
|
* TEST TITLE : Create/Open a File For Reading Or Writing
|
|
* Indirectly From a Symbolic Link File
|
|
*
|
|
* PARENT DOCUMENT : symtds01
|
|
*
|
|
* TEST CASE TOTAL : 5
|
|
*
|
|
* WALL CLOCK TIME : 3
|
|
*
|
|
* EXECUTED BY : whom ever
|
|
*
|
|
* CPU TYPES : ALL
|
|
*
|
|
* AUTHOR : David Fenner
|
|
*
|
|
* CO-PILOT : Jon Hendrickson
|
|
*
|
|
* DATE STARTED : 07/25/90
|
|
*
|
|
* INITIAL RELEASE : UNICOS 6.0
|
|
*
|
|
* TEST CASES
|
|
*
|
|
* For symlink
|
|
*
|
|
* 1. Create symbolic link with abnormal object name path
|
|
* 2. Create symbolic link with normal object name path
|
|
* 3. Create symbolic link with path to an existing object file
|
|
* 4. Receive EEXIST error when creating an already existing symbolic link file.
|
|
* 5. Receive ENAMETOOLONG error when creating symbolic link which exceeds PATH_MAX in length
|
|
*
|
|
* For readlink
|
|
*
|
|
* 1. Read a symbolic link file which points at no object file
|
|
* 2. Read a symbolic link file which points at an object file
|
|
* 3. Receive ENAMETOOLONG error when reading symbolic link which exceeds PATH_MAX in length
|
|
* 4. Receive an EINVAL error when reading a file which is not a symbolic
|
|
* link file.
|
|
*
|
|
* For stat
|
|
*
|
|
* 1. Get object file status through symbolic link file
|
|
* 2. Receive ENOENT error when accessing non-existent object file through symbolic link file
|
|
* 3. Receive ELOOP error when nesting of symbolic links exceed maximum
|
|
*
|
|
* For lstat
|
|
*
|
|
* 1. Get symbolic link file status when pointing at no object file
|
|
* 2. Get symbolic link file status when pointing at an object file
|
|
* 3. Get object file status when argument is not a symbolic link
|
|
* file.
|
|
*
|
|
* For mkdir
|
|
*
|
|
* 1. Receive EEXIST error when creating a directory through a symbolic link file
|
|
*
|
|
* For rmdir
|
|
*
|
|
* 1. Receive ENOTDIR error when removing an existing directory through a symbolic link file
|
|
*
|
|
* For chdir
|
|
*
|
|
* 1. Change current working directory through a symbolic link file
|
|
* 2. Receive ENOENT error when accessing non-existent directory through symbolic link file
|
|
* 3. Receive ELOOP error when nesting of symbolic links exceed maximum
|
|
*
|
|
* For link
|
|
*
|
|
* 1. Link an object file to a new file through symbolic link file
|
|
* 2. Receive ENOENT error when accessing non-existent object file through symbolic link file
|
|
* 3. Receive ELOOP error when nesting of symbolic links exceed maximum
|
|
*
|
|
* For unlink
|
|
*
|
|
* 1. Delete a symbolic link file and not the object file which it points at
|
|
*
|
|
* For chmod
|
|
*
|
|
* 1. Change file permissions of object file through a symbolic link file
|
|
* 2. Receive ENOENT error when accessing non-existent directory through symbolic link file
|
|
* 3. Receive ELOOP error when nesting of symbolic links exceed maximum
|
|
*
|
|
* For utime
|
|
*
|
|
* 1. Change inode times of object file through a symbolic link file
|
|
* 2. Receive ENOENT error when accessing non-existent directory through symbolic link file
|
|
* 3. Receive ELOOP error when nesting of symbolic links exceed maximum
|
|
*
|
|
* For rename
|
|
*
|
|
* 1. Rename a symbolic link file which points at no object file
|
|
* 2. Rename a symbolic link file which points at an object file without any object file alterations.
|
|
* 3. Receive EXDEV when trying to rename a symbolic link file to an address outside of current file system
|
|
*
|
|
* For open
|
|
*
|
|
* 1. Create an object file through a symbolic link file
|
|
* 2. Open an object file through a symbolic link file
|
|
* 3. Receive EEXIST error when exclusively creating an object file through a symbolic link file
|
|
* 4. Receive ENOENT error when accessing non-existent object file through symbolic link file
|
|
* 5. Receive ELOOP error when nesting of symbolic links exceed maximum
|
|
*
|
|
* ENVIRONMENTAL NEEDS
|
|
* None
|
|
*
|
|
* DETAILED DESCRIPTION
|
|
*
|
|
* Self-documenting code so see below
|
|
*
|
|
*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
|
|
|
|
#include <stdio.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <fcntl.h> /* open(2) system call */
|
|
#include <errno.h>
|
|
#include <sys/types.h>
|
|
#include <utime.h> /* utime(2) system call */
|
|
#include <sys/param.h>
|
|
#include <sys/stat.h> /* stat(2) and lstat(2) system calls */
|
|
|
|
#include "test.h"
|
|
#include "usctest.h"
|
|
|
|
void setup();
|
|
void cleanup();
|
|
void help();
|
|
void delete_files();
|
|
void do_EEXIST();
|
|
void do_ENOENT();
|
|
void do_ELOOP();
|
|
void do_ENOTDIR();
|
|
void do_EXDEV();
|
|
void do_ENAMETOOLONG();
|
|
void do_EINVAL();
|
|
void do_readlink();
|
|
void do_stat();
|
|
void do_chdir();
|
|
void do_link();
|
|
void do_unlink();
|
|
void do_chmod();
|
|
void do_utime();
|
|
void do_rename();
|
|
void do_open();
|
|
|
|
#define S_FILE "symbolic" /* Name of symbolic link file */
|
|
#define O_FILE "object" /* Name of object file */
|
|
#define A_S_FILE "asymbolic" /* Another name for a symbolic link file */
|
|
#define Y_A_S_FILE "/NiCkEr" /* Yet another symbolic link file */
|
|
#define BIG_STRING "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
|
|
|
|
#define DEFAULT_TCID "symlink01"
|
|
|
|
#define SYMLINK "symlink01"
|
|
#define READLINK "readlink01"
|
|
#define STAT "stat04"
|
|
#define LSTAT "lstat01"
|
|
#define MKDIR "mkdir05"
|
|
#define RMDIR "rmdir03"
|
|
#define CHDIR "chdir01"
|
|
#define LINK "link01"
|
|
#define UNLINK "unlink01"
|
|
#define CHMOD "chmod01"
|
|
#define UTIME "utime01"
|
|
#define RENAME "rename01"
|
|
#define OPEN "open01"
|
|
|
|
#define cktcsid(s1,s2) (!strcmp(s1,s2))
|
|
#define BUFMAX 512
|
|
#define MODE 0700
|
|
#define MASK 0100777 /* A regular file with r,w,x for all mask */
|
|
|
|
/*
|
|
* Lets be optimistic and only define messages for passing test cases
|
|
*/
|
|
const char *msgs[] = {
|
|
"Creation of symbolic link file to no object file is ok",
|
|
"Creation of symbolic link file and object file via symbolic link is ok",
|
|
"Creating an existing symbolic link file error is caught",
|
|
"Creating a symbolic link which exceeds maximum pathname error is caught",
|
|
"Reading of symbolic link file contents checks out ok",
|
|
"Reading a symbolic link which exceeds maximum pathname error is caught",
|
|
"Getting stat info about object file through symbolic link file is ok",
|
|
"Stat(2) error when accessing non-existent object through symbolic link is caught",
|
|
"lstat(2) of symbolic link file which points to no object file is ok",
|
|
"lstat(2) of symbolic link file which points at an object file is ok",
|
|
"mkdir(2) of object file through symbolic link file failed as expected",
|
|
"rmdir(2) of object file through symbolic link file failed as expected",
|
|
"chdir(2) to object file location through symbolic link file is ok",
|
|
"chdir(2) to non-existent object file location through symbolic link file failed as expected",
|
|
"link(2) to a symbolic link, which is pointing to an existing object file worked - file created and link count adjusted",
|
|
"link(2) to a symbolic link, which is pointing to a non-existing object file worked ok - file created and link count adjusted.",
|
|
"unlink(2) of symbolic link file with no object file removal is ok",
|
|
"chmod(2) of object file permissions through symbolic link file is ok",
|
|
"chmod(2) error when accessing non-existent object through symbolic link is caught",
|
|
"utime(2) change of object file access and modify times through symbolic link file is ok",
|
|
"utime(2) error when accessing non-existent object through symbolic link is caught",
|
|
"rename(3) of symbolic link file name which points at no object file is ok",
|
|
"rename(3) of symbolic link file name which points at object file is ok",
|
|
"rename(3) error of symbolic link file name across file systems is caught",
|
|
"open(2) with (O_CREAT | O_RDWR) to create object file through symbolic link file and all writes, reads, and lseeks are ok",
|
|
"open(2) with O_RDWR of existing object file through symbolic link file and all writes, reads, and lseeks are ok",
|
|
"open(2) with (O_CREAT | O_EXCL) error is caught when creating object file through symbolic link file",
|
|
"open(2) error with O_RDWR is caught when processing symbolic link file which points at no object file",
|
|
"Nested symbolic link access condition caught. ELOOP is returned",
|
|
"Reading a nonsymbolic link file error condition is caught. EINVAL is returned",
|
|
"lstat(2) of object file returns object file inode information",
|
|
"NULL"
|
|
};
|
|
|
|
/*
|
|
* Define test object setup and validation functions
|
|
*/
|
|
int creat_both(), creat_symlink(), creat_path_max(), ck_symlink(),
|
|
creat_object(), ck_object(), ck_both(), ck_path_max();
|
|
|
|
|
|
/*
|
|
* Define test cases
|
|
*/
|
|
struct all_test_cases
|
|
{
|
|
char *tcid;
|
|
int test_fail;
|
|
int errno_val;
|
|
int pass_msg;
|
|
int (*test_setup)();
|
|
int (*ck_test)();
|
|
char *fn_arg[3];
|
|
|
|
} test_objects[] = {
|
|
{SYMLINK, 0, 0, 0, creat_symlink, ck_symlink, {"%bc+eFhi!k", S_FILE, NULL}},
|
|
{SYMLINK, 0, 0, 0, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}},
|
|
{SYMLINK, 0, 0, 1, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}},
|
|
{SYMLINK, 1, EEXIST, 2, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}},
|
|
{SYMLINK, 1, ENAMETOOLONG, 3, creat_path_max, ck_path_max, {O_FILE, S_FILE, NULL}},
|
|
{READLINK, 0, 0, 4, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}},
|
|
{READLINK, 0, 0, 4, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}},
|
|
{READLINK, 1, ENAMETOOLONG, 5, creat_path_max, ck_path_max, {O_FILE, S_FILE, NULL}},
|
|
{READLINK, 1, EINVAL, 29, creat_object, ck_object, {O_FILE, NULL, NULL}},
|
|
{STAT, 0, 0, 6, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}},
|
|
{STAT, 1, ENOENT, 7, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}},
|
|
{STAT, 1, ELOOP, 28, creat_symlink, ck_symlink, {S_FILE, S_FILE, NULL}},
|
|
{LSTAT, 0, 0, 8, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}},
|
|
{LSTAT, 0, 0, 9, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}},
|
|
{LSTAT, 0, 0, 30, creat_object, ck_object, {O_FILE, NULL, NULL}},
|
|
{MKDIR, 1, EEXIST, 10, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}},
|
|
{RMDIR, 1, ENOTDIR, 11, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}},
|
|
{CHDIR, 0, 0, 12, creat_symlink, ck_symlink, {O_FILE, S_FILE, O_FILE}},
|
|
{CHDIR, 1, ENOENT, 13, creat_symlink, ck_symlink, {"%bc+eFhi!k", S_FILE, NULL}},
|
|
{CHDIR, 1, ELOOP, 28, creat_symlink, ck_symlink, {S_FILE, S_FILE, NULL}},
|
|
{LINK, 0, 0, 14, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}},
|
|
{LINK, 0, 0, 15, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}},
|
|
/* The following link test case is invalid - leaving it defined so */
|
|
/* I don't have to change all the entries in the all_tcses array after link */
|
|
{LINK, 1, -1, -1, creat_symlink, ck_symlink, {NULL, NULL, NULL}},
|
|
{UNLINK, 0, 0, 16, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}},
|
|
{CHMOD, 0, 0, 17, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}},
|
|
{CHMOD, 1, ENOENT, 18, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}},
|
|
{CHMOD, 1, ELOOP, 28, creat_symlink, ck_symlink, {S_FILE, S_FILE, NULL}},
|
|
{UTIME, 0, 0, 19, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}},
|
|
{UTIME, 1, ENOENT, 20, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}},
|
|
{UTIME, 1, ELOOP, 28, creat_symlink, ck_symlink, {S_FILE, S_FILE, NULL}},
|
|
{RENAME, 0, 0, 21, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}},
|
|
{RENAME, 0, 0, 22, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}},
|
|
{RENAME, 1, EXDEV, 23, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}},
|
|
{OPEN, 0, 0, 24, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}},
|
|
{OPEN, 0, 0, 25, creat_both, ck_both, {O_FILE, S_FILE, O_FILE}},
|
|
{OPEN, 1, EEXIST, 26, creat_symlink, ck_symlink, {O_FILE, S_FILE, O_FILE}},
|
|
{OPEN, 1, ENOENT, 27, creat_symlink, ck_symlink, {O_FILE, S_FILE, NULL}},
|
|
{OPEN, 1, ELOOP, 28, creat_symlink, ck_symlink, {S_FILE, S_FILE, NULL}}
|
|
};
|
|
|
|
/*
|
|
* Define tcses
|
|
*/
|
|
struct tcses
|
|
{
|
|
char *tcid;
|
|
char *syscall;
|
|
int test_cases; /* number of entries in test_objects array */
|
|
struct all_test_cases *tc_ptr;
|
|
char *desc;
|
|
} all_tcses[] = {
|
|
|
|
{ SYMLINK, "symlink", 5, &test_objects[0],
|
|
"Make a Symbolic Link to a File" },
|
|
{ READLINK, "readlink", 4, &test_objects[5],
|
|
"Reads Value of a Symbolic Link" },
|
|
{ STAT, "stat", 3, &test_objects[9],
|
|
"Gets File Status Indirectly From a Symbolic Link file" },
|
|
{ LSTAT, "lstat", 3, &test_objects[12],
|
|
"Get file Status About a Symbolic Link File" },
|
|
{ MKDIR, "mkdir", 1, &test_objects[15],
|
|
"Fail When Making a Directory File Indirectly from a symlink" },
|
|
{ RMDIR, "rmdir", 1, &test_objects[16],
|
|
"Fail When Removing a Directory File Indirectly from a symlink" },
|
|
{ CHDIR, "chdir", 3, &test_objects[17],
|
|
"Changes CWD Location Indirectly from a symlink" },
|
|
{ LINK, "link", 2, &test_objects[20],
|
|
"Creates a Link To a File Indirectly From a Symbolic" },
|
|
{ UNLINK, "unlink", 1, &test_objects[23],
|
|
"Removes a Link To a File but not the Object File" },
|
|
{ CHMOD, "chmod", 3, &test_objects[24],
|
|
"Change Object File Permissions Indirectly From a Symbolic" },
|
|
{ UTIME, "utime", 3, &test_objects[27],
|
|
"Set File Access And Modify Object File Times via symlink" },
|
|
{ RENAME, "rename", 3, &test_objects[30],
|
|
"Rename a Symbolic Link File And Not Any Object file" },
|
|
{ OPEN, "open", 5, &test_objects[33],
|
|
"Create/Open a File For Reading Or Writing via symlink" },
|
|
};
|
|
|
|
/*
|
|
* Define GLOBAL variables
|
|
*/
|
|
|
|
int TST_TOTAL;
|
|
int TEST_RESULT;
|
|
time_t a_time_value = 100;
|
|
char *TCID;
|
|
char *Selectedtests = NULL; /* Name (tcid) of selected test cases */
|
|
char test_msg[BUFMAX];
|
|
char full_path[PATH_MAX+1];
|
|
extern int Tst_count;
|
|
extern char *TESTDIR;
|
|
extern char *strrchr();
|
|
extern int errno;
|
|
|
|
struct stat asymlink, statter;
|
|
char Buffer[1024];
|
|
char Buf[1024];
|
|
|
|
char *Tcid = NULL;
|
|
|
|
option_t Options[] = {
|
|
{ "T:", NULL, &Tcid }, /* -T tcid option */
|
|
{ NULL, NULL, NULL }
|
|
};
|
|
|
|
/***********************************************************************
|
|
* MAIN
|
|
***********************************************************************/
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
struct tcses *tcs_ptr, *get_tcs_info();
|
|
int do_syscalltests();
|
|
void cleanup();
|
|
int lc; /* loop counter */
|
|
const char *msg; /* message returned from parse_opts */
|
|
|
|
|
|
/***************************************************************
|
|
* parse standard options, and exit if there is an error
|
|
***************************************************************/
|
|
if ( (msg=parse_opts(argc, argv, Options, &help)) != (char *) NULL ) {
|
|
tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
|
|
tst_exit();
|
|
}
|
|
|
|
/*
|
|
* If the -T option was used, use that TCID or use the default
|
|
*/
|
|
if ( Tcid != NULL ) {
|
|
TCID = Tcid;
|
|
Selectedtests=Tcid;
|
|
|
|
}
|
|
#ifndef ALL
|
|
else {
|
|
TCID = DEFAULT_TCID;
|
|
Selectedtests = DEFAULT_TCID;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Get test case specification information and assign TST_TOTAL
|
|
*/
|
|
if ((tcs_ptr=get_tcs_info(Selectedtests)) == NULL) {
|
|
TST_TOTAL=1;
|
|
tst_brkm(TBROK, cleanup,
|
|
"Unknown symbolic link test case specification executed");
|
|
}
|
|
|
|
/***************************************************************
|
|
* perform global setup for test
|
|
***************************************************************/
|
|
|
|
setup();
|
|
|
|
/***************************************************************
|
|
* check looping state if -c option given
|
|
***************************************************************/
|
|
for (lc=0; TEST_LOOPING(lc); lc++) {
|
|
|
|
/* reset Tst_count in case we are looping. */
|
|
Tst_count=0;
|
|
|
|
/*
|
|
* Execute tcs testing function and all defined test cases
|
|
*/
|
|
do_syscalltests(tcs_ptr);
|
|
|
|
} /* End for TEST_LOOPING */
|
|
|
|
/*
|
|
* End appropriately
|
|
*/
|
|
cleanup();
|
|
|
|
return 0;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This function maps the name of the process to a test case specification
|
|
* defined in the all_tcses array of tcses structures. Either a pointer
|
|
* to the mapped test case specification information is returned or a
|
|
* null pointer.
|
|
*
|
|
* Argument is path to program name.
|
|
***********************************************************************/
|
|
struct tcses *get_tcs_info(ptr)
|
|
char *ptr;
|
|
{
|
|
int ctr;
|
|
struct tcses *tcs_ptr;
|
|
|
|
#if ALL
|
|
if ( ptr == NULL ) {
|
|
|
|
TST_TOTAL=0;
|
|
for (ctr=1; ctr < sizeof(all_tcses)/sizeof(struct tcses); ctr++)
|
|
TST_TOTAL += all_tcses[ctr].test_cases;
|
|
return all_tcses;
|
|
}
|
|
#endif
|
|
|
|
|
|
for(ctr=0; ctr < (sizeof(all_tcses)/sizeof(struct tcses)); ctr++) {
|
|
if ( strcmp(ptr, all_tcses[ctr].tcid) == 0 ||
|
|
strcmp(ptr, all_tcses[ctr].syscall) == 0 ) {
|
|
tcs_ptr = &all_tcses[ctr];
|
|
TCID = all_tcses[ctr].tcid;
|
|
TST_TOTAL=tcs_ptr->test_cases;
|
|
return(tcs_ptr);
|
|
}
|
|
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Determines if what path points at is a symbolic link file
|
|
*
|
|
* Argument is path to symbolic link file.
|
|
*
|
|
* Return status is one if a symbolic link file. Zero if not a symbolic
|
|
* link file and a minus one if the path doesn't point at a file.
|
|
***********************************************************************/
|
|
int
|
|
see_if_a_symlink(path)
|
|
char *path;
|
|
{
|
|
if (lstat(path, &asymlink) < 0)
|
|
return(-1);
|
|
|
|
if ((asymlink.st_mode & S_IFMT) == S_IFLNK)
|
|
return(1);
|
|
else
|
|
return(0);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This function performs without any hesitation, file(s) deletions
|
|
***********************************************************************/
|
|
void
|
|
delete_files(path1, path2)
|
|
char *path1, *path2;
|
|
{
|
|
unlink(path1);
|
|
unlink(path2);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* This routine creates a symbolic link file.
|
|
*
|
|
* Argument one is symbolic link pathname to point at.
|
|
* Argument two is name of symbolic link file.
|
|
*
|
|
***********************************************************************/
|
|
int
|
|
creat_symlink(path1, path2)
|
|
char *path1, *path2;
|
|
{
|
|
TEST( symlink(path1, path2) );
|
|
errno=TEST_ERRNO;
|
|
if (TEST_RETURN == -1) {
|
|
TEST_RESULT=TBROK;
|
|
sprintf(test_msg,
|
|
"symlink(2) Failure when creating setup %s object file: errno:%d %s",
|
|
path1, errno, strerror(errno));
|
|
return(0);
|
|
}
|
|
else {
|
|
sprintf(Buf, "symlink(%s, %s) was succesful.\n", path1, path2);
|
|
strcat(Buffer, Buf);
|
|
#if DEBUG
|
|
tst_resm(TPASS, "symlink(%s, %s) was succesful.", path1, path2);
|
|
#endif
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* This routine creates a regular file.
|
|
*
|
|
* Argument one is a pathname
|
|
*
|
|
***********************************************************************/
|
|
int
|
|
creat_object(path1)
|
|
char *path1;
|
|
{
|
|
int fd;
|
|
if ((fd=creat(path1, MODE)) == -1) {
|
|
TEST_RESULT=TBROK;
|
|
sprintf(test_msg,
|
|
"creat(2) Failure when creating setup %s object file: errno:%d %s",
|
|
path1, errno, strerror(errno));
|
|
return(0);
|
|
}
|
|
else {
|
|
sprintf(Buf, "creat(%s, %#o) was succesful.\n", path1, MODE);
|
|
strcat(Buffer, Buf);
|
|
#if DEBUG
|
|
tst_resm(TPASS, "creat(%s, %#o) was succesful.", path1, MODE);
|
|
#endif
|
|
}
|
|
if (close(fd) == -1) {
|
|
TEST_RESULT=TBROK;
|
|
sprintf(test_msg,
|
|
"close(2) Failure when closing setup %s object file: errno:%d %s",
|
|
path1, errno, strerror(errno));
|
|
return(0);
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* This routine creates a symbolic link file and a regular file.
|
|
*
|
|
* Argument one is a pathname of object file
|
|
* Argument two is symbolic link file name
|
|
* Argument three is regular file name
|
|
*
|
|
***********************************************************************/
|
|
int
|
|
creat_both(path1, path2, path3)
|
|
char *path1, *path2, *path3;
|
|
{
|
|
if (creat_symlink(path1, path2) == -1)
|
|
return(0);
|
|
else if (creat_object(path3) == -1)
|
|
return(0);
|
|
return(1);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* This routine checks if symbolic link file is a symbolic link file.
|
|
*
|
|
* Argument one is a pathname of object file
|
|
* Argument two is symbolic link file name
|
|
* Argument three is regular file name
|
|
*
|
|
***********************************************************************/
|
|
int
|
|
ck_symlink(path1, path2, path3)
|
|
char *path1, *path2, *path3;
|
|
{
|
|
int ret;
|
|
|
|
if ((ret=see_if_a_symlink(path2)) == -1) {
|
|
TEST_RESULT=TBROK;
|
|
sprintf(test_msg,
|
|
"lstat(2) Failure when accessing %s symbolic link file which should contain %s path to %s file ",
|
|
path2, path1, path3);
|
|
return(0);
|
|
}
|
|
else if (ret == 0) {
|
|
TEST_RESULT=TBROK;
|
|
sprintf(test_msg,
|
|
"%s is not a symbolic link file which contains %s path to %s file",
|
|
path2, path1, path3);
|
|
return(0);
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* This routine checks if symbolic link file points at object file.
|
|
*
|
|
* Argument one is a pathname of object file
|
|
* Argument two is symbolic link file name
|
|
* Argument three is regular file name
|
|
*
|
|
***********************************************************************/
|
|
int
|
|
ck_both(path1, path2, path3)
|
|
char *path1, *path2, *path3;
|
|
{
|
|
if (ck_symlink(path1, path2, path3) == 0)
|
|
return(0);
|
|
else if ((stat(path3, &statter) == -1) && (errno == ENOENT)) {
|
|
TEST_RESULT=TBROK;
|
|
sprintf(test_msg, "stat(2) Failure when accessing %s object file ", path3);
|
|
return(0);
|
|
}
|
|
else if ((stat(path2, &asymlink) == -1) && (errno == ENOENT)) {
|
|
TEST_RESULT=TBROK;
|
|
sprintf(test_msg, "stat(2) Failure when accessing %s symbolic link file ",
|
|
path2);
|
|
return(0);
|
|
}
|
|
else if (statter.st_ino != asymlink.st_ino) {
|
|
TEST_RESULT=TBROK;
|
|
sprintf(test_msg,
|
|
"stat(2) Failure when accessing %s object file through %s symbolic link file ",
|
|
path3, path2);
|
|
return(0);
|
|
}
|
|
return(1);
|
|
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine populates full_path with a pathname whose length exceeds
|
|
* the PATH_MAX define value in param.h
|
|
*
|
|
* Argument one is a pathname of object file
|
|
* Argument two is symbolic link file name
|
|
* Argument three is regular file name
|
|
***********************************************************************/
|
|
int
|
|
creat_path_max(path1, path2, path3)
|
|
char *path1, *path2, *path3;
|
|
{
|
|
int ctr, to_go, size, whole_chunks;
|
|
char *cwd, *getcwd();
|
|
|
|
if ((cwd = getcwd((char *)NULL, 64)) == NULL)
|
|
{
|
|
TEST_RESULT=TBROK;
|
|
sprintf(test_msg,
|
|
"getcwd(3) Failure in setup of %s %s %s test case object elements",
|
|
path1, path2, path3);
|
|
return(0);
|
|
}
|
|
cwd = getcwd((char *)NULL, 64);
|
|
size = strlen(cwd);
|
|
|
|
to_go = PATH_MAX - size;
|
|
size = strlen(path1);
|
|
whole_chunks = to_go / size;
|
|
strcpy(full_path, cwd);
|
|
for (ctr=0; ctr < whole_chunks; ctr++) {
|
|
strcat(full_path, path1);
|
|
}
|
|
size= strlen(full_path);
|
|
to_go = PATH_MAX - size;
|
|
strcat(full_path, "/");
|
|
for (ctr=0; ctr < to_go; ctr++)
|
|
strcat(full_path, "Z");
|
|
|
|
return(1);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks that full_path's length exceeds the PATH_MAX
|
|
* define value in param.h
|
|
*
|
|
* Argument one is a pathname of object file
|
|
* Argument two is symbolic link file name
|
|
* Argument three is regular file name
|
|
***********************************************************************/
|
|
int
|
|
ck_path_max(path1, path2, path3)
|
|
char *path1, *path2, *path3;
|
|
{
|
|
if (strlen(full_path) == (PATH_MAX+1))
|
|
return(1);
|
|
else
|
|
{
|
|
TEST_RESULT=TBROK;
|
|
sprintf(test_msg, "%s %d %s %s %s %s",
|
|
"full_path character array length was not", (PATH_MAX+1),
|
|
"characters long for test case object elements",
|
|
path1, path2, path3);
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks if the stat(2) and lstat(2) calls return the same
|
|
* information when the path is not a symbolic link file
|
|
*
|
|
* Argument one is a pathname of object file
|
|
* Argument two is symbolic link file name
|
|
* Argument three is regular file name
|
|
*
|
|
***********************************************************************/
|
|
int
|
|
ck_object(path1, path2, path3)
|
|
char *path1, *path2, *path3;
|
|
{
|
|
int ret;
|
|
|
|
if ((ret=see_if_a_symlink(path1)) < 0) {
|
|
TEST_RESULT=TFAIL;
|
|
sprintf(test_msg,
|
|
"lstat(2) failed to return inode information for a regular object file");
|
|
return(0);
|
|
}
|
|
else if (ret == 1) {
|
|
TEST_RESULT=TFAIL;
|
|
sprintf(test_msg,
|
|
"lstat(2) detected a regular object file as a symbolic link file");
|
|
return(0);
|
|
}
|
|
else if (stat(path1, &statter) == -1) {
|
|
TEST_RESULT=TBROK;
|
|
sprintf(test_msg,
|
|
"stat(2) failed to return inode information for a regular object file");
|
|
return(0);
|
|
}
|
|
else if (bcmp((char *)&statter, (char *)&asymlink, sizeof(statter)) != 0) {
|
|
TEST_RESULT=TFAIL;
|
|
sprintf(test_msg,
|
|
"lstat(2) and stat(2) do not return same inode information for an object file");
|
|
return(0);
|
|
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* Main test case processing function
|
|
*
|
|
* Argument is a ptr into the all_tcses array of structures of type tcses
|
|
***********************************************************************/
|
|
int
|
|
do_syscalltests(tcs)
|
|
struct tcses *tcs;
|
|
{
|
|
int ctr, ret;
|
|
struct all_test_cases *tc_ptr;
|
|
|
|
/*
|
|
* loop through desired number of test cases
|
|
*/
|
|
for (ctr=0, tc_ptr=tcs->tc_ptr; ctr < TST_TOTAL; ctr++, tc_ptr++) {
|
|
|
|
Buffer[0]='\0';
|
|
|
|
/*
|
|
* If running all test cases for all tcid, set the TCID if needed.
|
|
*/
|
|
if ( Selectedtests == NULL ) {
|
|
if ( strcmp(tcs->tcid, tc_ptr->tcid) != 0 ) {
|
|
TCID = tc_ptr->tcid;
|
|
Tst_count=0;
|
|
}
|
|
}
|
|
/*
|
|
* Insure that we are executing the correct tcs test case
|
|
*/
|
|
if (strcmp(tcs->tcid, tc_ptr->tcid) != 0) {
|
|
tst_resm(TBROK, "%s TCID attempted to execute %s %d %d test case",
|
|
tcs->tcid, tc_ptr->tcid, tc_ptr->test_fail, tc_ptr->errno_val);
|
|
continue;
|
|
}
|
|
TEST_RESULT=TPASS;
|
|
delete_files(S_FILE, O_FILE);
|
|
/*
|
|
* Perform test case setup
|
|
*/
|
|
ret = (tc_ptr->test_setup)(tc_ptr->fn_arg[0], tc_ptr->fn_arg[1],
|
|
tc_ptr->fn_arg[2], tc_ptr->errno_val);
|
|
|
|
/* If an expected error, try it out */
|
|
|
|
if (tc_ptr->test_fail) {
|
|
/*
|
|
* Try to perform test verification function
|
|
*/
|
|
if (! (tc_ptr->ck_test)(tc_ptr->fn_arg[0], tc_ptr->fn_arg[1],
|
|
tc_ptr->fn_arg[2], tc_ptr->errno_val))
|
|
tst_resm(TEST_RESULT, test_msg);
|
|
else if (tc_ptr->errno_val == EEXIST)
|
|
do_EEXIST(tc_ptr);
|
|
else if (tc_ptr->errno_val == ENOENT)
|
|
do_ENOENT(tc_ptr);
|
|
else if (tc_ptr->errno_val == ELOOP)
|
|
do_ELOOP(tc_ptr);
|
|
else if (tc_ptr->errno_val == ENOTDIR)
|
|
do_ENOTDIR(tc_ptr);
|
|
else if (tc_ptr->errno_val == EXDEV)
|
|
do_EXDEV(tc_ptr);
|
|
else if (tc_ptr->errno_val == ENAMETOOLONG)
|
|
do_ENAMETOOLONG(tc_ptr);
|
|
else if (tc_ptr->errno_val == EINVAL)
|
|
do_EINVAL(tc_ptr);
|
|
else
|
|
tst_resm(TBROK, "Test Case Declaration Error");
|
|
}
|
|
else if (ret == 1) { /* No setup function error */
|
|
|
|
if (tc_ptr->errno_val != 0)
|
|
tst_resm(TBROK, "Test Case Declaration Error");
|
|
else {
|
|
/*
|
|
* Perform test verification function
|
|
*/
|
|
ret=(tc_ptr->ck_test)(tc_ptr->fn_arg[0], tc_ptr->fn_arg[1],
|
|
tc_ptr->fn_arg[2], tc_ptr->errno_val);
|
|
|
|
/* Perform requested symbolic link system call test */
|
|
|
|
if ((cktcsid(tc_ptr->tcid, SYMLINK)) ||
|
|
(cktcsid(tc_ptr->tcid, LSTAT))) {
|
|
if (ret == 1)
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
tst_resm(TEST_RESULT, test_msg);
|
|
}
|
|
else if (ret == 0)
|
|
tst_resm(TEST_RESULT, test_msg);
|
|
else if (cktcsid(tc_ptr->tcid, READLINK))
|
|
do_readlink(tc_ptr);
|
|
else if (cktcsid(tc_ptr->tcid, STAT))
|
|
do_stat(tc_ptr);
|
|
else if (cktcsid(tc_ptr->tcid, CHDIR))
|
|
do_chdir(tc_ptr);
|
|
else if (cktcsid(tc_ptr->tcid, LINK))
|
|
do_link(tc_ptr);
|
|
else if (cktcsid(tc_ptr->tcid, UNLINK))
|
|
do_unlink(tc_ptr);
|
|
else if (cktcsid(tc_ptr->tcid, CHMOD))
|
|
do_chmod(tc_ptr);
|
|
else if (cktcsid(tc_ptr->tcid, UTIME))
|
|
do_utime(tc_ptr);
|
|
else if (cktcsid(tc_ptr->tcid, RENAME))
|
|
do_rename(tc_ptr);
|
|
else if (cktcsid(tc_ptr->tcid, OPEN))
|
|
do_open(tc_ptr);
|
|
else
|
|
tst_resm(TBROK, "Unknown test case processing actions declared");
|
|
}
|
|
}
|
|
else
|
|
tst_resm(TBROK, "Test Case Declaration Error");
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks for the return of EEXIST errno from requested
|
|
* system call
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_EEXIST(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
if (cktcsid(tc_ptr->tcid, SYMLINK)) {
|
|
|
|
TEST( symlink(tc_ptr->fn_arg[0], tc_ptr->fn_arg[1]) );
|
|
errno=TEST_ERRNO;
|
|
if ((TEST_RETURN == -1) && (errno == EEXIST))
|
|
if ( STD_FUNCTIONAL_TEST )
|
|
tst_resm(TPASS, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s %s",
|
|
"Expected EEXIST error when creating a symbolic link file",
|
|
"which already existed");
|
|
}
|
|
else if (cktcsid(tc_ptr->tcid, MKDIR)) {
|
|
|
|
TEST ( mkdir(tc_ptr->fn_arg[1],MODE) );
|
|
errno=TEST_ERRNO;
|
|
if ((TEST_RETURN == -1) && (errno == EEXIST))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else {
|
|
|
|
tst_resm(TFAIL, "%s %s",
|
|
"Expected EEXIST error when creating a directory by a symbolic",
|
|
"link file which pointed at no object file");
|
|
rmdir(tc_ptr->fn_arg[1]);
|
|
}
|
|
}
|
|
else if (cktcsid(tc_ptr->tcid, OPEN)) {
|
|
|
|
TEST( open(tc_ptr->fn_arg[1], (O_EXCL | O_CREAT)) )
|
|
errno=TEST_ERRNO;
|
|
if ((TEST_RETURN == -1) && (errno == EEXIST))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s %s errno:%d %s",
|
|
"Expected EEXIST error for exclusively opening an object file",
|
|
"through a symbolic link file was not received:",
|
|
errno, strerror(errno));
|
|
}
|
|
else
|
|
tst_resm(TBROK, "Unknown test case processing actions declared");
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks for the return of ENOENT errno from requested
|
|
* system call
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_ENOENT(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
if (cktcsid(tc_ptr->tcid, STAT)) {
|
|
|
|
if ((stat(tc_ptr->fn_arg[1], &asymlink) == -1) && (errno == ENOENT))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s %s errno:%d %s",
|
|
"Expected ENOENT error for stating a non-existent directory",
|
|
"through a symbolic link file was not received:",
|
|
errno, strerror(errno));
|
|
}
|
|
else if (cktcsid(tc_ptr->tcid, CHDIR)) {
|
|
if ((chdir(tc_ptr->fn_arg[1]) == -1) && (errno == ENOENT))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else {
|
|
tst_resm(TFAIL, "%s %s errno:%d %s",
|
|
"Expected ENOENT error for changing to a non-existent",
|
|
"directory through a symbolic link file was not received:",
|
|
errno, strerror(errno));
|
|
chdir(TESTDIR);
|
|
}
|
|
}
|
|
else if (cktcsid(tc_ptr->tcid, LINK)) {
|
|
|
|
if ((link(tc_ptr->fn_arg[1], "nick") == -1) && (errno == ENOENT))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
{
|
|
tst_resm(TFAIL, "%s %s errno:%d %s",
|
|
"Expected ENOENT error condition when link(2) a symbolic",
|
|
"link which pointed at no object:", errno, strerror(errno));
|
|
delete_files("nick", NULL);
|
|
}
|
|
}
|
|
else if (cktcsid(tc_ptr->tcid, CHMOD)) {
|
|
|
|
if ((chmod(tc_ptr->fn_arg[1], MODE) == -1) && (errno == ENOENT))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s %s errno:%d %s",
|
|
"Expected ENOENT error condition when chmod(2) a symbolic",
|
|
"link which pointed at no object,", errno, strerror(errno));
|
|
}
|
|
else if (cktcsid(tc_ptr->tcid, UTIME)) {
|
|
|
|
if ((utime(tc_ptr->fn_arg[1], NULL) == -1) && (errno == ENOENT))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s %s errno:%d %s",
|
|
"Expected ENOENT error condition when utime(2) a symbolic",
|
|
"link which pointed at no object:", errno, strerror(errno));
|
|
}
|
|
else if (cktcsid(tc_ptr->tcid, OPEN)) {
|
|
|
|
if ((open(tc_ptr->fn_arg[1], O_RDWR) == -1) && (errno == ENOENT))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s %s errno:%d %s",
|
|
"Expected ENOENT error for opening a non-existent object",
|
|
" file through a symbolic link file was not received,",
|
|
errno, strerror(errno));
|
|
}
|
|
else
|
|
tst_resm(TBROK, "Unknown test case processing actions declared");
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks for the return of ELOOP errno from requested
|
|
* system call
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_ELOOP(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
if (cktcsid(tc_ptr->tcid, STAT)) {
|
|
|
|
TEST( stat(tc_ptr->fn_arg[1], &asymlink) );
|
|
errno=TEST_ERRNO;
|
|
if ((TEST_RETURN == -1) && (errno == ELOOP))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, "%s errno:%d %s",
|
|
"Expected ELOOP errno from stat(2) (nested symb link),",
|
|
errno, strerror(errno));
|
|
else
|
|
Tst_count++;
|
|
}
|
|
else if (cktcsid(tc_ptr->tcid, CHDIR)) {
|
|
|
|
TEST( chdir(tc_ptr->fn_arg[1]) );
|
|
errno=TEST_ERRNO;
|
|
if ((TEST_RETURN == -1) && (errno == ELOOP))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else {
|
|
|
|
tst_resm(TFAIL, "%s errno:%d %s",
|
|
"Expected ELOOP error condition when chdir(2) a nested symbolic link:",
|
|
errno, strerror(errno));
|
|
chdir(TESTDIR);
|
|
}
|
|
}
|
|
else if (cktcsid(tc_ptr->tcid, LINK)) {
|
|
|
|
TEST ( link(tc_ptr->fn_arg[1], O_FILE) );
|
|
errno=TEST_ERRNO;
|
|
if ((TEST_RETURN == -1) && (errno == ELOOP))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s errno:%d %s",
|
|
"Expected ELOOP error condition when link(2) a nested symbolic link:",
|
|
errno, strerror(errno));
|
|
}
|
|
else if (cktcsid(tc_ptr->tcid, CHMOD)) {
|
|
|
|
TEST ( chmod(tc_ptr->fn_arg[1], MODE) );
|
|
errno=TEST_ERRNO;
|
|
if ((TEST_RETURN == -1) && (errno == ELOOP))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s errno:%d %s",
|
|
"Expected ELOOP error condition when chmod(2) a nested symbolic link:",
|
|
errno, strerror(errno));
|
|
return;
|
|
}
|
|
else if (cktcsid(tc_ptr->tcid, UTIME)) {
|
|
|
|
TEST( utime(tc_ptr->fn_arg[1], NULL) );
|
|
errno=TEST_ERRNO;
|
|
|
|
if ((TEST_RETURN == -1) && (errno == ELOOP))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s errno:%d %s",
|
|
"Expected ELOOP error condition when utime(2) a nested symbolic link:",
|
|
errno, strerror(errno));
|
|
}
|
|
else if (cktcsid(tc_ptr->tcid, OPEN)) {
|
|
|
|
int fd;
|
|
TEST( open(tc_ptr->fn_arg[1], O_CREAT) );
|
|
fd=TEST_RETURN;
|
|
errno=TEST_ERRNO;
|
|
if ((fd == -1) && (errno == ELOOP))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s errno:%d %s",
|
|
"Expected ELOOP error condition when open(2) a nested symbolic link:",
|
|
errno, strerror(errno));
|
|
}
|
|
else
|
|
tst_resm(TBROK, "Unknown test case processing actions declared");
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks for the return of ENOTDIR errno from requested
|
|
* system call
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_ENOTDIR(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
if (cktcsid(tc_ptr->tcid, RMDIR)) {
|
|
|
|
TEST( mkdir(tc_ptr->fn_arg[0], MODE) );
|
|
errno=TEST_ERRNO;
|
|
if (TEST_RETURN == -1)
|
|
tst_resm(TBROK, "mkdir(2) Failure when creating %s",
|
|
tc_ptr->fn_arg[0]);
|
|
else if ((rmdir(tc_ptr->fn_arg[1]) == -1) && (errno == ENOTDIR)) {
|
|
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
rmdir(tc_ptr->fn_arg[0]);
|
|
}
|
|
else
|
|
tst_resm(TFAIL, "%s %s errno:%d %s",
|
|
"Expected ENOTDIR error for removing a non-existent",
|
|
"directory through a symbolic link file was not received,",
|
|
errno, strerror(errno));
|
|
}
|
|
else
|
|
tst_resm(TBROK, "Unknown test case processing actions declared");
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks for the return of EXDEV errno from requested
|
|
* system call
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_EXDEV(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
if (cktcsid(tc_ptr->tcid, RENAME)) {
|
|
|
|
TEST( rename(tc_ptr->fn_arg[1], Y_A_S_FILE) );
|
|
errno=TEST_ERRNO;
|
|
if ((TEST_RETURN == -1) && (errno == EXDEV)) {
|
|
if (see_if_a_symlink(Y_A_S_FILE) == -1)
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s %s %s file outside of current file system",
|
|
"rename(3) returned -1 when trying to move symbolic link file",
|
|
"outside of current file system, but created", Y_A_S_FILE);
|
|
}
|
|
else {
|
|
tst_resm(TFAIL, "%s %s errno:%d %s",
|
|
"Expected EXDEV error for renaming an existing symbolic",
|
|
"link file to a location outside of existing file system,",
|
|
errno, strerror(errno));
|
|
delete_files("/NiCkEr", NULL);
|
|
}
|
|
}
|
|
else
|
|
tst_resm(TBROK, "Unknown test case processing actions declared");
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks for the return of ENAMETOOLONG errno from requested
|
|
* system call
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_ENAMETOOLONG(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
int ret;
|
|
|
|
if (cktcsid(tc_ptr->tcid, SYMLINK)) {
|
|
|
|
TEST( symlink(tc_ptr->fn_arg[0], full_path) );
|
|
errno=TEST_ERRNO;
|
|
if ((TEST_RETURN == -1) && (errno == ENAMETOOLONG))
|
|
if (see_if_a_symlink(full_path) == -1)
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s %s %d %s",
|
|
"symlink(2) returned -1 when trying to create a symbolic",
|
|
"link file whose name exceeded", (PATH_MAX+1),
|
|
"characters, but it created the symbolic link file");
|
|
else
|
|
tst_resm(TFAIL,
|
|
"Expected ENAMETOOLONG error when creating %s symbolic link file with a path exceeding %d characters: errno:%d %s",
|
|
tc_ptr->fn_arg[1], (PATH_MAX+1), errno, strerror(errno));
|
|
}
|
|
else if (cktcsid(tc_ptr->tcid, READLINK)) {
|
|
|
|
char scratch[PATH_MAX+1];
|
|
|
|
ret=readlink(full_path, scratch, strlen(full_path));
|
|
if (( ret == -1) && (errno == ENAMETOOLONG))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL,
|
|
"Expected ENAMETOOLONG error when reading %s symbolic link file with a path exceeding %d characters: errno:%d %s",
|
|
tc_ptr->fn_arg[1], (PATH_MAX+1), errno, strerror(errno));
|
|
}
|
|
else
|
|
tst_resm(TBROK, "Unknown test case processing actions declared");
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks for the return of EINVAL errno from requested
|
|
* system call
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_EINVAL(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
if (cktcsid(tc_ptr->tcid, READLINK)) {
|
|
TEST( readlink(tc_ptr->fn_arg[0], test_msg, BUFMAX) );
|
|
errno=TEST_ERRNO;
|
|
if (TEST_RETURN == -1) {
|
|
if (errno == EINVAL) {
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
} else
|
|
tst_resm(TFAIL, "readlink(2) ret:-1, errno:%d, : Exp errno:%d",
|
|
errno, EINVAL);
|
|
}
|
|
else {
|
|
tst_resm(TFAIL, "readlink(2) did not returned -1 when reading %s",
|
|
"a file which is not a symbolic link file");
|
|
}
|
|
}
|
|
else
|
|
tst_resm(TBROK, "Unknown test case processing actions declared");
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks out the readlink(2) system call for a successful
|
|
* invocation
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_readlink(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
char scratch[PATH_MAX];
|
|
int ret;
|
|
|
|
ret=readlink(tc_ptr->fn_arg[1], scratch, strlen(tc_ptr->fn_arg[0]));
|
|
|
|
/*** the TEST macro cannot be used here for some reason ****/
|
|
|
|
if (ret == -1) {
|
|
tst_resm(TFAIL,
|
|
"readlink(2) failure on %s symbolic link file, errno=%d",
|
|
tc_ptr->fn_arg[1], errno);
|
|
|
|
}
|
|
else if (strncmp(tc_ptr->fn_arg[0], scratch,
|
|
strlen(tc_ptr->fn_arg[0])) != 0) {
|
|
|
|
/* Must null terminate scratch because readlink(2) doesn't */
|
|
|
|
scratch[strlen(tc_ptr->fn_arg[0])] = '\0';
|
|
|
|
tst_resm(TFAIL,
|
|
"readlink(2) Error : Expected %s symbolic link file contents but %s actual contents were returned",
|
|
tc_ptr->fn_arg[0], scratch);
|
|
}
|
|
else if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks out the stat(2) system call for a successful
|
|
* invocation
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_stat(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
if (statter.st_dev != asymlink.st_dev)
|
|
tst_resm(TFAIL,
|
|
"stat of symbolic link reference to object device info %ld != stat of object file device info %ld",
|
|
statter.st_dev, asymlink.st_dev);
|
|
|
|
else if (statter.st_mode != asymlink.st_mode)
|
|
tst_resm(TFAIL,
|
|
"stat of symbolic link reference to object file permissions %ld != stat of object file permissions %ld",
|
|
statter.st_mode, asymlink.st_mode);
|
|
|
|
else if (statter.st_nlink != asymlink.st_nlink)
|
|
tst_resm(TFAIL,
|
|
"stat of symbolic link reference to object file link count %ld != stat of object file link count %ld",
|
|
statter.st_nlink, asymlink.st_nlink);
|
|
|
|
else if (statter.st_uid != asymlink.st_uid)
|
|
tst_resm(TFAIL,
|
|
"stat of symbolic link reference to object file uid %ld != stat of object file uid %ld",
|
|
statter.st_uid, asymlink.st_uid);
|
|
|
|
else if (statter.st_gid != asymlink.st_gid)
|
|
tst_resm(TFAIL,
|
|
"stat of symbolic link reference to object file gid %ld != stat of object file gid %ld",
|
|
statter.st_gid, asymlink.st_gid);
|
|
|
|
else if (statter.st_size != asymlink.st_size)
|
|
tst_resm(TFAIL,
|
|
"stat of symbolic link reference to object file size %ld != stat of object file size %ld",
|
|
statter.st_size, asymlink.st_size);
|
|
|
|
else if (statter.st_atime != asymlink.st_atime)
|
|
tst_resm(TFAIL,
|
|
"stat of symbolic link reference to object access time %ld != stat of object file access time %ld",
|
|
statter.st_atime, asymlink.st_atime);
|
|
|
|
else if (statter.st_mtime != asymlink.st_mtime)
|
|
tst_resm(TFAIL,
|
|
"stat of symbolic link reference to object modify time %ld != stat of object file modify time %ld",
|
|
statter.st_atime, asymlink.st_atime);
|
|
|
|
else if (statter.st_ctime != asymlink.st_ctime)
|
|
tst_resm(TFAIL,
|
|
"stat of symbolic link reference to object change time %ld != stat of object file change time %ld",
|
|
statter.st_atime, asymlink.st_atime);
|
|
else if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks out the chdir(2) system call for a successful
|
|
* invocation
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_chdir(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
if (mkdir(tc_ptr->fn_arg[2],MODE) == -1)
|
|
tst_resm(TFAIL, "Could not create a setup directory file");
|
|
else {
|
|
|
|
sprintf(Buf, "mkdir(%s, %#o) was successful\n", tc_ptr->fn_arg[2],MODE);
|
|
strcat(Buffer, Buf);
|
|
|
|
if (chdir(tc_ptr->fn_arg[1]) == -1)
|
|
tst_resm(TFAIL, "%sCould not change a directory file through a %s",
|
|
Buffer, "symbolic link which which pointed at object");
|
|
else {
|
|
|
|
char *cwd, *getcwd();
|
|
char expected_location[PATH_MAX];
|
|
/*
|
|
* Build expected current directory position
|
|
*/
|
|
strcpy(expected_location, TESTDIR);
|
|
strcat(expected_location, "/");
|
|
strcat(expected_location, tc_ptr->fn_arg[2]);
|
|
|
|
if ((cwd = getcwd((char *)NULL, 64)) == NULL)
|
|
tst_resm(TFAIL, "getcwd(3) FAILURE");
|
|
else if (strcmp(cwd, expected_location) == 0)
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else {
|
|
tst_resm(TFAIL, "%s%s %s %s not equal to expected %s", Buffer,
|
|
"chdir(2) returned successfully, but getcwd(3) indicated",
|
|
"new current working directory location", cwd, expected_location);
|
|
}
|
|
chdir(TESTDIR);
|
|
}
|
|
rmdir(tc_ptr->fn_arg[2]);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks out the link(2) system call for a successful
|
|
* invocation
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_link(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
struct stat stbuf;
|
|
|
|
if (link(tc_ptr->fn_arg[1], "nick") == -1) {
|
|
tst_resm(TFAIL, "%slink(%s, \"nick\") failed, errno: %d\n%s %s",
|
|
Buffer, tc_ptr->fn_arg[1], errno,
|
|
"link of new file to object file via symbolic link file failed",
|
|
"when expected not to");
|
|
}
|
|
else {
|
|
sprintf(Buf, "link(%s, \"nick\") was successful\n", tc_ptr->fn_arg[1]);
|
|
strcat(Buffer, Buf);
|
|
|
|
if ( STD_FUNCTIONAL_TEST ) {
|
|
/*
|
|
* Check that links counts were properly set
|
|
*/
|
|
if (lstat(tc_ptr->fn_arg[1], &asymlink) == -1) {
|
|
tst_resm(TBROK, "lstat(%s) failed. errno: %d",
|
|
tc_ptr->fn_arg[1], errno);
|
|
|
|
} else if (lstat("nick", &statter) == -1) {
|
|
tst_resm(TBROK, "lstat(nick) failed, errno:%d", errno);
|
|
} else {
|
|
if (statter.st_ino == asymlink.st_ino) {
|
|
if ((statter.st_nlink ==2) && (asymlink.st_nlink == 2)) {
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
} else {
|
|
lstat(tc_ptr->fn_arg[2], &stbuf);
|
|
|
|
tst_resm(TFAIL,
|
|
"%slink(%s, %s) failed to adjust link count.\n\
|
|
count for nick is %d, count for %s is %d, count for %s is %d.",
|
|
Buffer, tc_ptr->fn_arg[1], "nick",
|
|
statter.st_nlink, tc_ptr->fn_arg[1], asymlink.st_nlink,
|
|
tc_ptr->fn_arg[2], stbuf.st_nlink);
|
|
}
|
|
} else {
|
|
tst_resm(TFAIL,
|
|
"%sA lstat of %s (ino:%d) and of\n\t\t\
|
|
%s (ino:%d), does not show them being the same ino.", Buffer,
|
|
tc_ptr->fn_arg[1], asymlink.st_ino, "nick", statter.st_ino);
|
|
}
|
|
}
|
|
}
|
|
delete_files("nick", NULL);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks out the unlink(2) system call for a successful
|
|
* invocation
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_unlink(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
if (stat(tc_ptr->fn_arg[2], &asymlink) == -1)
|
|
tst_resm(TBROK,
|
|
"stat(2) Failure when accessing %s object file", tc_ptr->fn_arg[2]);
|
|
else if (unlink(tc_ptr->fn_arg[1]) == -1)
|
|
tst_resm(TFAIL, "unlink(2) failed when removing symbolic link file");
|
|
else {
|
|
sprintf(Buf, "unlink(%s) was successful\n", tc_ptr->fn_arg[1]);
|
|
strcat(Buffer, Buf);
|
|
if (stat(tc_ptr->fn_arg[2], &statter) == -1)
|
|
tst_resm(TFAIL,"%s %s",
|
|
"unlink(2) failed because it not only removed symbolic link",
|
|
"file which pointed at object file, but object file as well");
|
|
|
|
else
|
|
if ((statter.st_ino == asymlink.st_ino) &&
|
|
(statter.st_dev == asymlink.st_dev) &&
|
|
(statter.st_size == asymlink.st_size))
|
|
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s%s %s %s", Buffer,
|
|
"unlink(2) failed because it not only removed symbolic link",
|
|
"file which pointed at object file, but it changed object",
|
|
"file inode information");
|
|
}
|
|
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks out the chmod(2) system call for a successful
|
|
* invocation
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_chmod(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
if (stat(tc_ptr->fn_arg[2], &asymlink) == -1)
|
|
tst_resm(TBROK,
|
|
"stat(2) Failure when accessing %s object file", tc_ptr->fn_arg[2]);
|
|
else if (chmod(tc_ptr->fn_arg[1], (MODE | MASK)) == -1)
|
|
tst_resm(TFAIL, "%s%s %s", Buffer,
|
|
"chmod(2) failed when changing file permission",
|
|
"through symbolic link file");
|
|
else {
|
|
sprintf(Buf, "chmod(%s, %#o) was successful\n", tc_ptr->fn_arg[1],
|
|
(MODE | MASK));
|
|
strcat(Buffer, Buf);
|
|
|
|
if (stat(tc_ptr->fn_arg[2], &statter) == -1)
|
|
tst_resm(TBROK,
|
|
"stat(2) Failure when accessing %s object file", tc_ptr->fn_arg[2]);
|
|
else
|
|
if ((statter.st_mode == (MODE | MASK)) &&
|
|
(statter.st_mode != asymlink.st_mode))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s%s %o to %o %s", Buffer,
|
|
"chmod(2) failed to change object file permissions from",
|
|
asymlink.st_mode, (MODE | MASK),
|
|
"through symbolic link file");
|
|
}
|
|
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks out the utime(2) system call for a successful
|
|
* invocation
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_utime(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
struct utimbuf utimes;
|
|
|
|
if (stat(tc_ptr->fn_arg[2], &asymlink) == -1)
|
|
tst_resm(TBROK, "stat(2) Failure when accessing %s object file",
|
|
tc_ptr->fn_arg[2]);
|
|
else {
|
|
/* Now add a few values to access and modify times */
|
|
|
|
utimes.actime = asymlink.st_atime + a_time_value;
|
|
utimes.modtime = asymlink.st_mtime + a_time_value;
|
|
|
|
/* Now hand off to utime(2) via symbolic link file*/
|
|
|
|
if (utime(tc_ptr->fn_arg[1], &utimes) == -1)
|
|
tst_resm(TFAIL, "%s %s",
|
|
"utime(2) failed to process object file access and modify",
|
|
"time updates through symbolic link");
|
|
else {
|
|
/* Now verify changes were made */
|
|
|
|
if (stat(tc_ptr->fn_arg[2], &statter) == -1)
|
|
tst_resm(TBROK,
|
|
"stat(2) Failure when accessing %s object file",
|
|
tc_ptr->fn_arg[2]);
|
|
else {
|
|
time_t temp, diff;
|
|
|
|
temp = statter.st_atime - asymlink.st_atime;
|
|
diff = (statter.st_mtime - asymlink.st_mtime) - temp;
|
|
|
|
if (! diff)
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, "%s %s %d greater than original times",
|
|
"utime(2) failed to change object file access and",
|
|
"modify times through symbolic link to a value",
|
|
a_time_value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks out the rename(2) system call for a successful
|
|
* invocation
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_rename(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
int pts_at_object = 0;
|
|
|
|
|
|
if (stat(tc_ptr->fn_arg[2], &statter) != -1)
|
|
pts_at_object=1;
|
|
|
|
TEST (rename(tc_ptr->fn_arg[1], A_S_FILE) );
|
|
errno=TEST_ERRNO;
|
|
if (TEST_RETURN == -1)
|
|
tst_resm(TFAIL, "rename(3) failed to rename %s symbolic link file to %s",
|
|
tc_ptr->fn_arg[2], A_S_FILE);
|
|
else if (pts_at_object)
|
|
if (ck_both(tc_ptr->fn_arg[0], A_S_FILE, tc_ptr->fn_arg[2]))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, test_msg);
|
|
else if ( ! ck_symlink(tc_ptr->fn_arg[0], A_S_FILE, NULL))
|
|
tst_resm(TFAIL, test_msg);
|
|
else if (stat(tc_ptr->fn_arg[1], &asymlink) != -1)
|
|
tst_resm(TFAIL,
|
|
"rename(3) did not remove %s when renaming to %s",
|
|
tc_ptr->fn_arg[1], A_S_FILE);
|
|
else if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* This routine checks out the open(2) system call for a successful
|
|
* invocation
|
|
*
|
|
* Argument is pointer to test_objects array of structures of type
|
|
* all_test_cases
|
|
***********************************************************************/
|
|
void
|
|
do_open(tc_ptr)
|
|
struct all_test_cases *tc_ptr;
|
|
{
|
|
int fd = -1;
|
|
int ret, pts_at_object = 0;
|
|
char scratch[PATH_MAX];
|
|
|
|
|
|
if (stat(tc_ptr->fn_arg[2], &statter) != -1)
|
|
pts_at_object=1;
|
|
|
|
if (pts_at_object) {
|
|
TEST( open(tc_ptr->fn_arg[1], O_RDWR) );
|
|
errno=TEST_ERRNO;
|
|
if ((fd=TEST_RETURN) == -1) {
|
|
tst_resm(TFAIL,
|
|
"open(2) Failure when opening object file through symbolic link file");
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
TEST(open(tc_ptr->fn_arg[1], (O_CREAT | O_RDWR), MODE) );
|
|
errno=TEST_ERRNO;
|
|
if ((fd=TEST_RETURN) == -1) {
|
|
tst_resm(TFAIL,
|
|
"open(2) Failure when creating object file through symbolic link file");
|
|
return;
|
|
}
|
|
}
|
|
if ((ret=write(fd, BIG_STRING, strlen(BIG_STRING))) == -1) {
|
|
tst_resm(TFAIL,
|
|
"write(2) Failure to object file opened through a symbolic link file: errno:%d",
|
|
errno);
|
|
}
|
|
else if (ret != strlen(BIG_STRING)) {
|
|
tst_resm(TFAIL,
|
|
"write(2) Failed to write %d bytes to object file opened through a symbolic link file",
|
|
strlen(BIG_STRING));
|
|
}
|
|
else if (lseek(fd, 0L, 0) == -1) {
|
|
tst_resm(TFAIL,
|
|
"lseek(2) Failed to position to beginning of object file opened through a symbolic link file: errno = %d",
|
|
errno);
|
|
}
|
|
else if ((ret=read(fd, scratch, strlen(BIG_STRING))) == -1) {
|
|
tst_resm(TFAIL,
|
|
"read(2) Failure of object file opened through a symbolic link file: errno = %d",
|
|
errno);
|
|
}
|
|
else if (ret != strlen(BIG_STRING)) {
|
|
tst_resm(TFAIL,
|
|
"read(2) Failed to read %d bytes to object file opened through a symbolic link file",
|
|
strlen(BIG_STRING));
|
|
}
|
|
else if (strncmp(BIG_STRING, scratch, strlen(BIG_STRING)) != 0) {
|
|
tst_resm(TFAIL,
|
|
"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",
|
|
BIG_STRING, scratch);
|
|
}
|
|
else {
|
|
/*
|
|
* Close off symbolic link file to object file access
|
|
*/
|
|
if (close(fd) == -1) {
|
|
tst_resm(TFAIL,
|
|
"close(2) Failure when closing object file accessed symbolic link file");
|
|
}
|
|
/*
|
|
* Now, lets open up and read object file and compare contents
|
|
*/
|
|
else if ((fd=open(tc_ptr->fn_arg[0], O_RDONLY)) == -1) {
|
|
tst_resm(TFAIL, "open(2) Failure when opening %s file: errno:%d %s",
|
|
tc_ptr->fn_arg[0], errno, strerror(errno));
|
|
}
|
|
else if ((ret=read(fd, scratch, strlen(BIG_STRING))) == -1) {
|
|
tst_resm(TFAIL,
|
|
"read(2) Failure of object file opened through a symbolic link file: errno:%d", errno);
|
|
}
|
|
else if (ret != strlen(BIG_STRING)) {
|
|
tst_resm(TFAIL,
|
|
"read(2) Failed to read %d bytes to object file opened through a symbolic link file",
|
|
strlen(BIG_STRING));
|
|
}
|
|
else if (strncmp(BIG_STRING, scratch, strlen(BIG_STRING)) != 0) {
|
|
tst_resm(TFAIL,
|
|
"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",
|
|
BIG_STRING, scratch);
|
|
}
|
|
else if (pts_at_object) {
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
}
|
|
else { /* Insure newly created object file is pointed at */
|
|
if (ck_both(tc_ptr->fn_arg[0], tc_ptr->fn_arg[1], tc_ptr->fn_arg[0]))
|
|
if ( TEST_RESULT != TPASS || STD_FUNCTIONAL_TEST )
|
|
tst_resm(TEST_RESULT, msgs[tc_ptr->pass_msg]);
|
|
else
|
|
Tst_count++;
|
|
else
|
|
tst_resm(TFAIL, test_msg);
|
|
}
|
|
close(fd);
|
|
}
|
|
}
|
|
|
|
/***************************************************************
|
|
* setup() - performs all ONE TIME setup for this test.
|
|
***************************************************************/
|
|
void
|
|
setup()
|
|
{
|
|
/* capture signals */
|
|
tst_sig(FORK, DEF_HANDLER, cleanup);
|
|
|
|
/* create a temporary directory and go to it */
|
|
tst_tmpdir();
|
|
|
|
/* Pause if that option was specified */
|
|
TEST_PAUSE;
|
|
|
|
} /* End setup() */
|
|
|
|
|
|
/***************************************************************
|
|
* cleanup() - performs all ONE TIME cleanup for this test at
|
|
* completion or premature exit.
|
|
***************************************************************/
|
|
void
|
|
cleanup()
|
|
{
|
|
/*
|
|
* print timing stats if that option was specified.
|
|
*/
|
|
TEST_CLEANUP;
|
|
|
|
/* remove temporary directory and all files in it. */
|
|
tst_rmdir();
|
|
|
|
/* exit with return code appropriate for results */
|
|
tst_exit();
|
|
|
|
} /* End cleanup() */
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
void help()
|
|
{
|
|
int ind;
|
|
|
|
printf(" -T id Determines which tests cases to execute:\n");
|
|
|
|
for (ind=0; ind<sizeof(all_tcses)/sizeof(struct tcses ); ind++) {
|
|
printf(" %s/%s - %s\n", all_tcses[ind].tcid, all_tcses[ind].syscall,
|
|
all_tcses[ind].desc);
|
|
}
|
|
}
|