root/fs/hfsplus/ioctl.c
// SPDX-License-Identifier: GPL-2.0
/*
 *  linux/fs/hfsplus/ioctl.c
 *
 * Copyright (C) 2003
 * Ethan Benson <erbenson@alaska.net>
 * partially derived from linux/fs/ext2/ioctl.c
 * Copyright (C) 1993, 1994, 1995
 * Remy Card (card@masi.ibp.fr)
 * Laboratoire MASI - Institut Blaise Pascal
 * Universite Pierre et Marie Curie (Paris VI)
 *
 * hfsplus ioctls
 */

#include <linux/capability.h>
#include <linux/fs.h>
#include <linux/mount.h>
#include <linux/sched.h>
#include <linux/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 = d_inode(dentry);
        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;
        u32 cnid = (unsigned long)dentry->d_fsdata;

        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(d_parent_ino(dentry));

        /*
         * Bootloader. Just using the inode here breaks in the case of
         * hard links - the firmware wants the ID of the hard link file,
         * but the inode points at the indirect inode
         */
        vh->finder_info[1] = bvh->finder_info[1] = cpu_to_be32(cnid);

        /* Per spec, the OS X system folder - same as finder_info[0] here */
        vh->finder_info[5] = bvh->finder_info[5] =
                cpu_to_be32(d_parent_ino(dentry));

        mutex_unlock(&sbi->vh_mutex);
        return 0;
}

long hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
        void __user *argp = (void __user *)arg;

        switch (cmd) {
        case HFSPLUS_IOC_BLESS:
                return hfsplus_ioctl_bless(file, argp);
        default:
                return -ENOTTY;
        }
}