diff options
-rw-r--r-- | Documentation/ioctl/ioctl-number.txt | 1 | ||||
-rw-r--r-- | fs/hfsplus/hfsplus_fs.h | 5 | ||||
-rw-r--r-- | fs/hfsplus/ioctl.c | 34 |
3 files changed, 40 insertions, 0 deletions
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index 4840334ea97..37a424868ee 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -218,6 +218,7 @@ Code Seq#(hex) Include File Comments 'h' 00-7F conflict! Charon filesystem <mailto:zapman@interlan.net> 'h' 00-1F linux/hpet.h conflict! +'h' 80-8F fs/hfsplus/ioctl.c 'i' 00-3F linux/i2o-dev.h conflict! 'i' 0B-1F linux/ipmi.h conflict! 'i' 80-8F linux/i8k.h diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 21a5b7fc6db..4e75ac646fe 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -317,6 +317,11 @@ static inline unsigned short hfsplus_min_io_size(struct super_block *sb) /* + * hfs+-specific ioctl for making the filesystem bootable + */ +#define HFSPLUS_IOC_BLESS _IO('h', 0x80) + +/* * Functions in any *.c used in other files */ diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c index f66c7655b3f..c640ba57074 100644 --- a/fs/hfsplus/ioctl.c +++ b/fs/hfsplus/ioctl.c @@ -20,6 +20,38 @@ #include <asm/uaccess.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) { 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) return hfsplus_ioctl_getflags(file, argp); case HFSPLUS_IOC_EXT2_SETFLAGS: return hfsplus_ioctl_setflags(file, argp); + case HFSPLUS_IOC_BLESS: + return hfsplus_ioctl_bless(file, argp); default: return -ENOTTY; } |