1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
4f08c3bdfSopenharmony_ci *  AUTHOR		: Richard Logan
5f08c3bdfSopenharmony_ci *  CO-PILOT		: William Roske
6f08c3bdfSopenharmony_ci * Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
7f08c3bdfSopenharmony_ci */
8f08c3bdfSopenharmony_ci
9f08c3bdfSopenharmony_ci/*
10f08c3bdfSopenharmony_ci * Test if link(2) fails with EMLINK.
11f08c3bdfSopenharmony_ci */
12f08c3bdfSopenharmony_ci
13f08c3bdfSopenharmony_ci#include <stdio.h>
14f08c3bdfSopenharmony_ci#include <sys/stat.h>
15f08c3bdfSopenharmony_ci#include "tst_test.h"
16f08c3bdfSopenharmony_ci
17f08c3bdfSopenharmony_ci#define BASENAME	"lkfile"
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_cistatic char fname[255];
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_cistatic int nlinks = 1000;
22f08c3bdfSopenharmony_ci
23f08c3bdfSopenharmony_cistatic void verify_link(void)
24f08c3bdfSopenharmony_ci{
25f08c3bdfSopenharmony_ci	int cnt;
26f08c3bdfSopenharmony_ci	char lname[1024];
27f08c3bdfSopenharmony_ci	struct stat fbuf, lbuf;
28f08c3bdfSopenharmony_ci
29f08c3bdfSopenharmony_ci	for (cnt = 1; cnt < nlinks; cnt++) {
30f08c3bdfSopenharmony_ci		sprintf(lname, "%s_%d", fname, cnt);
31f08c3bdfSopenharmony_ci		TST_EXP_PASS_SILENT(link(fname, lname), "link(%s, %s)", fname, lname);
32f08c3bdfSopenharmony_ci	}
33f08c3bdfSopenharmony_ci
34f08c3bdfSopenharmony_ci	SAFE_STAT(fname, &fbuf);
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_ci	for (cnt = 1; cnt < nlinks; cnt++) {
37f08c3bdfSopenharmony_ci		sprintf(lname, "%s_%d", fname, cnt);
38f08c3bdfSopenharmony_ci
39f08c3bdfSopenharmony_ci		SAFE_STAT(lname, &lbuf);
40f08c3bdfSopenharmony_ci		if (fbuf.st_nlink <= 1 || lbuf.st_nlink <= 1 ||
41f08c3bdfSopenharmony_ci		    (fbuf.st_nlink != lbuf.st_nlink)) {
42f08c3bdfSopenharmony_ci
43f08c3bdfSopenharmony_ci			tst_res(TFAIL,
44f08c3bdfSopenharmony_ci				 "link(%s, %s[1-%d]) ret %ld for %d "
45f08c3bdfSopenharmony_ci			         "files, stat values do not match %d %d",
46f08c3bdfSopenharmony_ci				 fname, fname, nlinks,
47f08c3bdfSopenharmony_ci				 TST_RET, nlinks,
48f08c3bdfSopenharmony_ci				 (int)fbuf.st_nlink, (int)lbuf.st_nlink);
49f08c3bdfSopenharmony_ci			break;
50f08c3bdfSopenharmony_ci		}
51f08c3bdfSopenharmony_ci	}
52f08c3bdfSopenharmony_ci
53f08c3bdfSopenharmony_ci	if (cnt >= nlinks) {
54f08c3bdfSopenharmony_ci		tst_res(TPASS,
55f08c3bdfSopenharmony_ci			 "link(%s, %s[1-%d]) ret %ld for %d files, "
56f08c3bdfSopenharmony_ci		         "stat linkcounts match %d",
57f08c3bdfSopenharmony_ci			 fname, fname, nlinks, TST_RET,
58f08c3bdfSopenharmony_ci			 nlinks, (int)fbuf.st_nlink);
59f08c3bdfSopenharmony_ci	}
60f08c3bdfSopenharmony_ci
61f08c3bdfSopenharmony_ci	for (cnt = 1; cnt < nlinks; cnt++) {
62f08c3bdfSopenharmony_ci		sprintf(lname, "%s_%d", fname, cnt);
63f08c3bdfSopenharmony_ci		SAFE_UNLINK(lname);
64f08c3bdfSopenharmony_ci	}
65f08c3bdfSopenharmony_ci}
66f08c3bdfSopenharmony_ci
67f08c3bdfSopenharmony_cistatic void setup(void)
68f08c3bdfSopenharmony_ci{
69f08c3bdfSopenharmony_ci	sprintf(fname, "%s_%d", BASENAME, getpid());
70f08c3bdfSopenharmony_ci	SAFE_TOUCH(fname, 0700, NULL);
71f08c3bdfSopenharmony_ci}
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_cistatic struct tst_test test = {
74f08c3bdfSopenharmony_ci        .test_all = verify_link,
75f08c3bdfSopenharmony_ci        .setup = setup,
76f08c3bdfSopenharmony_ci        .needs_tmpdir = 1,
77f08c3bdfSopenharmony_ci};
78