162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  linux/fs/hfsplus/ioctl.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2003
662306a36Sopenharmony_ci * Ethan Benson <erbenson@alaska.net>
762306a36Sopenharmony_ci * partially derived from linux/fs/ext2/ioctl.c
862306a36Sopenharmony_ci * Copyright (C) 1993, 1994, 1995
962306a36Sopenharmony_ci * Remy Card (card@masi.ibp.fr)
1062306a36Sopenharmony_ci * Laboratoire MASI - Institut Blaise Pascal
1162306a36Sopenharmony_ci * Universite Pierre et Marie Curie (Paris VI)
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * hfsplus ioctls
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include <linux/capability.h>
1762306a36Sopenharmony_ci#include <linux/fs.h>
1862306a36Sopenharmony_ci#include <linux/mount.h>
1962306a36Sopenharmony_ci#include <linux/sched.h>
2062306a36Sopenharmony_ci#include <linux/uaccess.h>
2162306a36Sopenharmony_ci#include "hfsplus_fs.h"
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/*
2462306a36Sopenharmony_ci * "Blessing" an HFS+ filesystem writes metadata to the superblock informing
2562306a36Sopenharmony_ci * the platform firmware which file to boot from
2662306a36Sopenharmony_ci */
2762306a36Sopenharmony_cistatic int hfsplus_ioctl_bless(struct file *file, int __user *user_flags)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	struct dentry *dentry = file->f_path.dentry;
3062306a36Sopenharmony_ci	struct inode *inode = d_inode(dentry);
3162306a36Sopenharmony_ci	struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
3262306a36Sopenharmony_ci	struct hfsplus_vh *vh = sbi->s_vhdr;
3362306a36Sopenharmony_ci	struct hfsplus_vh *bvh = sbi->s_backup_vhdr;
3462306a36Sopenharmony_ci	u32 cnid = (unsigned long)dentry->d_fsdata;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	if (!capable(CAP_SYS_ADMIN))
3762306a36Sopenharmony_ci		return -EPERM;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	mutex_lock(&sbi->vh_mutex);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	/* Directory containing the bootable system */
4262306a36Sopenharmony_ci	vh->finder_info[0] = bvh->finder_info[0] =
4362306a36Sopenharmony_ci		cpu_to_be32(parent_ino(dentry));
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	/*
4662306a36Sopenharmony_ci	 * Bootloader. Just using the inode here breaks in the case of
4762306a36Sopenharmony_ci	 * hard links - the firmware wants the ID of the hard link file,
4862306a36Sopenharmony_ci	 * but the inode points at the indirect inode
4962306a36Sopenharmony_ci	 */
5062306a36Sopenharmony_ci	vh->finder_info[1] = bvh->finder_info[1] = cpu_to_be32(cnid);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	/* Per spec, the OS X system folder - same as finder_info[0] here */
5362306a36Sopenharmony_ci	vh->finder_info[5] = bvh->finder_info[5] =
5462306a36Sopenharmony_ci		cpu_to_be32(parent_ino(dentry));
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	mutex_unlock(&sbi->vh_mutex);
5762306a36Sopenharmony_ci	return 0;
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cilong hfsplus_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	void __user *argp = (void __user *)arg;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	switch (cmd) {
6562306a36Sopenharmony_ci	case HFSPLUS_IOC_BLESS:
6662306a36Sopenharmony_ci		return hfsplus_ioctl_bless(file, argp);
6762306a36Sopenharmony_ci	default:
6862306a36Sopenharmony_ci		return -ENOTTY;
6962306a36Sopenharmony_ci	}
7062306a36Sopenharmony_ci}
71