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