1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Wrapper functions for accessing the file_struct fd array.
41da177e4SLinus Torvalds */
51da177e4SLinus Torvalds
61da177e4SLinus Torvalds #ifndef __LINUX_FILE_H
71da177e4SLinus Torvalds #define __LINUX_FILE_H
81da177e4SLinus Torvalds
91da177e4SLinus Torvalds #include <linux/compiler.h>
100c9e63fdSEric Dumazet #include <linux/types.h>
119f3acc31SAl Viro #include <linux/posix_types.h>
12deefa7f3SKees Cook #include <linux/errno.h>
1354da6a09SPeter Zijlstra #include <linux/cleanup.h>
14257b1c2cSChristian Brauner #include <linux/err.h>
151da177e4SLinus Torvalds
169f3acc31SAl Viro struct file;
178b7d91ebSChristoph Lameter
18b3c97528SHarvey Harrison extern void fput(struct file *);
191da177e4SLinus Torvalds
20ce8d2cdfSDave Hansen struct file_operations;
215e876fb4SSargun Dhillon struct task_struct;
22ce8d2cdfSDave Hansen struct vfsmount;
23ce8d2cdfSDave Hansen struct dentry;
24d93aa9d8SAl Viro struct inode;
252c48b9c4SAl Viro struct path;
26d93aa9d8SAl Viro extern struct file *alloc_file_pseudo(struct inode *, struct vfsmount *,
27d93aa9d8SAl Viro const char *, int flags, const struct file_operations *);
28bac0a9e5SChristian Brauner extern struct file *alloc_file_pseudo_noaccount(struct inode *, struct vfsmount *,
29bac0a9e5SChristian Brauner const char *, int flags, const struct file_operations *);
30183266f2SAl Viro extern struct file *alloc_file_clone(struct file *, int flags,
31183266f2SAl Viro const struct file_operations *);
32ce8d2cdfSDave Hansen
3388a2f646SAl Viro /* either a reference to struct file + flags
3488a2f646SAl Viro * (cloned vs. borrowed, pos locked), with
3588a2f646SAl Viro * flags stored in lower bits of value,
3688a2f646SAl Viro * or empty (represented by 0).
3788a2f646SAl Viro */
38a5b470baSAl Viro struct fd {
3988a2f646SAl Viro unsigned long word;
40a5b470baSAl Viro };
419c225f26SLinus Torvalds #define FDPUT_FPUT 1
429c225f26SLinus Torvalds #define FDPUT_POS_UNLOCK 2
43a5b470baSAl Viro
4488a2f646SAl Viro #define fd_file(f) ((struct file *)((f).word & ~(FDPUT_FPUT|FDPUT_POS_UNLOCK)))
fd_empty(struct fd f)4588a2f646SAl Viro static inline bool fd_empty(struct fd f)
4688a2f646SAl Viro {
4788a2f646SAl Viro return unlikely(!f.word);
4888a2f646SAl Viro }
4988a2f646SAl Viro
5088a2f646SAl Viro #define EMPTY_FD (struct fd){0}
BORROWED_FD(struct file * f)51de12c339SAl Viro static inline struct fd BORROWED_FD(struct file *f)
52de12c339SAl Viro {
53de12c339SAl Viro return (struct fd){(unsigned long)f};
54de12c339SAl Viro }
CLONED_FD(struct file * f)55de12c339SAl Viro static inline struct fd CLONED_FD(struct file *f)
56de12c339SAl Viro {
57de12c339SAl Viro return (struct fd){(unsigned long)f | FDPUT_FPUT};
58de12c339SAl Viro }
591da91ea8SAl Viro
fdput(struct fd fd)60a5b470baSAl Viro static inline void fdput(struct fd fd)
61a5b470baSAl Viro {
6288a2f646SAl Viro if (fd.word & FDPUT_FPUT)
631da91ea8SAl Viro fput(fd_file(fd));
64a5b470baSAl Viro }
65a5b470baSAl Viro
66b3c97528SHarvey Harrison extern struct file *fget(unsigned int fd);
67bd2a31d5SAl Viro extern struct file *fget_raw(unsigned int fd);
685e876fb4SSargun Dhillon extern struct file *fget_task(struct task_struct *task, unsigned int fd);
6963b6df14SAl Viro extern struct file *fget_task_next(struct task_struct *task, unsigned int *fd);
70bd2a31d5SAl Viro extern void __f_unlock_pos(struct file *);
71de12c339SAl Viro
72de12c339SAl Viro struct fd fdget(unsigned int fd);
73de12c339SAl Viro struct fd fdget_raw(unsigned int fd);
7463b6df14SAl Viro struct fd fdget_pos(unsigned int fd);
7563b6df14SAl Viro
fdput_pos(struct fd f)7663b6df14SAl Viro static inline void fdput_pos(struct fd f)
7788a2f646SAl Viro {
781da91ea8SAl Viro if (f.word & FDPUT_POS_UNLOCK)
7963b6df14SAl Viro __f_unlock_pos(fd_file(f));
8063b6df14SAl Viro fdput(f);
8163b6df14SAl Viro }
8254da6a09SPeter Zijlstra
83a0fde7edSChristian Brauner DEFINE_CLASS(fd, struct fd, fdput(_T), fdget(fd), int fd)
84*d7a9616cSAl Viro DEFINE_CLASS(fd_raw, struct fd, fdput(_T), fdget_raw(fd), int fd)
8554da6a09SPeter Zijlstra DEFINE_CLASS(fd_pos, struct fd, fdput_pos(_T), fdget_pos(fd), int fd)
86fe17f22dSAl Viro
878280d161SAl Viro extern int f_dupfd(unsigned int from, struct file *file, unsigned flags);
88b3c97528SHarvey Harrison extern int replace_fd(unsigned fd, struct file *file, unsigned flags);
89fe17f22dSAl Viro extern void set_close_on_exec(unsigned int fd, int flag);
904022e7afSJens Axboe extern bool get_close_on_exec(unsigned int fd);
911a7bd226SAl Viro extern int __get_unused_fd_flags(unsigned flags, unsigned long nofile);
92b3c97528SHarvey Harrison extern int get_unused_fd_flags(unsigned flags);
931da177e4SLinus Torvalds extern void put_unused_fd(unsigned int fd);
9454da6a09SPeter Zijlstra
9554da6a09SPeter Zijlstra DEFINE_CLASS(get_unused_fd, int, if (_T >= 0) put_unused_fd(_T),
96257b1c2cSChristian Brauner get_unused_fd_flags(flags), unsigned flags)
9754da6a09SPeter Zijlstra DEFINE_FREE(fput, struct file *, if (!IS_ERR_OR_NULL(_T)) fput(_T))
98c6269149SChristian Brauner
99c6269149SChristian Brauner /*
100c6269149SChristian Brauner * take_fd() will take care to set @fd to -EBADF ensuring that
101c6269149SChristian Brauner * CLASS(get_unused_fd) won't call put_unused_fd(). This makes it
102c6269149SChristian Brauner * easier to rely on CLASS(get_unused_fd):
103c6269149SChristian Brauner *
104c6269149SChristian Brauner * struct file *f;
105c6269149SChristian Brauner *
106c6269149SChristian Brauner * CLASS(get_unused_fd, fd)(O_CLOEXEC);
107c6269149SChristian Brauner * if (fd < 0)
108c6269149SChristian Brauner * return fd;
109c6269149SChristian Brauner *
110c6269149SChristian Brauner * f = dentry_open(&path, O_RDONLY, current_cred());
11186509e38SMathias Krause * if (IS_ERR(f))
112c6269149SChristian Brauner * return PTR_ERR(f);
113c6269149SChristian Brauner *
114c6269149SChristian Brauner * fd_install(fd, f);
115c6269149SChristian Brauner * return take_fd(fd);
116c6269149SChristian Brauner */
117c6269149SChristian Brauner #define take_fd(fd) __get_and_null(fd, -EBADF)
118b3c97528SHarvey Harrison
1191da177e4SLinus Torvalds extern void fd_install(unsigned int fd, struct file *file);
1204e94ddfeSChristian Brauner
1219c930054SXie Yongji int receive_fd(struct file *file, int __user *ufd, unsigned int o_flags);
12242eb0d54SChristoph Hellwig
12366590610SKees Cook int receive_fd_replace(int new_fd, struct file *file, unsigned int o_flags);
1244a9d4b02SAl Viro
1254a9d4b02SAl Viro extern void flush_delayed_fput(void);
1264a9d4b02SAl Viro extern void __fput_sync(struct file *);
1272374c09bSChristoph Hellwig
1282374c09bSChristoph Hellwig extern unsigned int sysctl_nr_open_min, sysctl_nr_open_max;
1291da177e4SLinus Torvalds
130 #endif /* __LINUX_FILE_H */
131