Beispiel #1
0
static long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
{
	struct _inode * inode;
	struct _dentry *dentry;
	struct file * file;
	struct _file * _file;
	int error;

	error = -EINVAL;
	if (length < 0)
		goto out;
	error = -EBADF;
	file = fget(fd);
	if (!file)
		goto out;

	_file = tx_cache_get_file_ro(file);
	/* explicitly opened as large or we are on 64-bit box */
	if (_file->f_flags & O_LARGEFILE)
		small = 0;

	dentry = f_get_dentry(_file);
	inode = d_get_inode(dentry);
	error = -EINVAL;
	if (!S_ISREG(inode->i_mode) || !(_file->f_mode & FMODE_WRITE))
		goto out_putf;

	error = -EINVAL;
	/* Cannot ftruncate over 2^31 bytes without large file support */
	if (small && length > MAX_NON_LFS)
		goto out_putf;

	error = -EPERM;
	if (IS_APPEND(inode))
		goto out_putf;

	error = locks_verify_truncate(parent(inode), file, length);
	if (!error)
		error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file);
out_putf:
	fput(file);
out:
	return error;
}
Beispiel #2
0
/*
 * When you add any new common ioctls to the switches above and below
 * please update compat_sys_ioctl() too.
 *
 * vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
 * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
 */
int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg)
{
	unsigned int flag;
	int on, error = 0;
	umode_t mode;
	
	struct _file *_filp = tx_cache_get_file(filp);
	/* Patch up ioctl for bad tx cases*/
	if((!_filp) || !_filp->f_dentry ){
#ifdef CONFIG_TX_KSTM_WARNINGS
		printk(KERN_ERR "Fixing up ioctl\n");
#endif
		return 0;
	}
	mode = d_get_inode_ro(f_get_dentry(_filp))->i_mode;

	switch (cmd) {
		case FIOCLEX:
			set_close_on_exec(fd, 1);
			break;

		case FIONCLEX:
			set_close_on_exec(fd, 0);
			break;

		case FIONBIO:
			if ((error = get_user(on, (int __user *)arg)) != 0)
				break;
			flag = O_NONBLOCK;
#ifdef __sparc__
			/* SunOS compatibility item. */
			if(O_NONBLOCK != O_NDELAY)
				flag |= O_NDELAY;
#endif
			if (on)
				_filp->f_flags |= flag;
			else
				_filp->f_flags &= ~flag;
			break;

		case FIOASYNC:
			if ((error = get_user(on, (int __user *)arg)) != 0)
				break;
			flag = on ? FASYNC : 0;

			/* Did FASYNC state change ? */
			if ((flag ^ _filp->f_flags) & FASYNC) {
				if (filp->f_op && filp->f_op->fasync) {
					lock_kernel();
					error = filp->f_op->fasync(fd, filp, on);
					unlock_kernel();
				}
				else error = -ENOTTY;
			}
			if (error != 0)
				break;

			if (on)
				_filp->f_flags |= FASYNC;
			else
				_filp->f_flags &= ~FASYNC;
			break;

		case FIOQSIZE:
			if (S_ISDIR(mode) ||
			    S_ISREG(mode) ||
			    S_ISLNK(mode)) {
				loff_t res = inode_get_bytes(f_get_dentry(_filp)->d_inode);
				error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
			}
			else
				error = -ENOTTY;
			break;
		default:
			if(live_transaction()){
				/* Short circuit this stupid ioctl */
				if(cmd == TIOCGWINSZ){
#ifdef CONFIG_TX_KSTM_WARNINGS
					printk(KERN_ERR "Warning: some bozo wants to know the terminal width in a transaction.\n");
#endif
					error = -EINVAL;
					break;
				} else if(cmd != TCGETS)
					BUG();
			}

			if (S_ISREG(mode))
				error = file_ioctl(filp, cmd, arg);
			else
				error = do_ioctl(filp, cmd, arg);
			break;
	}
	return error;
}