#include <errno.h>
#include <fcntl.h>
#include <sys/mount.h>
+#include <sys/utsname.h>
#include <getopt.h>
#include <mntent.h>
#include <pwd.h>
#include "fstab.h"
#include "xcommon.h"
+#include "nls.h"
#include "mount_constants.h"
#include "nfs_paths.h"
#include "nfs4_mount.h"
#include "nfsumount.h"
#include "mount.h"
+#include "error.h"
char *progname;
+int nfs_mount_data_version;
int nomtab;
int verbose;
int sloppy;
{ NULL, 0, 0, 0 }
};
+#define MAKE_VERSION(p,q,r) (65536 * (p) + 256 * (q) + (r))
+
+int linux_version_code(void)
+{
+ struct utsname my_utsname;
+ int p, q, r;
+
+ if (uname(&my_utsname) == 0) {
+ p = atoi(strtok(my_utsname.release, "."));
+ q = atoi(strtok(NULL, "."));
+ r = atoi(strtok(NULL, "."));
+ return MAKE_VERSION(p,q,r);
+ }
+ return 0;
+}
+
+/*
+ * Choose the version of the nfs_mount_data structure that is appropriate
+ * for the kernel that is doing the mount.
+ *
+ * NFS_MOUNT_VERSION: maximum version supported by these sources
+ * nfs_mount_data_version: maximum version supported by the running kernel
+ */
+static void discover_nfs_mount_data_version(void)
+{
+ int kernel_version = linux_version_code();
+
+ if (kernel_version) {
+ if (kernel_version < MAKE_VERSION(2, 1, 32))
+ nfs_mount_data_version = 1;
+ else if (kernel_version < MAKE_VERSION(2, 2, 18))
+ nfs_mount_data_version = 3;
+ else if (kernel_version < MAKE_VERSION(2, 3, 0))
+ nfs_mount_data_version = 4;
+ else if (kernel_version < MAKE_VERSION(2, 3, 99))
+ nfs_mount_data_version = 3;
+ else if (kernel_version < MAKE_VERSION(2, 6, 3))
+ nfs_mount_data_version = 4;
+ else
+ nfs_mount_data_version = 6;
+ }
+ if (nfs_mount_data_version > NFS_MOUNT_VERSION)
+ nfs_mount_data_version = NFS_MOUNT_VERSION;
+}
+
/* Try to build a canonical options string. */
static char * fix_opts_string (int flags, const char *extra_opts) {
const struct opt_map *om;
return new_opts;
}
-
-int add_mtab(char *fsname, char *mount_point, char *fstype, int flags, char *opts, int freq, int passno)
+static int add_mtab(char *spec, char *mount_point, char *fstype,
+ int flags, char *opts, int freq, int pass)
{
struct mntent ment;
FILE *mtab;
+ int result = EX_FILEIO;
- ment.mnt_fsname = fsname;
+ ment.mnt_fsname = spec;
ment.mnt_dir = mount_point;
ment.mnt_type = fstype;
ment.mnt_opts = fix_opts_string(flags, opts);
- ment.mnt_freq = 0;
- ment.mnt_passno= 0;
+ ment.mnt_freq = freq;
+ ment.mnt_passno = pass;
- if(flags & MS_REMOUNT) {
+ if (flags & MS_REMOUNT) {
update_mtab(ment.mnt_dir, &ment);
return 0;
}
lock_mtab();
- if ((mtab = setmntent(MOUNTED, "a+")) == NULL) {
+ if ((mtab = setmntent(MOUNTED, "a+")) == NULL) {
unlock_mtab();
- fprintf(stderr, "Can't open " MOUNTED);
- return 1;
+ nfs_error(_("Can't open mtab: %s"),
+ strerror(errno));
+ goto fail_unlock;
}
- if (addmntent(mtab, &ment) == 1) {
- endmntent(mtab);
- unlock_mtab();
- fprintf(stderr, "Can't write mount entry");
- return 1;
+ if (addmntent(mtab, &ment) == 1) {
+ nfs_error(_("Can't write mount entry to mtab: %s"),
+ strerror(errno));
+ goto fail_close;
}
- if (fchmod(fileno(mtab), 0644) == -1) {
- endmntent(mtab);
- unlock_mtab();
- fprintf(stderr, "Can't set perms on " MOUNTED);
- return 1;
+ if (fchmod(fileno(mtab), 0644) == -1) {
+ nfs_error(_("Can't set permissions on mtab: %s"),
+ strerror(errno));
+ goto fail_close;
}
- endmntent(mtab);
+ result = 0;
+fail_close:
+ endmntent(mtab);
+fail_unlock:
unlock_mtab();
- return 0;
+ return result;
}
int do_mount_syscall(char *spec, char *node, char *type, int flags, void *data)
}
}
-static void mount_error(char *mntpnt, char *node)
-{
- switch(errno) {
- case ENOTDIR:
- fprintf(stderr, "%s: mount point %s is not a directory\n",
- progname, mntpnt);
- break;
- case EBUSY:
- fprintf(stderr, "%s: %s is already mounted or busy\n",
- progname, mntpnt);
- break;
- case ENOENT:
- if (node) {
- fprintf(stderr, "%s: %s failed, reason given by server: %s\n",
- progname, node, strerror(errno));
- } else
- fprintf(stderr, "%s: mount point %s does not exist\n",
- progname, mntpnt);
- break;
- default:
- fprintf(stderr, "%s: %s\n", progname, strerror(errno));
- }
-}
static int chk_mountpoint(char *mount_point)
{
struct stat sb;
if (stat(mount_point, &sb) < 0){
- mount_error(mount_point, NULL);
+ mount_error(NULL, mount_point, errno);
return 1;
}
if (S_ISDIR(sb.st_mode) == 0){
- errno = ENOTDIR;
- mount_error(mount_point, NULL);
+ mount_error(NULL, mount_point, ENOTDIR);
return 1;
}
if (access(mount_point, X_OK) < 0) {
- mount_error(mount_point, NULL);
+ mount_error(NULL, mount_point, errno);
return 1;
}
progname = basename(argv[0]);
+ discover_nfs_mount_data_version();
+
if(!strncmp(progname, "umount", strlen("umount"))) {
if(argc < 2) {
umount_usage();
mount_opts);
if (mnt_err) {
- mount_error(mount_point, spec);
+ mount_error(spec, mount_point, errno);
exit(EX_FAIL);
}
}
if (!nomtab)
- add_mtab(spec, mount_point, fs_type,
- flags, extra_opts, 0, 0);
+ mnt_err = add_mtab(spec, mount_point, fs_type, flags, extra_opts,
+ 0, 0 /* these are always zero for NFS */ );
- return 0;
+ exit(mnt_err);
}