8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / fs.d / nfs / nfsref / nfsref.c
blob2fe520df0f4a88d4e8fc7507ffcd1b5486b33210
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <strings.h>
30 #include <string.h>
31 #include <limits.h>
32 #include <libnvpair.h>
33 #include <locale.h>
34 #include <sys/stat.h>
35 #include <sys/fs_reparse.h>
36 #include <rp_plugin.h>
37 #include <uuid/uuid.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <priv.h>
42 #include <nfs/nfs4.h>
43 #include <rpcsvc/nfs4_prot.h>
44 #include "ref_subr.h"
46 #ifndef TEXT_DOMAIN
47 #define TEXT_DOMAIN "SUNW_OST_OSCMD"
48 #endif /* TEXT_DOMAIN */
50 extern int errno;
52 void
53 usage()
55 fprintf(stderr, gettext("Usage:\n"));
56 fprintf(stderr,
57 gettext("\tnfsref [-t type] add path location [location ...]\n"));
58 fprintf(stderr, gettext("\tnfsref [-t type] remove path\n"));
59 fprintf(stderr, gettext("\tnfsref [-t type] lookup path\n"));
63 * Copy a string from source to destination, escaping space
64 * with a backslash and escaping the escape character as well.
66 int
67 add_escape(char *src, char *dest, int limit)
69 char *sp, *dp;
70 int destlen = 0;
72 sp = src;
73 dp = dest;
75 while (*sp && destlen < limit) {
76 if (*sp == '\\') {
77 *dp++ = '\\';
78 *dp++ = '\\';
79 destlen++;
80 } else if (*sp == ' ') {
81 *dp++ = '\\';
82 *dp++ = ' ';
83 destlen++;
84 } else
85 *dp++ = *sp;
86 destlen++;
87 sp++;
89 if (limit <= 0)
90 return (-1);
91 return (destlen);
94 int
95 addref(char *sl_path, char *svc_type, int optind, int argc, char *argv[])
97 int err, fd, i, len, oldlen, notfound = 0;
98 char *text, *location;
99 nvlist_t *nvl = NULL;
100 char buf[SYMLINK_MAX];
101 struct stat sbuf;
103 /* Get an nvlist */
104 nvl = reparse_init();
105 if (nvl == NULL)
106 return (ENOMEM);
108 /* Get the reparse point data, if the RP exists */
109 err = readlink(sl_path, buf, SYMLINK_MAX);
110 if (err == -1) {
111 if (errno == ENOENT) {
112 notfound = 1;
113 err = 0;
114 } else {
115 reparse_free(nvl);
116 return (errno);
118 } else {
119 buf[err] = '\0';
122 /* Get any data into nvlist */
123 if (notfound == 0)
124 err = reparse_parse(buf, nvl);
125 if (err != 0) {
126 reparse_free(nvl);
127 return (err);
131 * Accumulate multiple locations on the command line into 'buf'
133 oldlen = len = 0;
134 location = NULL;
135 for (i = optind; i < argc; i++) {
136 bzero(buf, sizeof (buf));
137 len += add_escape(argv[i], buf, SYMLINK_MAX) + 2;
138 location = realloc(location, len);
139 location[oldlen] = '\0';
140 oldlen = len;
141 strlcat(location, buf, len);
142 strlcat(location, " ", len);
144 location[len - 2] = '\0';
146 /* Add to the list */
147 err = reparse_add(nvl, svc_type, location);
148 if (err) {
149 reparse_free(nvl);
150 return (err);
153 /* Get the new or modified symlink contents */
154 err = reparse_unparse(nvl, &text);
155 reparse_free(nvl);
156 if (err)
157 return (err);
159 /* Delete first if found */
160 if (notfound == 0) {
161 err = reparse_delete(sl_path);
162 if (err) {
163 free(text);
164 return (err);
168 /* Finally, write out the reparse point */
169 err = reparse_create(sl_path, text);
170 free(text);
171 if (err)
172 return (err);
174 err = lstat(sl_path, &sbuf);
175 if (err == 0 && strcasecmp(sbuf.st_fstype, "ZFS") != 0)
176 printf(gettext(
177 "Warning: referrals do not work on this filesystem\n"));
179 if (notfound)
180 printf(gettext("Created reparse point %s\n"), sl_path);
181 else
182 printf(gettext("Added to reparse point %s\n"), sl_path);
184 return (0);
188 delref(char *sl_path, char *svc_type)
190 char *cp;
191 char *svc_data;
192 int err;
193 nvlist_t *nvl;
194 nvpair_t *curr;
195 char buf[SYMLINK_MAX];
196 int fd, fd2;
197 FILE *fp, *fp2;
198 char uuid[UUID_PRINTABLE_STRING_LENGTH], path[256], loc[2048];
200 /* Get an nvlist */
201 if (!(nvl = reparse_init()))
202 return (ENOMEM);
204 /* Get the symlink data (should be there) */
205 err = readlink(sl_path, buf, SYMLINK_MAX);
206 if (err == -1) {
207 reparse_free(nvl);
208 return (errno);
210 buf[err] = '\0';
212 /* Get the records into the nvlist */
213 err = reparse_parse(buf, nvl);
214 if (err) {
215 reparse_free(nvl);
216 return (err);
219 /* Remove from nvlist */
220 err = reparse_remove(nvl, svc_type);
221 if (err) {
222 reparse_free(nvl);
223 return (err);
226 /* Any list entries left? If so, turn nvlist back to string. */
227 curr = nvlist_next_nvpair(nvl, NULL);
228 if (curr != NULL) {
229 err = reparse_unparse(nvl, &cp);
230 reparse_free(nvl);
231 if (err)
232 return (err);
233 } else {
234 reparse_free(nvl);
235 cp = NULL;
238 /* Finally, delete and perhaps recreate the reparse point */
239 err = reparse_delete(sl_path);
240 if (err) {
241 free(cp);
242 return (err);
245 if (cp != NULL) {
246 err = reparse_create(sl_path, cp);
247 free(cp);
248 if (err)
249 return (err);
251 printf(gettext("Removed svc_type '%s' from %s\n"), svc_type, sl_path);
252 return (err);
256 lookup(char *sl_path, char *svc_type, int type_set)
258 int err;
259 size_t bufsize;
260 char buf[1024];
261 char *type, *svc_data;
262 nvlist_t *nvl;
263 nvpair_t *curr;
264 fs_locations4 fsl;
265 XDR xdr;
267 if (!(nvl = reparse_init()))
268 return (-1);
270 /* Get reparse point data */
271 err = readlink(sl_path, buf, SYMLINK_MAX);
272 if (err == -1)
273 return (errno);
274 buf[err] = '\0';
276 /* Parse it to an nvlist */
277 err = reparse_parse(buf, nvl);
278 if (err) {
279 reparse_free(nvl);
280 return (err);
283 /* Look for entries of the requested service type */
284 curr = NULL;
285 while ((curr = nvlist_next_nvpair(nvl, curr)) != NULL) {
286 type = nvpair_name(curr);
287 if (type_set && strcasecmp(type, svc_type) == 0)
288 break;
289 if (!type_set && strncasecmp(type, "nfs", 3) == 0)
290 break;
292 if (curr == NULL) {
293 reparse_free(nvl);
294 return (ENOENT);
297 /* Get the service data and look it up */
298 nvpair_value_string(curr, &svc_data);
300 bufsize = sizeof (buf);
301 err = reparse_deref(type, svc_data, buf, &bufsize);
302 reparse_free(nvl);
303 if (err)
304 return (err);
306 xdrmem_create(&xdr, buf, bufsize, XDR_DECODE);
307 err = xdr_fs_locations4(&xdr, &fsl);
308 XDR_DESTROY(&xdr);
309 if (err != TRUE)
310 return (ENOENT);
311 printf(gettext("%s points to: "), sl_path);
312 print_referral_summary(&fsl);
313 return (0);
316 extern char *optarg;
317 extern int optind, optopt;
320 main(int argc, char *argv[])
322 char c, *command, *sl_path, *svc_type;
323 int type_set, err;
325 (void) setlocale(LC_ALL, "");
326 (void) textdomain(TEXT_DOMAIN);
328 svc_type = "nfs-basic"; /* Default from SMF some day */
329 type_set = 0; /* Lookup any nfs type */
331 /* Look for options (just the service type now) */
332 while ((c = getopt(argc, argv, "t:")) != -1) {
333 switch (c) {
334 case 't':
335 svc_type = optarg;
336 type_set = 1;
337 break;
339 default:
340 usage();
341 exit(1);
345 /* Make sure there's at least a command and one argument */
346 if (optind + 1 >= argc) {
347 usage();
348 exit(1);
351 err = rp_plugin_init();
352 switch (err) {
353 case RP_OK:
354 break;
355 case RP_NO_PLUGIN_DIR:
356 fprintf(stderr,
357 gettext("Warning: no plugin directory, continuing...\n"));
358 break;
359 case RP_NO_PLUGIN:
360 fprintf(stderr,
361 gettext("Warning: no plugin found, continuing...\n"));
362 break;
363 case RP_NO_MEMORY:
364 fprintf(stderr,
365 gettext("rp_plugin_init failed, no memory\n"));
366 exit(0);
367 default:
368 fprintf(stderr,
369 gettext("rp_plugin_init failed, error %d\n"), err);
370 exit(0);
373 command = argv[optind++];
374 sl_path = argv[optind++];
376 if (strcmp(command, "add") == 0) {
378 if (optind >= argc) {
379 usage();
380 exit(1);
383 err = addref(sl_path, svc_type, optind, argc, argv);
385 } else if (strcmp(command, "remove") == 0) {
387 err = delref(sl_path, svc_type);
389 } else if (strcmp(command, "lookup") == 0) {
391 err = lookup(sl_path, svc_type, type_set);
393 } else {
394 usage();
395 exit(1);
397 if (err != 0)
398 fprintf(stderr, gettext("Command %s failed: %s\n"), command,
399 strerror(err));
400 return (err);