lstat03.c revision 7d0a4a57fbcd47f72b67c08df532e8ef47f6fdae
1/* 2 * 3 * Copyright (c) International Business Machines Corp., 2001 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 */ 19 20/* 21 * Test Name: lstat03 22 * 23 * Test Description: 24 * Verify that, lstat(2) succeeds to get the status of a file pointed to by 25 * symlink and fills the stat structure elements. 26 * 27 * Expected Result: 28 * lstat() should return value 0 on success and the stat structure elements 29 * should be filled with the symlink file information. 30 * 31 * Algorithm: 32 * Setup: 33 * Setup signal handling. 34 * Create temporary directory. 35 * Pause for SIGUSR1 if option specified. 36 * 37 * Test: 38 * Loop if the proper options are given. 39 * Execute system call 40 * Check return code, if system call failed (return=-1) 41 * Log the errno and Issue a FAIL message. 42 * Otherwise, 43 * Verify the Functionality of system call 44 * if successful, 45 * Issue Functionality-Pass message. 46 * Otherwise, 47 * Issue Functionality-Fail message. 48 * Cleanup: 49 * Print errno log and/or timing stats if options given 50 * Delete the temporary directory created. 51 * 52 * Usage: <for command-line> 53 * lstat03 [-c n] [-f] [-i n] [-I x] [-P x] [-t] 54 * where, -c n : Run n copies concurrently. 55 * -f : Turn off functionality Testing. 56 * -i n : Execute test n times. 57 * -I x : Execute test for x seconds. 58 * -P x : Pause for x seconds between iterations. 59 * -t : Turn on syscall timing. 60 * 61 * HISTORY 62 * 07/2001 Ported by Wayne Boyer 63 * 64 * RESTRICTIONS: 65 * This test should be run by 'non-super-user' only. 66 * 67 */ 68#include <stdio.h> 69#include <sys/types.h> 70#include <sys/fcntl.h> 71#include <sys/stat.h> 72#include <errno.h> 73#include <string.h> 74#include <signal.h> 75#include <pwd.h> 76 77#include "test.h" 78#include "usctest.h" 79 80#define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH 81#define TESTFILE "testfile" 82#define SFILE "sfile" 83#define FILE_SIZE 1024 84#define BUF_SIZE 256 85#define PERMS 0644 86 87char *TCID = "lstat03"; /* Test program identifier. */ 88int TST_TOTAL = 1; /* Total number of test cases. */ 89extern int Tst_count; /* Test Case counter for tst_* routines */ 90uid_t user_id; /* user id/group id of test process */ 91gid_t group_id; 92 93char nobody_uid[] = "nobody"; 94struct passwd *ltpuser; 95 96void setup(); /* Setup function for the test */ 97void cleanup(); /* Cleanup function for the test */ 98 99int main(int ac, char **av) 100{ 101 struct stat stat_buf; /* stat structure buffer */ 102 int lc; /* loop counter */ 103 char *msg; /* message returned from parse_opts */ 104 105 /* Parse standard options given to run the test. */ 106 msg = parse_opts(ac, av, NULL, NULL); 107 if (msg != NULL) { 108 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); 109 110 } 111 112 setup(); 113 114 for (lc = 0; TEST_LOOPING(lc); lc++) { 115 116 Tst_count = 0; 117 118 /* 119 * Call lstat(2) to get the status of 120 * symlink file into stat structure. 121 */ 122 TEST(lstat(SFILE, &stat_buf)); 123 124 if (TEST_RETURN == -1) { 125 tst_resm(TFAIL, 126 "lstat(%s, &stat_buf) Failed, errno=%d : %s", 127 SFILE, TEST_ERRNO, strerror(TEST_ERRNO)); 128 continue; 129 } 130 /* 131 * Perform functional verification if test 132 * executed without (-f) option. 133 */ 134 if (STD_FUNCTIONAL_TEST) { 135 /* 136 * Verify the data returned by lstat(2) 137 * aganist the expected data. 138 */ 139 if ((stat_buf.st_uid != user_id) || 140 (stat_buf.st_gid != group_id) || 141 (!(stat_buf.st_mode && S_IFLNK)) || 142 (stat_buf.st_size != strlen(TESTFILE))) { 143 tst_resm(TFAIL, "Functionality of lstat(2) on " 144 "'%s' Failed", SFILE); 145 } else { 146 tst_resm(TPASS, "Functionality of lstat(2) on " 147 "'%s' Succcessful", SFILE); 148 } 149 } else { 150 tst_resm(TPASS, "call succeeded"); 151 } 152 } 153 154 cleanup(); 155 156} 157 158/* 159 * setup() - Performs setup function for the test. 160 * Creat a temporary directory and chdir to it. 161 * Creat a test file and write some known data into it. 162 * Close the test file and creat a symlink of test file under 163 * temporary directory. 164 * Get uid/gid of test process. 165 */ 166void setup() 167{ 168 int i, fd; /* file handle for test file */ 169 char tst_buff[BUF_SIZE]; /* data buffer */ 170 int wbytes; /* no. of bytes to be written */ 171 int write_len = 0; /* size of data */ 172 173 tst_sig(NOFORK, DEF_HANDLER, cleanup); 174 175 /* Switch to nobody user for correct error code collection */ 176 if (geteuid() != 0) { 177 tst_brkm(TBROK, NULL, "Test must be run as root"); 178 } 179 ltpuser = getpwnam(nobody_uid); 180 if (setuid(ltpuser->pw_uid) == -1) { 181 tst_resm(TINFO, "setuid failed to " 182 "to set the effective uid to %d", ltpuser->pw_uid); 183 perror("setuid"); 184 } 185 186 TEST_PAUSE; 187 188 tst_tmpdir(); 189 190 if ((fd = open(TESTFILE, O_RDWR | O_CREAT, FILE_MODE)) == -1) { 191 tst_brkm(TBROK, cleanup, 192 "open(%s, O_RDWR|O_CREAT, %#o) Failed, errno=%d : %s", 193 TESTFILE, FILE_MODE, errno, strerror(errno)); 194 } 195 196 /* Fill the test buffer with the known data */ 197 for (i = 0; i < BUF_SIZE; i++) { 198 tst_buff[i] = 'a'; 199 } 200 201 /* Write to the file 1k data from the buffer */ 202 while (write_len < FILE_SIZE) { 203 if ((wbytes = write(fd, tst_buff, sizeof(tst_buff))) <= 0) { 204 tst_brkm(TBROK, cleanup, 205 "write(2) on %s Failed, errno=%d : %s", 206 TESTFILE, errno, strerror(errno)); 207 } else { 208 write_len += wbytes; 209 } 210 } 211 212 if (close(fd) == -1) { 213 tst_resm(TWARN, "close(%s) Failed, errno=%d : %s", 214 TESTFILE, errno, strerror(errno)); 215 } 216 217 /* Create a symlink of testfile */ 218 if (symlink(TESTFILE, SFILE) < 0) { 219 tst_brkm(TBROK, cleanup, "symlink() of %s Failed, errno=%d : " 220 "%s", TESTFILE, errno, strerror(errno)); 221 } 222 223 /* Get the uid/gid of the process */ 224 user_id = getuid(); 225 group_id = getgid(); 226} 227 228/* 229 * cleanup() - performs all ONE TIME cleanup for this test at 230 * completion or premature exit. 231 * Remove the symlink file, test file and temporary directory. 232 */ 233void cleanup() 234{ 235 /* 236 * print timing stats if that option was specified. 237 * print errno log if that option was specified. 238 */ 239 TEST_CLEANUP; 240 241 tst_rmdir(); 242 243}