fs/file_attr.c

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

File Facts

System
Linux kernel
Corpus path
fs/file_attr.c
Extension
.c
Size
12546 bytes
Lines
487
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_DEFINE5(file_getattr, int, dfd, const char __user *, filename,
		struct file_attr __user *, ufattr, size_t, usize,
		unsigned int, at_flags)
{
	struct path filepath __free(path_put) = {};
	unsigned int lookup_flags = 0;
	struct file_attr fattr;
	struct file_kattr fa = { .flags_valid = true }; /* hint only */
	int error;

	BUILD_BUG_ON(sizeof(struct file_attr) < FILE_ATTR_SIZE_VER0);
	BUILD_BUG_ON(sizeof(struct file_attr) != FILE_ATTR_SIZE_LATEST);

	if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
		return -EINVAL;

	if (!(at_flags & AT_SYMLINK_NOFOLLOW))
		lookup_flags |= LOOKUP_FOLLOW;

	if (usize > PAGE_SIZE)
		return -E2BIG;

	if (usize < FILE_ATTR_SIZE_VER0)
		return -EINVAL;

	CLASS(filename_maybe_null, name)(filename, at_flags);
	if (!name && dfd >= 0) {
		CLASS(fd, f)(dfd);
		if (fd_empty(f))
			return -EBADF;

		filepath = fd_file(f)->f_path;
		path_get(&filepath);
	} else {
		error = filename_lookup(dfd, name, lookup_flags, &filepath,
					NULL);
		if (error)
			return error;
	}

	error = vfs_fileattr_get(filepath.dentry, &fa);
	if (error == -ENOIOCTLCMD || error == -ENOTTY)
		error = -EOPNOTSUPP;
	if (error)
		return error;

	fileattr_to_file_attr(&fa, &fattr);
	error = copy_struct_to_user(ufattr, usize, &fattr,
				    sizeof(struct file_attr), NULL);

	return error;
}

SYSCALL_DEFINE5(file_setattr, int, dfd, const char __user *, filename,
		struct file_attr __user *, ufattr, size_t, usize,
		unsigned int, at_flags)
{
	struct path filepath __free(path_put) = {};
	unsigned int lookup_flags = 0;
	struct file_attr fattr;
	struct file_kattr fa = {};
	int error;

	BUILD_BUG_ON(sizeof(struct file_attr) < FILE_ATTR_SIZE_VER0);
	BUILD_BUG_ON(sizeof(struct file_attr) != FILE_ATTR_SIZE_LATEST);

	if ((at_flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
		return -EINVAL;

	if (!(at_flags & AT_SYMLINK_NOFOLLOW))
		lookup_flags |= LOOKUP_FOLLOW;

	if (usize > PAGE_SIZE)
		return -E2BIG;

	if (usize < FILE_ATTR_SIZE_VER0)
		return -EINVAL;

	error = copy_struct_from_user(&fattr, sizeof(struct file_attr), ufattr,
				      usize);
	if (error)
		return error;

	error = file_attr_to_fileattr(&fattr, &fa);
	if (error)
		return error;

	CLASS(filename_maybe_null, name)(filename, at_flags);
	if (!name && dfd >= 0) {
		CLASS(fd, f)(dfd);

Annotation

Implementation Notes