| diff -up nfs-utils-1.3.0/configure.ac.orig nfs-utils-1.3.0/configure.ac |
| --- nfs-utils-1.3.0/configure.ac.orig 2017-03-31 15:55:05.544831618 -0400 |
| +++ nfs-utils-1.3.0/configure.ac 2017-03-31 15:58:38.833955546 -0400 |
| @@ -64,8 +64,14 @@ unitdir=/usr/lib/systemd/system |
| AC_ARG_WITH(systemd, |
| [AC_HELP_STRING([--with-systemd@<:@=unit-dir-path@:>@], |
| [install systemd unit files @<:@Default: no, and path defaults to /usr/lib/systemd/system if not given@:>@])], |
| - test "$withval" = "no" && use_systemd=0 || unitdir=$withval use_systemd=1 |
| - use_systemd=0 |
| + if test "$withval" != "no" ; then |
| + use_systemd=1 |
| + if test "$withval" != "yes" ; then |
| + unitdir=$withval |
| + fi |
| + else |
| + use_systemd=0 |
| + fi |
| ) |
| AM_CONDITIONAL(INSTALL_SYSTEMD, [test "$use_systemd" = 1]) |
| AC_SUBST(unitdir) |
| diff -up nfs-utils-1.3.0/.gitignore.orig nfs-utils-1.3.0/.gitignore |
| --- nfs-utils-1.3.0/.gitignore.orig 2014-03-25 11:12:07.000000000 -0400 |
| +++ nfs-utils-1.3.0/.gitignore 2017-03-31 15:55:47.123245655 -0400 |
| @@ -69,6 +69,7 @@ tests/nsm_client/nlm_sm_inter_clnt.c |
| tests/nsm_client/nlm_sm_inter_svc.c |
| tests/nsm_client/nlm_sm_inter_xdr.c |
| utils/nfsidmap/nfsidmap |
| +systemd/nfs-server-generator |
| # cscope database files |
| cscope.* |
| # generic editor backup et al |
| diff -up nfs-utils-1.3.0/support/export/export.c.orig nfs-utils-1.3.0/support/export/export.c |
| --- nfs-utils-1.3.0/support/export/export.c.orig 2017-03-31 15:55:05.528831459 -0400 |
| +++ nfs-utils-1.3.0/support/export/export.c 2017-03-31 15:55:47.124245665 -0400 |
| @@ -15,6 +15,8 @@ |
| #include <sys/param.h> |
| #include <netinet/in.h> |
| #include <stdlib.h> |
| +#include <dirent.h> |
| +#include <errno.h> |
| #include "xmalloc.h" |
| #include "nfslib.h" |
| #include "exportfs.h" |
| @@ -68,11 +70,15 @@ static void warn_duplicated_exports(nfs_ |
| /** |
| * export_read - read entries from /etc/exports |
| * @fname: name of file to read from |
| + * @ignore_hosts: don't check validity of host names |
| * |
| * Returns number of read entries. |
| + * @ignore_hosts can be set when the host names won't be used |
| + * and when getting delays or errors due to problems with |
| + * hostname looking is not acceptable. |
| */ |
| int |
| -export_read(char *fname) |
| +export_read(char *fname, int ignore_hosts) |
| { |
| struct exportent *eep; |
| nfs_export *exp; |
| @@ -81,7 +87,7 @@ export_read(char *fname) |
| |
| setexportent(fname, "r"); |
| while ((eep = getexportent(0,1)) != NULL) { |
| - exp = export_lookup(eep->e_hostname, eep->e_path, 0); |
| + exp = export_lookup(eep->e_hostname, eep->e_path, ignore_hosts); |
| if (!exp) { |
| if (export_create(eep, 0)) |
| /* possible complaints already logged */ |
| @@ -94,6 +100,70 @@ export_read(char *fname) |
| |
| return volumes; |
| } |
| + |
| +/** |
| + * export_d_read - read entries from /etc/exports. |
| + * @fname: name of directory to read from |
| + * @ignore_hosts: don't check validity of host names |
| + * |
| + * Returns number of read entries. |
| + * Based on mnt_table_parse_dir() in |
| + * util-linux-ng/shlibs/mount/src/tab_parse.c |
| + */ |
| +int |
| +export_d_read(const char *dname, int ignore_hosts) |
| +{ |
| + int n = 0, i; |
| + struct dirent **namelist = NULL; |
| + int volumes = 0; |
| + |
| + |
| + n = scandir(dname, &namelist, NULL, versionsort); |
| + if (n < 0) { |
| + if (errno == ENOENT) |
| + /* Silently return */ |
| + return volumes; |
| + xlog(L_NOTICE, "scandir %s: %s", dname, strerror(errno)); |
| + } else if (n == 0) |
| + return volumes; |
| + |
| + for (i = 0; i < n; i++) { |
| + struct dirent *d = namelist[i]; |
| + size_t namesz; |
| + char fname[PATH_MAX + 1]; |
| + int fname_len; |
| + |
| + |
| + if (d->d_type != DT_UNKNOWN |
| + && d->d_type != DT_REG |
| + && d->d_type != DT_LNK) |
| + continue; |
| + if (*d->d_name == '.') |
| + continue; |
| + |
| +#define _EXT_EXPORT_SIZ (sizeof(_EXT_EXPORT) - 1) |
| + namesz = strlen(d->d_name); |
| + if (!namesz |
| + || namesz < _EXT_EXPORT_SIZ + 1 |
| + || strcmp(d->d_name + (namesz - _EXT_EXPORT_SIZ), |
| + _EXT_EXPORT)) |
| + continue; |
| + |
| + fname_len = snprintf(fname, PATH_MAX +1, "%s/%s", dname, d->d_name); |
| + if (fname_len > PATH_MAX) { |
| + xlog(L_WARNING, "Too long file name: %s in %s", d->d_name, dname); |
| + continue; |
| + } |
| + |
| + volumes += export_read(fname, ignore_hosts); |
| + } |
| + |
| + for (i = 0; i < n; i++) |
| + free(namelist[i]); |
| + free(namelist); |
| + |
| + return volumes; |
| +} |
| |
| /** |
| * export_create - create an in-core nfs_export record from an export entry |
| diff -up nfs-utils-1.3.0/support/include/exportfs.h.orig nfs-utils-1.3.0/support/include/exportfs.h |
| --- nfs-utils-1.3.0/support/include/exportfs.h.orig 2017-03-31 15:55:05.528831459 -0400 |
| +++ nfs-utils-1.3.0/support/include/exportfs.h 2017-03-31 15:55:47.124245665 -0400 |
| @@ -133,7 +133,8 @@ struct addrinfo * client_resolve(const |
| int client_member(const char *client, |
| const char *name); |
| |
| -int export_read(char *fname); |
| +int export_read(char *fname, int ignore_hosts); |
| +int export_d_read(const char *dname, int ignore_hosts); |
| void export_reset(nfs_export *); |
| nfs_export * export_lookup(char *hname, char *path, int caconical); |
| nfs_export * export_find(const struct addrinfo *ai, |
| diff -up nfs-utils-1.3.0/systemd/Makefile.am.orig nfs-utils-1.3.0/systemd/Makefile.am |
| --- nfs-utils-1.3.0/systemd/Makefile.am.orig 2017-03-31 15:55:05.545831628 -0400 |
| +++ nfs-utils-1.3.0/systemd/Makefile.am 2017-03-31 15:55:47.124245665 -0400 |
| @@ -4,7 +4,6 @@ MAINTAINERCLEANFILES = Makefile.in |
| |
| unit_files = \ |
| nfs-client.target \ |
| - \ |
| auth-rpcgss-module.service \ |
| nfs-blkmap.service \ |
| nfs-config.service \ |
| @@ -15,8 +14,6 @@ unit_files = \ |
| rpc-gssd.service \ |
| rpc-statd-notify.service \ |
| rpc-statd.service \ |
| - rpc-svcgssd.service \ |
| - \ |
| proc-fs-nfsd.mount \ |
| var-lib-nfs-rpc_pipefs.mount |
| |
| @@ -25,8 +22,16 @@ man7_MANS = nfs.systemd.man |
| EXTRA_DIST = $(unit_files) $(man5_MANS) $(man7_MANS) |
| |
| unit_dir = /usr/lib/systemd/system |
| +generator_dir = /usr/lib/systemd/system-generators |
| + |
| +EXTRA_PROGRAMS = nfs-server-generator |
| +genexecdir = $(generator_dir) |
| +nfs_server_generator_LDADD = ../support/export/libexport.a \ |
| + ../support/nfs/libnfs.a \ |
| + ../support/misc/libmisc.a |
| |
| if INSTALL_SYSTEMD |
| +genexec_PROGRAMS = nfs-server-generator |
| install-data-hook: $(unit_files) |
| mkdir -p $(DESTDIR)/$(unitdir) |
| cp $(unit_files) $(DESTDIR)/$(unitdir) |
| diff -up nfs-utils-1.3.0/systemd/nfs-server-generator.c.orig nfs-utils-1.3.0/systemd/nfs-server-generator.c |
| --- nfs-utils-1.3.0/systemd/nfs-server-generator.c.orig 2017-03-31 15:55:47.124245665 -0400 |
| +++ nfs-utils-1.3.0/systemd/nfs-server-generator.c 2017-03-31 15:55:47.124245665 -0400 |
| @@ -0,0 +1,179 @@ |
| +/* |
| + * nfs-server-generator: |
| + * systemd generator to create ordering dependencies between |
| + * nfs-server and various filesystem mounts |
| + * |
| + * 1/ nfs-server should start Before any 'nfs' mountpoints are |
| + * mounted, in case they are loop-back mounts. This ordering is particularly |
| + * important for the shutdown side, so the nfs-server is stopped |
| + * after the filesystems are unmounted. |
| + * 2/ nfs-server should start After all exported filesystems are mounted |
| + * so there is no risk of exporting the underlying directory. |
| + * This is particularly important for _net mounts which |
| + * are not caught by "local-fs.target". |
| + */ |
| + |
| +#ifdef HAVE_CONFIG_H |
| +#include <config.h> |
| +#endif |
| + |
| +#include <sys/stat.h> |
| +#include <sys/types.h> |
| +#include <unistd.h> |
| +#include <stdlib.h> |
| +#include <string.h> |
| +#include <ctype.h> |
| +#include <stdio.h> |
| +#include <mntent.h> |
| + |
| +#include "misc.h" |
| +#include "nfslib.h" |
| +#include "exportfs.h" |
| + |
| +/* A simple "set of strings" to remove duplicates |
| + * found in /etc/exports |
| + */ |
| +struct list { |
| + struct list *next; |
| + char *name; |
| +}; |
| +static int is_unique(struct list **lp, char *path) |
| +{ |
| + struct list *l = *lp; |
| + |
| + while (l) { |
| + if (strcmp(l->name, path) == 0) |
| + return 0; |
| + l = l->next; |
| + } |
| + l = malloc(sizeof(*l)); |
| + if (l == NULL) |
| + return 0; |
| + l->name = path; |
| + l->next = *lp; |
| + *lp = l; |
| + return 1; |
| +} |
| + |
| +/* We need to convert a path name to a systemd unit |
| + * name. This requires some translation ('/' -> '-') |
| + * and some escaping. |
| + */ |
| +static void systemd_escape(FILE *f, char *path) |
| +{ |
| + while (*path == '/') |
| + path++; |
| + if (!*path) { |
| + /* "/" becomes "-", otherwise leading "/" is ignored */ |
| + fputs("-", f); |
| + return; |
| + } |
| + while (*path) { |
| + char c = *path++; |
| + |
| + if (c == '/') { |
| + /* multiple non-trailing slashes become '-' */ |
| + while (*path == '/') |
| + path++; |
| + if (*path) |
| + fputs("-", f); |
| + } else if (isalnum(c) || c == ':' || c == '.') |
| + fputc(c, f); |
| + else |
| + fprintf(f, "\\x%02x", c & 0xff); |
| + } |
| +} |
| + |
| +static int has_noauto_flag(char *path) |
| +{ |
| + FILE *fstab; |
| + struct mntent *mnt; |
| + |
| + fstab = setmntent("/etc/fstab", "r"); |
| + if (!fstab) |
| + return 0; |
| + |
| + while ((mnt = getmntent(fstab)) != NULL) { |
| + int l = strlen(mnt->mnt_dir); |
| + if (strncmp(mnt->mnt_dir, path, l) != 0) |
| + continue; |
| + if (path[l] && path[l] != '/') |
| + continue; |
| + if (hasmntopt(mnt, "noauto")) |
| + break; |
| + } |
| + fclose(fstab); |
| + return mnt != NULL; |
| +} |
| + |
| +int main(int argc, char *argv[]) |
| +{ |
| + char *path; |
| + char dirbase[] = "/nfs-server.service.d"; |
| + char filebase[] = "/order-with-mounts.conf"; |
| + nfs_export *exp; |
| + int i; |
| + struct list *list = NULL; |
| + FILE *f, *fstab; |
| + struct mntent *mnt; |
| + |
| + /* Avoid using any external services */ |
| + xlog_syslog(0); |
| + |
| + if (argc != 4 || argv[1][0] != '/') { |
| + fprintf(stderr, "nfs-server-generator: create systemd dependencies for nfs-server\n"); |
| + fprintf(stderr, "Usage: normal-dir early-dir late-dir\n"); |
| + exit(1); |
| + } |
| + |
| + path = malloc(strlen(argv[1]) + sizeof(dirbase) + sizeof(filebase)); |
| + if (!path) |
| + exit(2); |
| + if (export_read(_PATH_EXPORTS, 1) + |
| + export_d_read(_PATH_EXPORTS_D, 1) == 0) |
| + /* Nothing is exported, so nothing to do */ |
| + exit(0); |
| + |
| + strcat(strcpy(path, argv[1]), dirbase); |
| + mkdir(path, 0755); |
| + strcat(path, filebase); |
| + f = fopen(path, "w"); |
| + if (!f) |
| + exit(1); |
| + fprintf(f, "# Automatically generated by nfs-server-generator\n\n[Unit]\n"); |
| + |
| + for (i = 0; i < MCL_MAXTYPES; i++) { |
| + for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { |
| + if (!is_unique(&list, exp->m_export.e_path)) |
| + continue; |
| + if (exp->m_export.e_mountpoint) |
| + continue; |
| + if (has_noauto_flag(exp->m_export.e_path)) |
| + continue; |
| + if (strchr(exp->m_export.e_path, ' ')) |
| + fprintf(f, "RequiresMountsFor=\"%s\"\n", |
| + exp->m_export.e_path); |
| + else |
| + fprintf(f, "RequiresMountsFor=%s\n", |
| + exp->m_export.e_path); |
| + } |
| + } |
| + |
| + fstab = setmntent("/etc/fstab", "r"); |
| + if (!fstab) |
| + exit(1); |
| + |
| + while ((mnt = getmntent(fstab)) != NULL) { |
| + if (strcmp(mnt->mnt_type, "nfs") != 0 && |
| + strcmp(mnt->mnt_type, "nfs4") != 0) |
| + continue; |
| + fprintf(f, "Before= "); |
| + systemd_escape(f, mnt->mnt_dir); |
| + fprintf(f, ".mount\n"); |
| + } |
| + |
| + fclose(fstab); |
| + fclose(f); |
| + |
| + exit(0); |
| +} |
| diff -up nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig nfs-utils-1.3.0/utils/exportfs/exportfs.c |
| --- nfs-utils-1.3.0/utils/exportfs/exportfs.c.orig 2017-03-31 15:55:05.553831708 -0400 |
| +++ nfs-utils-1.3.0/utils/exportfs/exportfs.c 2017-03-31 15:55:47.125245675 -0400 |
| @@ -26,7 +26,6 @@ |
| #include <fcntl.h> |
| #include <netdb.h> |
| #include <errno.h> |
| -#include <dirent.h> |
| #include <limits.h> |
| #include <time.h> |
| |
| @@ -48,7 +47,6 @@ static void error(nfs_export *exp, int e |
| static void usage(const char *progname, int n); |
| static void validate_export(nfs_export *exp); |
| static int matchhostname(const char *hostname1, const char *hostname2); |
| -static int export_d_read(const char *dname); |
| static void grab_lockfile(void); |
| static void release_lockfile(void); |
| |
| @@ -190,8 +188,8 @@ main(int argc, char **argv) |
| atexit(release_lockfile); |
| |
| if (f_export && ! f_ignore) { |
| - if (! (export_read(_PATH_EXPORTS) + |
| - export_d_read(_PATH_EXPORTS_D))) { |
| + if (! (export_read(_PATH_EXPORTS, 0) + |
| + export_d_read(_PATH_EXPORTS_D, 0))) { |
| if (f_verbose) |
| xlog(L_WARNING, "No file systems exported!"); |
| } |
| @@ -705,63 +703,6 @@ out: |
| return result; |
| } |
| |
| -/* Based on mnt_table_parse_dir() in |
| - util-linux-ng/shlibs/mount/src/tab_parse.c */ |
| -static int |
| -export_d_read(const char *dname) |
| -{ |
| - int n = 0, i; |
| - struct dirent **namelist = NULL; |
| - int volumes = 0; |
| - |
| - |
| - n = scandir(dname, &namelist, NULL, versionsort); |
| - if (n < 0) { |
| - if (errno == ENOENT) |
| - /* Silently return */ |
| - return volumes; |
| - xlog(L_NOTICE, "scandir %s: %s", dname, strerror(errno)); |
| - } else if (n == 0) |
| - return volumes; |
| - |
| - for (i = 0; i < n; i++) { |
| - struct dirent *d = namelist[i]; |
| - size_t namesz; |
| - char fname[PATH_MAX + 1]; |
| - int fname_len; |
| - |
| - |
| - if (d->d_type != DT_UNKNOWN |
| - && d->d_type != DT_REG |
| - && d->d_type != DT_LNK) |
| - continue; |
| - if (*d->d_name == '.') |
| - continue; |
| - |
| -#define _EXT_EXPORT_SIZ (sizeof(_EXT_EXPORT) - 1) |
| - namesz = strlen(d->d_name); |
| - if (!namesz |
| - || namesz < _EXT_EXPORT_SIZ + 1 |
| - || strcmp(d->d_name + (namesz - _EXT_EXPORT_SIZ), |
| - _EXT_EXPORT)) |
| - continue; |
| - |
| - fname_len = snprintf(fname, PATH_MAX +1, "%s/%s", dname, d->d_name); |
| - if (fname_len > PATH_MAX) { |
| - xlog(L_WARNING, "Too long file name: %s in %s", d->d_name, dname); |
| - continue; |
| - } |
| - |
| - volumes += export_read(fname); |
| - } |
| - |
| - for (i = 0; i < n; i++) |
| - free(namelist[i]); |
| - free(namelist); |
| - |
| - return volumes; |
| -} |
| - |
| static char |
| dumpopt(char c, char *fmt, ...) |
| { |