xref: /freebsd/tools/test/stress2/misc/nlink5.sh (revision 4b9d6057)
1#!/bin/sh
2#
3# SPDX-License-Identifier: BSD-2-Clause
4#
5# Copyright (c) 2022 Peter Holm <pho@FreeBSD.org>
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28
29# https://reviews.freebsd.org/D35514
30# Rename dir a/b to c/d
31
32# Test scenario suggestion by kib
33
34. ../default.cfg
35
36UFS_LINK_MAX=`grep UFS_LINK_MAX /usr/include/ufs/ufs/dinode.h 2>/dev/null`
37[ -z "$UFS_LINK_MAX" ] && exit 0
38UFS_LINK_MAX=`echo $UFS_LINK_MAX | awk '{print $3}'`
39cat > /tmp/nlink5.c <<EOF
40#include <sys/stat.h>
41#include <ufs/ufs/dinode.h>
42#include <err.h>
43#include <errno.h>
44#include <stdio.h>
45#include <unistd.h>
46
47int
48main (void) {
49	int i, mx;
50	char dir[100];
51
52	mx = UFS_LINK_MAX - 2;
53	for (i = 0; i < mx; i++) {
54		snprintf(dir, sizeof(dir), "%d", i);
55		if (mkdir(dir, 0700) == -1)
56			err(1, "mkdir(%s)", dir);
57	}
58
59	/* The following mkdir(2) must fail */
60	i = mx;
61	snprintf(dir, sizeof(dir), "%d", i);
62	if (mkdir(dir, 0700) != -1)	/* this must fail */
63		err(1, "mkdir(%s)", dir);
64	if (errno != EMLINK)
65		err(1, "Must fail: mkdir(%s)", dir);
66
67	/* Must succeed */
68	i = 0;
69	snprintf(dir, sizeof(dir), "%d", i);
70	if (rmdir(dir) == -1)
71		err(1, "rmdir(%s)", dir);
72	snprintf(dir, sizeof(dir), "%s", "x");
73	if (mkdir(dir, 0700) == -1)
74		err(1, "mkdir(%s)", dir);
75
76	/* Make room for two top level directories */
77	if (rmdir("1") == -1)
78		err(1, "rmdir(1)");
79	if (rmdir("2") == -1)
80		err(1, "rmdir(2)");
81
82	/* mkdir a c */
83	snprintf(dir, sizeof(dir), "%s", "a");
84	if (mkdir(dir, 0700) == -1)
85		err(1, "mkdir(%s)", dir);
86	snprintf(dir, sizeof(dir), "%s", "c");
87	if (mkdir(dir, 0700) == -1)
88		err(1, "mkdir(%s)", dir);
89
90	/* mkdir a/b */
91	snprintf(dir, sizeof(dir), "%s/%s", "a", "b");
92	if (mkdir(dir, 0700) == -1)
93		err(1, "mkdir(%s)", dir);
94
95	/* mv a/b c/d */
96	if (rename("a/b", "c/d") == -1)
97		err(1, "rename(a/b, c/d)");
98
99	return (0);
100}
101EOF
102mycc -o /tmp/nlink5 -Wall -Wextra -O2 /tmp/nlink5.c || exit 1
103rm /tmp/nlink5.c
104
105set -e
106here=`pwd`
107mount | grep -q "on $mntpoint " && umount -f $mntpoint
108mdconfig -l | grep "md$mdstart " && mdconfig -d -u $mdstart
109mdconfig -a -t swap -s 1g -u $mdstart
110newfs -Un /dev/md$mdstart > /dev/null
111mount /dev/md$mdstart $mntpoint
112set +e
113
114cd $mntpoint
115/tmp/nlink5; s=$?
116n=`find . -type d -maxdepth 1 | wc -l`
117[ $n -ne $((UFS_LINK_MAX - 1)) ] && s=2
118cd $here
119
120umount $mntpoint
121mdconfig -d -u $mdstart
122rm /tmp/nlink5
123exit $s
124