159247Srwatson/*-
295018Srwatson * Copyright (c) 1999-2002 Robert N. M. Watson
359247Srwatson * All rights reserved.
459247Srwatson *
586429Srwatson * This software was developed by Robert Watson for the TrustedBSD Project.
686429Srwatson *
759247Srwatson * Redistribution and use in source and binary forms, with or without
859247Srwatson * modification, are permitted provided that the following conditions
959247Srwatson * are met:
1059247Srwatson * 1. Redistributions of source code must retain the above copyright
1159247Srwatson *    notice, this list of conditions and the following disclaimer.
1259247Srwatson * 2. Redistributions in binary form must reproduce the above copyright
1359247Srwatson *    notice, this list of conditions and the following disclaimer in the
1459247Srwatson *    documentation and/or other materials provided with the distribution.
1559247Srwatson *
1659247Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1759247Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1859247Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1959247Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2059247Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2159247Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2259247Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2359247Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2459247Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2559247Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2659247Srwatson * SUCH DAMAGE.
2759247Srwatson *
2874275Srwatson * $FreeBSD$
2959247Srwatson */
3059247Srwatson/*
3186429Srwatson * Developed by the TrustedBSD Project.
3286429Srwatson * Support for file system extended attribute.
3359247Srwatson */
3459247Srwatson
3559247Srwatson#include <sys/types.h>
3659247Srwatson#include <sys/uio.h>
3759247Srwatson#include <sys/extattr.h>
3859445Srwatson#include <sys/param.h>
3959445Srwatson#include <sys/mount.h>
4059445Srwatson
4159247Srwatson#include <ufs/ufs/extattr.h>
4259445Srwatson
4374275Srwatson#include <errno.h>
4459247Srwatson#include <fcntl.h>
4574275Srwatson#include <libutil.h>
4659247Srwatson#include <stdio.h>
4759247Srwatson#include <stdlib.h>
4859247Srwatson#include <string.h>
4959247Srwatson#include <unistd.h>
5059247Srwatson
5186994Sjedgarint initattr(int argc, char *argv[]);
5288740Srwatsonint showattr(int argc, char *argv[]);
5386994Sjedgarlong num_inodes_by_path(char *path);
5486994Sjedgarvoid usage(void);
5559401Srwatson
5659247Srwatsonvoid
57201387Sedusage(void)
5859247Srwatson{
5959247Srwatson
6059247Srwatson	fprintf(stderr,
6159247Srwatson	    "usage:\n"
6295018Srwatson	    "  extattrctl start path\n"
6395018Srwatson	    "  extattrctl stop path\n"
6495018Srwatson	    "  extattrctl initattr [-f] [-p path] attrsize attrfile\n"
6595018Srwatson	    "  extattrctl showattr attrfile\n"
6695018Srwatson	    "  extattrctl enable path attrnamespace attrname attrfile\n"
6795018Srwatson	    "  extattrctl disable path attrnamespace attrname\n");
6859401Srwatson	exit(-1);
6959247Srwatson}
7059247Srwatson
7159445Srwatsonlong
7259445Srwatsonnum_inodes_by_path(char *path)
7359445Srwatson{
7459445Srwatson	struct statfs	buf;
7559445Srwatson	int	error;
7659445Srwatson
7759445Srwatson	error = statfs(path, &buf);
7859445Srwatson	if (error) {
7959445Srwatson		perror("statfs");
8059445Srwatson		return (-1);
8159445Srwatson	}
8259445Srwatson
8359445Srwatson	return (buf.f_files);
8459445Srwatson}
8559445Srwatson
8693928Sdesstatic const char zero_buf[8192];
8793928Sdes
8859401Srwatsonint
8959401Srwatsoninitattr(int argc, char *argv[])
9059401Srwatson{
9159247Srwatson	struct ufs_extattr_fileheader	uef;
9259445Srwatson	char	*fs_path = NULL;
9393928Sdes	int	ch, i, error, flags;
9493928Sdes	ssize_t	wlen;
9593928Sdes	size_t	easize;
9659247Srwatson
9793928Sdes	flags = O_CREAT | O_WRONLY | O_TRUNC | O_EXCL;
9859445Srwatson	optind = 0;
9965777Srwatson	while ((ch = getopt(argc, argv, "fp:r:w:")) != -1)
10059401Srwatson		switch (ch) {
10165777Srwatson		case 'f':
10293928Sdes			flags &= ~O_EXCL;
10365767Srwatson			break;
10459401Srwatson		case 'p':
10593928Sdes			fs_path = optarg;
10659401Srwatson			break;
10759401Srwatson		case '?':
10859401Srwatson		default:
10959401Srwatson			usage();
11059401Srwatson		}
11159401Srwatson
11259401Srwatson	argc -= optind;
11359401Srwatson	argv += optind;
11459401Srwatson
11559401Srwatson	if (argc != 2)
11659247Srwatson		usage();
11759401Srwatson
11859401Srwatson	error = 0;
11993928Sdes	if ((i = open(argv[1], flags, 0600)) == -1) {
12065377Srwatson		/* unable to open file */
12159445Srwatson		perror(argv[1]);
12265377Srwatson		return (-1);
12365377Srwatson	}
12493928Sdes	uef.uef_magic = UFS_EXTATTR_MAGIC;
12593928Sdes	uef.uef_version = UFS_EXTATTR_VERSION;
12693928Sdes	uef.uef_size = atoi(argv[0]);
12793928Sdes	if (write(i, &uef, sizeof(uef)) == -1)
12893928Sdes		error = -1;
12993928Sdes	else if (fs_path != NULL) {
13093928Sdes		easize = (sizeof uef + uef.uef_size) *
13193928Sdes		    num_inodes_by_path(fs_path);
13293928Sdes		while (easize > 0) {
13393928Sdes			if (easize > sizeof zero_buf)
13493928Sdes				wlen = write(i, zero_buf, sizeof zero_buf);
13593928Sdes			else
13693928Sdes				wlen = write(i, zero_buf, easize);
13793928Sdes			if (wlen == -1) {
13893928Sdes				error = -1;
13993928Sdes				break;
14093928Sdes			}
14193928Sdes			easize -= wlen;
14293928Sdes		}
14393928Sdes	}
14465377Srwatson	if (error == -1) {
14565377Srwatson		perror(argv[1]);
14659445Srwatson		unlink(argv[1]);
147216292Skevlo		close(i);
14859401Srwatson		return (-1);
14959401Srwatson	}
15059247Srwatson
151216292Skevlo	close(i);
15259401Srwatson	return (0);
15359401Srwatson}
15459401Srwatson
15559401Srwatsonint
15688740Srwatsonshowattr(int argc, char *argv[])
15788740Srwatson{
15888740Srwatson	struct ufs_extattr_fileheader	uef;
15988740Srwatson	int i, fd;
16088740Srwatson
16188740Srwatson	if (argc != 1)
16288740Srwatson		usage();
16388740Srwatson
16488740Srwatson	fd = open(argv[0], O_RDONLY);
16588740Srwatson	if (fd == -1) {
16688740Srwatson		perror(argv[0]);
16788740Srwatson		return (-1);
16888740Srwatson	}
16988740Srwatson
17088740Srwatson	i = read(fd, &uef, sizeof(uef));
17188740Srwatson	if (i == -1) {
17288740Srwatson		perror(argv[0]);
173216292Skevlo		close(fd);
17488740Srwatson		return (-1);
17588740Srwatson	}
17688740Srwatson	if (i != sizeof(uef)) {
17788740Srwatson		fprintf(stderr, "%s: invalid file header\n", argv[0]);
178216292Skevlo		close(fd);
17988740Srwatson		return (-1);
18088740Srwatson	}
18188740Srwatson
18288740Srwatson	if (uef.uef_magic != UFS_EXTATTR_MAGIC) {
18388740Srwatson		fprintf(stderr, "%s: bad magic\n", argv[0]);
184216292Skevlo		close(fd);
18588740Srwatson		return (-1);
18688740Srwatson	}
18788740Srwatson
18888740Srwatson	printf("%s: version %d, size %d\n", argv[0], uef.uef_version,
18988740Srwatson	    uef.uef_size);
19088740Srwatson
191216292Skevlo	close(fd);
19288740Srwatson	return (0);
19388740Srwatson}
19488740Srwatson
19588740Srwatsonint
19659401Srwatsonmain(int argc, char *argv[])
19759401Srwatson{
19874441Srwatson	int	error = 0, attrnamespace;
19959401Srwatson
20059401Srwatson	if (argc < 2)
20159401Srwatson		usage();
20259401Srwatson
20359247Srwatson	if (!strcmp(argv[1], "start")) {
20459401Srwatson		if (argc != 3)
20559247Srwatson			usage();
20674275Srwatson		error = extattrctl(argv[2], UFS_EXTATTR_CMD_START, NULL, 0,
20774275Srwatson		    NULL);
20874275Srwatson		if (error) {
20965377Srwatson			perror("extattrctl start");
21074275Srwatson			return (-1);
21174275Srwatson		}
21259247Srwatson	} else if (!strcmp(argv[1], "stop")) {
21359401Srwatson		if (argc != 3)
21459247Srwatson			usage();
21574275Srwatson		error = extattrctl(argv[2], UFS_EXTATTR_CMD_STOP, NULL, 0,
21674275Srwatson		   NULL);
21774275Srwatson		if (error) {
21865377Srwatson			perror("extattrctl stop");
21974275Srwatson			return (-1);
22074275Srwatson		}
22159247Srwatson	} else if (!strcmp(argv[1], "enable")) {
22274275Srwatson		if (argc != 6)
22359247Srwatson			usage();
22474441Srwatson		error = extattr_string_to_namespace(argv[3], &attrnamespace);
22574275Srwatson		if (error) {
22665377Srwatson			perror("extattrctl enable");
22774275Srwatson			return (-1);
22874275Srwatson		}
22974394Stmm		error = extattrctl(argv[2], UFS_EXTATTR_CMD_ENABLE, argv[5],
23074441Srwatson		    attrnamespace, argv[4]);
23174275Srwatson		if (error) {
23274275Srwatson			perror("extattrctl enable");
23374275Srwatson			return (-1);
23474275Srwatson		}
23559247Srwatson	} else if (!strcmp(argv[1], "disable")) {
23674275Srwatson		if (argc != 5)
23759247Srwatson			usage();
23874441Srwatson		error = extattr_string_to_namespace(argv[3], &attrnamespace);
23974275Srwatson		if (error) {
24065377Srwatson			perror("extattrctl disable");
24174275Srwatson			return (-1);
24274275Srwatson		}
24374275Srwatson		error = extattrctl(argv[2], UFS_EXTATTR_CMD_DISABLE, NULL,
24474441Srwatson		    attrnamespace, argv[4]);
24574275Srwatson		if (error) {
24674275Srwatson			perror("extattrctl disable");
24774275Srwatson			return (-1);
24874275Srwatson		}
24959247Srwatson	} else if (!strcmp(argv[1], "initattr")) {
25059401Srwatson		argc -= 2;
25159401Srwatson		argv += 2;
25259401Srwatson		error = initattr(argc, argv);
25374275Srwatson		if (error)
25474275Srwatson			return (-1);
25588740Srwatson	} else if (!strcmp(argv[1], "showattr")) {
25688740Srwatson		argc -= 2;
25788740Srwatson		argv += 2;
25888740Srwatson		error = showattr(argc, argv);
25988740Srwatson		if (error)
26088740Srwatson			return (-1);
26159401Srwatson	} else
26259247Srwatson		usage();
26386994Sjedgar
26486994Sjedgar	return (0);
26559247Srwatson}
266