18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Pioctl operations for Coda.
48c2ecf20Sopenharmony_ci * Original version: (C) 1996 Peter Braam
58c2ecf20Sopenharmony_ci * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Carnegie Mellon encourages users of this code to contribute improvements
88c2ecf20Sopenharmony_ci * to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/types.h>
128c2ecf20Sopenharmony_ci#include <linux/kernel.h>
138c2ecf20Sopenharmony_ci#include <linux/time.h>
148c2ecf20Sopenharmony_ci#include <linux/fs.h>
158c2ecf20Sopenharmony_ci#include <linux/stat.h>
168c2ecf20Sopenharmony_ci#include <linux/errno.h>
178c2ecf20Sopenharmony_ci#include <linux/string.h>
188c2ecf20Sopenharmony_ci#include <linux/namei.h>
198c2ecf20Sopenharmony_ci#include <linux/module.h>
208c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include <linux/coda.h>
238c2ecf20Sopenharmony_ci#include "coda_psdev.h"
248c2ecf20Sopenharmony_ci#include "coda_linux.h"
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/* pioctl ops */
278c2ecf20Sopenharmony_cistatic int coda_ioctl_permission(struct inode *inode, int mask);
288c2ecf20Sopenharmony_cistatic long coda_pioctl(struct file *filp, unsigned int cmd,
298c2ecf20Sopenharmony_ci			unsigned long user_data);
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/* exported from this file */
328c2ecf20Sopenharmony_ciconst struct inode_operations coda_ioctl_inode_operations = {
338c2ecf20Sopenharmony_ci	.permission	= coda_ioctl_permission,
348c2ecf20Sopenharmony_ci	.setattr	= coda_setattr,
358c2ecf20Sopenharmony_ci};
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ciconst struct file_operations coda_ioctl_operations = {
388c2ecf20Sopenharmony_ci	.unlocked_ioctl	= coda_pioctl,
398c2ecf20Sopenharmony_ci	.llseek		= noop_llseek,
408c2ecf20Sopenharmony_ci};
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* the coda pioctl inode ops */
438c2ecf20Sopenharmony_cistatic int coda_ioctl_permission(struct inode *inode, int mask)
448c2ecf20Sopenharmony_ci{
458c2ecf20Sopenharmony_ci	return (mask & MAY_EXEC) ? -EACCES : 0;
468c2ecf20Sopenharmony_ci}
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistatic long coda_pioctl(struct file *filp, unsigned int cmd,
498c2ecf20Sopenharmony_ci			unsigned long user_data)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	struct path path;
528c2ecf20Sopenharmony_ci	int error;
538c2ecf20Sopenharmony_ci	struct PioctlData data;
548c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(filp);
558c2ecf20Sopenharmony_ci	struct inode *target_inode = NULL;
568c2ecf20Sopenharmony_ci	struct coda_inode_info *cnp;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	/* get the Pioctl data arguments from user space */
598c2ecf20Sopenharmony_ci	if (copy_from_user(&data, (void __user *)user_data, sizeof(data)))
608c2ecf20Sopenharmony_ci		return -EINVAL;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	/*
638c2ecf20Sopenharmony_ci	 * Look up the pathname. Note that the pathname is in
648c2ecf20Sopenharmony_ci	 * user memory, and namei takes care of this
658c2ecf20Sopenharmony_ci	 */
668c2ecf20Sopenharmony_ci	error = user_path_at(AT_FDCWD, data.path,
678c2ecf20Sopenharmony_ci			     data.follow ? LOOKUP_FOLLOW : 0, &path);
688c2ecf20Sopenharmony_ci	if (error)
698c2ecf20Sopenharmony_ci		return error;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	target_inode = d_inode(path.dentry);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	/* return if it is not a Coda inode */
748c2ecf20Sopenharmony_ci	if (target_inode->i_sb != inode->i_sb) {
758c2ecf20Sopenharmony_ci		error = -EINVAL;
768c2ecf20Sopenharmony_ci		goto out;
778c2ecf20Sopenharmony_ci	}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	/* now proceed to make the upcall */
808c2ecf20Sopenharmony_ci	cnp = ITOC(target_inode);
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci	error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data);
838c2ecf20Sopenharmony_ciout:
848c2ecf20Sopenharmony_ci	path_put(&path);
858c2ecf20Sopenharmony_ci	return error;
868c2ecf20Sopenharmony_ci}
87