/* -*- Mode: C; -*- * ---------------------------------------------------------------------------- * Title: map_static support for unfs3 * Created: 2013-09-12 * Author: Gilbert Baumann * ---------------------------------------------------------------------------- * (c) copyright 2013 by Gilbert Baumann, see LICENSE FILE for details. */ #include #include #include #include "map_static.h" /* -- Static Mapping ----------------------------------------------------------------------- */ /* * The nfsd documentation says: * * This option enables static mapping. It specifies the name of the * file that describes the uid/gid mapping, e.g. * * map_static=/etc/nfs/foobar.map * * The file’s format looks like this * * # Mapping for client foobar: * # remote local * uid 0-99 - # squash these * uid 100-500 1000 # map 100-500 to 1000-1500 * gid 0-49 - # squash these * gid 50-100 700 # map 50-100 to 700-750 * */ /* -- TODO --------------------------------------------------------------------------------- */ /* * - Having no map file, should map identity * - Check for being bijective */ /* ----------------------------------------------------------------------------------------- */ struct map_static *read_map_static(char *filename) { FILE *input = fopen(filename, "r"); char buf[256], kind[256], remote[256], local[256]; char *s, *p; int lineno = 0; int lo, hi, to; int k; struct map_static *res = NULL; if (input == 0) { fprintf(stderr, "Cannot open static map file \"%s\"\n", filename); return 0; } while ((s = fgets(buf, sizeof(buf), input)) != NULL) { int n = strlen(s); lineno++; if ((n == 0) || (s[n - 1] != '\n')) { int c = getc(input); if (c == EOF) { fprintf(stderr, "%s:%d: warning: Line not ended by '\\n'\n", filename, lineno); goto parse; } else { fprintf(stderr, "%s:%d: line too long --- ignoring\n", filename, lineno); while ((c != EOF) && (c != '\n')) c = getc(input); } } else { s[n - 1] = '\0'; parse: p = strchr(s, '#'); if (p) *p = 0; n = sscanf(s, " %s %s %s", kind, remote, local); if (n == 3) { if (0 == strcmp(kind, "gid")) k = 'g'; else if (0 == strcmp(kind, "uid")) k = 'u'; else { fprintf(stderr, "%s:%d: first part must be either \"uid\" or \"gid\".\n", filename, lineno); goto bad; } /* remote part */ if ((0 == strcmp("-", remote))) { lo = hi = -1; } else if ((2 == sscanf(remote, "%d-%d%n", &lo, &hi, &n)) && (n == (int) strlen(remote))) { } else if ((1 == sscanf(remote, "%d%n", &lo, &n)) && (n == (int) strlen(remote))) { hi = lo; } else { fprintf(stderr, "%s:%d: bad remote part.\n", filename, lineno); goto bad; } /* local part */ if ((0 == strcmp("-", local))) { to = -1; } else if ((1 == sscanf(local, "%d%n", &to, &n)) && (n == (int) strlen(local))) { } else { fprintf(stderr, "%s:%d: bad local part.\n", filename, lineno); goto bad; } if (lo > hi) { fprintf(stderr, "%s:%d: reverse range.\n", filename, lineno); goto bad; } /* all fine */ { struct map_static *q = calloc(1, sizeof(*q)); q->kind = k; q->remote_lo = lo; q->remote_hi = hi; q->local_base = to; q->next = res; res = q; } } else if (n != -1) fprintf(stderr, "%s:%d: malformed line (n = %d).\n", filename, lineno, n); bad: ; } } fclose(input); return res; } int map_static_uid_L2R(struct map_static *map, int uid) { struct map_static *p; for (p = map; p; p = p->next) { if ((p->kind == 'u') && (uid >= p->local_base) && (uid <= p->local_base + (p->remote_hi - p->remote_lo))) return (p->remote_lo == -1) ? -2 : p->remote_lo + (uid - p->local_base); } return -1; } int map_static_gid_L2R(struct map_static *map, int gid) { struct map_static *p; for (p = map; p; p = p->next) { if ((p->kind == 'g') && (gid >= p->local_base) && (gid <= p->local_base + (p->remote_hi - p->remote_lo))) return (p->remote_lo == -1) ? -2 : p->remote_lo + (gid - p->local_base); } return -1; } int map_static_uid_R2L(struct map_static *map, int uid) { struct map_static *p; for (p = map; p; p = p->next) { if ((p->kind == 'u') && (uid >= p->remote_lo) && (uid <= p->remote_hi)) return (p->local_base == -1) ? -2 : p->local_base + (uid - p->remote_lo); } return -1; } int map_static_gid_R2L(struct map_static *map, int gid) { struct map_static *p; for (p = map; p; p = p->next) { if ((p->kind == 'g') && (gid >= p->remote_lo) && (gid <= p->remote_hi)) return (p->local_base == -1) ? -2 : p->local_base + (gid - p->remote_lo); } return -1; } #if 1 int main(int argc, char **argv) { struct map_static *q, *p; q = read_map_static(argv[1]); for (p = q; p; p = p->next) { printf("# we will map [%d,%d] to %d\n", p->remote_lo, p->remote_hi, p->local_base); } printf("sizeof (unsigned long) = %d\n", sizeof(unsigned long)); printf("sizeof (unsigned int) = %d\n", sizeof(unsigned int)); printf("sizeof (uid_t) = %d\n", sizeof(uid_t)); return 0; } #endif