blob: 0720bfdc18ab61749ccf663914f894eda0f1fd0c [file] [log] [blame]
// setattr.c by kanda.motohiro@gmail.com
// xfs extended attribute corruption bug reproducer
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/xattr.h>
#include <sys/stat.h>
#define die() do { perror(""); \
fprintf(stderr, "error at line %d\n", __LINE__); \
exit(1); } while (0)
#define fail(...) do { \
fprintf(stderr, __VA_ARGS__); exit (1); \
} while (0)
int main(int argc, char *argv[])
{
int ret;
int fd;
char *path;
char *name = "user.world";
char *value;
struct stat sbuf;
size_t size = sizeof(value);
if (argc != 2)
fail("Usage: %s <file>\n", argv[0]);
path = argv[1];
fd = open(path, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fd < 0) die();
/*
* The value should be 3/4 the size of a fs block to ensure that we
* get to extents format.
*/
ret = fstat(fd, &sbuf);
if (ret < 0) die();
size = sbuf.st_blksize * 3 / 4;
if (!size)
fail("Invalid st_blksize(%ld)\n", sbuf.st_blksize);
value = malloc(size);
if (!value)
fail("Failed to allocate memory\n");
/* First, create a small xattr. */
memset(value, '0', 1);
ret = fsetxattr(fd, name, value, 1, XATTR_CREATE);
if (ret < 0) die();
close(fd);
fd = open(path, O_RDWR);
if (fd < 0) die();
/* Then, replace it with bigger one, forcing short form to leaf conversion. */
memset(value, '1', size);
ret = fsetxattr(fd, name, value, size, XATTR_REPLACE);
if (ret < 0) die();
close(fd);
return 0;
}