/* * parse_hesiod.c * * Module for Linux automountd to parse a hesiod filesystem entry. */ #include #include #include #include #include #include #include #define MODULE_PARSE #include "automount.h" #define MODPREFIX "parse(hesiod): " int parse_version = AUTOFS_PARSE_VERSION; /* Required by protocol */ #define HESIOD_LEN 512 /* Break out the fields in an AFS record of the form: "AFS /afs/athena/mit/tytso w /mit/tytso-afs" */ static int parse_afs(struct autofs_point *ap, const char *filsysline, const char *name, int name_len, char *source, int source_len, char *options, int options_len) { const char *p; int i; p = filsysline; /* Skip whitespace. */ while (isspace(*p)) p++; /* Skip the filesystem type. */ while (!isspace(*p)) p++; /* Skip whitespace. */ while (isspace(*p)) p++; /* Isolate the source for this AFS fs. */ for (i = 0; (!isspace(p[i]) && i < source_len); i++) { if (!p[i]) { error(ap->logopt, MODPREFIX "unexpeced end of input looking for AFS " "source: %s", p); return 1; } source[i] = p[i]; } source[i] = 0; p += i; /* Skip whitespace. */ while ((*p) && (isspace(*p))) p++; /* Isolate the options for this AFS fs. */ for (i = 0; (!isspace(p[i]) && i < options_len); i++) { if (!p[i]) { error(ap->logopt, MODPREFIX "unexpeced end of input looking for AFS " "options: %s", p); return 1; } options[i] = p[i]; } options[i] = 0; /* Hack for "r" or "w" options. */ if (!strcmp(options, "r")) strcpy(options, "ro"); if (!strcmp(options, "w")) strcpy(options, "rw"); debug(ap->logopt, MODPREFIX "parsing AFS record gives '%s'->'%s' with options" " '%s'", name, source, options); return 0; } /* * Break out the fields in an NFS record of the form: * "NFS /export/src nelson.tx.ncsu.edu w /ncsu/tx-src" */ static int parse_nfs(struct autofs_point *ap, const char *filsysline, const char *name, int name_len, char *source, int source_len, char *options, int options_len) { const char *p; char mount[HESIOD_LEN + 1]; int i; p = filsysline; /* Skip whitespace. */ while (isspace(*p)) p++; /* Skip the filesystem type. */ while (!isspace(*p)) p++; /* Skip whitespace. */ while (isspace(*p)) p++; /* Isolate the remote mountpoint for this NFS fs. */ for (i = 0; (!isspace(p[i]) && i < ((int) sizeof(mount) - 1)); i++) { if (!p[i]) { error(ap->logopt, MODPREFIX "unexpeced end of input looking for NFS " "mountpoint: %s", p); return 1; } mount[i] = p[i]; } mount[i] = 0; p += i; /* Skip whitespace. */ while ((*p) && (isspace(*p))) p++; /* Isolate the remote host. */ for (i = 0; (!isspace(p[i]) && i < source_len); i++) { if (!p[i]) { error(ap->logopt, MODPREFIX "unexpeced end of input looking for NFS " "host: %s", p); return 1; } source[i] = p[i]; } source[i] = 0; p += i; if (strlen(source) + strlen(mount) + 2 > source_len) { error(ap->logopt, MODPREFIX "entry too log for mount source"); return 1; } /* Append ":mountpoint" to the source to get "host:mountpoint". */ strcat(source, ":"); strcat(source, mount); /* Skip whitespace. */ while ((*p) && (isspace(*p))) p++; /* Isolate the mount options. */ for (i = 0; (!isspace(p[i]) && i < options_len); i++) { if (!p[i]) { error(ap->logopt, MODPREFIX "unexpeced end of input looking for NFS " "mount options: %s", p); return 1; } options[i] = p[i]; } options[i] = 0; /* Hack for "r" or "w" options. */ if (!strcmp(options, "r")) strcpy(options, "ro"); if (!strcmp(options, "w")) strcpy(options, "rw"); debug(ap->logopt, MODPREFIX "parsing NFS record gives '%s'->'%s' with options" "'%s'", name, source, options); return 0; } /* Break out the fields in a generic record of the form: "UFS /dev/ra0g w /site" */ static int parse_generic(struct autofs_point *ap, const char *filsysline, const char *name, int name_len, char *source, int source_len, char *options, int options_len) { const char *p; int i; p = filsysline; /* Skip whitespace. */ while (isspace(*p)) p++; /* Skip the filesystem type. */ while (!isspace(*p)) p++; /* Skip whitespace. */ while (isspace(*p)) p++; /* Isolate the source for this fs. */ for (i = 0; (!isspace(p[i]) && i < source_len); i++) { if (!p[i]) { error(ap->logopt, MODPREFIX "unexpeced end of input looking for generic " "mount source: %s", p); return 1; } source[i] = p[i]; } source[i] = 0; p += i; /* Skip whitespace. */ while ((*p) && (isspace(*p))) p++; /* Isolate the mount options. */ for (i = 0; (!isspace(p[i]) && i < options_len); i++) { if (!p[i]) { error(ap->logopt, MODPREFIX "unexpeced end of input looking for generic " "mount options: %s", p); return 1; } options[i] = p[i]; } options[i] = 0; /* Hack for "r" or "w" options. */ if (!strcmp(options, "r")) strcpy(options, "ro"); if (!strcmp(options, "w")) strcpy(options, "rw"); debug(ap->logopt, MODPREFIX "parsing generic record gives '%s'->'%s' with options '%s'", name, source, options); return 0; } int parse_init(int argc, const char *const *argv, void **context) { *context = NULL; return 0; } int parse_reinit(int argc, const char *const *argv, void **context) { return 0; } int parse_done(void *context) { return 0; } int parse_mount(struct autofs_point *ap, const char *name, int name_len, const char *mapent, void *context) { char source[HESIOD_LEN + 1]; char fstype[HESIOD_LEN + 1]; char options[HESIOD_LEN + 1]; char *q; const char *p; int ret; ap->entry->current = NULL; master_source_current_signal(ap->entry); p = mapent; q = fstype; /* Skip any initial whitespace... */ while (isspace(*p)) p++; /* Isolate the filesystem type... */ while (!isspace(*p)) { *q++ = tolower(*p++); } *q = 0; /* If it's an error message... */ if (!strcasecmp(fstype, "err")) { error(ap->logopt, MODPREFIX "%s", mapent); return 1; /* If it's an AFS fs... */ } else if (!strcasecmp(fstype, "afs")) ret = parse_afs(ap, mapent, name, name_len, source, sizeof(source), options, sizeof(options)); /* If it's NFS... */ else if (!strcasecmp(fstype, "nfs")) ret = parse_nfs(ap, mapent, name, name_len, source, sizeof(source), options, sizeof(options)); /* Punt. */ else ret = parse_generic(ap, mapent, name, name_len, source, sizeof(source), options, sizeof(options)); if (ret) { error(ap->logopt, MODPREFIX "failed to parse entry"); return 1; } else { debug(ap->logopt, MODPREFIX "mount %s is type %s from %s", name, fstype, source); } return do_mount(ap, ap->path, name, name_len, source, fstype, options); }