Merge branch 'for-linus' into for-next
[linux-2.6-microblaze.git] / tools / testing / selftests / efivarfs / open-unlink.c
1 // SPDX-License-Identifier: GPL-2.0
2 #include <errno.h>
3 #include <stdio.h>
4 #include <stdint.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <sys/ioctl.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 #include <linux/fs.h>
12
13 static int set_immutable(const char *path, int immutable)
14 {
15         unsigned int flags;
16         int fd;
17         int rc;
18         int error;
19
20         fd = open(path, O_RDONLY);
21         if (fd < 0)
22                 return fd;
23
24         rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
25         if (rc < 0) {
26                 error = errno;
27                 close(fd);
28                 errno = error;
29                 return rc;
30         }
31
32         if (immutable)
33                 flags |= FS_IMMUTABLE_FL;
34         else
35                 flags &= ~FS_IMMUTABLE_FL;
36
37         rc = ioctl(fd, FS_IOC_SETFLAGS, &flags);
38         error = errno;
39         close(fd);
40         errno = error;
41         return rc;
42 }
43
44 static int get_immutable(const char *path)
45 {
46         unsigned int flags;
47         int fd;
48         int rc;
49         int error;
50
51         fd = open(path, O_RDONLY);
52         if (fd < 0)
53                 return fd;
54
55         rc = ioctl(fd, FS_IOC_GETFLAGS, &flags);
56         if (rc < 0) {
57                 error = errno;
58                 close(fd);
59                 errno = error;
60                 return rc;
61         }
62         close(fd);
63         if (flags & FS_IMMUTABLE_FL)
64                 return 1;
65         return 0;
66 }
67
68 int main(int argc, char **argv)
69 {
70         const char *path;
71         char buf[5];
72         int fd, rc;
73
74         if (argc < 2) {
75                 fprintf(stderr, "usage: %s <path>\n", argv[0]);
76                 return EXIT_FAILURE;
77         }
78
79         path = argv[1];
80
81         /* attributes: EFI_VARIABLE_NON_VOLATILE |
82          *              EFI_VARIABLE_BOOTSERVICE_ACCESS |
83          *              EFI_VARIABLE_RUNTIME_ACCESS
84          */
85         *(uint32_t *)buf = 0x7;
86         buf[4] = 0;
87
88         /* create a test variable */
89         fd = open(path, O_WRONLY | O_CREAT, 0600);
90         if (fd < 0) {
91                 perror("open(O_WRONLY)");
92                 return EXIT_FAILURE;
93         }
94
95         rc = write(fd, buf, sizeof(buf));
96         if (rc != sizeof(buf)) {
97                 perror("write");
98                 return EXIT_FAILURE;
99         }
100
101         close(fd);
102
103         rc = get_immutable(path);
104         if (rc < 0) {
105                 perror("ioctl(FS_IOC_GETFLAGS)");
106                 return EXIT_FAILURE;
107         } else if (rc) {
108                 rc = set_immutable(path, 0);
109                 if (rc < 0) {
110                         perror("ioctl(FS_IOC_SETFLAGS)");
111                         return EXIT_FAILURE;
112                 }
113         }
114
115         fd = open(path, O_RDONLY);
116         if (fd < 0) {
117                 perror("open");
118                 return EXIT_FAILURE;
119         }
120
121         if (unlink(path) < 0) {
122                 perror("unlink");
123                 return EXIT_FAILURE;
124         }
125
126         rc = read(fd, buf, sizeof(buf));
127         if (rc > 0) {
128                 fprintf(stderr, "reading from an unlinked variable "
129                                 "shouldn't be possible\n");
130                 return EXIT_FAILURE;
131         }
132
133         return EXIT_SUCCESS;
134 }