Commit a051f71ce97c53cde3ac64de64eb02d658d9308e

Authored by Matthew Garrett
Committed by Al Viro
1 parent 0347b6e95c

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: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Showing 3 changed files with 40 additions and 0 deletions Side-by-side Diff

Documentation/ioctl/ioctl-number.txt
... ... @@ -218,6 +218,7 @@
218 218 'h' 00-7F conflict! Charon filesystem
219 219 <mailto:zapman@interlan.net>
220 220 'h' 00-1F linux/hpet.h conflict!
  221 +'h' 80-8F fs/hfsplus/ioctl.c
221 222 'i' 00-3F linux/i2o-dev.h conflict!
222 223 'i' 0B-1F linux/ipmi.h conflict!
223 224 'i' 80-8F linux/i8k.h
fs/hfsplus/hfsplus_fs.h
... ... @@ -317,6 +317,11 @@
317 317  
318 318  
319 319 /*
  320 + * hfs+-specific ioctl for making the filesystem bootable
  321 + */
  322 +#define HFSPLUS_IOC_BLESS _IO('h', 0x80)
  323 +
  324 +/*
320 325 * Functions in any *.c used in other files
321 326 */
322 327  
... ... @@ -20,6 +20,38 @@
20 20 #include <asm/uaccess.h>
21 21 #include "hfsplus_fs.h"
22 22  
  23 +/*
  24 + * "Blessing" an HFS+ filesystem writes metadata to the superblock informing
  25 + * the platform firmware which file to boot from
  26 + */
  27 +static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
  28 +{
  29 + struct dentry *dentry = file->f_path.dentry;
  30 + struct inode *inode = dentry->d_inode;
  31 + struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
  32 + struct hfsplus_vh *vh = sbi->s_vhdr;
  33 + struct hfsplus_vh *bvh = sbi->s_backup_vhdr;
  34 +
  35 + if (!capable(CAP_SYS_ADMIN))
  36 + return -EPERM;
  37 +
  38 + mutex_lock(&sbi->vh_mutex);
  39 +
  40 + /* Directory containing the bootable system */
  41 + vh->finder_info[0] = bvh->finder_info[0] =
  42 + cpu_to_be32(parent_ino(dentry));
  43 +
  44 + /* Bootloader */
  45 + vh->finder_info[1] = bvh->finder_info[1] = cpu_to_be32(inode->i_ino);
  46 +
  47 + /* Per spec, the OS X system folder - same as finder_info[0] here */
  48 + vh->finder_info[5] = bvh->finder_info[5] =
  49 + cpu_to_be32(parent_ino(dentry));
  50 +
  51 + mutex_unlock(&sbi->vh_mutex);
  52 + return 0;
  53 +}
  54 +
23 55 static int hfsplus_ioctl_getflags(struct file *file, int __user *user_flags)
24 56 {
25 57 struct inode *inode = file->f_path.dentry->d_inode;
... ... @@ -108,6 +140,8 @@
108 140 return hfsplus_ioctl_getflags(file, argp);
109 141 case HFSPLUS_IOC_EXT2_SETFLAGS:
110 142 return hfsplus_ioctl_setflags(file, argp);
  143 + case HFSPLUS_IOC_BLESS:
  144 + return hfsplus_ioctl_bless(file, argp);
111 145 default:
112 146 return -ENOTTY;
113 147 }