blob: 6e9099d2934368d2aa41ffc30f4e438f8d42531d [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001/* SPDX-License-Identifier: GPL-2.0 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * Wrapper functions for accessing the file_struct fd array.
4 */
5
6#ifndef __LINUX_FILE_H
7#define __LINUX_FILE_H
8
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <linux/compiler.h>
Eric Dumazet0c9e63f2006-03-23 03:00:12 -080010#include <linux/types.h>
Al Viro9f3acc32008-04-24 07:44:08 -040011#include <linux/posix_types.h>
Kees Cookdeefa7f2020-06-10 20:47:45 -070012#include <linux/errno.h>
Peter Zijlstra3c6cc62c2023-05-26 12:23:48 +020013#include <linux/cleanup.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014
Al Viro9f3acc32008-04-24 07:44:08 -040015struct file;
Christoph Lameter8b7d91e2006-12-06 20:32:52 -080016
Harvey Harrisonb3c97522008-02-13 15:03:15 -080017extern void fput(struct file *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
Dave Hansence8d2cd2007-10-16 23:31:13 -070019struct file_operations;
Sargun Dhillon5e876fb2020-01-07 09:59:24 -080020struct task_struct;
Dave Hansence8d2cd2007-10-16 23:31:13 -070021struct vfsmount;
22struct dentry;
Al Virod93aa9d2018-06-09 09:40:05 -040023struct inode;
Al Viro2c48b9c2009-08-09 00:52:35 +040024struct path;
Al Virod93aa9d2018-06-09 09:40:05 -040025extern struct file *alloc_file_pseudo(struct inode *, struct vfsmount *,
26 const char *, int flags, const struct file_operations *);
Al Viro183266f2018-06-17 14:15:10 -040027extern struct file *alloc_file_clone(struct file *, int flags,
28 const struct file_operations *);
Dave Hansence8d2cd2007-10-16 23:31:13 -070029
Linus Torvalds1da177e2005-04-16 15:20:36 -070030static inline void fput_light(struct file *file, int fput_needed)
31{
Steven Rostedtc2b3e742010-12-13 19:38:08 -050032 if (fput_needed)
Linus Torvalds1da177e2005-04-16 15:20:36 -070033 fput(file);
34}
35
Al Viroa5b470b2012-08-27 19:55:01 -040036struct fd {
37 struct file *file;
Linus Torvalds9c225f22014-03-03 09:36:58 -080038 unsigned int flags;
Al Viroa5b470b2012-08-27 19:55:01 -040039};
Linus Torvalds9c225f22014-03-03 09:36:58 -080040#define FDPUT_FPUT 1
41#define FDPUT_POS_UNLOCK 2
Al Viroa5b470b2012-08-27 19:55:01 -040042
43static inline void fdput(struct fd fd)
44{
Linus Torvalds9c225f22014-03-03 09:36:58 -080045 if (fd.flags & FDPUT_FPUT)
Al Viroa5b470b2012-08-27 19:55:01 -040046 fput(fd.file);
47}
48
Harvey Harrisonb3c97522008-02-13 15:03:15 -080049extern struct file *fget(unsigned int fd);
Al Virobd2a31d2014-03-04 14:54:22 -050050extern struct file *fget_raw(unsigned int fd);
Sargun Dhillon5e876fb2020-01-07 09:59:24 -080051extern struct file *fget_task(struct task_struct *task, unsigned int fd);
Al Virobd2a31d2014-03-04 14:54:22 -050052extern unsigned long __fdget(unsigned int fd);
53extern unsigned long __fdget_raw(unsigned int fd);
54extern unsigned long __fdget_pos(unsigned int fd);
Al Viro63b6df12016-04-20 17:08:21 -040055extern void __f_unlock_pos(struct file *);
Al Virobd2a31d2014-03-04 14:54:22 -050056
57static inline struct fd __to_fd(unsigned long v)
58{
59 return (struct fd){(struct file *)(v & ~3),v & 3};
60}
Al Viroa5b470b2012-08-27 19:55:01 -040061
62static inline struct fd fdget(unsigned int fd)
63{
Al Virobd2a31d2014-03-04 14:54:22 -050064 return __to_fd(__fdget(fd));
Al Viroa5b470b2012-08-27 19:55:01 -040065}
66
67static inline struct fd fdget_raw(unsigned int fd)
68{
Al Virobd2a31d2014-03-04 14:54:22 -050069 return __to_fd(__fdget_raw(fd));
Al Viroa5b470b2012-08-27 19:55:01 -040070}
71
Al Viro63b6df12016-04-20 17:08:21 -040072static inline struct fd fdget_pos(int fd)
73{
74 return __to_fd(__fdget_pos(fd));
75}
76
77static inline void fdput_pos(struct fd f)
78{
79 if (f.flags & FDPUT_POS_UNLOCK)
80 __f_unlock_pos(f.file);
81 fdput(f);
82}
83
Peter Zijlstra3c6cc62c2023-05-26 12:23:48 +020084DEFINE_CLASS(fd, struct fd, fdput(_T), fdget(fd), int fd)
85
Al Virofe17f222012-08-21 11:48:11 -040086extern int f_dupfd(unsigned int from, struct file *file, unsigned flags);
Al Viro8280d162012-08-21 12:11:46 -040087extern int replace_fd(unsigned fd, struct file *file, unsigned flags);
Harvey Harrisonb3c97522008-02-13 15:03:15 -080088extern void set_close_on_exec(unsigned int fd, int flag);
Al Virofe17f222012-08-21 11:48:11 -040089extern bool get_close_on_exec(unsigned int fd);
Jens Axboe4022e7a2020-03-19 19:23:18 -060090extern int __get_unused_fd_flags(unsigned flags, unsigned long nofile);
Al Viro1a7bd222012-08-12 17:18:05 -040091extern int get_unused_fd_flags(unsigned flags);
Harvey Harrisonb3c97522008-02-13 15:03:15 -080092extern void put_unused_fd(unsigned int fd);
Linus Torvalds1da177e2005-04-16 15:20:36 -070093
Peter Zijlstra3c6cc62c2023-05-26 12:23:48 +020094DEFINE_CLASS(get_unused_fd, int, if (_T >= 0) put_unused_fd(_T),
95 get_unused_fd_flags(flags), unsigned flags)
96
Harvey Harrisonb3c97522008-02-13 15:03:15 -080097extern void fd_install(unsigned int fd, struct file *file);
Linus Torvalds1da177e2005-04-16 15:20:36 -070098
Christoph Hellwig42eb0d52021-03-25 09:22:09 +010099extern int __receive_fd(struct file *file, int __user *ufd,
Kees Cook66590612020-06-10 08:20:05 -0700100 unsigned int o_flags);
Xie Yongji9c930052021-08-31 18:36:24 +0800101
102extern int receive_fd(struct file *file, unsigned int o_flags);
103
Kees Cook66590612020-06-10 08:20:05 -0700104static inline int receive_fd_user(struct file *file, int __user *ufd,
105 unsigned int o_flags)
106{
Kees Cookdeefa7f2020-06-10 20:47:45 -0700107 if (ufd == NULL)
108 return -EFAULT;
Christoph Hellwig42eb0d52021-03-25 09:22:09 +0100109 return __receive_fd(file, ufd, o_flags);
Kees Cook66590612020-06-10 08:20:05 -0700110}
Christoph Hellwig42eb0d52021-03-25 09:22:09 +0100111int receive_fd_replace(int new_fd, struct file *file, unsigned int o_flags);
Kees Cook66590612020-06-10 08:20:05 -0700112
Al Viro4a9d4b02012-06-24 09:56:45 +0400113extern void flush_delayed_fput(void);
114extern void __fput_sync(struct file *);
115
Christoph Hellwig2374c09b2020-04-24 08:43:36 +0200116extern unsigned int sysctl_nr_open_min, sysctl_nr_open_max;
117
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118#endif /* __LINUX_FILE_H */