11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Pioctl operations for Coda.
31977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur * Original version: (C) 1996 Peter Braam
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Rewritten for Linux 2.1: (C) 1997 Carnegie Mellon University
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Carnegie Mellon encourages users of this code to contribute improvements
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>.
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/time.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/stat.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/namei.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/coda.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/coda_psdev.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2431a203df9c109480fc6d48ba0a68763e89199acbAl Viro#include "coda_linux.h"
2531a203df9c109480fc6d48ba0a68763e89199acbAl Viro
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* pioctl ops */
2710556cb21a0d0b24d95f00ea6df16f599a3345b2Al Virostatic int coda_ioctl_permission(struct inode *inode, int mask);
282ff82f852189226cda3cb192985a4a7fc750ab26John Kacurstatic long coda_pioctl(struct file *filp, unsigned int cmd,
292ff82f852189226cda3cb192985a4a7fc750ab26John Kacur			unsigned long user_data);
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* exported from this file */
321977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacurconst struct inode_operations coda_ioctl_inode_operations = {
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.permission	= coda_ioctl_permission,
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.setattr	= coda_setattr,
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
374b6f5d20b04dcbc3d888555522b90ba6d36c4106Arjan van de Venconst struct file_operations coda_ioctl_operations = {
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner		= THIS_MODULE,
392ff82f852189226cda3cb192985a4a7fc750ab26John Kacur	.unlocked_ioctl	= coda_pioctl,
406038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann	.llseek		= noop_llseek,
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* the coda pioctl inode ops */
4410556cb21a0d0b24d95f00ea6df16f599a3345b2Al Virostatic int coda_ioctl_permission(struct inode *inode, int mask)
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
46f696a3659fc4b3a3bf4bc83d9dbec5e5a2ffd929Miklos Szeredi	return (mask & MAY_EXEC) ? -EACCES : 0;
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
492ff82f852189226cda3cb192985a4a7fc750ab26John Kacurstatic long coda_pioctl(struct file *filp, unsigned int cmd,
502ff82f852189226cda3cb192985a4a7fc750ab26John Kacur			unsigned long user_data)
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
522d8f30380ab8c706f4e0a8f1aaa22b5886e9ac8aAl Viro	struct path path;
531977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur	int error;
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct PioctlData data;
552ff82f852189226cda3cb192985a4a7fc750ab26John Kacur	struct inode *inode = filp->f_dentry->d_inode;
561977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur	struct inode *target_inode = NULL;
571977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur	struct coda_inode_info *cnp;
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
591977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur	/* get the Pioctl data arguments from user space */
60f7cc02b8715618e179242ba9cc10bdc5146ae565Yoshihisa Abe	if (copy_from_user(&data, (void __user *)user_data, sizeof(data)))
61f7cc02b8715618e179242ba9cc10bdc5146ae565Yoshihisa Abe		return -EINVAL;
621977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur
631977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur	/*
641977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur	 * Look up the pathname. Note that the pathname is in
651977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur	 * user memory, and namei takes care of this
661977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur	 */
672ff82f852189226cda3cb192985a4a7fc750ab26John Kacur	if (data.follow)
681977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur		error = user_path(data.path, &path);
692ff82f852189226cda3cb192985a4a7fc750ab26John Kacur	else
701977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur		error = user_lpath(data.path, &path);
712ff82f852189226cda3cb192985a4a7fc750ab26John Kacur
722ff82f852189226cda3cb192985a4a7fc750ab26John Kacur	if (error)
73f7cc02b8715618e179242ba9cc10bdc5146ae565Yoshihisa Abe		return error;
74f7cc02b8715618e179242ba9cc10bdc5146ae565Yoshihisa Abe
75f7cc02b8715618e179242ba9cc10bdc5146ae565Yoshihisa Abe	target_inode = path.dentry->d_inode;
762ff82f852189226cda3cb192985a4a7fc750ab26John Kacur
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* return if it is not a Coda inode */
781977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur	if (target_inode->i_sb != inode->i_sb) {
792ff82f852189226cda3cb192985a4a7fc750ab26John Kacur		error = -EINVAL;
802ff82f852189226cda3cb192985a4a7fc750ab26John Kacur		goto out;
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* now proceed to make the upcall */
841977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur	cnp = ITOC(target_inode);
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data);
872ff82f852189226cda3cb192985a4a7fc750ab26John Kacurout:
88f7cc02b8715618e179242ba9cc10bdc5146ae565Yoshihisa Abe	path_put(&path);
891977bb2ed8ffdd161fe1c9eef1f9fd283e41d4b5John Kacur	return error;
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
91