diff options
Diffstat (limited to 'support/export/fsloc.c')
-rw-r--r-- | support/export/fsloc.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/support/export/fsloc.c b/support/export/fsloc.c new file mode 100644 index 0000000..1b869b6 --- /dev/null +++ b/support/export/fsloc.c @@ -0,0 +1,203 @@ +/* + * 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]); + free(mp); + 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=strchr(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); +} |