X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fmountd%2Fcache.c;h=2468bc5916084e06323341ed6aeab006378beef9;hp=609c6e3ed015f23b14934471104d184c06be5590;hb=0fe42a6e2cd7252c5c12a5f4edb4c27789b0c043;hpb=86c3a79a108091fe08869a887438cc2d4e1126ed diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c index 609c6e3..2468bc5 100644 --- a/utils/mountd/cache.c +++ b/utils/mountd/cache.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -167,6 +168,41 @@ void auth_unix_gid(FILE *f) } #if USE_BLKID +static const char *get_uuid_blkdev(char *path) +{ + static blkid_cache cache = NULL; + struct stat stb; + char *devname; + blkid_tag_iterate iter; + blkid_dev dev; + const char *type; + const char *val = NULL; + + if (cache == NULL) + blkid_get_cache(&cache, NULL); + + if (stat(path, &stb) != 0) + return NULL; + devname = blkid_devno_to_devname(stb.st_dev); + if (!devname) + return NULL; + dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL); + free(devname); + if (!dev) + return NULL; + iter = blkid_tag_iterate_begin(dev); + if (!iter) + return NULL; + while (blkid_tag_next(iter, &type, &val) == 0) + if (strcmp(type, "UUID") == 0) + break; + blkid_tag_iterate_end(iter); + return val; +} +#else +#define get_uuid_blkdev(path) (NULL) +#endif + int get_uuid(char *path, char *uuid, int uuidlen, char *u) { /* extract hex digits from uuidstr and compose a uuid @@ -174,36 +210,22 @@ int get_uuid(char *path, char *uuid, int uuidlen, char *u) * a smaller uuid. Then compare with uuid */ int i = 0; - const char *val; + const char *val = NULL; + char fsid_val[17]; if (path) { - static blkid_cache cache = NULL; - struct stat stb; - char *devname; - blkid_tag_iterate iter; - blkid_dev dev; - const char *type; - if (cache == NULL) - blkid_get_cache(&cache, NULL); - - if (stat(path, &stb) != 0) - return 0; - devname = blkid_devno_to_devname(stb.st_dev); - if (!devname) - return 0; - dev = blkid_get_dev(cache, devname, BLKID_DEV_NORMAL); - free(devname); - if (!dev) - return 0; - iter = blkid_tag_iterate_begin(dev); - if (!iter) - return 0; - while (blkid_tag_next(iter, &type, &val) == 0) - if (strcmp(type, "UUID") == 0) - break; - blkid_tag_iterate_end(iter); - if (!type) - return 0; + val = get_uuid_blkdev(path); + if (!val) { + struct statfs64 st; + + if (statfs64(path, &st)) + return 0; + if (!st.f_fsid.__val[0] && !st.f_fsid.__val[1]) + return 0; + snprintf(fsid_val, 17, "%08x%08x", + st.f_fsid.__val[0], st.f_fsid.__val[1]); + val = fsid_val; + } } else { val = uuid; } @@ -229,7 +251,6 @@ int get_uuid(char *path, char *uuid, int uuidlen, char *u) } return 1; } -#endif /* Iterate through /etc/mtab, finding mountpoints * at or below a given path @@ -373,7 +394,7 @@ void nfsd_fh(FILE *f) /* Now determine export point for this fsid/domain */ for (i=0 ; i < MCL_MAXTYPES; i++) { nfs_export *next_exp; - for (exp = exportlist[i]; exp; exp = next_exp) { + for (exp = exportlist[i].p_head; exp; exp = next_exp) { struct stat stb; char u[16]; char *path; @@ -439,20 +460,15 @@ void nfsd_fh(FILE *f) if (!is_mountpoint(path)) continue; check_uuid: -#if USE_BLKID if (exp->m_export.e_uuid) get_uuid(NULL, exp->m_export.e_uuid, uuidlen, u); - else if (get_uuid(path, NULL, - uuidlen, u) == 0) + else if (get_uuid(path, NULL, uuidlen, u) == 0) continue; if (memcmp(u, fhuuid, uuidlen) != 0) continue; break; -#else - continue; -#endif } if (use_ipaddr) { if (he == NULL) { @@ -548,7 +564,7 @@ static void write_fsloc(FILE *f, struct exportent *ep, char *path) release_replicas(servers); } -static void write_secinfo(FILE *f, struct exportent *ep) +static void write_secinfo(FILE *f, struct exportent *ep, int flag_mask) { struct sec_entry *p; @@ -562,7 +578,7 @@ static void write_secinfo(FILE *f, struct exportent *ep) qword_printint(f, p - ep->e_secinfo); for (p = ep->e_secinfo; p->flav; p++) { qword_printint(f, p->flav->fnum); - qword_printint(f, p->flags); + qword_printint(f, p->flags & flag_mask); } } @@ -574,17 +590,14 @@ static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *ex qword_printint(f, time(0)+30*60); if (exp) { int different_fs = strcmp(path, exp->e_path) != 0; - - if (different_fs) - qword_printint(f, exp->e_flags & ~NFSEXP_FSID); - else - qword_printint(f, exp->e_flags); + int flag_mask = different_fs ? ~NFSEXP_FSID : ~0; + + qword_printint(f, exp->e_flags & flag_mask); qword_printint(f, exp->e_anonuid); qword_printint(f, exp->e_anongid); qword_printint(f, exp->e_fsid); write_fsloc(f, exp, path); - write_secinfo(f, exp); -#if USE_BLKID + write_secinfo(f, exp, flag_mask); if (exp->e_uuid == NULL || different_fs) { char u[16]; if (get_uuid(path, NULL, 16, u)) { @@ -592,76 +605,53 @@ static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *ex qword_printhex(f, u, 16); } } else { + char u[16]; + get_uuid(NULL, exp->e_uuid, 16, u); qword_print(f, "uuid"); - qword_printhex(f, exp->e_uuid, 16); + qword_printhex(f, u, 16); } -#endif } return qword_eol(f); } -void nfsd_export(FILE *f) +static int is_subdirectory(char *subpath, char *path) { - /* requests are: - * domain path - * determine export options and return: - * domain path expiry flags anonuid anongid fsid - */ + int l = strlen(path); - char *cp; - int i; - char *dom, *path; - nfs_export *exp, *found = NULL; - int found_type = 0; - struct in_addr addr; - struct hostent *he = NULL; - - - if (readline(fileno(f), &lbuf, &lbuflen) != 1) - return; - - xlog(D_CALL, "nfsd_export: inbuf '%s'", lbuf); + return strcmp(subpath, path) == 0 + || (strncmp(subpath, path, l) == 0 && path[l] == '/'); +} - cp = lbuf; - dom = malloc(strlen(cp)); - path = malloc(strlen(cp)); +static int path_matches(nfs_export *exp, char *path) +{ + if (exp->m_export.e_flags & NFSEXP_CROSSMOUNT) + return is_subdirectory(path, exp->m_export.e_path); + return strcmp(path, exp->m_export.e_path) == 0; +} - if (!dom || !path) - goto out; +static int client_matches(nfs_export *exp, char *dom, struct hostent *he) +{ + if (use_ipaddr) + return client_check(exp->m_client, he); + return client_member(dom, exp->m_client->m_hostname); +} - if (qword_get(&cp, dom, strlen(lbuf)) <= 0) - goto out; - if (qword_get(&cp, path, strlen(lbuf)) <= 0) - goto out; +static int export_matches(nfs_export *exp, char *dom, char *path, struct hostent *he) +{ + return path_matches(exp, path) && client_matches(exp, dom, he); +} - auth_reload(); +static nfs_export *lookup_export(char *dom, char *path, struct hostent *he) +{ + nfs_export *exp; + nfs_export *found = NULL; + int found_type = 0; + int i; - /* now find flags for this export point in this domain */ for (i=0 ; i < MCL_MAXTYPES; i++) { - for (exp = exportlist[i]; exp; exp = exp->m_next) { - if (!use_ipaddr && !client_member(dom, exp->m_client->m_hostname)) + for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { + if (!export_matches(exp, dom, path, he)) continue; - if (exp->m_export.e_flags & NFSEXP_CROSSMOUNT) { - /* if path is a mountpoint below e_path, then OK */ - int l = strlen(exp->m_export.e_path); - if (strcmp(path, exp->m_export.e_path) == 0 || - (strncmp(path, exp->m_export.e_path, l) == 0 && - path[l] == '/' && - is_mountpoint(path))) - /* ok */; - else - continue; - } else if (strcmp(path, exp->m_export.e_path) != 0) - continue; - if (use_ipaddr) { - if (he == NULL) { - if (!inet_aton(dom, &addr)) - goto out; - he = client_resolve(addr); - } - if (!client_check(exp->m_client, he)) - continue; - } if (!found) { found = exp; found_type = i; @@ -689,6 +679,50 @@ void nfsd_export(FILE *f) } } } + return found; +} + +void nfsd_export(FILE *f) +{ + /* requests are: + * domain path + * determine export options and return: + * domain path expiry flags anonuid anongid fsid + */ + + char *cp; + char *dom, *path; + nfs_export *found = NULL; + struct in_addr addr; + struct hostent *he = NULL; + + + if (readline(fileno(f), &lbuf, &lbuflen) != 1) + return; + + xlog(D_CALL, "nfsd_export: inbuf '%s'", lbuf); + + cp = lbuf; + dom = malloc(strlen(cp)); + path = malloc(strlen(cp)); + + if (!dom || !path) + goto out; + + if (qword_get(&cp, dom, strlen(lbuf)) <= 0) + goto out; + if (qword_get(&cp, path, strlen(lbuf)) <= 0) + goto out; + + auth_reload(); + + if (use_ipaddr) { + if (!inet_aton(dom, &addr)) + goto out; + he = client_resolve(addr); + } + + found = lookup_export(dom, path, he); if (found) { if (dump_to_cache(f, dom, path, &found->m_export) < 0) {