1f08c3bdfSopenharmony_ci/****************************************************************************** 2f08c3bdfSopenharmony_ci * 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2006 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 6f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 7f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 8f08c3bdfSopenharmony_ci * (at your option) any later version. 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 11f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 12f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13f08c3bdfSopenharmony_ci * the GNU General Public License for more details. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 16f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 17f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18f08c3bdfSopenharmony_ci * 19f08c3bdfSopenharmony_ci * NAME 20f08c3bdfSopenharmony_ci * linkat01.c 21f08c3bdfSopenharmony_ci * 22f08c3bdfSopenharmony_ci * DESCRIPTION 23f08c3bdfSopenharmony_ci * This test case will verify basic function of linkat 24f08c3bdfSopenharmony_ci * added by kernel 2.6.16 or up. 25f08c3bdfSopenharmony_ci * 26f08c3bdfSopenharmony_ci * USAGE: <for command-line> 27f08c3bdfSopenharmony_ci * linkat01 [-c n] [-e] [-i n] [-I x] [-P x] [-t] [-p] 28f08c3bdfSopenharmony_ci * where: 29f08c3bdfSopenharmony_ci * -c n : Run n copies simultaneously. 30f08c3bdfSopenharmony_ci * -e : Turn on errno logging. 31f08c3bdfSopenharmony_ci * -i n : Execute test n times. 32f08c3bdfSopenharmony_ci * -I x : Execute test for x seconds. 33f08c3bdfSopenharmony_ci * -p : Pause for SIGUSR1 before starting 34f08c3bdfSopenharmony_ci * -P x : Pause for x seconds between iterations. 35f08c3bdfSopenharmony_ci * -t : Turn on syscall timing. 36f08c3bdfSopenharmony_ci * 37f08c3bdfSopenharmony_ci * Author 38f08c3bdfSopenharmony_ci * Yi Yang <yyangcdl@cn.ibm.com> 39f08c3bdfSopenharmony_ci * 40f08c3bdfSopenharmony_ci * History 41f08c3bdfSopenharmony_ci * 08/25/2006 Created first by Yi Yang <yyangcdl@cn.ibm.com> 42f08c3bdfSopenharmony_ci * 43f08c3bdfSopenharmony_ci *****************************************************************************/ 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_ci#define _GNU_SOURCE 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ci#include <sys/types.h> 48f08c3bdfSopenharmony_ci#include <sys/stat.h> 49f08c3bdfSopenharmony_ci#include <sys/time.h> 50f08c3bdfSopenharmony_ci#include <fcntl.h> 51f08c3bdfSopenharmony_ci#include <unistd.h> 52f08c3bdfSopenharmony_ci#include <stdlib.h> 53f08c3bdfSopenharmony_ci#include <errno.h> 54f08c3bdfSopenharmony_ci#include <string.h> 55f08c3bdfSopenharmony_ci#include <signal.h> 56f08c3bdfSopenharmony_ci#include <inttypes.h> 57f08c3bdfSopenharmony_ci#include <limits.h> 58f08c3bdfSopenharmony_ci#include "test.h" 59f08c3bdfSopenharmony_ci#include "lapi/syscalls.h" 60f08c3bdfSopenharmony_ci#include "safe_macros.h" 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci#ifndef AT_FDCWD 63f08c3bdfSopenharmony_ci#define AT_FDCWD -100 64f08c3bdfSopenharmony_ci#endif 65f08c3bdfSopenharmony_ci#ifndef AT_SYMLINK_FOLLOW 66f08c3bdfSopenharmony_ci#define AT_SYMLINK_FOLLOW 0x400 67f08c3bdfSopenharmony_ci#endif 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_cistruct test_struct; 70f08c3bdfSopenharmony_cistatic void setup(); 71f08c3bdfSopenharmony_cistatic void cleanup(); 72f08c3bdfSopenharmony_cistatic void setup_every_copy(); 73f08c3bdfSopenharmony_cistatic void mylinkat_test(struct test_struct *desc); 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci#define TEST_DIR1 "olddir" 76f08c3bdfSopenharmony_ci#define TEST_DIR2 "newdir" 77f08c3bdfSopenharmony_ci#define TEST_DIR3 "deldir" 78f08c3bdfSopenharmony_ci#define TEST_FILE1 "oldfile" 79f08c3bdfSopenharmony_ci#define TEST_FILE2 "newfile" 80f08c3bdfSopenharmony_ci#define TEST_FIFO "fifo" 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_ci#define DPATHNAME_FMT "%s/" TEST_DIR2 "/" TEST_FILE1 83f08c3bdfSopenharmony_ci#define SPATHNAME_FMT "%s/" TEST_DIR1 "/" TEST_FILE1 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_cistatic char dpathname[PATH_MAX]; 86f08c3bdfSopenharmony_cistatic char spathname[PATH_MAX]; 87f08c3bdfSopenharmony_cistatic int olddirfd, newdirfd = -1, cwd_fd = AT_FDCWD, stdinfd = 0, badfd = 88f08c3bdfSopenharmony_ci -1, deldirfd; 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_cistruct test_struct { 91f08c3bdfSopenharmony_ci int *oldfd; 92f08c3bdfSopenharmony_ci const char *oldfn; 93f08c3bdfSopenharmony_ci int *newfd; 94f08c3bdfSopenharmony_ci const char *newfn; 95f08c3bdfSopenharmony_ci int flags; 96f08c3bdfSopenharmony_ci const char *referencefn1; 97f08c3bdfSopenharmony_ci const char *referencefn2; 98f08c3bdfSopenharmony_ci int expected_errno; 99f08c3bdfSopenharmony_ci} test_desc[] = { 100f08c3bdfSopenharmony_ci /* 1. relative paths */ 101f08c3bdfSopenharmony_ci { 102f08c3bdfSopenharmony_ci &olddirfd, TEST_FILE1, &newdirfd, TEST_FILE1, 0, 103f08c3bdfSopenharmony_ci TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0}, 104f08c3bdfSopenharmony_ci /* 2. abs path at source */ 105f08c3bdfSopenharmony_ci { 106f08c3bdfSopenharmony_ci &olddirfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0}, 107f08c3bdfSopenharmony_ci /* 3. abs path at dst */ 108f08c3bdfSopenharmony_ci { 109f08c3bdfSopenharmony_ci &olddirfd, TEST_FILE1, &newdirfd, dpathname, 0, 110f08c3bdfSopenharmony_ci TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0}, 111f08c3bdfSopenharmony_ci /* 4. relative paths to cwd */ 112f08c3bdfSopenharmony_ci { 113f08c3bdfSopenharmony_ci &cwd_fd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0, 114f08c3bdfSopenharmony_ci TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0}, 115f08c3bdfSopenharmony_ci /* 5. relative paths to cwd */ 116f08c3bdfSopenharmony_ci { 117f08c3bdfSopenharmony_ci &olddirfd, TEST_FILE1, &cwd_fd, TEST_DIR2 "/" TEST_FILE1, 0, 118f08c3bdfSopenharmony_ci TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0}, 119f08c3bdfSopenharmony_ci /* 6. abs path at source */ 120f08c3bdfSopenharmony_ci { 121f08c3bdfSopenharmony_ci &cwd_fd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0}, 122f08c3bdfSopenharmony_ci /* 7. abs path at dst */ 123f08c3bdfSopenharmony_ci { 124f08c3bdfSopenharmony_ci &olddirfd, TEST_FILE1, &cwd_fd, dpathname, 0, 125f08c3bdfSopenharmony_ci TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0}, 126f08c3bdfSopenharmony_ci /* 8. relative paths to invalid */ 127f08c3bdfSopenharmony_ci { 128f08c3bdfSopenharmony_ci &stdinfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0, 129f08c3bdfSopenharmony_ci 0, 0, ENOTDIR}, 130f08c3bdfSopenharmony_ci /* 9. relative paths to invalid */ 131f08c3bdfSopenharmony_ci { 132f08c3bdfSopenharmony_ci &olddirfd, TEST_FILE1, &stdinfd, TEST_DIR2 "/" TEST_FILE1, 0, 133f08c3bdfSopenharmony_ci 0, 0, ENOTDIR}, 134f08c3bdfSopenharmony_ci /* 10. abs path at source */ 135f08c3bdfSopenharmony_ci { 136f08c3bdfSopenharmony_ci &stdinfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0}, 137f08c3bdfSopenharmony_ci /* 11. abs path at dst */ 138f08c3bdfSopenharmony_ci { 139f08c3bdfSopenharmony_ci &olddirfd, TEST_FILE1, &stdinfd, dpathname, 0, 140f08c3bdfSopenharmony_ci TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0}, 141f08c3bdfSopenharmony_ci /* 12. relative paths to bad */ 142f08c3bdfSopenharmony_ci { 143f08c3bdfSopenharmony_ci &badfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0, 144f08c3bdfSopenharmony_ci 0, 0, EBADF}, 145f08c3bdfSopenharmony_ci /* 13. relative paths to bad */ 146f08c3bdfSopenharmony_ci { 147f08c3bdfSopenharmony_ci &olddirfd, TEST_FILE1, &badfd, TEST_DIR2 "/" TEST_FILE1, 0, 148f08c3bdfSopenharmony_ci 0, 0, EBADF}, 149f08c3bdfSopenharmony_ci /* 14. abs path at source */ 150f08c3bdfSopenharmony_ci { 151f08c3bdfSopenharmony_ci &badfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0}, 152f08c3bdfSopenharmony_ci /* 15. abs path at dst */ 153f08c3bdfSopenharmony_ci { 154f08c3bdfSopenharmony_ci &olddirfd, TEST_FILE1, &badfd, dpathname, 0, 155f08c3bdfSopenharmony_ci TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0}, 156f08c3bdfSopenharmony_ci /* 16. relative paths to deleted */ 157f08c3bdfSopenharmony_ci { 158f08c3bdfSopenharmony_ci &deldirfd, TEST_DIR1 "/" TEST_FILE1, &newdirfd, TEST_FILE1, 0, 159f08c3bdfSopenharmony_ci 0, 0, ENOENT}, 160f08c3bdfSopenharmony_ci /* 17. relative paths to deleted */ 161f08c3bdfSopenharmony_ci { 162f08c3bdfSopenharmony_ci &olddirfd, TEST_FILE1, &deldirfd, TEST_DIR2 "/" TEST_FILE1, 0, 163f08c3bdfSopenharmony_ci 0, 0, ENOENT}, 164f08c3bdfSopenharmony_ci /* 18. abs path at source */ 165f08c3bdfSopenharmony_ci { 166f08c3bdfSopenharmony_ci &deldirfd, spathname, &newdirfd, TEST_FILE1, 0, 0, 0, 0}, 167f08c3bdfSopenharmony_ci /* 19. abs path at dst */ 168f08c3bdfSopenharmony_ci { 169f08c3bdfSopenharmony_ci &olddirfd, TEST_FILE1, &deldirfd, dpathname, 0, 170f08c3bdfSopenharmony_ci TEST_DIR1 "/" TEST_FILE1, TEST_DIR2 "/" TEST_FILE1, 0}, 171f08c3bdfSopenharmony_ci /* 20. x-device link */ 172f08c3bdfSopenharmony_ci { 173f08c3bdfSopenharmony_ci &cwd_fd, "/proc/cpuinfo", &newdirfd, TEST_FILE1, 0, 0, 0, EXDEV}, 174f08c3bdfSopenharmony_ci /* 21. directory link */ 175f08c3bdfSopenharmony_ci { 176f08c3bdfSopenharmony_ci &olddirfd, ".", &newdirfd, TEST_FILE1, 0, 0, 0, EPERM}, 177f08c3bdfSopenharmony_ci /* 22. invalid flag */ 178f08c3bdfSopenharmony_ci { 179f08c3bdfSopenharmony_ci &olddirfd, TEST_FILE1, &newdirfd, TEST_FILE1, 1, 0, 0, EINVAL}, 180f08c3bdfSopenharmony_ci /* 23. fifo link */ 181f08c3bdfSopenharmony_ci /* XXX (garrcoop): Removed because it hangs the overall test. Need to 182f08c3bdfSopenharmony_ci * find a legitimate means to exercise this functionality, if in fact 183f08c3bdfSopenharmony_ci * it's a valid testcase -- which it should be. 184f08c3bdfSopenharmony_ci */ 185f08c3bdfSopenharmony_ci /* { &olddirfd, TEST_FIFO, &newdirfd, TEST_FILE1, 0, 186f08c3bdfSopenharmony_ci TEST_DIR1"/"TEST_FIFO, TEST_DIR2"/"TEST_FILE1, 0 } */ 187f08c3bdfSopenharmony_ci}; 188f08c3bdfSopenharmony_ci 189f08c3bdfSopenharmony_cichar *TCID = "linkat01"; 190f08c3bdfSopenharmony_ciint TST_TOTAL = sizeof(test_desc) / sizeof(*test_desc); 191f08c3bdfSopenharmony_ci 192f08c3bdfSopenharmony_cistatic int mylinkat(int olddirfd, const char *oldfilename, int newdirfd, 193f08c3bdfSopenharmony_ci const char *newfilename, int flags) 194f08c3bdfSopenharmony_ci{ 195f08c3bdfSopenharmony_ci return tst_syscall(__NR_linkat, olddirfd, oldfilename, newdirfd, 196f08c3bdfSopenharmony_ci newfilename, flags); 197f08c3bdfSopenharmony_ci} 198f08c3bdfSopenharmony_ci 199f08c3bdfSopenharmony_ciint main(int ac, char **av) 200f08c3bdfSopenharmony_ci{ 201f08c3bdfSopenharmony_ci int lc; 202f08c3bdfSopenharmony_ci int i; 203f08c3bdfSopenharmony_ci 204f08c3bdfSopenharmony_ci tst_parse_opts(ac, av, NULL, NULL); 205f08c3bdfSopenharmony_ci 206f08c3bdfSopenharmony_ci setup(); 207f08c3bdfSopenharmony_ci 208f08c3bdfSopenharmony_ci for (lc = 0; TEST_LOOPING(lc); lc++) { 209f08c3bdfSopenharmony_ci 210f08c3bdfSopenharmony_ci tst_count = 0; 211f08c3bdfSopenharmony_ci 212f08c3bdfSopenharmony_ci for (i = 0; i < TST_TOTAL; i++) { 213f08c3bdfSopenharmony_ci setup_every_copy(); 214f08c3bdfSopenharmony_ci mylinkat_test(&test_desc[i]); 215f08c3bdfSopenharmony_ci } 216f08c3bdfSopenharmony_ci 217f08c3bdfSopenharmony_ci } 218f08c3bdfSopenharmony_ci 219f08c3bdfSopenharmony_ci cleanup(); 220f08c3bdfSopenharmony_ci tst_exit(); 221f08c3bdfSopenharmony_ci} 222f08c3bdfSopenharmony_ci 223f08c3bdfSopenharmony_cistatic void setup_every_copy(void) 224f08c3bdfSopenharmony_ci{ 225f08c3bdfSopenharmony_ci close(newdirfd); 226f08c3bdfSopenharmony_ci unlink(dpathname); 227f08c3bdfSopenharmony_ci rmdir(TEST_DIR2); 228f08c3bdfSopenharmony_ci 229f08c3bdfSopenharmony_ci SAFE_MKDIR(cleanup, TEST_DIR2, 0700); 230f08c3bdfSopenharmony_ci newdirfd = SAFE_OPEN(cleanup, TEST_DIR2, O_DIRECTORY); 231f08c3bdfSopenharmony_ci} 232f08c3bdfSopenharmony_ci 233f08c3bdfSopenharmony_cistatic void mylinkat_test(struct test_struct *desc) 234f08c3bdfSopenharmony_ci{ 235f08c3bdfSopenharmony_ci int fd; 236f08c3bdfSopenharmony_ci 237f08c3bdfSopenharmony_ci TEST(mylinkat 238f08c3bdfSopenharmony_ci (*desc->oldfd, desc->oldfn, *desc->newfd, desc->newfn, 239f08c3bdfSopenharmony_ci desc->flags)); 240f08c3bdfSopenharmony_ci 241f08c3bdfSopenharmony_ci if (TEST_ERRNO == desc->expected_errno) { 242f08c3bdfSopenharmony_ci if (TEST_RETURN == 0 && desc->referencefn1 != NULL) { 243f08c3bdfSopenharmony_ci int tnum = rand(), vnum = ~tnum; 244f08c3bdfSopenharmony_ci fd = SAFE_OPEN(cleanup, desc->referencefn1, 245f08c3bdfSopenharmony_ci O_RDWR); 246f08c3bdfSopenharmony_ci SAFE_WRITE(cleanup, SAFE_WRITE_ALL, fd, &tnum, 247f08c3bdfSopenharmony_ci sizeof(tnum)); 248f08c3bdfSopenharmony_ci SAFE_CLOSE(cleanup, fd); 249f08c3bdfSopenharmony_ci 250f08c3bdfSopenharmony_ci fd = SAFE_OPEN(cleanup, desc->referencefn2, 251f08c3bdfSopenharmony_ci O_RDONLY); 252f08c3bdfSopenharmony_ci SAFE_READ(cleanup, 1, fd, &vnum, sizeof(vnum)); 253f08c3bdfSopenharmony_ci SAFE_CLOSE(cleanup, fd); 254f08c3bdfSopenharmony_ci 255f08c3bdfSopenharmony_ci if (tnum == vnum) 256f08c3bdfSopenharmony_ci tst_resm(TPASS, 257f08c3bdfSopenharmony_ci "linkat is functionality correct"); 258f08c3bdfSopenharmony_ci else { 259f08c3bdfSopenharmony_ci tst_resm(TFAIL, 260f08c3bdfSopenharmony_ci "The link file's content isn't " 261f08c3bdfSopenharmony_ci "as same as the original file's " 262f08c3bdfSopenharmony_ci "although linkat returned 0"); 263f08c3bdfSopenharmony_ci } 264f08c3bdfSopenharmony_ci } else { 265f08c3bdfSopenharmony_ci if (TEST_RETURN == 0) 266f08c3bdfSopenharmony_ci tst_resm(TPASS, 267f08c3bdfSopenharmony_ci "linkat succeeded as expected"); 268f08c3bdfSopenharmony_ci else 269f08c3bdfSopenharmony_ci tst_resm(TPASS | TTERRNO, 270f08c3bdfSopenharmony_ci "linkat failed as expected"); 271f08c3bdfSopenharmony_ci } 272f08c3bdfSopenharmony_ci } else { 273f08c3bdfSopenharmony_ci if (TEST_RETURN == 0) 274f08c3bdfSopenharmony_ci tst_resm(TFAIL, "linkat succeeded unexpectedly"); 275f08c3bdfSopenharmony_ci else 276f08c3bdfSopenharmony_ci tst_resm(TFAIL | TTERRNO, 277f08c3bdfSopenharmony_ci "linkat failed unexpectedly; expected %d - %s", 278f08c3bdfSopenharmony_ci desc->expected_errno, 279f08c3bdfSopenharmony_ci strerror(desc->expected_errno)); 280f08c3bdfSopenharmony_ci } 281f08c3bdfSopenharmony_ci} 282f08c3bdfSopenharmony_ci 283f08c3bdfSopenharmony_civoid setup(void) 284f08c3bdfSopenharmony_ci{ 285f08c3bdfSopenharmony_ci char *cwd; 286f08c3bdfSopenharmony_ci int fd; 287f08c3bdfSopenharmony_ci 288f08c3bdfSopenharmony_ci tst_sig(NOFORK, DEF_HANDLER, cleanup); 289f08c3bdfSopenharmony_ci 290f08c3bdfSopenharmony_ci tst_tmpdir(); 291f08c3bdfSopenharmony_ci 292f08c3bdfSopenharmony_ci cwd = get_current_dir_name(); 293f08c3bdfSopenharmony_ci if (cwd == NULL) { 294f08c3bdfSopenharmony_ci tst_brkm(TFAIL | TERRNO, cleanup, 295f08c3bdfSopenharmony_ci "Failed to get current working directory"); 296f08c3bdfSopenharmony_ci } 297f08c3bdfSopenharmony_ci 298f08c3bdfSopenharmony_ci SAFE_MKDIR(cleanup, TEST_DIR1, 0700); 299f08c3bdfSopenharmony_ci SAFE_MKDIR(cleanup, TEST_DIR3, 0700); 300f08c3bdfSopenharmony_ci olddirfd = SAFE_OPEN(cleanup, TEST_DIR1, O_DIRECTORY); 301f08c3bdfSopenharmony_ci deldirfd = SAFE_OPEN(cleanup, TEST_DIR3, O_DIRECTORY); 302f08c3bdfSopenharmony_ci SAFE_RMDIR(cleanup, TEST_DIR3); 303f08c3bdfSopenharmony_ci fd = SAFE_OPEN(cleanup, TEST_DIR1 "/" TEST_FILE1, O_CREAT | O_EXCL, 0600); 304f08c3bdfSopenharmony_ci SAFE_CLOSE(cleanup, fd); 305f08c3bdfSopenharmony_ci SAFE_MKFIFO(cleanup, TEST_DIR1 "/" TEST_FIFO, 0600); 306f08c3bdfSopenharmony_ci 307f08c3bdfSopenharmony_ci snprintf(dpathname, sizeof(dpathname), DPATHNAME_FMT, cwd); 308f08c3bdfSopenharmony_ci snprintf(spathname, sizeof(spathname), SPATHNAME_FMT, cwd); 309f08c3bdfSopenharmony_ci 310f08c3bdfSopenharmony_ci free(cwd); 311f08c3bdfSopenharmony_ci} 312f08c3bdfSopenharmony_ci 313f08c3bdfSopenharmony_cistatic void cleanup(void) 314f08c3bdfSopenharmony_ci{ 315f08c3bdfSopenharmony_ci tst_rmdir(); 316f08c3bdfSopenharmony_ci} 317