public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
[parent not found: <fa.ea9o20r.kje5qn@ifi.uio.no>]
* [PATCH] get/set FAT filesystem attribute bits
@ 2005-01-03 20:57 H. Peter Anvin
  2005-01-03 21:24 ` Nicholas Miell
  2005-01-04  8:34 ` OGAWA Hirofumi
  0 siblings, 2 replies; 20+ messages in thread
From: H. Peter Anvin @ 2005-01-03 20:57 UTC (permalink / raw)
  To: hirofumi, linux-kernel, Andrew Morton

[-- Attachment #1: Type: text/plain, Size: 266 bytes --]

This patch adds a set of ioctls to get and set the FAT filesystem native 
attribute bits, including the unused bits (6 and 7.)

It also includes some very minor code cleanups; mostly by macroizing a 
few idioms.

	-hpa

Signed-Off-By: H. Peter Anvin <hpa@zytor.com>

[-- Attachment #2: fat-filesystem-attributes.patch --]
[-- Type: text/x-patch, Size: 8224 bytes --]

Index: linux-2.5/fs/fat/dir.c
===================================================================
RCS file: /home/hpa/kernel/bkcvs/linux-2.5/fs/fat/dir.c,v
retrieving revision 1.28
diff -u -r1.28 dir.c
--- linux-2.5/fs/fat/dir.c	1 Nov 2004 00:18:37 -0000	1.28
+++ linux-2.5/fs/fat/dir.c	3 Jan 2005 15:06:16 -0000
@@ -663,7 +663,7 @@
 		both = 1;
 		break;
 	default:
-		return -EINVAL;
+		return fat_generic_ioctl(inode, filp, cmd, arg);
 	}
 
 	d1 = (struct dirent __user *)arg;
Index: linux-2.5/fs/fat/file.c
===================================================================
RCS file: /home/hpa/kernel/bkcvs/linux-2.5/fs/fat/file.c,v
retrieving revision 1.26
diff -u -r1.26 file.c
--- linux-2.5/fs/fat/file.c	24 Aug 2004 18:43:21 -0000	1.26
+++ linux-2.5/fs/fat/file.c	3 Jan 2005 15:06:41 -0000
@@ -19,6 +19,7 @@
 	.read		= generic_file_read,
 	.write		= fat_file_write,
 	.mmap		= generic_file_mmap,
+	.ioctl		= fat_generic_ioctl,
 	.fsync		= file_fsync,
 	.readv		= generic_file_readv,
 	.writev		= generic_file_writev,
Index: linux-2.5/fs/fat/inode.c
===================================================================
RCS file: /home/hpa/kernel/bkcvs/linux-2.5/fs/fat/inode.c,v
retrieving revision 1.108
diff -u -r1.108 inode.c
--- linux-2.5/fs/fat/inode.c	20 Oct 2004 15:16:56 -0000	1.108
+++ linux-2.5/fs/fat/inode.c	3 Jan 2005 20:50:25 -0000
@@ -562,7 +562,6 @@
 	MSDOS_I(inode)->i_attrs = 0;
 	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0;
 	inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0;
-	MSDOS_I(inode)->i_ctime_ms = 0;
 	inode->i_nlink = fat_subdirs(inode)+2;
 
 	return 0;
@@ -1218,8 +1217,7 @@
 		MSDOS_SB(sb)->options.isvfat
 		? date_dos2unix(le16_to_cpu(de->ctime), le16_to_cpu(de->cdate))
 		: inode->i_mtime.tv_sec;
-	inode->i_ctime.tv_nsec = de->ctime_ms * 1000000;
-	MSDOS_I(inode)->i_ctime_ms = de->ctime_ms;
+	inode->i_ctime.tv_nsec = de->ctime_ms * 1000000U;
 
 	return 0;
 }
@@ -1255,21 +1253,18 @@
 	raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
 	    [i_pos & (sbi->dir_per_block - 1)];
 	if (S_ISDIR(inode->i_mode)) {
-		raw_entry->attr = ATTR_DIR;
 		raw_entry->size = 0;
 	}
 	else {
-		raw_entry->attr = ATTR_NONE;
 		raw_entry->size = cpu_to_le32(inode->i_size);
 	}
-	raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) |
-	    MSDOS_I(inode)->i_attrs;
+	raw_entry->attr = msdos_attr(inode);
 	raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart);
 	raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16);
 	fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date);
 	if (sbi->options.isvfat) {
 		fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate);
-		raw_entry->ctime_ms = MSDOS_I(inode)->i_ctime_ms; /* use i_ctime.tv_nsec? */
+		raw_entry->ctime_ms = inode->i_ctime.tv_nsec / 1000000U;
 	}
 	spin_unlock(&sbi->inode_hash_lock);
 	mark_buffer_dirty(bh);
@@ -1328,4 +1323,105 @@
 	unlock_kernel();
 	return error;
 }
+
+int fat_generic_ioctl(struct inode * inode, struct file * filp,
+		      unsigned int cmd, unsigned long arg)
+{
+	struct super_block *sb = inode->i_sb;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+
+	switch (cmd) {
+	case FAT_IOCTL_GET_ATTRIBUTES:
+	{
+		u8 attr;
+		
+		/* msdos_attr() isn't atomic */
+		down(&inode->i_sem);
+
+		if ( inode->i_ino == MSDOS_ROOT_INO )
+			attr = ATTR_DIR;
+		else
+			attr = msdos_attr(inode);
+
+		up(&inode->i_sem);
+
+		return put_user(attr, (u8 __user *)arg);
+	}
+	case FAT_IOCTL_SET_ATTRIBUTES:
+	{
+		u8 attr, oldattr;
+		int err;
+		int is_dir;
+		struct iattr ia;
+
+		if ( (err = get_user(attr, (u8 __user *)arg)) )
+			return err;
+
+		if (IS_RDONLY(inode))
+			return -EROFS;
+
+		/* ATTR_VOLUME and ATTR_DIR cannot be changed; this also
+		   prevents the user from turning us into a VFAT
+		   longname entry. */
+		attr &= ~(ATTR_VOLUME|ATTR_DIR);
+
+		down(&inode->i_sem);
+
+		/* This is equivalent to an fchmod */
+		ia.ia_valid = ATTR_MODE|ATTR_CTIME;
+		ia.ia_ctime = CURRENT_TIME;
+
+		is_dir = S_ISDIR(inode->i_mode);
+
+		/* Merge in ATTR_VOLUME and ATTR_DIR */
+		attr |= (MSDOS_I(inode)->i_attrs & ATTR_VOLUME) |
+			(is_dir ? ATTR_DIR : 0);
+
+		if (is_dir) {
+			ia.ia_mode = MSDOS_MKMODE(attr,
+				S_IRWXUGO & ~sbi->options.fs_dmask)
+				| S_IFDIR;
+		} else {
+			ia.ia_mode = MSDOS_MKMODE(attr,
+				(S_IRUGO|S_IWUGO|(inode->i_mode & S_IXUGO))
+				& ~sbi->options.fs_fmask)
+				| S_IFREG;
+		}
+
+		if ( (err = inode_change_ok(inode, &ia)) )
+			goto out;
+		
+		/* The root directory has no attributes */
+		if ( inode->i_ino == MSDOS_ROOT_INO && attr != ATTR_DIR ) {
+			err = -EINVAL;
+			goto out;
+		}
+
+		oldattr = msdos_attr(inode);
+		if (sbi->options.sys_immutable) {
+			if ((attr^oldattr) & ATTR_SYS) {
+				if (!capable(CAP_LINUX_IMMUTABLE)) {
+					err = -EPERM;
+					goto out;
+				}
+				
+				if ( attr & ATTR_SYS )
+					inode->i_flags |= S_IMMUTABLE;
+				else
+					inode->i_flags &= S_IMMUTABLE;
+			}
+		}
+
+		MSDOS_I(inode)->i_attrs = attr & ATTR_UNUSED;
+		
+		err = inode_setattr(inode, &ia);
+	out:
+		up(&inode->i_sem);
+		return err;
+	}
+	default:
+		return -ENOTTY;	/* Inappropriate ioctl for device */
+	}
+}
+
 MODULE_LICENSE("GPL");
Index: linux-2.5/include/linux/compat_ioctl.h
===================================================================
RCS file: /home/hpa/kernel/bkcvs/linux-2.5/include/linux/compat_ioctl.h,v
retrieving revision 1.35
diff -u -r1.35 compat_ioctl.h
--- linux-2.5/include/linux/compat_ioctl.h	16 Nov 2004 04:09:40 -0000	1.35
+++ linux-2.5/include/linux/compat_ioctl.h	3 Jan 2005 19:15:21 -0000
@@ -571,6 +571,9 @@
 COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK)
 COMPATIBLE_IOCTL(DEVFSDIOC_RELEASE_EVENT_QUEUE)
 COMPATIBLE_IOCTL(DEVFSDIOC_SET_DEBUG_MASK)
+/* FAT */
+COMPATIBLE_IOCTL(FAT_IOCTL_GET_ATTRIBUTES)
+COMPATIBLE_IOCTL(FAT_IOCTL_SET_ATTRIBUTES)
 /* Raw devices */
 COMPATIBLE_IOCTL(RAW_SETBIND)
 COMPATIBLE_IOCTL(RAW_GETBIND)
Index: linux-2.5/include/linux/msdos_fs.h
===================================================================
RCS file: /home/hpa/kernel/bkcvs/linux-2.5/include/linux/msdos_fs.h,v
retrieving revision 1.41
diff -u -r1.41 msdos_fs.h
--- linux-2.5/include/linux/msdos_fs.h	20 Oct 2004 15:16:45 -0000	1.41
+++ linux-2.5/include/linux/msdos_fs.h	3 Jan 2005 20:35:36 -0000
@@ -95,6 +95,9 @@
  */
 #define	VFAT_IOCTL_READDIR_BOTH		_IOR('r', 1, struct dirent [2])
 #define	VFAT_IOCTL_READDIR_SHORT	_IOR('r', 2, struct dirent [2])
+/* Badness: 1..6 conflict with linux/videotext.h, despite ioctl-numbers.txt */
+#define FAT_IOCTL_GET_ATTRIBUTES	_IOR('r', 0x10, __u8)
+#define FAT_IOCTL_SET_ATTRIBUTES	_IOW('r', 0x11, __u8)
 
 /* 
  * vfat shortname flags
@@ -202,6 +205,13 @@
 	return container_of(inode, struct msdos_inode_info, vfs_inode);
 }
 
+static inline u8 msdos_attr(struct inode *inode)
+{
+	return MSDOS_MKATTR(inode->i_mode) |
+		MSDOS_I(inode)->i_attrs |
+		(S_ISDIR(inode->i_mode) ? ATTR_DIR : 0);
+}
+
 static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len)
 {
 #ifdef __BIG_ENDIAN
@@ -267,6 +277,8 @@
 int fat_fill_super(struct super_block *sb, void *data, int silent,
 		   struct inode_operations *fs_dir_inode_ops, int isvfat);
 extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
+extern int fat_generic_ioctl(struct inode * inode, struct file * filp,
+			     unsigned int cmd, unsigned long arg);
 
 /* fat/misc.c */
 extern void fat_fs_panic(struct super_block *s, const char *fmt, ...);
Index: linux-2.5/include/linux/msdos_fs_i.h
===================================================================
RCS file: /home/hpa/kernel/bkcvs/linux-2.5/include/linux/msdos_fs_i.h,v
retrieving revision 1.11
diff -u -r1.11 msdos_fs_i.h
--- linux-2.5/include/linux/msdos_fs_i.h	20 Oct 2004 15:15:45 -0000	1.11
+++ linux-2.5/include/linux/msdos_fs_i.h	3 Jan 2005 20:37:05 -0000
@@ -20,7 +20,6 @@
 	int i_start;	/* first cluster or 0 */
 	int i_logstart;	/* logical first cluster */
 	int i_attrs;	/* unused attribute bits */
-	int i_ctime_ms;	/* unused change time in milliseconds */
 	loff_t i_pos;	/* on-disk position of directory entry or 0 */
 	struct hlist_node i_fat_hash;	/* hash by i_location */
 	struct inode vfs_inode;

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2005-01-06  1:54 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <fa.i537e7s.1d6m90c@ifi.uio.no>
     [not found] ` <fa.ihdqkec.1i5umji@ifi.uio.no>
2005-01-06  0:07   ` Re: [PATCH] get/set FAT filesystem attribute bits Bodo Eggert
2005-01-06  0:15     ` Nicholas Miell
2005-01-06  1:58       ` Bodo Eggert
2005-01-06  1:35     ` H. Peter Anvin
     [not found] <fa.ea9o20r.kje5qn@ifi.uio.no>
     [not found] ` <fa.lub44op.a2ec2d@ifi.uio.no>
2005-01-04 11:57   ` Bodo Eggert
2005-01-04 21:26     ` H. Peter Anvin
2005-01-03 20:57 H. Peter Anvin
2005-01-03 21:24 ` Nicholas Miell
2005-01-03 21:35   ` H. Peter Anvin
2005-01-03 21:46     ` Nicholas Miell
2005-01-03 22:02       ` H. Peter Anvin
2005-01-03 22:10         ` Nicholas Miell
2005-01-03 22:25           ` H. Peter Anvin
2005-01-03 23:16             ` Nicholas Miell
2005-01-03 23:22               ` H. Peter Anvin
2005-01-03 23:46                 ` Nicholas Miell
2005-01-04 10:09         ` Anton Altaparmakov
2005-01-04 21:45           ` Nicholas Miell
2005-01-04  8:34 ` OGAWA Hirofumi
2005-01-04  9:41   ` H. Peter Anvin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox