示例#1
0
int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{	
	struct file * filp;
	extern int sock_fcntl (struct file *, unsigned int cmd,
			       unsigned long arg);
	if (fd >= NR_OPEN || !(filp = current->filp[fd]))
		return -EBADF;
	switch (cmd) {
		case F_DUPFD:
			return dupfd(fd,arg);
		case F_GETFD:
			return FD_ISSET(fd, &current->close_on_exec);
		case F_SETFD:
			if (arg&1)
				FD_SET(fd, &current->close_on_exec);
			else
				FD_CLR(fd, &current->close_on_exec);
			return 0;
		case F_GETFL:
			return filp->f_flags;
		case F_SETFL:
			filp->f_flags &= ~(O_APPEND | O_NONBLOCK);
			filp->f_flags |= arg & (O_APPEND | O_NONBLOCK);
			return 0;
		case F_GETLK:
			return fcntl_getlk(fd, (struct flock *) arg);
		case F_SETLK:
			return fcntl_setlk(fd, cmd, (struct flock *) arg);
		case F_SETLKW:
			return fcntl_setlk(fd, cmd, (struct flock *) arg);
		default:
			/* sockets need a few special fcntls. */
			if (S_ISSOCK (filp->f_inode->i_mode))
			  {
			     return (sock_fcntl (filp, cmd, arg));
			  }
			return -EINVAL;
	}
}
示例#2
0
文件: fcntl.c 项目: nemumu/linux
static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
                     struct file *filp)
{
    long err = -EINVAL;

    switch (cmd) {
    case F_DUPFD:
        err = f_dupfd(arg, filp, 0);
        break;
    case F_DUPFD_CLOEXEC:
        err = f_dupfd(arg, filp, O_CLOEXEC);
        break;
    case F_GETFD:
        err = get_close_on_exec(fd) ? FD_CLOEXEC : 0;
        break;
    case F_SETFD:
        err = 0;
        set_close_on_exec(fd, arg & FD_CLOEXEC);
        break;
    case F_GETFL:
        err = filp->f_flags;
        break;
    case F_SETFL:
        err = setfl(fd, filp, arg);
        break;
#if BITS_PER_LONG != 32
    /* 32-bit arches must use fcntl64() */
    case F_OFD_GETLK:
#endif
    case F_GETLK:
        err = fcntl_getlk(filp, cmd, (struct flock __user *) arg);
        break;
#if BITS_PER_LONG != 32
    /* 32-bit arches must use fcntl64() */
    case F_OFD_SETLK:
    case F_OFD_SETLKW:
#endif
    /* Fallthrough */
    case F_SETLK:
    case F_SETLKW:
        err = fcntl_setlk(fd, filp, cmd, (struct flock __user *) arg);
        break;
    case F_GETOWN:
        /*
         * XXX If f_owner is a process group, the
         * negative return value will get converted
         * into an error.  Oops.  If we keep the
         * current syscall conventions, the only way
         * to fix this will be in libc.
         */
        err = f_getown(filp);
        force_successful_syscall_return();
        break;
    case F_SETOWN:
        err = f_setown(filp, arg, 1);
        break;
    case F_GETOWN_EX:
        err = f_getown_ex(filp, arg);
        break;
    case F_SETOWN_EX:
        err = f_setown_ex(filp, arg);
        break;
    case F_GETOWNER_UIDS:
        err = f_getowner_uids(filp, arg);
        break;
    case F_GETSIG:
        err = filp->f_owner.signum;
        break;
    case F_SETSIG:
        /* arg == 0 restores default behaviour. */
        if (!valid_signal(arg)) {
            break;
        }
        err = 0;
        filp->f_owner.signum = arg;
        break;
    case F_GETLEASE:
        err = fcntl_getlease(filp);
        break;
    case F_SETLEASE:
        err = fcntl_setlease(fd, filp, arg);
        break;
    case F_NOTIFY:
        err = fcntl_dirnotify(fd, filp, arg);
        break;
    case F_SETPIPE_SZ:
    case F_GETPIPE_SZ:
        err = pipe_fcntl(filp, cmd, arg);
        break;
    case F_ADD_SEALS:
    case F_GET_SEALS:
        err = shmem_fcntl(filp, cmd, arg);
        break;
    default:
        break;
    }
    return err;
}
示例#3
0
asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{	
	struct file * filp;
	long err = -EBADF;

	lock_kernel();
	filp = fget(fd);
	if (!filp)
		goto out;

	err = 0;
	switch (cmd) {
		case F_DUPFD:
			err = dupfd(fd, arg);
			break;
		case F_GETFD:
			err = FD_ISSET(fd, current->files->close_on_exec);
			break;
		case F_SETFD:
			if (arg&1)
				FD_SET(fd, current->files->close_on_exec);
			else
				FD_CLR(fd, current->files->close_on_exec);
			break;
		case F_GETFL:
			err = filp->f_flags;
			break;
		case F_SETFL:
			err = setfl(fd, filp, arg);
			break;
		case F_GETLK:
			err = fcntl_getlk(fd, (struct flock *) arg);
			break;
		case F_SETLK:
			err = fcntl_setlk(fd, cmd, (struct flock *) arg);
			break;
		case F_SETLKW:
			err = fcntl_setlk(fd, cmd, (struct flock *) arg);
			break;
		case F_GETOWN:
			/*
			 * XXX If f_owner is a process group, the
			 * negative return value will get converted
			 * into an error.  Oops.  If we keep the
			 * current syscall conventions, the only way
			 * to fix this will be in libc.
			 */
			err = filp->f_owner.pid;
			break;
		case F_SETOWN:
			filp->f_owner.pid = arg;
			filp->f_owner.uid = current->uid;
			filp->f_owner.euid = current->euid;
			if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
				err = sock_fcntl (filp, F_SETOWN, arg);
			break;
		case F_GETSIG:
			err = filp->f_owner.signum;
			break;
		case F_SETSIG:
			if (arg <= 0 || arg > _NSIG) {
				err = -EINVAL;
				break;
			}
			err = 0;
			filp->f_owner.signum = arg;
			break;
		default:
			/* sockets need a few special fcntls. */
			err = -EINVAL;
			if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
				err = sock_fcntl (filp, cmd, arg);
			break;
	}
	fput(filp);
out:
	unlock_kernel();
	return err;
}
示例#4
0
COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
		       compat_ulong_t, arg)
{
	struct fd f = fdget_raw(fd);
	struct flock flock;
	long err = -EBADF;

	if (!f.file)
		return err;

	if (unlikely(f.file->f_mode & FMODE_PATH)) {
		if (!check_fcntl_cmd(cmd))
			goto out_put;
	}

	err = security_file_fcntl(f.file, cmd, arg);
	if (err)
		goto out_put;

	switch (cmd) {
	case F_GETLK:
		err = get_compat_flock(&flock, compat_ptr(arg));
		if (err)
			break;
		err = fcntl_getlk(f.file, convert_fcntl_cmd(cmd), &flock);
		if (err)
			break;
		err = fixup_compat_flock(&flock);
		if (!err)
			err = put_compat_flock(&flock, compat_ptr(arg));
		break;
	case F_GETLK64:
	case F_OFD_GETLK:
		err = get_compat_flock64(&flock, compat_ptr(arg));
		if (err)
			break;
		err = fcntl_getlk(f.file, convert_fcntl_cmd(cmd), &flock);
		if (!err)
			err = put_compat_flock64(&flock, compat_ptr(arg));
		break;
	case F_SETLK:
	case F_SETLKW:
		err = get_compat_flock(&flock, compat_ptr(arg));
		if (err)
			break;
		err = fcntl_setlk(fd, f.file, convert_fcntl_cmd(cmd), &flock);
		break;
	case F_SETLK64:
	case F_SETLKW64:
	case F_OFD_SETLK:
	case F_OFD_SETLKW:
		err = get_compat_flock64(&flock, compat_ptr(arg));
		if (err)
			break;
		err = fcntl_setlk(fd, f.file, convert_fcntl_cmd(cmd), &flock);
		break;
	default:
		err = do_fcntl(fd, cmd, arg, f.file);
		break;
	}
out_put:
	fdput(f);
	return err;
}
示例#5
0
asmlinkage int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{	
	struct file * filp;

	if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))
		return -EBADF;
	switch (cmd) {
		case F_DUPFD:
			return dupfd(fd,arg);
		case F_GETFD:
			return FD_ISSET(fd, &current->files->close_on_exec);
		case F_SETFD:
			if (arg&1)
				FD_SET(fd, &current->files->close_on_exec);
			else
				FD_CLR(fd, &current->files->close_on_exec);
			return 0;
		case F_GETFL:
			return filp->f_flags;
		case F_SETFL:
			/*
			 * In the case of an append-only file, O_APPEND
			 * cannot be cleared
			 */
			if (IS_APPEND(filp->f_inode) && !(arg & O_APPEND))
				return -EPERM;
			if ((arg & FASYNC) && !(filp->f_flags & FASYNC) &&
			    filp->f_op->fasync)
				filp->f_op->fasync(filp->f_inode, filp, 1);
			if (!(arg & FASYNC) && (filp->f_flags & FASYNC) &&
			    filp->f_op->fasync)
				filp->f_op->fasync(filp->f_inode, filp, 0);
			filp->f_flags &= ~(O_APPEND | O_NONBLOCK | FASYNC);
			filp->f_flags |= arg & (O_APPEND | O_NONBLOCK |
						FASYNC);
			return 0;
		case F_GETLK:
			return fcntl_getlk(fd, (struct flock *) arg);
		case F_SETLK:
			return fcntl_setlk(fd, cmd, (struct flock *) arg);
		case F_SETLKW:
			return fcntl_setlk(fd, cmd, (struct flock *) arg);
		case F_GETOWN:
			/*
			 * XXX If f_owner is a process group, the
			 * negative return value will get converted
			 * into an error.  Oops.  If we keep the the
			 * current syscall conventions, the only way
			 * to fix this will be in libc.
			 */
			return filp->f_owner;
		case F_SETOWN:
			filp->f_owner = arg; /* XXX security implications? */
			if (S_ISSOCK (filp->f_inode->i_mode))
				sock_fcntl (filp, F_SETOWN, arg);
			return 0;
		default:
			/* sockets need a few special fcntls. */
			if (S_ISSOCK (filp->f_inode->i_mode))
			  {
			     return (sock_fcntl (filp, cmd, arg));
			  }
			return -EINVAL;
	}
}