Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 69eb66d7 authored by Dave Kleikamp's avatar Dave Kleikamp
Browse files

JFS: add uid, gid, and umask mount options



OS/2 doesn't initialize the uid, gid, or unix-style permission bits.  The
uid, gid, & umask mount options perform pretty much like those for the fat
file system, overriding what is stored on disk.  This is useful for users
sharing the file system with OS/2.

I implemented a little feature so that if you mask the execute bit, it
will be re-enabled on directories when the appropriate read bit is unmasked.
I didn't want to implement an fmask & dmask option.

Signed-off-by: default avatarDave Kleikamp <shaggy@austin.ibm.com>
parent be0bf7da
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -184,6 +184,9 @@ cleanup:
	} else
		inode->i_mode &= ~current->fs->umask;
	
	JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
			       inode->i_mode;

	return rc;
}

+44 −6
Original line number Diff line number Diff line
@@ -3074,14 +3074,40 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno,
static int copy_from_dinode(struct dinode * dip, struct inode *ip)
{
	struct jfs_inode_info *jfs_ip = JFS_IP(ip);
	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);

	jfs_ip->fileset = le32_to_cpu(dip->di_fileset);
	jfs_ip->mode2 = le32_to_cpu(dip->di_mode);

	ip->i_mode = le32_to_cpu(dip->di_mode) & 0xffff;
	if (sbi->umask != -1) {
		ip->i_mode = (ip->i_mode & ~0777) | (0777 & ~sbi->umask);
		/* For directories, add x permission if r is allowed by umask */
		if (S_ISDIR(ip->i_mode)) {
			if (ip->i_mode & 0400)
				ip->i_mode |= 0100;
			if (ip->i_mode & 0040)
				ip->i_mode |= 0010;
			if (ip->i_mode & 0004)
				ip->i_mode |= 0001;
		}
	}
	ip->i_nlink = le32_to_cpu(dip->di_nlink);
	ip->i_uid = le32_to_cpu(dip->di_uid);
	ip->i_gid = le32_to_cpu(dip->di_gid);

	jfs_ip->saved_uid = le32_to_cpu(dip->di_uid);
	if (sbi->uid == -1)
		ip->i_uid = jfs_ip->saved_uid;
	else {
		ip->i_uid = sbi->uid;
	}

	jfs_ip->saved_gid = le32_to_cpu(dip->di_gid);
	if (sbi->gid == -1)
		ip->i_gid = jfs_ip->saved_gid;
	else {
		ip->i_gid = sbi->gid;
	}

	ip->i_size = le64_to_cpu(dip->di_size);
	ip->i_atime.tv_sec = le32_to_cpu(dip->di_atime.tv_sec);
	ip->i_atime.tv_nsec = le32_to_cpu(dip->di_atime.tv_nsec);
@@ -3132,21 +3158,33 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
static void copy_to_dinode(struct dinode * dip, struct inode *ip)
{
	struct jfs_inode_info *jfs_ip = JFS_IP(ip);
	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);

	dip->di_fileset = cpu_to_le32(jfs_ip->fileset);
	dip->di_inostamp = cpu_to_le32(JFS_SBI(ip->i_sb)->inostamp);
	dip->di_inostamp = cpu_to_le32(sbi->inostamp);
	dip->di_number = cpu_to_le32(ip->i_ino);
	dip->di_gen = cpu_to_le32(ip->i_generation);
	dip->di_size = cpu_to_le64(ip->i_size);
	dip->di_nblocks = cpu_to_le64(PBLK2LBLK(ip->i_sb, ip->i_blocks));
	dip->di_nlink = cpu_to_le32(ip->i_nlink);
	if (sbi->uid == -1)
		dip->di_uid = cpu_to_le32(ip->i_uid);
	else
		dip->di_uid = cpu_to_le32(jfs_ip->saved_uid);
	if (sbi->gid == -1)
		dip->di_gid = cpu_to_le32(ip->i_gid);
	else
		dip->di_gid = cpu_to_le32(jfs_ip->saved_gid);
	/*
	 * mode2 is only needed for storing the higher order bits.
	 * Trust i_mode for the lower order ones
	 */
	dip->di_mode = cpu_to_le32((jfs_ip->mode2 & 0xffff0000) | ip->i_mode);
	if (sbi->umask == -1)
		dip->di_mode = cpu_to_le32((jfs_ip->mode2 & 0xffff0000) |
					   ip->i_mode);
	else /* Leave the original permissions alone */
		dip->di_mode = cpu_to_le32(jfs_ip->mode2);

	dip->di_atime.tv_sec = cpu_to_le32(ip->i_atime.tv_sec);
	dip->di_atime.tv_nsec = cpu_to_le32(ip->i_atime.tv_nsec);
	dip->di_ctime.tv_sec = cpu_to_le32(ip->i_ctime.tv_sec);
+5 −0
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@
struct jfs_inode_info {
	int	fileset;	/* fileset number (always 16)*/
	uint	mode2;		/* jfs-specific mode		*/
	uint	saved_uid;	/* saved for uid mount option */
	uint	saved_gid;	/* saved for gid mount option */
	pxd_t   ixpxd;		/* inode extent descriptor	*/
	dxd_t	acl;		/* dxd describing acl	*/
	dxd_t	ea;		/* dxd describing ea	*/
@@ -170,6 +172,9 @@ struct jfs_sb_info {
	uint		state;		/* mount/recovery state	*/
	unsigned long	flag;		/* mount time flags */
	uint		p_state;	/* state prior to going no integrity */
	uint		uid;		/* uid to override on-disk uid */
	uint		gid;		/* gid to override on-disk gid */
	uint		umask;		/* umask to override on-disk umask */
};

/* jfs_sb_info commit_state */
+7 −0
Original line number Diff line number Diff line
@@ -82,6 +82,13 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
	} else
		inode->i_gid = current->fsgid;

	/*
	 * New inodes need to save sane values on disk when
	 * uid & gid mount options are used
	 */
	jfs_inode->saved_uid = inode->i_uid;
	jfs_inode->saved_gid = inode->i_gid;

	/*
	 * Allocate inode to quota.
	 */
+34 −4
Original line number Diff line number Diff line
@@ -194,7 +194,7 @@ static void jfs_put_super(struct super_block *sb)
enum {
	Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize,
	Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota,
	Opt_usrquota, Opt_grpquota
	Opt_usrquota, Opt_grpquota, Opt_uid, Opt_gid, Opt_umask
};

static match_table_t tokens = {
@@ -208,6 +208,9 @@ static match_table_t tokens = {
	{Opt_ignore, "quota"},
	{Opt_usrquota, "usrquota"},
	{Opt_grpquota, "grpquota"},
	{Opt_uid, "uid=%u"},
	{Opt_gid, "gid=%u"},
	{Opt_umask, "umask=%u"},
	{Opt_err, NULL}
};

@@ -312,7 +315,29 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
			       "JFS: quota operations not supported\n");
			break;
#endif

		case Opt_uid:
		{
			char *uid = args[0].from;
			sbi->uid = simple_strtoul(uid, &uid, 0);
			break;
		}
		case Opt_gid:
		{
			char *gid = args[0].from;
			sbi->gid = simple_strtoul(gid, &gid, 0);
			break;
		}
		case Opt_umask:
		{
			char *umask = args[0].from;
			sbi->umask = simple_strtoul(umask, &umask, 8);
			if (sbi->umask & ~0777) {
				printk(KERN_ERR
				       "JFS: Invalid value of umask\n");
				goto cleanup;
			}
			break;
		}
		default:
			printk("jfs: Unrecognized mount option \"%s\" "
					" or missing value\n", p);
@@ -400,6 +425,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
		return -ENOSPC;
	sb->s_fs_info = sbi;
	sbi->sb = sb;
	sbi->uid = sbi->gid = sbi->umask = -1;

	/* initialize the mount flag and determine the default error handler */
	flag = JFS_ERR_REMOUNT_RO;
@@ -562,10 +588,14 @@ static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
{
	struct jfs_sb_info *sbi = JFS_SBI(vfs->mnt_sb);

	if (sbi->uid != -1)
		seq_printf(seq, ",uid=%d", sbi->uid);
	if (sbi->gid != -1)
		seq_printf(seq, ",gid=%d", sbi->gid);
	if (sbi->umask != -1)
		seq_printf(seq, ",umask=%03o", sbi->umask);
	if (sbi->flag & JFS_NOINTEGRITY)
		seq_puts(seq, ",nointegrity");
	else
		seq_puts(seq, ",integrity");

#if defined(CONFIG_QUOTA)
	if (sbi->flag & JFS_USRQUOTA)