// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2016 Oracle.  All Rights Reserved.
 * Author: Darrick J. Wong <darrick.wong@oracle.com>
 */
#include <sys/types.h>
#include <sys/stat.h>
#include <attr/attributes.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <asm/types.h>
#include <xfs/xfs.h>
#include <xfs/handle.h>

#define ATTRBUFSZ		1024
#define BSTATBUF_NR		32

/* Read all the extended attributes of a file handle. */
void
read_handle_xattrs(
	struct xfs_handle	*handle)
{
	struct attrlist_cursor	cur;
	char			attrbuf[ATTRBUFSZ];
	char			*firstname = NULL;
	struct attrlist		*attrlist = (struct attrlist *)attrbuf;
	struct attrlist_ent	*ent;
	int			i;
	int			flags = 0;
	int			error;

	memset(&cur, 0, sizeof(cur));
	while ((error = attr_list_by_handle(handle, sizeof(*handle),
					    attrbuf, ATTRBUFSZ, flags,
					    &cur)) == 0) {
		for (i = 0; i < attrlist->al_count; i++) {
			ent = ATTR_ENTRY(attrlist, i);

			if (i != 0)
				continue;

			if (firstname == NULL) {
				firstname = malloc(ent->a_valuelen);
				memcpy(firstname, ent->a_name, ent->a_valuelen);
			} else {
				if (memcmp(firstname, ent->a_name,
					   ent->a_valuelen) == 0)
					fprintf(stderr,
						"Saw duplicate xattr \"%s\", buggy XFS?\n",
						ent->a_name);
				else
					fprintf(stderr,
						"Test passes.\n");
				goto out;
			}
		}

		if (!attrlist->al_more)
			break;
	}

out:
	if (firstname)
		free(firstname);
	if (error)
		perror("attr_list_by_handle");
	return;
}

int main(
	int			argc,
	char			*argv[])
{
	struct xfs_handle	*fshandle;
	size_t			fshandle_len;
	struct xfs_handle	*handle;
	size_t			handle_len;
	int			error;

	if (argc != 2) {
		fprintf(stderr, "Usage: %s filename\n", argv[0]);
		return 1;
	}

	error = path_to_fshandle(argv[1], (void **)&fshandle, &fshandle_len);
	if (error) {
		perror("getting fshandle");
		return 2;
	}

	error = path_to_handle(argv[1], (void **)&handle, &handle_len);
	if (error) {
		perror("getting handle");
		return 3;
	}

	read_handle_xattrs(handle);

	free_handle(handle, handle_len);
	free_handle(fshandle, fshandle_len);
	return 0;
}
