/* * 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 #include #include #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; ih_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] && ih_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); }