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