xref: /linux/fs/hfsplus/ioctl.c (revision 8be98d2f2a0a262f8bf8a0bc1fdf522b3c7aab17)
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