autofs-5.0.6 - add function to check mount.nfs version From: Ian Kent Add a function to check if the mount.nfs version is greater than or equal to a given version. --- CHANGELOG | 1 configure | 62 ++++++++++++++++++++++ configure.in | 1 include/config.h.in | 6 ++ include/mounts.h | 7 ++ lib/mounts.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 224 insertions(+), 0 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7e5783f..359c293 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -28,6 +28,7 @@ - fix init script usage message. - ignore duplicate exports in auto.net. - add kernel verion check function. +- add function to check mount.nfs version. 28/06/2011 autofs-5.0.6 ----------------------- diff --git a/configure b/configure index f78b322..ec394e7 100755 --- a/configure +++ b/configure @@ -645,6 +645,8 @@ HAVE_E2FSCK E2FSCK HAVE_UMOUNT UMOUNT +HAVE_MOUNT_NFS +MOUNT_NFS HAVE_MOUNT MOUNT DMALLOCLIB @@ -3248,6 +3250,66 @@ else HAVE_MOUNT=0 fi +for ac_prog in mount.nfs +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_MOUNT_NFS+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MOUNT_NFS in + [\\/]* | ?:[\\/]*) + ac_cv_path_MOUNT_NFS="$MOUNT_NFS" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $searchpath +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_MOUNT_NFS="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +MOUNT_NFS=$ac_cv_path_MOUNT_NFS +if test -n "$MOUNT_NFS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MOUNT_NFS" >&5 +$as_echo "$MOUNT_NFS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$MOUNT_NFS" && break +done +test -n "$MOUNT_NFS" || MOUNT_NFS="/sbin/mount.nfs " + +if test -n "$MOUNT_NFS"; then + +$as_echo "#define HAVE_MOUNT_NFS 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define PATH_MOUNT_NFS "$MOUNT_NFS" +_ACEOF + + HAVE_MOUNT_NFS=1 +else + HAVE_MOUNT_NFS=0 +fi + for ac_prog in umount do # Extract the first word of "$ac_prog", so it can be a program name with args. diff --git a/configure.in b/configure.in index c017829..5477508 100644 --- a/configure.in +++ b/configure.in @@ -137,6 +137,7 @@ AC_SUBST(DMALLOCLIB) # Programs needed for various system functions or modules # AF_PATH_INCLUDE(MOUNT, mount, /bin/mount, $searchpath) +AF_PATH_INCLUDE(MOUNT_NFS, mount.nfs, /sbin/mount.nfs , $searchpath) AF_PATH_INCLUDE(UMOUNT, umount, /bin/umount, $searchpath) AF_PATH_INCLUDE(E2FSCK, fsck.ext2 e2fsck, , $searchpath) AF_PATH_INCLUDE(E3FSCK, fsck.ext3 e3fsck, , $searchpath) diff --git a/include/config.h.in b/include/config.h.in index fb4aadb..f79d579 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -45,6 +45,9 @@ /* define if you have MOUNT */ #undef HAVE_MOUNT +/* define if you have MOUNT_NFS */ +#undef HAVE_MOUNT_NFS + /* define if the mount command supports the -s option */ #undef HAVE_SLOPPY_MOUNT @@ -111,6 +114,9 @@ /* define if you have MOUNT */ #undef PATH_MOUNT +/* define if you have MOUNT_NFS */ +#undef PATH_MOUNT_NFS + /* define if you have RANLIB */ #undef PATH_RANLIB diff --git a/include/mounts.h b/include/mounts.h index 3947d83..6a6ebab 100644 --- a/include/mounts.h +++ b/include/mounts.h @@ -89,6 +89,13 @@ static inline unsigned int linux_version_code(void) return KERNEL_VERSION(p, q, r); } +struct nfs_mount_vers { + unsigned int major; + unsigned int minor; + unsigned int fix; +}; +int check_nfs_mount_version(struct nfs_mount_vers *, struct nfs_mount_vers *); + unsigned int query_kproto_ver(void); unsigned int get_kver_major(void); unsigned int get_kver_minor(void); diff --git a/lib/mounts.c b/lib/mounts.c index f26579e..efe0438 100644 --- a/lib/mounts.c +++ b/lib/mounts.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -30,6 +32,8 @@ #define MAX_OPTIONS_LEN 80 #define MAX_MNT_NAME_LEN 30 +#define EBUFSIZ 1024 + const unsigned int t_indirect = AUTOFS_TYPE_INDIRECT; const unsigned int t_direct = AUTOFS_TYPE_DIRECT; const unsigned int t_offset = AUTOFS_TYPE_OFFSET; @@ -131,6 +135,149 @@ unsigned int get_kver_minor(void) return kver.minor; } +#ifdef HAVE_MOUNT_NFS +static int extract_version(char *start, struct nfs_mount_vers *vers) +{ + char *s_ver = strchr(start, ' '); + while (*s_ver && !isdigit(*s_ver)) { + s_ver++; + if (!*s_ver) + return 0; + break; + } + vers->major = atoi(strtok(s_ver, ".")); + vers->minor = (unsigned int) atoi(strtok(NULL, ".")); + vers->fix = (unsigned int) atoi(strtok(NULL, ".")); + return 1; +} + +int check_nfs_mount_version(struct nfs_mount_vers *vers, + struct nfs_mount_vers *check) +{ + pid_t f; + int ret, status, pipefd[2]; + char errbuf[EBUFSIZ + 1], *p, *sp; + int errp, errn; + sigset_t allsigs, tmpsig, oldsig; + char *s_ver; + int cancel_state; + + if (pipe(pipefd)) + return -1; + + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state); + + sigfillset(&allsigs); + pthread_sigmask(SIG_BLOCK, &allsigs, &oldsig); + + f = fork(); + if (f == 0) { + reset_signals(); + close(pipefd[0]); + dup2(pipefd[1], STDOUT_FILENO); + dup2(pipefd[1], STDERR_FILENO); + close(pipefd[1]); + + execl(PATH_MOUNT_NFS, PATH_MOUNT_NFS, "-V", (char *) NULL); + _exit(255); /* execv() failed */ + } + + ret = 0; + + tmpsig = oldsig; + + sigaddset(&tmpsig, SIGCHLD); + pthread_sigmask(SIG_SETMASK, &tmpsig, NULL); + + close(pipefd[1]); + + if (f < 0) { + close(pipefd[0]); + pthread_sigmask(SIG_SETMASK, &oldsig, NULL); + pthread_setcancelstate(cancel_state, NULL); + return -1; + } + + errp = 0; + do { + while (1) { + errn = read(pipefd[0], errbuf + errp, EBUFSIZ - errp); + if (errn == -1 && errno == EINTR) + continue; + break; + } + + if (errn > 0) { + errp += errn; + + sp = errbuf; + while (errp && (p = memchr(sp, '\n', errp))) { + *p++ = '\0'; + errp -= (p - sp); + sp = p; + } + + if (errp && sp != errbuf) + memmove(errbuf, sp, errp); + + if (errp >= EBUFSIZ) { + /* Line too long, split */ + errbuf[errp] = '\0'; + if ((s_ver = strstr(errbuf, "nfs-utils"))) { + if (extract_version(s_ver, vers)) + ret = 1; + } + errp = 0; + } + + if ((s_ver = strstr(errbuf, "nfs-utils"))) { + if (extract_version(s_ver, vers)) + ret = 1; + } + } + } while (errn > 0); + + close(pipefd[0]); + + if (errp > 0) { + /* End of file without \n */ + errbuf[errp] = '\0'; + if ((s_ver = strstr(errbuf, "nfs-utils"))) { + if (extract_version(s_ver, vers)) + ret = 1; + } + } + + if (ret) { + if (vers->major == check->major && + vers->minor == check->minor && + vers->fix == check->fix) + ; + else { + if (vers->major < check->major) + ret = 0; + else if (vers->minor < check->minor) + ret = 0; + else if (vers->fix < check->fix) + ret = 0; + } + } + + if (waitpid(f, &status, 0) != f) ; + + pthread_sigmask(SIG_SETMASK, &oldsig, NULL); + pthread_setcancelstate(cancel_state, NULL); + + return ret; +} +#else +int check_nfs_mount_version(struct nfs_mount_vers *vers, + struct nfs_mount_vers *check) +{ + return 0; +} +#endif + /* * Make common autofs mount options string */