dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / fs.d / nfs / lib / replica.c
blob797a73e84e361cf0b943ce512096af2c0e87c2aa
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * replica.c
25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
30 * Parse replicated server lists of the form:
32 * host1:/path1,host2,host3,host4:/path2,host5:/path3
34 * into an array containing its constituent parts:
36 * host1 /path1
37 * host2 /path2
38 * host3 /path2
39 * host4 /path2
40 * host5 /path3
41 * where a server could also be represented in form of literal address
42 * and in case it is an IPv6 literal address it will be enclosed in
43 * square brackets [IPv6 Literal address]
44 * Problems indicated by null return; they will be memory allocation
45 * errors worthy of an error message unless count == -1, which means
46 * a parse error.
49 #include <stdio.h>
50 #include <malloc.h>
51 #include <string.h>
52 #include <strings.h>
53 #include <sys/types.h>
54 #include <errno.h>
55 #include "replica.h"
57 void
58 free_replica(struct replica *list, int count)
60 int i;
62 for (i = 0; i < count; i++) {
63 free(list[i].host);
64 free(list[i].path);
66 free(list);
69 struct replica *
70 parse_replica(char *special, int *count)
72 struct replica *list = NULL;
73 char *root, *special2;
74 char *proot, *x, *y;
75 int scount, v6addr, i;
76 int found_colon = 0;
78 *count = 0;
79 scount = 0;
80 v6addr = 0;
81 root = special2 = strdup(special);
82 proot = root;
84 while (root) {
85 switch (*root) {
86 case '[':
87 if ((root != special2) && (*(root -1) != ',')) {
88 root++;
89 break;
91 y = strchr(root, ']');
92 if (!y) {
93 root++;
94 break;
96 if ((*(y + 1) != ',') && (*(y + 1) != ':')) {
97 root = y + 1;
98 break;
101 * Found a v6 Literal Address, so set "v6addr"
102 * and grab the address and store it in the list
103 * under "host part".
105 proot = root + 1;
106 root = y + 1;
107 v6addr = 1;
108 if ((list = reallocarray(list, *count + 1,
109 sizeof (struct replica))) == NULL)
110 goto bad;
111 bzero(&list[(*count)++], sizeof (struct replica));
112 *y = '\0';
113 list[*count-1].host = strdup(proot);
114 if (!list[*count-1].host)
115 goto bad;
116 break;
117 case ':':
118 *root = '\0';
119 x = root + 1;
121 * Find comma (if present), which bounds the path.
122 * The comma implies that the user is trying to
123 * specify failover syntax if another colon follows.
125 if (((y = strchr(x, ',')) != NULL) &&
126 (strchr((y + 1), ':'))) {
127 root = y + 1;
128 *y = '\0';
129 } else {
130 found_colon = 1;
131 root = NULL;
134 * If "v6addr" is set, unset it, and since the "host
135 * part" is already taken care of, skip to the "path
136 * path" part.
138 if (v6addr == 1)
139 v6addr = 0;
140 else {
141 if ((list = reallocarray(list, *count + 1,
142 sizeof (struct replica))) == NULL)
143 goto bad;
144 bzero(&list[(*count)++],
145 sizeof (struct replica));
146 list[*count-1].host = strdup(proot);
147 if (!list[*count-1].host)
148 goto bad;
149 proot = root;
152 for (i = scount; i < *count; i++) {
153 list[i].path = strdup(x);
154 if (!list[i].path)
155 goto bad;
157 scount = i;
158 proot = root;
159 if (y)
160 *y = ',';
161 break;
162 case ',':
164 * If "v6addr" is set, unset it and continue
165 * else grab the address and store it in the list
166 * under "host part".
168 if (v6addr == 1) {
169 v6addr = 0;
170 proot = ++root;
171 } else {
172 *root = '\0';
173 root++;
174 if ((list = reallocarray(list, *count + 1,
175 sizeof (struct replica))) == NULL)
176 goto bad;
177 bzero(&list[(*count)++],
178 sizeof (struct replica));
179 list[*count-1].host = strdup(proot);
180 if (!list[*count-1].host)
181 goto bad;
182 proot = root;
183 *(root - 1) = ',';
185 break;
186 default:
187 if (*root == '\0')
188 root = NULL;
189 else
190 root++;
193 if (found_colon) {
194 free(special2);
195 return (list);
197 bad:
198 if (list)
199 free_replica(list, *count);
200 if (!found_colon)
201 *count = -1;
202 free(special2);
203 return (NULL);