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