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