163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang/*
263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang * Copyright (c) 2014 Fujitsu Ltd.
363147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang * Author: Zeng Linggang <zenglg.jy@cn.fujitsu.com>
463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *
563147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang * This program is free software;  you can redistribute it and/or modify
663147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang * it under the terms of the GNU General Public License as published by
763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang * the Free Software Foundation; either version 2 of the License, or
863147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang * (at your option) any later version.
963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *
1063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang * This program is distributed in the hope that it will be useful,
1163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang * but WITHOUT ANY WARRANTY; without even the implied warranty of
1263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1363147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang * GNU Library General Public License for more details.
1463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *
1563147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang * You should have received a copy of the GNU General Public License
1663147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang * along with this program; if not, write to the Free Software
1763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1863147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *
1963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang */
2063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang/*
2163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang * Test Description:
2263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *  Verify that,
2363147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *   1. link() fails with -1 return value and sets errno to EPERM
2463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *      if oldpath is a directory.
2563147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *   2. link() fails with -1 return value and sets errno to EXDEV
2663147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *      if oldpath and newpath are not on the same mounted file system( Linux
2763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *      permits a file system to be mounted at multiple points, but link()
2863147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *      does not work across different mount points, even if the same
2963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *      file system is mounted on both. ).
3063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *   3. link() fails with -1 return value and sets errno to EROFS
3163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *      if the file is on a read-only file system.
3263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *   4. link() fails with -1 return value and sets errno to ELOOP
3363147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang *      if too many symbolic links were encountered in resolving path.
3463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang */
3563147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
3663147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#include <stdio.h>
3763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#include <stdlib.h>
3863147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#include <unistd.h>
3963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#include <fcntl.h>
4063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#include <errno.h>
4163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#include <string.h>
4263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#include <signal.h>
4363147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#include <sys/types.h>
4463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#include <sys/stat.h>
4563147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#include <pwd.h>
4663147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#include <sys/mount.h>
4763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
4863147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#include "test.h"
4963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#include "safe_macros.h"
5063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
5163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#define DIR_MODE	(S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP| \
5263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang			 S_IXGRP|S_IROTH|S_IXOTH)
5363147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#define MNT_POINT	"mntpoint"
5463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#define TEST_FILE	"testfile"
5563147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#define TEST_FILE1	"testfile1"
5663147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#define TEST_FILE2	"mntpoint/testfile3"
5763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang#define TEST_FILE3	"mntpoint/testfile4"
5863147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
5963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggangstatic char test_file4[PATH_MAX] = ".";
6063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggangstatic void setup(void);
6163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggangstatic void cleanup(void);
6263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
636383fd959dd889299c63fba116c81b6f81c21e76Cyril Hrubisstatic const char *device;
6463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggangstatic int mount_flag;
6563147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
6663147204cf7928ccbc29a784d6b9638664c6584bZeng Linggangstatic struct test_case_t {
6763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	char *oldpath;
6863147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	char *newpath;
6963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	int exp_errno;
7063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang} test_cases[] = {
7163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	{TEST_FILE1, TEST_FILE, EPERM},
7263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	{TEST_FILE2, TEST_FILE, EXDEV},
7363147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	{TEST_FILE2, TEST_FILE3, EROFS},
7463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	{test_file4, TEST_FILE, ELOOP},
7563147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang};
7663147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
7763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggangstatic void link_verify(const struct test_case_t *);
7863147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
7963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggangchar *TCID = "link08";
8063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggangint TST_TOTAL = ARRAY_SIZE(test_cases);
8163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
8263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggangint main(int ac, char **av)
8363147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang{
8463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	int i, lc;
8563147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
86d6d11d08678aac1ed2c370ea8e42e5f45aea07beCyril Hrubis	tst_parse_opts(ac, av, NULL, NULL);
8763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
8863147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	setup();
8963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
9063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	for (lc = 0; TEST_LOOPING(lc); lc++) {
9163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang		tst_count = 0;
9263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang		for (i = 0; i < TST_TOTAL; i++)
9363147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang			link_verify(&test_cases[i]);
9463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	}
9563147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
9663147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	cleanup();
9763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	tst_exit();
9863147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
9963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang}
10063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
10163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggangstatic void link_verify(const struct test_case_t *tc)
10263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang{
10363147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	TEST(link(tc->oldpath, tc->newpath));
10463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
10563147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	if (TEST_RETURN != -1) {
10663147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang		tst_resm(TFAIL, "link succeeded unexpectedly");
10763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang		return;
10863147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	}
10963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
11063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	if (TEST_ERRNO == tc->exp_errno) {
11163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang		tst_resm(TPASS | TTERRNO, "link failed as expected");
11263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	} else {
11363147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang		tst_resm(TFAIL | TTERRNO,
11463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang			 "link failed unexpectedly; expected: %d - %s",
11563147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang			 tc->exp_errno, strerror(tc->exp_errno));
11663147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	}
11763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang}
11863147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
11963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
12063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggangstatic void setup(void)
12163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang{
12263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	int i;
1236383fd959dd889299c63fba116c81b6f81c21e76Cyril Hrubis	const char *fs_type;
12463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
125d1e794d62b1bf619df8390535e4c2a58899b1145Cyril Hrubis	tst_require_root();
12663147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
12763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	tst_sig(NOFORK, DEF_HANDLER, cleanup);
12863147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
12963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	TEST_PAUSE;
13063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
13163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	tst_tmpdir();
13263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
1336383fd959dd889299c63fba116c81b6f81c21e76Cyril Hrubis	fs_type = tst_dev_fs_type();
1346383fd959dd889299c63fba116c81b6f81c21e76Cyril Hrubis	device = tst_acquire_device(cleanup);
1356383fd959dd889299c63fba116c81b6f81c21e76Cyril Hrubis
1366383fd959dd889299c63fba116c81b6f81c21e76Cyril Hrubis	if (!device)
1376383fd959dd889299c63fba116c81b6f81c21e76Cyril Hrubis		tst_brkm(TCONF, cleanup, "Failed to acquire device");
1386383fd959dd889299c63fba116c81b6f81c21e76Cyril Hrubis
13963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	SAFE_MKDIR(cleanup, TEST_FILE1, DIR_MODE);
14063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
14163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	SAFE_MKDIR(cleanup, "test_eloop", DIR_MODE);
14263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	SAFE_SYMLINK(cleanup, "../test_eloop", "test_eloop/test_eloop");
14363147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	for (i = 0; i < 43; i++)
14463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang		strcat(test_file4, "/test_eloop");
14563147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
146d5e1788b647aca13ee89f41c08113d7b5fa1c499Zorro Lang	tst_mkfs(cleanup, device, fs_type, NULL, NULL);
14763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	SAFE_MKDIR(cleanup, MNT_POINT, DIR_MODE);
1486383fd959dd889299c63fba116c81b6f81c21e76Cyril Hrubis	if (mount(device, MNT_POINT, fs_type, 0, NULL) < 0) {
14963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang		tst_brkm(TBROK | TERRNO, cleanup,
15063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang			 "mount device:%s failed", device);
15163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	}
15263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	mount_flag = 1;
15363147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
15463147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	SAFE_TOUCH(cleanup, TEST_FILE2, 0644, NULL);
1556383fd959dd889299c63fba116c81b6f81c21e76Cyril Hrubis	if (mount(device, MNT_POINT, fs_type,
15663147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang		  MS_REMOUNT | MS_RDONLY, NULL) < 0) {
15763147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang		tst_brkm(TBROK | TERRNO, cleanup,
15863147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang			 "mount device:%s failed", device);
15963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang	}
16063147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang}
16163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
16263147204cf7928ccbc29a784d6b9638664c6584bZeng Linggangstatic void cleanup(void)
16363147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang{
164c60a23034267b51ba36459a605592f4d3bc4172bCyril Hrubis	if (mount_flag && tst_umount(MNT_POINT) < 0)
16563147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang		tst_resm(TWARN | TERRNO, "umount device:%s failed", device);
16663147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
1676383fd959dd889299c63fba116c81b6f81c21e76Cyril Hrubis	if (device)
168bbdb9f78378c7e038f463efa39d2470e1c51ad54Cyril Hrubis		tst_release_device(device);
16963147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang
1706383fd959dd889299c63fba116c81b6f81c21e76Cyril Hrubis	tst_rmdir();
17163147204cf7928ccbc29a784d6b9638664c6584bZeng Linggang}
172