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