1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (c) 2014 Fujitsu Ltd. 3f08c3bdfSopenharmony_ci * Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com> 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify it 6f08c3bdfSopenharmony_ci * under the terms of version 2 of the GNU General Public License as 7f08c3bdfSopenharmony_ci * published by the Free Software Foundation. 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful, but 10f08c3bdfSopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 11f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License along 14f08c3bdfSopenharmony_ci * with this program. 15f08c3bdfSopenharmony_ci */ 16f08c3bdfSopenharmony_ci/* 17f08c3bdfSopenharmony_ci * Test that linkat() fails and sets the proper errno values. 18f08c3bdfSopenharmony_ci */ 19f08c3bdfSopenharmony_ci 20f08c3bdfSopenharmony_ci#define _GNU_SOURCE 21f08c3bdfSopenharmony_ci 22f08c3bdfSopenharmony_ci#include <sys/types.h> 23f08c3bdfSopenharmony_ci#include <sys/stat.h> 24f08c3bdfSopenharmony_ci#include <unistd.h> 25f08c3bdfSopenharmony_ci#include <stdlib.h> 26f08c3bdfSopenharmony_ci#include <errno.h> 27f08c3bdfSopenharmony_ci#include <string.h> 28f08c3bdfSopenharmony_ci#include <signal.h> 29f08c3bdfSopenharmony_ci#include <pwd.h> 30f08c3bdfSopenharmony_ci#include <sys/mount.h> 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ci#include "test.h" 33f08c3bdfSopenharmony_ci#include "lapi/syscalls.h" 34f08c3bdfSopenharmony_ci#include "safe_macros.h" 35f08c3bdfSopenharmony_ci#include "lapi/fcntl.h" 36f08c3bdfSopenharmony_ci 37f08c3bdfSopenharmony_ci#define DIR_MODE (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \ 38f08c3bdfSopenharmony_ci S_IXGRP|S_IROTH|S_IXOTH) 39f08c3bdfSopenharmony_ci#define TEST_FILE "testfile" 40f08c3bdfSopenharmony_ci#define TEST_EXIST "testexist" 41f08c3bdfSopenharmony_ci#define TEST_ELOOP "testeloop" 42f08c3bdfSopenharmony_ci#define TEST_EACCES "./tmp/testeeacces" 43f08c3bdfSopenharmony_ci#define TEST_EACCES2 "./tmp/testeeacces2" 44f08c3bdfSopenharmony_ci#define TEST_EROFS "mntpoint" 45f08c3bdfSopenharmony_ci#define TEST_EROFS2 "mntpoint/testerofs2" 46f08c3bdfSopenharmony_ci#define TEST_EMLINK "emlink_dir/testfile0" 47f08c3bdfSopenharmony_ci#define TEST_EMLINK2 "emlink_dir/testfile" 48f08c3bdfSopenharmony_ci#define BASENAME "mntpoint/basename" 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_cistatic char nametoolong[PATH_MAX+2]; 51f08c3bdfSopenharmony_cistatic const char *device; 52f08c3bdfSopenharmony_cistatic int mount_flag; 53f08c3bdfSopenharmony_cistatic int max_hardlinks; 54f08c3bdfSopenharmony_cistatic const char *fs_type; 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_cistatic void setup(void); 57f08c3bdfSopenharmony_cistatic void cleanup(void); 58f08c3bdfSopenharmony_cistatic void setup_eacces(void); 59f08c3bdfSopenharmony_cistatic void cleanup_eacces(void); 60f08c3bdfSopenharmony_cistatic void setup_erofs(void); 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_cistatic struct test_struct { 63f08c3bdfSopenharmony_ci const char *oldfname; 64f08c3bdfSopenharmony_ci const char *newfname; 65f08c3bdfSopenharmony_ci int flags; 66f08c3bdfSopenharmony_ci int expected_errno; 67f08c3bdfSopenharmony_ci void (*setupfunc) (void); 68f08c3bdfSopenharmony_ci void (*cleanfunc) (void); 69f08c3bdfSopenharmony_ci} test_cases[] = { 70f08c3bdfSopenharmony_ci {TEST_FILE, nametoolong, 0, ENAMETOOLONG, NULL, NULL}, 71f08c3bdfSopenharmony_ci {nametoolong, TEST_FILE, 0, ENAMETOOLONG, NULL, NULL}, 72f08c3bdfSopenharmony_ci {TEST_EXIST, TEST_EXIST, 0, EEXIST, NULL, NULL}, 73f08c3bdfSopenharmony_ci {TEST_ELOOP, TEST_FILE, AT_SYMLINK_FOLLOW, ELOOP, NULL, NULL}, 74f08c3bdfSopenharmony_ci {TEST_EACCES, TEST_EACCES2, 0, EACCES, setup_eacces, cleanup_eacces}, 75f08c3bdfSopenharmony_ci {TEST_EROFS, TEST_EROFS2, 0, EROFS, setup_erofs, NULL}, 76f08c3bdfSopenharmony_ci {TEST_EMLINK, TEST_EMLINK2, 0, EMLINK, NULL, NULL}, 77f08c3bdfSopenharmony_ci}; 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_cichar *TCID = "linkat02"; 80f08c3bdfSopenharmony_ciint TST_TOTAL = ARRAY_SIZE(test_cases); 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_cistatic struct passwd *ltpuser; 83f08c3bdfSopenharmony_cistatic void linkat_verify(const struct test_struct *); 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ciint main(int ac, char **av) 86f08c3bdfSopenharmony_ci{ 87f08c3bdfSopenharmony_ci int lc; 88f08c3bdfSopenharmony_ci int i; 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_ci tst_parse_opts(ac, av, NULL, NULL); 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_ci setup(); 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_ci for (lc = 0; TEST_LOOPING(lc); lc++) { 95f08c3bdfSopenharmony_ci tst_count = 0; 96f08c3bdfSopenharmony_ci for (i = 0; i < TST_TOTAL; i++) 97f08c3bdfSopenharmony_ci linkat_verify(&test_cases[i]); 98f08c3bdfSopenharmony_ci } 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_ci cleanup(); 101f08c3bdfSopenharmony_ci tst_exit(); 102f08c3bdfSopenharmony_ci} 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_cistatic void linkat_verify(const struct test_struct *desc) 105f08c3bdfSopenharmony_ci{ 106f08c3bdfSopenharmony_ci if (desc->expected_errno == EMLINK && max_hardlinks == 0) { 107f08c3bdfSopenharmony_ci tst_resm(TCONF, "EMLINK test is not appropriate"); 108f08c3bdfSopenharmony_ci return; 109f08c3bdfSopenharmony_ci } 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci if (desc->setupfunc != NULL) { 112f08c3bdfSopenharmony_ci desc->setupfunc(); 113f08c3bdfSopenharmony_ci } 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci TEST(tst_syscall(__NR_linkat, AT_FDCWD, desc->oldfname, 116f08c3bdfSopenharmony_ci AT_FDCWD, desc->newfname, desc->flags)); 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_ci if (desc->cleanfunc != NULL) 119f08c3bdfSopenharmony_ci desc->cleanfunc(); 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci if (TEST_RETURN != -1) { 122f08c3bdfSopenharmony_ci tst_resm(TFAIL, 123f08c3bdfSopenharmony_ci "linkat(""AT_FDCWD"", %s, ""AT_FDCWD"", %s, %d) " 124f08c3bdfSopenharmony_ci "succeeded unexpectedly", desc->oldfname, 125f08c3bdfSopenharmony_ci desc->newfname, desc->flags); 126f08c3bdfSopenharmony_ci return; 127f08c3bdfSopenharmony_ci } 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci if (TEST_ERRNO == desc->expected_errno) { 130f08c3bdfSopenharmony_ci tst_resm(TPASS | TTERRNO, "linkat failed as expected"); 131f08c3bdfSopenharmony_ci } else { 132f08c3bdfSopenharmony_ci tst_resm(TFAIL | TTERRNO, 133f08c3bdfSopenharmony_ci "linkat failed unexpectedly; expected: " 134f08c3bdfSopenharmony_ci "%d - %s", desc->expected_errno, 135f08c3bdfSopenharmony_ci strerror(desc->expected_errno)); 136f08c3bdfSopenharmony_ci } 137f08c3bdfSopenharmony_ci} 138f08c3bdfSopenharmony_ci 139f08c3bdfSopenharmony_cistatic void setup(void) 140f08c3bdfSopenharmony_ci{ 141f08c3bdfSopenharmony_ci tst_require_root(); 142f08c3bdfSopenharmony_ci 143f08c3bdfSopenharmony_ci tst_sig(NOFORK, DEF_HANDLER, cleanup); 144f08c3bdfSopenharmony_ci 145f08c3bdfSopenharmony_ci tst_tmpdir(); 146f08c3bdfSopenharmony_ci 147f08c3bdfSopenharmony_ci fs_type = tst_dev_fs_type(); 148f08c3bdfSopenharmony_ci device = tst_acquire_device(cleanup); 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_ci if (!device) 151f08c3bdfSopenharmony_ci tst_brkm(TCONF, cleanup, "Failed to acquire device"); 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci TEST_PAUSE; 154f08c3bdfSopenharmony_ci 155f08c3bdfSopenharmony_ci ltpuser = SAFE_GETPWNAM(cleanup, "nobody"); 156f08c3bdfSopenharmony_ci 157f08c3bdfSopenharmony_ci SAFE_TOUCH(cleanup, TEST_FILE, 0644, NULL); 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_ci memset(nametoolong, 'a', PATH_MAX+1); 160f08c3bdfSopenharmony_ci 161f08c3bdfSopenharmony_ci SAFE_TOUCH(cleanup, TEST_EXIST, 0644, NULL); 162f08c3bdfSopenharmony_ci 163f08c3bdfSopenharmony_ci SAFE_SYMLINK(cleanup, TEST_ELOOP, "test_file_eloop2"); 164f08c3bdfSopenharmony_ci SAFE_SYMLINK(cleanup, "test_file_eloop2", TEST_ELOOP); 165f08c3bdfSopenharmony_ci 166f08c3bdfSopenharmony_ci SAFE_MKDIR(cleanup, "./tmp", DIR_MODE); 167f08c3bdfSopenharmony_ci SAFE_TOUCH(cleanup, TEST_EACCES, 0666, NULL); 168f08c3bdfSopenharmony_ci 169f08c3bdfSopenharmony_ci tst_mkfs(cleanup, device, fs_type, NULL, NULL); 170f08c3bdfSopenharmony_ci SAFE_MKDIR(cleanup, "mntpoint", DIR_MODE); 171f08c3bdfSopenharmony_ci 172f08c3bdfSopenharmony_ci SAFE_MOUNT(cleanup, device, "mntpoint", fs_type, 0, NULL); 173f08c3bdfSopenharmony_ci mount_flag = 1; 174f08c3bdfSopenharmony_ci 175f08c3bdfSopenharmony_ci max_hardlinks = tst_fs_fill_hardlinks(cleanup, "emlink_dir"); 176f08c3bdfSopenharmony_ci} 177f08c3bdfSopenharmony_ci 178f08c3bdfSopenharmony_cistatic void setup_eacces(void) 179f08c3bdfSopenharmony_ci{ 180f08c3bdfSopenharmony_ci SAFE_SETEUID(cleanup, ltpuser->pw_uid); 181f08c3bdfSopenharmony_ci} 182f08c3bdfSopenharmony_ci 183f08c3bdfSopenharmony_cistatic void cleanup_eacces(void) 184f08c3bdfSopenharmony_ci{ 185f08c3bdfSopenharmony_ci SAFE_SETEUID(cleanup, 0); 186f08c3bdfSopenharmony_ci} 187f08c3bdfSopenharmony_ci 188f08c3bdfSopenharmony_cistatic void setup_erofs(void) 189f08c3bdfSopenharmony_ci{ 190f08c3bdfSopenharmony_ci SAFE_MOUNT(cleanup, device, "mntpoint", fs_type, 191f08c3bdfSopenharmony_ci MS_REMOUNT | MS_RDONLY, NULL); 192f08c3bdfSopenharmony_ci mount_flag = 1; 193f08c3bdfSopenharmony_ci} 194f08c3bdfSopenharmony_ci 195f08c3bdfSopenharmony_cistatic void cleanup(void) 196f08c3bdfSopenharmony_ci{ 197f08c3bdfSopenharmony_ci if (mount_flag && tst_umount("mntpoint") < 0) 198f08c3bdfSopenharmony_ci tst_resm(TWARN | TERRNO, "umount device:%s failed", device); 199f08c3bdfSopenharmony_ci 200f08c3bdfSopenharmony_ci if (device) 201f08c3bdfSopenharmony_ci tst_release_device(device); 202f08c3bdfSopenharmony_ci 203f08c3bdfSopenharmony_ci tst_rmdir(); 204f08c3bdfSopenharmony_ci} 205