fs/fcntl.c

Source file repositories/reference/linux-study-clean/fs/fcntl.c

File Facts

System
Linux kernel
Corpus path
fs/fcntl.c
Extension
.c
Size
27090 bytes
Lines
1184
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: syscall or user/kernel boundary
Status
core implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
{	
	CLASS(fd_raw, f)(fd);
	long err;

	if (fd_empty(f))
		return -EBADF;

	if (unlikely(fd_file(f)->f_mode & FMODE_PATH)) {
		if (!check_fcntl_cmd(cmd))
			return -EBADF;
	}

	err = security_file_fcntl(fd_file(f), cmd, arg);
	if (!err)
		err = do_fcntl(fd, cmd, arg, fd_file(f));

	return err;
}

#if BITS_PER_LONG == 32
SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
		unsigned long, arg)
{	
	void __user *argp = (void __user *)arg;
	CLASS(fd_raw, f)(fd);
	struct flock64 flock;
	long err;

	if (fd_empty(f))
		return -EBADF;

	if (unlikely(fd_file(f)->f_mode & FMODE_PATH)) {
		if (!check_fcntl_cmd(cmd))
			return -EBADF;
	}

	err = security_file_fcntl(fd_file(f), cmd, arg);
	if (err)
		return err;
	
	switch (cmd) {
	case F_GETLK64:
	case F_OFD_GETLK:
		err = -EFAULT;
		if (copy_from_user(&flock, argp, sizeof(flock)))
			break;
		err = fcntl_getlk64(fd_file(f), cmd, &flock);
		if (!err && copy_to_user(argp, &flock, sizeof(flock)))
			err = -EFAULT;
		break;
	case F_SETLK64:
	case F_SETLKW64:
	case F_OFD_SETLK:
	case F_OFD_SETLKW:
		err = -EFAULT;
		if (copy_from_user(&flock, argp, sizeof(flock)))
			break;
		err = fcntl_setlk64(fd, fd_file(f), cmd, &flock);
		break;
	default:
		err = do_fcntl(fd, cmd, arg, fd_file(f));
		break;
	}
	return err;
}
#endif

#ifdef CONFIG_COMPAT
/* careful - don't use anywhere else */
#define copy_flock_fields(dst, src)		\
	(dst)->l_type = (src)->l_type;		\
	(dst)->l_whence = (src)->l_whence;	\
	(dst)->l_start = (src)->l_start;	\
	(dst)->l_len = (src)->l_len;		\
	(dst)->l_pid = (src)->l_pid;

static int get_compat_flock(struct flock *kfl, const struct compat_flock __user *ufl)
{
	struct compat_flock fl;

	if (copy_from_user(&fl, ufl, sizeof(struct compat_flock)))
		return -EFAULT;
	copy_flock_fields(kfl, &fl);
	return 0;
}

static int get_compat_flock64(struct flock *kfl, const struct compat_flock64 __user *ufl)
{
	struct compat_flock64 fl;

Annotation

Implementation Notes