kern/114847: [PATCH]: dirmask support for NTFS ala MSDOSFS

Ighighi ighighi at gmail.com
Tue Jul 24 04:20:02 UTC 2007


>Number:         114847
>Category:       kern
>Synopsis:       [PATCH]: dirmask support for NTFS ala MSDOSFS
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jul 24 04:20:01 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator:     Ighighi
>Release:        6.2-STABLE
>Organization:
>Environment:
FreeBSD orion 6.2-STABLE FreeBSD 6.2-STABLE #0: Thu Jul 19 17:44:47 VET 2007     root at orion:/usr/obj/usr/src/sys/CUSTOM  i386

>Description:
The "-m mask" option alone is useless since we are forced to add the
executable bits to browse directories, but these bits make no sense on
regular files in NTFS volumes most of the time.

Example code taken from src/sys/fs/msdosfs/* and src/sbin/mount_msdosfs/*
It was successfully built and tested on 6.2-STABLE and known to patch correctly
on -CURRENT.

It changes the ABI of the kernel module so any applications that use
<fs/ntfs/ntfs.h> & <fs/ntfs/ntfsmount.h> may need to be recompiled.
I'm not aware of none (other than mount_ntfs(8), of course).
An alternative patch will be posted later that just adds executable bits
to every directory, that preserves ABI compatibility.
>How-To-Repeat:

>Fix:
To apply this patch, run:
  patch -d /usr < /path/do/patch
Now, either rebuild the world and the kernel or run:
  cd /usr/src/sys/modules/ntfs
  make clean && make && make install clean
  cp -f /sys/fs/ntfs/ntfs.h /usr/include/fs/ntfs/
  cp -f /sys/fs/ntfs/ntfsmount.h /usr/include/fs/ntfs/
  cd /usr/src/sbin/mount_ntfs
  make clean && make && make install clean
  kldunload -v ntfs
  kldload -v ntfs

Enjoy, you may use a line like this in /etc/fstab:
 /dev/ad0s1 /mnt/win ntfs ro,noexec,noatime,-m644,-M755 0 0



Patch attached with submission follows:

#
# (!c) 2007 by Ighighi
#
# This patch adds dirmask support to NTFS ala MSDOSFS.
# The "-m mask" option alone is useless since we are forced to add the
# executable bits to browse directories, but these bits make no sense
# on regular files in NTFS volumes most of the time.
#
# To apply this patch, run:
#   patch -d /usr < /path/do/patch
# Now, either rebuild the world and the kernel or run:
#  cd /usr/src/sys/modules/ntfs
#  make clean && make && make install clean
#  cp -f /sys/fs/ntfs/ntfs.h /usr/include/fs/ntfs/
#  cp -f /sys/fs/ntfs/ntfsmount.h /usr/include/fs/ntfs/
#  cd /usr/src/sbin/mount_ntfs
#  make clean && make && make install clean
#  kldunload -v ntfs
#  kldload -v ntfs
#
# Enjoy, you may use a line like this in /etc/fstab:
#  /dev/ad0s1 /mnt/win ntfs ro,noexec,noatime,-m644,-M755 0 0
#

--- src/sbin/mount_ntfs/mount_ntfs.c.orig	2005-06-10 05:51:42.000000000 -0400
+++ src/sbin/mount_ntfs/mount_ntfs.c	2007-07-23 20:51:08.000000000 -0400
@@ -75,18 +75,18 @@
 {
 	struct ntfs_args args;
 	struct stat sb;
-	int c, mntflags, set_gid, set_uid, set_mask;
+	int c, mntflags, set_gid, set_uid, set_mask, set_dirmask;
 	char *dev, *dir, mntpath[MAXPATHLEN];
 
-	mntflags = set_gid = set_uid = set_mask = 0;
+	mntflags = set_gid = set_uid = set_mask = set_dirmask = 0;
 	(void)memset(&args, '\0', sizeof(args));
 	args.cs_ntfs = NULL;
 	args.cs_local = NULL;
 
 #ifdef TRANSITION_PERIOD_HACK
-	while ((c = getopt(argc, argv, "aiu:g:m:o:C:W:")) !=  -1) {
+	while ((c = getopt(argc, argv, "aiu:g:m:M:o:C:W:")) !=  -1) {
 #else
-	while ((c = getopt(argc, argv, "aiu:g:m:o:C:")) !=  -1) {
+	while ((c = getopt(argc, argv, "aiu:g:m:M:o:C:")) !=  -1) {
 #endif
 		switch (c) {
 		case 'u':
@@ -101,6 +101,10 @@
 			args.mode = a_mask(optarg);
 			set_mask = 1;
 			break;
+		case 'M':
+			args.dirmode = a_mask(optarg);
+			set_dirmask = 1;
+			break;
 		case 'i':
 			args.flag |= NTFS_MFLAG_CASEINS;
 			break;
@@ -146,6 +150,15 @@
 	if (optind + 2 != argc)
 		usage();
 
+	if (set_mask && !set_dirmask) {
+		args.dirmode = args.mode;
+		set_dirmask = 1;
+	}
+	else if (set_dirmask && !set_mask) {
+		args.mode = args.dirmode;
+		set_mask = 1;
+	}
+
 	dev = argv[optind];
 	dir = argv[optind + 1];
 
@@ -183,7 +196,8 @@
 		if (!set_gid)
 			args.gid = sb.st_gid;
 		if (!set_mask)
-			args.mode = sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+			args.mode = args.dirmode =
+				sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
 	}
 
 	if (mount("ntfs", mntpath, mntflags, &args) < 0)
@@ -254,10 +268,10 @@
 {
 #ifdef TRANSITION_PERIOD_HACK
 	fprintf(stderr, "%s\n%s\n",
-	"usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask]",
+	"usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-M mask] [-m mask]",
 	"                  [-C charset] [-W u2wtable] special node");
 #else
-	fprintf(stderr, "usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-m mask] [-C charset] special node\n");
+	fprintf(stderr, "usage: mount_ntfs [-a] [-i] [-u user] [-g group] [-M mask] [-m mask] [-C charset] special node\n");
 #endif
 	exit(EX_USAGE);
 }
--- src/sbin/mount_ntfs/mount_ntfs.8.orig	2005-02-10 05:19:31.000000000 -0400
+++ src/sbin/mount_ntfs/mount_ntfs.8	2007-07-23 20:34:21.000000000 -0400
@@ -42,6 +42,7 @@
 .Op Fl i
 .Op Fl u Ar user
 .Op Fl g Ar group
+.Op Fl M Ar mask
 .Op Fl m Ar mask
 .Op Fl C Ar charset
 .Op Fl W Ar u2wtable
@@ -82,6 +83,37 @@
 .It Fl m Ar mask
 Specify the maximum file permissions for files
 in the file system.
+(For example, a
+.Ar mask
+of
+.Li 755
+specifies that, by default, the owner should have
+read, write, and execute permissions for files, but
+others should only have read and execute permissions.
+See
+.Xr chmod 1
+for more information about octal file modes.
+Only the nine low-order bits of
+.Ar mask
+are used.
+The value of
+.Ar -M
+is used if it is supplied and
+.Ar -m
+is omitted.
+The default
+.Ar mask
+is taken from the
+directory on which the file system is being mounted.
+.It Fl M Ar mask
+Specify the maximum file permissions for directories
+in the file system.
+The value of
+.Ar -m
+is used if it is supplied and
+.Ar -M
+is omitted.
+See the previous option's description for details.                                   
 .It Fl C Ar charset
 Specify local
 .Ar charset
--- src/sys/fs/ntfs/ntfs.h.orig	2004-12-06 16:22:16.000000000 -0400
+++ src/sys/fs/ntfs/ntfs.h	2007-07-23 20:19:22.000000000 -0400
@@ -249,6 +249,7 @@
 	uid_t           ntm_uid;
 	gid_t           ntm_gid;
 	mode_t          ntm_mode;
+	mode_t		ntm_dirmode;
 	u_int           ntm_flag;
 	cn_t		ntm_cfree;
 	struct ntvattrdef *ntm_ad;
--- src/sys/fs/ntfs/ntfsmount.h.orig	2003-09-26 16:26:23.000000000 -0400
+++ src/sys/fs/ntfs/ntfsmount.h	2007-07-23 20:19:02.000000000 -0400
@@ -38,6 +38,7 @@
 	uid_t	uid;			/* uid that owns ntfs files */
 	gid_t	gid;			/* gid that owns ntfs files */
 	mode_t	mode;			/* mask to be applied for ntfs perms */
+	mode_t	dirmode;		/* mask to be applied for directories */
 	u_long	flag;			/* additional flags */
 	char	*cs_ntfs;		/* NTFS Charset */
 	char	*cs_local;		/* Local Charset */
--- src/sys/fs/ntfs/ntfs_vfsops.c.orig	2006-10-10 05:43:20.000000000 -0400
+++ src/sys/fs/ntfs/ntfs_vfsops.c	2007-07-23 20:21:50.000000000 -0400
@@ -131,6 +131,7 @@
 	ma = mount_argf(ma, "uid", "%d", args.uid);
 	ma = mount_argf(ma, "gid", "%d", args.gid);
 	ma = mount_argf(ma, "mode", "%d", args.mode);
+	ma = mount_argf(ma, "dirmode", "%d", args.dirmode);
 	ma = mount_argb(ma, args.flag & NTFS_MFLAG_CASEINS, "nocaseins");
 	ma = mount_argb(ma, args.flag & NTFS_MFLAG_ALLNAMES, "noallnames");
 	if (args.flag & NTFS_MFLAG_KICONV) {
@@ -144,7 +145,7 @@
 }
 
 static const char *ntfs_opts[] = {
-	"from", "export", "uid", "gid", "mode", "caseins", "allnames",
+	"from", "export", "uid", "gid", "mode", "dirmode", "caseins", "allnames",
 	"kiconv", "cs_ntfs", "cs_local", NULL
 };
 
@@ -319,6 +320,8 @@
 		ntmp->ntm_gid = v;
 	if (1 == vfs_scanopt(mp->mnt_optnew, "mode", "%d", &v))
 		ntmp->ntm_mode = v;
+	if (1 == vfs_scanopt(mp->mnt_optnew, "dirmode", "%d", &v))
+		ntmp->ntm_dirmode = v;
 	vfs_flagopt(mp->mnt_optnew,
 	    "caseins", &ntmp->ntm_flag, NTFS_MFLAG_CASEINS);
 	vfs_flagopt(mp->mnt_optnew,
@@ -342,10 +345,10 @@
 
 	mp->mnt_data = (qaddr_t)ntmp;
 
-	dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o\n",
+	dprintf(("ntfs_mountfs(): case-%s,%s uid: %d, gid: %d, mode: %o, dirmode: %o\n",
 		(ntmp->ntm_flag & NTFS_MFLAG_CASEINS)?"insens.":"sens.",
 		(ntmp->ntm_flag & NTFS_MFLAG_ALLNAMES)?" allnames,":"",
-		ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode));
+		ntmp->ntm_uid, ntmp->ntm_gid, ntmp->ntm_mode, ntmp->ntm_dirmode));
 
 	/*
 	 * We read in some system nodes to do not allow 
--- src/sys/fs/ntfs/ntfs_vnops.c.orig	2006-11-15 21:47:02.000000000 -0400
+++ src/sys/fs/ntfs/ntfs_vnops.c	2007-07-23 20:25:41.000000000 -0400
@@ -186,7 +186,8 @@
 
 	vap->va_fsid = dev2udev(ip->i_dev);
 	vap->va_fileid = ip->i_number;
-	vap->va_mode = ip->i_mp->ntm_mode;
+	vap->va_mode = (vp->v_type == VDIR) ?
+	    ip->i_mp->ntm_dirmode : ip->i_mp->ntm_mode;
 	vap->va_nlink = (ip->i_nlink || ip->i_flag & IN_LOADED ? ip->i_nlink : 1);
 	vap->va_uid = ip->i_mp->ntm_uid;
 	vap->va_gid = ip->i_mp->ntm_gid;
@@ -392,13 +393,16 @@
 {
 	struct vnode *vp = ap->a_vp;
 	struct ntnode *ip = VTONT(vp);
-	mode_t mode = ap->a_mode;
+	mode_t file_mode, mode = ap->a_mode;
 #ifdef QUOTA
 	int error;
 #endif
 
 	dprintf(("ntfs_access: %d\n",ip->i_number));
 
+	file_mode = (vp->v_type == VDIR) ?
+	    ip->i_mp->ntm_dirmode : ip->i_mp->ntm_mode;
+
 	/*
 	 * Disallow write attempts on read-only filesystems;
 	 * unless the file is a socket, fifo, or a block or
@@ -419,7 +423,7 @@
 		}
 	}
 
-	return (vaccess(vp->v_type, ip->i_mp->ntm_mode, ip->i_mp->ntm_uid,
+	return (vaccess(vp->v_type, file_mode, ip->i_mp->ntm_uid,
 	    ip->i_mp->ntm_gid, ap->a_mode, ap->a_cred, NULL));
 } 
 


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list