]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/mountd/fsloc.c
statd: Replace note() with xlog() in rpc.statd
[nfs-utils.git] / utils / mountd / fsloc.c
1 /*
2  * COPYRIGHT (c) 2006
3  * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
4  * ALL RIGHTS RESERVED
5  *
6  * Permission is granted to use, copy, create derivative works
7  * and redistribute this software and such derivative works
8  * for any purpose, so long as the name of The University of
9  * Michigan is not used in any advertising or publicity
10  * pertaining to the use of distribution of this software
11  * without specific, written prior authorization.  If the
12  * above copyright notice or any other identification of the
13  * University of Michigan is included in any copy of any
14  * portion of this software, then the disclaimer below must
15  * also be included.
16  *
17  * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
18  * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
19  * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
20  * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
21  * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
23  * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
24  * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
25  * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
26  * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
27  * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGES.
29  */
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <syslog.h>
34
35 #include "fsloc.h"
36 #include "exportfs.h"
37
38 /* Debugging tool: prints out @servers info to syslog */
39 static void replicas_print(struct servers *sp)
40 {
41         int i;
42         if (!sp) {
43                 xlog(L_NOTICE, "NULL replicas pointer\n");
44                 return;
45         }
46         xlog(L_NOTICE, "replicas listsize=%i\n", sp->h_num);
47         for (i=0; i<sp->h_num; i++) {
48                 xlog(L_NOTICE, "    %s:%s\n",
49                        sp->h_mp[i]->h_host, sp->h_mp[i]->h_path);
50         }
51 }
52
53 #ifdef DEBUG
54 /* Called by setting 'Method = stub' in config file.  Just returns
55  * some syntactically correct gibberish for testing purposes.
56  */
57 static struct servers *method_stub(char *key)
58 {
59         struct servers *sp;
60         struct mount_point *mp;
61
62         xlog(L_NOTICE, "called method_stub\n");
63         sp = malloc(sizeof(struct servers));
64         if (!sp)
65                 return NULL;
66         mp = calloc(1, sizeof(struct mount_point));
67         if (!mp) {
68                 free(sp);
69                 return NULL;
70         }
71         sp->h_num = 1;
72         sp->h_mp[0] = mp;
73         mp->h_host = strdup("stub_server");
74         mp->h_path = strdup("/my/test/path");
75         sp->h_referral = 1;
76         return sp;
77 }
78 #endif  /* DEBUG */
79
80 /* Scan @list, which is a NULL-terminated array of strings of the
81  * form path@host[+host], and return corresponding servers structure.
82  */
83 static struct servers *parse_list(char **list)
84 {
85         int i;
86         struct servers *res;
87         struct mount_point *mp;
88         char *cp;
89
90         res = malloc(sizeof(struct servers));
91         if (!res)
92                 return NULL;
93         res->h_num = 0;
94
95         /* parse each of the answers in sucession. */
96         for (i=0; list[i] && i<FSLOC_MAX_LIST; i++) {
97                 mp = calloc(1, sizeof(struct mount_point));
98                 if (!mp) {
99                         release_replicas(res);
100                         return NULL;
101                 }
102                 cp = strchr(list[i], '@');
103                 if ((!cp) || list[i][0] != '/') {
104                         xlog(L_WARNING, "invalid entry '%s'", list[i]);
105                         continue; /* XXX Need better error handling */
106                 }
107                 res->h_mp[i] = mp;
108                 res->h_num++;
109                 mp->h_path = strndup(list[i], cp - list[i]);
110                 cp++;
111                 mp->h_host = strdup(cp);
112                 /* hosts are '+' separated, kernel expects ':' separated */
113                 while ( (cp = strchr(mp->h_host, '+')) )
114                        *cp = ':';
115         }
116         return res;
117 }
118
119 /* @data is a string of form path@host[+host][:path@host[+host]]
120  */
121 static struct servers *method_list(char *data)
122 {
123         char *copy, *ptr=data;
124         char **list;
125         int i, listsize;
126         struct servers *rv=NULL;
127
128         xlog(L_NOTICE, "method_list(%s)\n", data);
129         for (ptr--, listsize=1; ptr; ptr=index(ptr, ':'), listsize++)
130                 ptr++;
131         list = malloc(listsize * sizeof(char *));
132         copy = strdup(data);
133         if (copy)
134                 xlog(L_NOTICE, "converted to %s\n", copy);
135         if (list && copy) {
136                 ptr = copy;
137                 for (i=0; i<listsize; i++) {
138                         list[i] = strsep(&ptr, ":");
139                 }
140                 rv = parse_list(list);
141         }
142         free(copy);
143         free(list);
144         replicas_print(rv);
145         return rv;
146 }
147
148 /* Returns appropriately filled struct servers, or NULL if had a problem */
149 struct servers *replicas_lookup(int method, char *data, char *key)
150 {
151         struct servers *sp=NULL;
152         switch(method) {
153         case FSLOC_NONE:
154                 break;
155         case FSLOC_REFER:
156                 sp = method_list(data);
157                 if (sp)
158                         sp->h_referral = 1;
159                 break;
160         case FSLOC_REPLICA:
161                 sp = method_list(data);
162                 if (sp)
163                         sp->h_referral = 0;
164                 break;
165 #ifdef DEBUG
166         case FSLOC_STUB:
167                 sp = method_stub(data);
168                 break;
169 #endif
170         default:
171                 xlog(L_WARNING, "Unknown method = %i", method);
172         }
173         replicas_print(sp);
174         return sp;
175 }
176
177 void release_replicas(struct servers *server)
178 {
179         int i;
180
181         if (!server) return;
182         for (i = 0; i < server->h_num; i++) {
183                 free(server->h_mp[i]->h_host);
184                 free(server->h_mp[i]->h_path);
185                 free(server->h_mp[i]);
186         }
187         free(server);
188 }