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