Commit a051f71c authored by Matthew Garrett's avatar Matthew Garrett Committed by Al Viro

hfsplus: add an ioctl to bless files

Making an hfsplus partition bootable requires the ability to "bless" a
file by putting its inode number in the volume header. Doing this from
userspace on a mounted filesystem is impractical since the kernel will
write back the original values on unmount. Add an ioctl to allow userspace
to update the volume header information based on the target file.
Signed-off-by: default avatarMatthew Garrett <mjg@redhat.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 0347b6e9
...@@ -218,6 +218,7 @@ Code Seq#(hex) Include File Comments ...@@ -218,6 +218,7 @@ Code Seq#(hex) Include File Comments
'h' 00-7F conflict! Charon filesystem 'h' 00-7F conflict! Charon filesystem
<mailto:zapman@interlan.net> <mailto:zapman@interlan.net>
'h' 00-1F linux/hpet.h conflict! 'h' 00-1F linux/hpet.h conflict!
'h' 80-8F fs/hfsplus/ioctl.c
'i' 00-3F linux/i2o-dev.h conflict! 'i' 00-3F linux/i2o-dev.h conflict!
'i' 0B-1F linux/ipmi.h conflict! 'i' 0B-1F linux/ipmi.h conflict!
'i' 80-8F linux/i8k.h 'i' 80-8F linux/i8k.h
......
...@@ -316,6 +316,11 @@ static inline unsigned short hfsplus_min_io_size(struct super_block *sb) ...@@ -316,6 +316,11 @@ static inline unsigned short hfsplus_min_io_size(struct super_block *sb)
#define HFSPLUS_IOC_EXT2_SETFLAGS FS_IOC_SETFLAGS #define HFSPLUS_IOC_EXT2_SETFLAGS FS_IOC_SETFLAGS
/*
* hfs+-specific ioctl for making the filesystem bootable
*/
#define HFSPLUS_IOC_BLESS _IO('h', 0x80)
/* /*
* Functions in any *.c used in other files * Functions in any *.c used in other files
*/ */
......
...@@ -20,6 +20,38 @@ ...@@ -20,6 +20,38 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include "hfsplus_fs.h" #include "hfsplus_fs.h"
/*
* "Blessing" an HFS+ filesystem writes metadata to the superblock informing
* the platform firmware which file to boot from
*/
static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
{
struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;
struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
struct hfsplus_vh *vh = sbi->s_vhdr;
struct hfsplus_vh *bvh = sbi->s_backup_vhdr;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
mutex_lock(&sbi->vh_mutex);
/* Directory containing the bootable system */
vh->finder_info[0] = bvh->finder_info[0] =
cpu_to_be32(parent_ino(dentry));
/* Bootloader */
vh->finder_info[1] = bvh->finder_info[1] = cpu_to_be32(inode->i_ino);
/* Per spec, the OS X system folder - same as finder_info[0] here */
vh->finder_info[5] = bvh->finder_info[5] =
cpu_to_be32(parent_ino(dentry));
mutex_unlock(&sbi->vh_mutex);
return 0;
}
static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags) static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
{ {
struct inode *inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
...@@ -108,6 +140,8 @@ long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -108,6 +140,8 @@ long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return hfsplus_ioctl_getflags(file, argp); return hfsplus_ioctl_getflags(file, argp);
case HFSPLUS_IOC_EXT2_SETFLAGS: case HFSPLUS_IOC_EXT2_SETFLAGS:
return hfsplus_ioctl_setflags(file, argp); return hfsplus_ioctl_setflags(file, argp);
case HFSPLUS_IOC_BLESS:
return hfsplus_ioctl_bless(file, argp);
default: default:
return -ENOTTY; return -ENOTTY;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment