1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/fs/hfsplus/ioctl.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) 2003
61da177e4SLinus Torvalds * Ethan Benson <erbenson@alaska.net>
71da177e4SLinus Torvalds * partially derived from linux/fs/ext2/ioctl.c
81da177e4SLinus Torvalds * Copyright (C) 1993, 1994, 1995
91da177e4SLinus Torvalds * Remy Card (card@masi.ibp.fr)
101da177e4SLinus Torvalds * Laboratoire MASI - Institut Blaise Pascal
111da177e4SLinus Torvalds * Universite Pierre et Marie Curie (Paris VI)
121da177e4SLinus Torvalds *
131da177e4SLinus Torvalds * hfsplus ioctls
141da177e4SLinus Torvalds */
151da177e4SLinus Torvalds
1616f7e0feSRandy Dunlap #include <linux/capability.h>
171da177e4SLinus Torvalds #include <linux/fs.h>
1842a74f20SDave Hansen #include <linux/mount.h>
191da177e4SLinus Torvalds #include <linux/sched.h>
207c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
211da177e4SLinus Torvalds #include "hfsplus_fs.h"
221da177e4SLinus Torvalds
23a051f71cSMatthew Garrett /*
24a051f71cSMatthew Garrett * "Blessing" an HFS+ filesystem writes metadata to the superblock informing
25a051f71cSMatthew Garrett * the platform firmware which file to boot from
26a051f71cSMatthew Garrett */
hfsplus_ioctl_bless(struct file * file,int __user * user_flags)27a051f71cSMatthew Garrett static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
28a051f71cSMatthew Garrett {
29a051f71cSMatthew Garrett struct dentry *dentry = file->f_path.dentry;
302b0143b5SDavid Howells struct inode *inode = d_inode(dentry);
31a051f71cSMatthew Garrett struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
32a051f71cSMatthew Garrett struct hfsplus_vh *vh = sbi->s_vhdr;
33a051f71cSMatthew Garrett struct hfsplus_vh *bvh = sbi->s_backup_vhdr;
347dea9665SMatthew Garrett u32 cnid = (unsigned long)dentry->d_fsdata;
35a051f71cSMatthew Garrett
36a051f71cSMatthew Garrett if (!capable(CAP_SYS_ADMIN))
37a051f71cSMatthew Garrett return -EPERM;
38a051f71cSMatthew Garrett
39a051f71cSMatthew Garrett mutex_lock(&sbi->vh_mutex);
40a051f71cSMatthew Garrett
41a051f71cSMatthew Garrett /* Directory containing the bootable system */
42a051f71cSMatthew Garrett vh->finder_info[0] = bvh->finder_info[0] =
43a051f71cSMatthew Garrett cpu_to_be32(parent_ino(dentry));
44a051f71cSMatthew Garrett
457dea9665SMatthew Garrett /*
467dea9665SMatthew Garrett * Bootloader. Just using the inode here breaks in the case of
477dea9665SMatthew Garrett * hard links - the firmware wants the ID of the hard link file,
487dea9665SMatthew Garrett * but the inode points at the indirect inode
497dea9665SMatthew Garrett */
507dea9665SMatthew Garrett vh->finder_info[1] = bvh->finder_info[1] = cpu_to_be32(cnid);
51a051f71cSMatthew Garrett
52a051f71cSMatthew Garrett /* Per spec, the OS X system folder - same as finder_info[0] here */
53a051f71cSMatthew Garrett vh->finder_info[5] = bvh->finder_info[5] =
54a051f71cSMatthew Garrett cpu_to_be32(parent_ino(dentry));
55a051f71cSMatthew Garrett
56a051f71cSMatthew Garrett mutex_unlock(&sbi->vh_mutex);
57a051f71cSMatthew Garrett return 0;
58a051f71cSMatthew Garrett }
59a051f71cSMatthew Garrett
hfsplus_ioctl(struct file * file,unsigned int cmd,unsigned long arg)6094744567SChristoph Hellwig long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
6194744567SChristoph Hellwig {
6294744567SChristoph Hellwig void __user *argp = (void __user *)arg;
6394744567SChristoph Hellwig
6494744567SChristoph Hellwig switch (cmd) {
65a051f71cSMatthew Garrett case HFSPLUS_IOC_BLESS:
66a051f71cSMatthew Garrett return hfsplus_ioctl_bless(file, argp);
671da177e4SLinus Torvalds default:
681da177e4SLinus Torvalds return -ENOTTY;
691da177e4SLinus Torvalds }
701da177e4SLinus Torvalds }
71