common/rc: Check 'tPnE' flags on a directory instead of a regilar file
[xfstests-dev.git] / src / attr_replace_test.c
1 // setattr.c by kanda.motohiro@gmail.com
2 // xfs extended attribute corruption bug reproducer
3 #include <stdio.h>
4 #include <string.h>
5 #include <fcntl.h>
6 #include <errno.h>
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <sys/xattr.h>
11 #include <sys/stat.h>
12 #include <sys/param.h>
13 #include <linux/limits.h>
14
15 #define die() do { perror(""); \
16 fprintf(stderr, "error at line %d\n", __LINE__); \
17 exit(1); } while (0)
18
19 #define fail(...) do { \
20 fprintf(stderr, __VA_ARGS__); exit (1); \
21 } while (0)
22
23 int main(int argc, char *argv[])
24 {
25         int ret;
26         int fd;
27         char *path;
28         char *name = "user.world";
29         char *value;
30         struct stat sbuf;
31         size_t size = sizeof(value);
32
33         if (argc != 2)
34                 fail("Usage: %s <file>\n", argv[0]);
35         path = argv[1];
36
37         fd = open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
38         if (fd < 0) die();
39
40         /*
41          * The value should be 3/4 the size of a fs block to ensure that we
42          * get to extents format.
43          */
44         ret = fstat(fd, &sbuf);
45         if (ret < 0) die();
46         size = sbuf.st_blksize * 3 / 4;
47         if (!size)
48                 fail("Invalid st_blksize(%ld)\n", sbuf.st_blksize);
49         size = MIN(size, XATTR_SIZE_MAX);
50         value = malloc(size);
51         if (!value)
52                 fail("Failed to allocate memory\n");
53
54         /* First, create a small xattr. */
55         memset(value, '0', 1);
56         ret = fsetxattr(fd, name, value, 1, XATTR_CREATE);
57         if (ret < 0) die();
58         close(fd);
59
60         fd = open(path, O_RDWR);
61         if (fd < 0) die();
62
63         /* Then, replace it with bigger one, forcing short form to leaf conversion. */
64         memset(value, '1', size);
65         ret = fsetxattr(fd, name, value, size, XATTR_REPLACE);
66         if (ret < 0) die();
67         close(fd);
68
69         return 0;
70 }