]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/extattrctl/extattrctl.c
ping(8): Fix a mandoc related issue
[FreeBSD/FreeBSD.git] / usr.sbin / extattrctl / extattrctl.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 1999-2002 Robert N. M. Watson
5  * All rights reserved.
6  *
7  * This software was developed by Robert Watson for the TrustedBSD Project.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32 /*
33  * Developed by the TrustedBSD Project.
34  * Support for file system extended attribute.
35  */
36
37 #include <sys/types.h>
38 #include <sys/uio.h>
39 #include <sys/extattr.h>
40 #include <sys/param.h>
41 #include <sys/mount.h>
42
43 #include <ufs/ufs/extattr.h>
44
45 #include <errno.h>
46 #include <fcntl.h>
47 #include <libutil.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <unistd.h>
52
53 int initattr(int argc, char *argv[]);
54 int showattr(int argc, char *argv[]);
55 long num_inodes_by_path(char *path);
56 void usage(void);
57
58 void
59 usage(void)
60 {
61
62         fprintf(stderr,
63             "usage:\n"
64             "  extattrctl start path\n"
65             "  extattrctl stop path\n"
66             "  extattrctl initattr [-f] [-p path] attrsize attrfile\n"
67             "  extattrctl showattr attrfile\n"
68             "  extattrctl enable path attrnamespace attrname attrfile\n"
69             "  extattrctl disable path attrnamespace attrname\n");
70         exit(-1);
71 }
72
73 long
74 num_inodes_by_path(char *path)
75 {
76         struct statfs   buf;
77         int     error;
78
79         error = statfs(path, &buf);
80         if (error) {
81                 perror("statfs");
82                 return (-1);
83         }
84
85         return (buf.f_files);
86 }
87
88 static const char zero_buf[8192];
89
90 int
91 initattr(int argc, char *argv[])
92 {
93         struct ufs_extattr_fileheader   uef;
94         char    *fs_path = NULL;
95         int     ch, i, error, flags;
96         ssize_t wlen;
97         size_t  easize;
98
99         flags = O_CREAT | O_WRONLY | O_TRUNC | O_EXCL;
100         optind = 0;
101         while ((ch = getopt(argc, argv, "fp:r:w:")) != -1)
102                 switch (ch) {
103                 case 'f':
104                         flags &= ~O_EXCL;
105                         break;
106                 case 'p':
107                         fs_path = optarg;
108                         break;
109                 case '?':
110                 default:
111                         usage();
112                 }
113
114         argc -= optind;
115         argv += optind;
116
117         if (argc != 2)
118                 usage();
119
120         error = 0;
121         if ((i = open(argv[1], flags, 0600)) == -1) {
122                 /* unable to open file */
123                 perror(argv[1]);
124                 return (-1);
125         }
126         uef.uef_magic = UFS_EXTATTR_MAGIC;
127         uef.uef_version = UFS_EXTATTR_VERSION;
128         uef.uef_size = atoi(argv[0]);
129         if (write(i, &uef, sizeof(uef)) == -1)
130                 error = -1;
131         else if (fs_path != NULL) {
132                 easize = (sizeof uef + uef.uef_size) *
133                     num_inodes_by_path(fs_path);
134                 while (easize > 0) {
135                         if (easize > sizeof zero_buf)
136                                 wlen = write(i, zero_buf, sizeof zero_buf);
137                         else
138                                 wlen = write(i, zero_buf, easize);
139                         if (wlen == -1) {
140                                 error = -1;
141                                 break;
142                         }
143                         easize -= wlen;
144                 }
145         }
146         if (error == -1) {
147                 perror(argv[1]);
148                 unlink(argv[1]);
149                 close(i);
150                 return (-1);
151         }
152
153         close(i);
154         return (0);
155 }
156
157 int
158 showattr(int argc, char *argv[])
159 {
160         struct ufs_extattr_fileheader   uef;
161         int i, fd;
162
163         if (argc != 1)
164                 usage();
165
166         fd = open(argv[0], O_RDONLY);
167         if (fd == -1) {
168                 perror(argv[0]);
169                 return (-1);
170         }
171
172         i = read(fd, &uef, sizeof(uef));
173         if (i == -1) {
174                 perror(argv[0]);
175                 close(fd);
176                 return (-1);
177         }
178         if (i != sizeof(uef)) {
179                 fprintf(stderr, "%s: invalid file header\n", argv[0]);
180                 close(fd);
181                 return (-1);
182         }
183
184         if (uef.uef_magic != UFS_EXTATTR_MAGIC) {
185                 fprintf(stderr, "%s: bad magic\n", argv[0]);
186                 close(fd);
187                 return (-1);
188         }
189
190         printf("%s: version %d, size %d\n", argv[0], uef.uef_version,
191             uef.uef_size);
192
193         close(fd);
194         return (0);
195 }
196
197 int
198 main(int argc, char *argv[])
199 {
200         int     error = 0, attrnamespace;
201
202         if (argc < 2)
203                 usage();
204
205         if (!strcmp(argv[1], "start")) {
206                 if (argc != 3)
207                         usage();
208                 error = extattrctl(argv[2], UFS_EXTATTR_CMD_START, NULL, 0,
209                     NULL);
210                 if (error) {
211                         perror("extattrctl start");
212                         return (-1);
213                 }
214         } else if (!strcmp(argv[1], "stop")) {
215                 if (argc != 3)
216                         usage();
217                 error = extattrctl(argv[2], UFS_EXTATTR_CMD_STOP, NULL, 0,
218                    NULL);
219                 if (error) {
220                         perror("extattrctl stop");
221                         return (-1);
222                 }
223         } else if (!strcmp(argv[1], "enable")) {
224                 if (argc != 6)
225                         usage();
226                 error = extattr_string_to_namespace(argv[3], &attrnamespace);
227                 if (error) {
228                         perror("extattrctl enable");
229                         return (-1);
230                 }
231                 error = extattrctl(argv[2], UFS_EXTATTR_CMD_ENABLE, argv[5],
232                     attrnamespace, argv[4]);
233                 if (error) {
234                         perror("extattrctl enable");
235                         return (-1);
236                 }
237         } else if (!strcmp(argv[1], "disable")) {
238                 if (argc != 5)
239                         usage();
240                 error = extattr_string_to_namespace(argv[3], &attrnamespace);
241                 if (error) {
242                         perror("extattrctl disable");
243                         return (-1);
244                 }
245                 error = extattrctl(argv[2], UFS_EXTATTR_CMD_DISABLE, NULL,
246                     attrnamespace, argv[4]);
247                 if (error) {
248                         perror("extattrctl disable");
249                         return (-1);
250                 }
251         } else if (!strcmp(argv[1], "initattr")) {
252                 argc -= 2;
253                 argv += 2;
254                 error = initattr(argc, argv);
255                 if (error)
256                         return (-1);
257         } else if (!strcmp(argv[1], "showattr")) {
258                 argc -= 2;
259                 argv += 2;
260                 error = showattr(argc, argv);
261                 if (error)
262                         return (-1);
263         } else
264                 usage();
265
266         return (0);
267 }