19754f5b6SRobert Watson /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni *
40a371dd9SRobert Watson * Copyright (c) 1999-2002 Robert N. M. Watson
59754f5b6SRobert Watson * All rights reserved.
69754f5b6SRobert Watson *
7a8843addSRobert Watson * This software was developed by Robert Watson for the TrustedBSD Project.
8a8843addSRobert Watson *
99754f5b6SRobert Watson * Redistribution and use in source and binary forms, with or without
109754f5b6SRobert Watson * modification, are permitted provided that the following conditions
119754f5b6SRobert Watson * are met:
129754f5b6SRobert Watson * 1. Redistributions of source code must retain the above copyright
139754f5b6SRobert Watson * notice, this list of conditions and the following disclaimer.
149754f5b6SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright
159754f5b6SRobert Watson * notice, this list of conditions and the following disclaimer in the
169754f5b6SRobert Watson * documentation and/or other materials provided with the distribution.
179754f5b6SRobert Watson *
189754f5b6SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
199754f5b6SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
209754f5b6SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
219754f5b6SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
229754f5b6SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
239754f5b6SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
249754f5b6SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
259754f5b6SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
269754f5b6SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
279754f5b6SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
289754f5b6SRobert Watson * SUCH DAMAGE.
299754f5b6SRobert Watson */
309754f5b6SRobert Watson /*
31a8843addSRobert Watson * Developed by the TrustedBSD Project.
32a8843addSRobert Watson * Support for file system extended attribute.
339754f5b6SRobert Watson */
349754f5b6SRobert Watson
359754f5b6SRobert Watson #include <sys/types.h>
369754f5b6SRobert Watson #include <sys/uio.h>
379754f5b6SRobert Watson #include <sys/extattr.h>
382a60effdSRobert Watson #include <sys/param.h>
392a60effdSRobert Watson #include <sys/mount.h>
402a60effdSRobert Watson
419754f5b6SRobert Watson #include <ufs/ufs/extattr.h>
422a60effdSRobert Watson
43bf6afea7SRobert Watson #include <errno.h>
449754f5b6SRobert Watson #include <fcntl.h>
45bf6afea7SRobert Watson #include <libutil.h>
469754f5b6SRobert Watson #include <stdio.h>
479754f5b6SRobert Watson #include <stdlib.h>
489754f5b6SRobert Watson #include <string.h>
499754f5b6SRobert Watson #include <unistd.h>
509754f5b6SRobert Watson
51f2dd987cSChris D. Faulhaber int initattr(int argc, char *argv[]);
52566726dbSRobert Watson int showattr(int argc, char *argv[]);
53f2dd987cSChris D. Faulhaber long num_inodes_by_path(char *path);
54f2dd987cSChris D. Faulhaber void usage(void);
557036b7cdSRobert Watson
569754f5b6SRobert Watson void
usage(void)579a958de5SEd Schouten usage(void)
589754f5b6SRobert Watson {
599754f5b6SRobert Watson
609754f5b6SRobert Watson fprintf(stderr,
619754f5b6SRobert Watson "usage:\n"
620a371dd9SRobert Watson " extattrctl start path\n"
630a371dd9SRobert Watson " extattrctl stop path\n"
640a371dd9SRobert Watson " extattrctl initattr [-f] [-p path] attrsize attrfile\n"
650a371dd9SRobert Watson " extattrctl showattr attrfile\n"
660a371dd9SRobert Watson " extattrctl enable path attrnamespace attrname attrfile\n"
670a371dd9SRobert Watson " extattrctl disable path attrnamespace attrname\n");
687036b7cdSRobert Watson exit(-1);
697036b7cdSRobert Watson }
707036b7cdSRobert Watson
712a60effdSRobert Watson long
num_inodes_by_path(char * path)722a60effdSRobert Watson num_inodes_by_path(char *path)
732a60effdSRobert Watson {
742a60effdSRobert Watson struct statfs buf;
752a60effdSRobert Watson int error;
762a60effdSRobert Watson
772a60effdSRobert Watson error = statfs(path, &buf);
782a60effdSRobert Watson if (error) {
792a60effdSRobert Watson perror("statfs");
802a60effdSRobert Watson return (-1);
812a60effdSRobert Watson }
822a60effdSRobert Watson
832a60effdSRobert Watson return (buf.f_files);
842a60effdSRobert Watson }
852a60effdSRobert Watson
8665528d17SDag-Erling Smørgrav static const char zero_buf[8192];
8765528d17SDag-Erling Smørgrav
887036b7cdSRobert Watson int
initattr(int argc,char * argv[])897036b7cdSRobert Watson initattr(int argc, char *argv[])
907036b7cdSRobert Watson {
917036b7cdSRobert Watson struct ufs_extattr_fileheader uef;
922a60effdSRobert Watson char *fs_path = NULL;
9365528d17SDag-Erling Smørgrav int ch, i, error, flags;
9465528d17SDag-Erling Smørgrav ssize_t wlen;
9565528d17SDag-Erling Smørgrav size_t easize;
967036b7cdSRobert Watson
9765528d17SDag-Erling Smørgrav flags = O_CREAT | O_WRONLY | O_TRUNC | O_EXCL;
982a60effdSRobert Watson optind = 0;
998f0dcdabSRobert Watson while ((ch = getopt(argc, argv, "fp:r:w:")) != -1)
1007036b7cdSRobert Watson switch (ch) {
1018f0dcdabSRobert Watson case 'f':
10265528d17SDag-Erling Smørgrav flags &= ~O_EXCL;
1031fec210aSRobert Watson break;
1047036b7cdSRobert Watson case 'p':
10565528d17SDag-Erling Smørgrav fs_path = optarg;
1067036b7cdSRobert Watson break;
1077036b7cdSRobert Watson case '?':
1087036b7cdSRobert Watson default:
1097036b7cdSRobert Watson usage();
1107036b7cdSRobert Watson }
1117036b7cdSRobert Watson
1127036b7cdSRobert Watson argc -= optind;
1137036b7cdSRobert Watson argv += optind;
1147036b7cdSRobert Watson
1157036b7cdSRobert Watson if (argc != 2)
1167036b7cdSRobert Watson usage();
1177036b7cdSRobert Watson
1187036b7cdSRobert Watson error = 0;
11965528d17SDag-Erling Smørgrav if ((i = open(argv[1], flags, 0600)) == -1) {
12065528d17SDag-Erling Smørgrav /* unable to open file */
12165528d17SDag-Erling Smørgrav perror(argv[1]);
12265528d17SDag-Erling Smørgrav return (-1);
12365528d17SDag-Erling Smørgrav }
1247036b7cdSRobert Watson uef.uef_magic = UFS_EXTATTR_MAGIC;
1257036b7cdSRobert Watson uef.uef_version = UFS_EXTATTR_VERSION;
1267036b7cdSRobert Watson uef.uef_size = atoi(argv[0]);
1277036b7cdSRobert Watson if (write(i, &uef, sizeof(uef)) == -1)
1287036b7cdSRobert Watson error = -1;
12965528d17SDag-Erling Smørgrav else if (fs_path != NULL) {
13065528d17SDag-Erling Smørgrav easize = (sizeof uef + uef.uef_size) *
13165528d17SDag-Erling Smørgrav num_inodes_by_path(fs_path);
13265528d17SDag-Erling Smørgrav while (easize > 0) {
13365528d17SDag-Erling Smørgrav if (easize > sizeof zero_buf)
13465528d17SDag-Erling Smørgrav wlen = write(i, zero_buf, sizeof zero_buf);
13565528d17SDag-Erling Smørgrav else
13665528d17SDag-Erling Smørgrav wlen = write(i, zero_buf, easize);
13765528d17SDag-Erling Smørgrav if (wlen == -1) {
13865528d17SDag-Erling Smørgrav error = -1;
13965528d17SDag-Erling Smørgrav break;
1402a60effdSRobert Watson }
14165528d17SDag-Erling Smørgrav easize -= wlen;
1422a60effdSRobert Watson }
1432a60effdSRobert Watson }
144bbf06077SRobert Watson if (error == -1) {
1452a60effdSRobert Watson perror(argv[1]);
1462a60effdSRobert Watson unlink(argv[1]);
147c10bc053SKevin Lo close(i);
1487036b7cdSRobert Watson return (-1);
1497036b7cdSRobert Watson }
1507036b7cdSRobert Watson
151c10bc053SKevin Lo close(i);
1527036b7cdSRobert Watson return (0);
1539754f5b6SRobert Watson }
1549754f5b6SRobert Watson
1559754f5b6SRobert Watson int
showattr(int argc,char * argv[])156566726dbSRobert Watson showattr(int argc, char *argv[])
157566726dbSRobert Watson {
158566726dbSRobert Watson struct ufs_extattr_fileheader uef;
159566726dbSRobert Watson int i, fd;
160566726dbSRobert Watson
161566726dbSRobert Watson if (argc != 1)
162566726dbSRobert Watson usage();
163566726dbSRobert Watson
164566726dbSRobert Watson fd = open(argv[0], O_RDONLY);
165566726dbSRobert Watson if (fd == -1) {
166566726dbSRobert Watson perror(argv[0]);
167566726dbSRobert Watson return (-1);
168566726dbSRobert Watson }
169566726dbSRobert Watson
170566726dbSRobert Watson i = read(fd, &uef, sizeof(uef));
171566726dbSRobert Watson if (i == -1) {
172566726dbSRobert Watson perror(argv[0]);
173c10bc053SKevin Lo close(fd);
174566726dbSRobert Watson return (-1);
175566726dbSRobert Watson }
176566726dbSRobert Watson if (i != sizeof(uef)) {
177566726dbSRobert Watson fprintf(stderr, "%s: invalid file header\n", argv[0]);
178c10bc053SKevin Lo close(fd);
179566726dbSRobert Watson return (-1);
180566726dbSRobert Watson }
181566726dbSRobert Watson
182566726dbSRobert Watson if (uef.uef_magic != UFS_EXTATTR_MAGIC) {
183566726dbSRobert Watson fprintf(stderr, "%s: bad magic\n", argv[0]);
184c10bc053SKevin Lo close(fd);
185566726dbSRobert Watson return (-1);
186566726dbSRobert Watson }
187566726dbSRobert Watson
188566726dbSRobert Watson printf("%s: version %d, size %d\n", argv[0], uef.uef_version,
189566726dbSRobert Watson uef.uef_size);
190566726dbSRobert Watson
191c10bc053SKevin Lo close(fd);
192566726dbSRobert Watson return (0);
193566726dbSRobert Watson }
194566726dbSRobert Watson
195566726dbSRobert Watson int
main(int argc,char * argv[])1969754f5b6SRobert Watson main(int argc, char *argv[])
1979754f5b6SRobert Watson {
198de5660b0SRobert Watson int error = 0, attrnamespace;
1999754f5b6SRobert Watson
2007036b7cdSRobert Watson if (argc < 2)
2019754f5b6SRobert Watson usage();
2029754f5b6SRobert Watson
2039754f5b6SRobert Watson if (!strcmp(argv[1], "start")) {
2047036b7cdSRobert Watson if (argc != 3)
2059754f5b6SRobert Watson usage();
206bf6afea7SRobert Watson error = extattrctl(argv[2], UFS_EXTATTR_CMD_START, NULL, 0,
207bf6afea7SRobert Watson NULL);
208bf6afea7SRobert Watson if (error) {
209bbf06077SRobert Watson perror("extattrctl start");
210bf6afea7SRobert Watson return (-1);
211bf6afea7SRobert Watson }
2129754f5b6SRobert Watson } else if (!strcmp(argv[1], "stop")) {
2137036b7cdSRobert Watson if (argc != 3)
2149754f5b6SRobert Watson usage();
215bf6afea7SRobert Watson error = extattrctl(argv[2], UFS_EXTATTR_CMD_STOP, NULL, 0,
216bf6afea7SRobert Watson NULL);
217bf6afea7SRobert Watson if (error) {
218bbf06077SRobert Watson perror("extattrctl stop");
219bf6afea7SRobert Watson return (-1);
220bf6afea7SRobert Watson }
2219754f5b6SRobert Watson } else if (!strcmp(argv[1], "enable")) {
222bf6afea7SRobert Watson if (argc != 6)
223bf6afea7SRobert Watson usage();
224de5660b0SRobert Watson error = extattr_string_to_namespace(argv[3], &attrnamespace);
225bf6afea7SRobert Watson if (error) {
226bf6afea7SRobert Watson perror("extattrctl enable");
227bf6afea7SRobert Watson return (-1);
228bf6afea7SRobert Watson }
229fccc713cSThomas Moestl error = extattrctl(argv[2], UFS_EXTATTR_CMD_ENABLE, argv[5],
230de5660b0SRobert Watson attrnamespace, argv[4]);
231bf6afea7SRobert Watson if (error) {
232bf6afea7SRobert Watson perror("extattrctl enable");
233bf6afea7SRobert Watson return (-1);
234bf6afea7SRobert Watson }
235bf6afea7SRobert Watson } else if (!strcmp(argv[1], "disable")) {
2367036b7cdSRobert Watson if (argc != 5)
2379754f5b6SRobert Watson usage();
238de5660b0SRobert Watson error = extattr_string_to_namespace(argv[3], &attrnamespace);
239bf6afea7SRobert Watson if (error) {
240bbf06077SRobert Watson perror("extattrctl disable");
241bf6afea7SRobert Watson return (-1);
242bf6afea7SRobert Watson }
243bf6afea7SRobert Watson error = extattrctl(argv[2], UFS_EXTATTR_CMD_DISABLE, NULL,
244de5660b0SRobert Watson attrnamespace, argv[4]);
245bf6afea7SRobert Watson if (error) {
246bf6afea7SRobert Watson perror("extattrctl disable");
247bf6afea7SRobert Watson return (-1);
248bf6afea7SRobert Watson }
2499754f5b6SRobert Watson } else if (!strcmp(argv[1], "initattr")) {
2507036b7cdSRobert Watson argc -= 2;
2517036b7cdSRobert Watson argv += 2;
2527036b7cdSRobert Watson error = initattr(argc, argv);
253bf6afea7SRobert Watson if (error)
254bf6afea7SRobert Watson return (-1);
255566726dbSRobert Watson } else if (!strcmp(argv[1], "showattr")) {
256566726dbSRobert Watson argc -= 2;
257566726dbSRobert Watson argv += 2;
258566726dbSRobert Watson error = showattr(argc, argv);
259566726dbSRobert Watson if (error)
260566726dbSRobert Watson return (-1);
2619754f5b6SRobert Watson } else
2629754f5b6SRobert Watson usage();
263f2dd987cSChris D. Faulhaber
264f2dd987cSChris D. Faulhaber return (0);
2659754f5b6SRobert Watson }
266