1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2022 Marcel Telka <marcel@telka.sk>
14  */
15 
16 /*
17  * Test for fchmodat(AT_SYMLINK_NOFOLLOW)
18  */
19 
20 #include <sys/param.h>
21 #include <string.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 
29 int
main(void)30 main(void)
31 {
32 	int ret = 0;
33 
34 	char template[MAXPATHLEN];
35 	char *path;
36 	char file[MAXPATHLEN];
37 	char link[MAXPATHLEN];
38 
39 	/* prepare template for temporary directory */
40 	if (strlcpy(template, "/tmp/XXXXXX", sizeof (template))
41 	    >= sizeof (template)) {
42 		(void) printf("FAIL: Template copy failed\n");
43 		exit(EXIT_FAILURE);
44 	}
45 
46 	/* create temporary directory */
47 	if ((path = mkdtemp(template)) == NULL) {
48 		(void) printf("FAIL: Temporary directory creation failed\n");
49 		exit(EXIT_FAILURE);
50 	}
51 
52 	/* format file and link paths */
53 	(void) snprintf(file, sizeof (file), "%s/file", path);
54 	(void) snprintf(link, sizeof (link), "%s/link", path);
55 
56 	/* create the file */
57 	int fd = open(file, O_WRONLY | O_CREAT, 0644);
58 	if (fd < 0) {
59 		(void) printf("FAIL: File %s creation failed\n", file);
60 		(void) rmdir(path);
61 		exit(EXIT_FAILURE);
62 	}
63 	(void) close(fd);
64 
65 	/* create symlink */
66 	if (symlink("file", link) != 0) {
67 		(void) printf("FAIL: Symlink %s creation failed\n", link);
68 		(void) unlink(file);
69 		(void) rmdir(path);
70 		exit(EXIT_FAILURE);
71 	}
72 
73 	/* test fchmodat(AT_SYMLINK_NOFOLLOW) for symlink */
74 	if (fchmodat(AT_FDCWD, link, 0666, AT_SYMLINK_NOFOLLOW) == 0) {
75 		(void) printf("FAIL: fchmodat(AT_SYMLINK_NOFOLLOW) "
76 		    "unexpectedly succeeded for symlink\n");
77 		ret = EXIT_FAILURE;
78 	}
79 	/* test fchmodat(AT_SYMLINK_NOFOLLOW) for regular file */
80 	if (fchmodat(AT_FDCWD, file, 0666, AT_SYMLINK_NOFOLLOW) != 0) {
81 		(void) printf("FAIL: fchmodat(AT_SYMLINK_NOFOLLOW) failed for "
82 		    "regular file\n");
83 		ret = EXIT_FAILURE;
84 	}
85 
86 	/* cleanup */
87 	(void) unlink(link);
88 	(void) unlink(file);
89 	(void) rmdir(path);
90 
91 	return (ret);
92 }
93