]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/mountd/fsloc.c
Add missing fsloc.[ch] files - oops.
[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                 syslog(LOG_INFO, "NULL replicas pointer");
44                 return;
45         }
46         syslog(LOG_INFO, "replicas listsize=%i", sp->h_num);
47         for (i=0; i<sp->h_num; i++) {
48                 syslog(LOG_INFO, "%s:%s",
49                        sp->h_mp[i]->h_host, sp->h_mp[i]->h_path);
50         }
51 }
52
53 /* Called by setting 'Method = stub' in config file.  Just returns
54  * some syntactically correct gibberish for testing purposes.
55  */
56 static struct servers *method_stub(char *key)
57 {
58         struct servers *sp;
59         struct mount_point *mp;
60
61         syslog(LOG_INFO, "called method_stub");
62         sp = malloc(sizeof(struct servers));
63         if (!sp)
64                 return NULL;
65         mp = calloc(1, sizeof(struct mount_point));
66         if (!mp) {
67                 free(sp);
68                 return NULL;
69         }
70         sp->h_num = 1;
71         sp->h_mp[0] = mp;
72         mp->h_host = strdup("stub_server");
73         mp->h_path = strdup("/my/test/path");
74         sp->h_referral = 1;
75         return sp;
76 }
77
78 /* Scan @list, which is a NULL-terminated array of strings of the
79  * form path@host[+host], and return corresponding servers structure.
80  */
81 static struct servers *parse_list(char **list)
82 {
83         int i;
84         struct servers *res;
85         struct mount_point *mp;
86         char *cp;
87
88         res = malloc(sizeof(struct servers));
89         if (!res)
90                 return NULL;
91         res->h_num = 0;
92
93         /* parse each of the answers in sucession. */
94         for (i=0; list[i] && i<FSLOC_MAX_LIST; i++) {
95                 mp = calloc(1, sizeof(struct mount_point));
96                 if (!mp) {
97                         release_replicas(res);
98                         return NULL;
99                 }
100                 cp = strchr(list[i], '@');
101                 if ((!cp) || list[i][0] != '/') {
102                         syslog(LOG_WARNING, "invalid entry '%s'", list[i]);
103                         continue; /* XXX Need better error handling */
104                 }
105                 res->h_mp[i] = mp;
106                 res->h_num++;
107                 mp->h_path = strndup(list[i], cp - list[i]);
108                 cp++;
109                 mp->h_host = strdup(cp);
110                 /* hosts are '+' separated, kernel expects ':' separated */
111                 while ( (cp = strchr(mp->h_host, '+')) )
112                        *cp = ':';
113         }
114         return res;
115 }
116
117 /* @data is a string of form path@host[+host][:path@host[+host]]
118  */
119 static struct servers *method_list(char *data)
120 {
121         char *copy, *ptr=data;
122         char **list;
123         int i, listsize;
124         struct servers *rv=NULL;
125
126         syslog(LOG_INFO, "method_list(%s)\n", data);
127         for (ptr--, listsize=1; ptr; ptr=index(ptr, ':'), listsize++)
128                 ptr++;
129         list = malloc(listsize * sizeof(char *));
130         copy = strdup(data);
131         if (copy)
132                 syslog(LOG_INFO, "converted to %s\n", copy);
133         if (list && copy) {
134                 ptr = copy;
135                 for (i=0; i<listsize; i++) {
136                         list[i] = strsep(&ptr, ":");
137                 }
138                 rv = parse_list(list);
139         }
140         free(copy);
141         free(list);
142         replicas_print(rv);
143         return rv;
144 }
145
146 /* Returns appropriately filled struct servers, or NULL if had a problem */
147 struct servers *replicas_lookup(int method, char *data, char *key)
148 {
149         struct servers *sp=NULL;
150         switch(method) {
151         case FSLOC_NONE:
152                 break;
153         case FSLOC_REFER:
154                 sp = method_list(data);
155                 if (sp)
156                         sp->h_referral = 1;
157                 break;
158         case FSLOC_REPLICA:
159                 sp = method_list(data);
160                 if (sp)
161                         sp->h_referral = 0;
162                 break;
163         case FSLOC_STUB:
164                 sp = method_stub(data);
165                 break;
166         default:
167                 syslog(LOG_WARNING, "Unknown method = %i", method);
168         }
169         replicas_print(sp);
170         return sp;
171 }
172
173 void release_replicas(struct servers *server)
174 {
175         int i;
176
177         if (!server) return;
178         for (i = 0; i < server->h_num; i++) {
179                 free(server->h_mp[i]->h_host);
180                 free(server->h_mp[i]->h_path);
181                 free(server->h_mp[i]);
182         }
183         free(server);
184 }