williamr@2: /* williamr@4: * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). williamr@4: * All rights reserved. williamr@4: * This component and the accompanying materials are made available williamr@4: * under the terms of "Eclipse Public License v1.0" williamr@4: * which accompanies this distribution, and is available williamr@4: * at the URL "http://www.eclipse.org/legal/epl-v10.html". williamr@2: * williamr@4: * Initial Contributors: williamr@4: * Nokia Corporation - initial contribution. williamr@4: * williamr@4: * Contributors: williamr@4: * williamr@4: * Description: williamr@2: * williamr@2: */ williamr@2: williamr@2: williamr@4: williamr@2: #ifndef _SYS_FILE_H_ williamr@2: #define _SYS_FILE_H_ williamr@2: williamr@2: #ifndef _KERNEL williamr@2: #include /* XXX */ williamr@2: #include williamr@2: #include williamr@2: #else williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: struct stat; williamr@2: struct thread; williamr@2: struct uio; williamr@2: struct knote; williamr@2: struct vnode; williamr@2: struct socket; williamr@2: williamr@2: williamr@2: #endif /* _KERNEL */ williamr@2: williamr@2: #define DTYPE_VNODE 1 /* file */ williamr@2: #define DTYPE_SOCKET 2 /* communications endpoint */ williamr@2: #define DTYPE_PIPE 3 /* pipe */ williamr@2: #define DTYPE_FIFO 4 /* fifo (named pipe) */ williamr@2: #define DTYPE_KQUEUE 5 /* event queue */ williamr@2: #define DTYPE_CRYPTO 6 /* crypto */ williamr@2: williamr@2: #ifdef _KERNEL williamr@2: williamr@2: struct file; williamr@2: struct ucred; williamr@2: williamr@2: typedef int fo_rdwr_t(struct file *fp, struct uio *uio, williamr@2: struct ucred *active_cred, int flags, williamr@2: struct thread *td); williamr@2: #define FOF_OFFSET 1 /* Use the offset in uio argument */ williamr@2: typedef int fo_ioctl_t(struct file *fp, u_long com, void *data, williamr@2: struct ucred *active_cred, struct thread *td); williamr@2: typedef int fo_poll_t(struct file *fp, int events, williamr@2: struct ucred *active_cred, struct thread *td); williamr@2: typedef int fo_kqfilter_t(struct file *fp, struct knote *kn); williamr@2: typedef int fo_stat_t(struct file *fp, struct stat *sb, williamr@2: struct ucred *active_cred, struct thread *td); williamr@2: typedef int fo_close_t(struct file *fp, struct thread *td); williamr@2: typedef int fo_flags_t; williamr@2: williamr@2: struct fileops { williamr@2: fo_rdwr_t *fo_read; williamr@2: fo_rdwr_t *fo_write; williamr@2: fo_ioctl_t *fo_ioctl; williamr@2: fo_poll_t *fo_poll; williamr@2: fo_kqfilter_t *fo_kqfilter; williamr@2: fo_stat_t *fo_stat; williamr@2: fo_close_t *fo_close; williamr@2: fo_flags_t fo_flags; /* DFLAG_* below */ williamr@2: }; williamr@2: williamr@2: #define DFLAG_PASSABLE 0x01 /* may be passed via unix sockets. */ williamr@2: #define DFLAG_SEEKABLE 0x02 /* seekable / nonsequential */ williamr@2: williamr@2: /* williamr@2: * Kernel descriptor table. williamr@2: * One entry for each open kernel vnode and socket. williamr@2: * williamr@2: * Below is the list of locks that protects members in struct file. williamr@2: * williamr@2: * (fl) filelist_lock williamr@2: * (f) f_mtx in struct file williamr@2: * none not locked williamr@2: */ williamr@2: williamr@2: struct file { williamr@2: LIST_ENTRY(file) f_list;/* (fl) list of active files */ williamr@2: short f_type; /* descriptor type */ williamr@2: void *f_data; /* file descriptor specific data */ williamr@2: u_int f_flag; /* see fcntl.h */ williamr@2: struct mtx *f_mtxp; /* mutex to protect data */ williamr@2: struct fileops *f_ops; /* File operations */ williamr@2: struct ucred *f_cred; /* credentials associated with descriptor */ williamr@2: int f_count; /* (f) reference count */ williamr@2: struct vnode *f_vnode; /* NULL or applicable vnode */ williamr@2: williamr@2: /* DFLAG_SEEKABLE specific fields */ williamr@2: off_t f_offset; williamr@2: williamr@2: /* DTYPE_SOCKET specific fields */ williamr@2: short f_gcflag; /* used by thread doing fd garbage collection */ williamr@2: #define FMARK 0x1 /* mark during gc() */ williamr@2: #define FDEFER 0x2 /* defer for next gc pass */ williamr@2: int f_msgcount; /* (f) references from message queue */ williamr@2: williamr@2: /* DTYPE_VNODE specific fields */ williamr@2: int f_seqcount; /* williamr@2: * count of sequential accesses -- cleared williamr@2: * by most seek operations. williamr@2: */ williamr@2: off_t f_nextoff; /* williamr@2: * offset of next expected read or write williamr@2: */ williamr@2: void *f_label; /* Place-holder for struct label pointer. */ williamr@2: }; williamr@2: williamr@2: #endif /* _KERNEL */ williamr@2: williamr@2: /* williamr@2: * Userland version of struct file, for sysctl williamr@2: */ williamr@2: struct xfile { williamr@2: size_t xf_size; /* size of struct xfile */ williamr@2: pid_t xf_pid; /* owning process */ williamr@2: uid_t xf_uid; /* effective uid of owning process */ williamr@2: int xf_fd; /* descriptor number */ williamr@2: void *xf_file; /* address of struct file */ williamr@2: short xf_type; /* descriptor type */ williamr@2: int xf_count; /* reference count */ williamr@2: int xf_msgcount; /* references from message queue */ williamr@2: off_t xf_offset; /* file offset */ williamr@2: void *xf_data; /* file descriptor specific data */ williamr@2: void *xf_vnode; /* vnode pointer */ williamr@2: u_int xf_flag; /* flags (see fcntl.h) */ williamr@2: }; williamr@2: williamr@2: #ifdef _KERNEL williamr@2: extern struct filelist filehead; /* (fl) head of list of open files */ williamr@2: extern struct fileops vnops; williamr@2: extern struct fileops badfileops; williamr@2: extern struct fileops socketops; williamr@2: extern int maxfiles; /* kernel limit on number of open files */ williamr@2: extern int maxfilesperproc; /* per process limit on number of open files */ williamr@2: extern int openfiles; /* (fl) actual number of open files */ williamr@2: extern struct sx filelist_lock; /* sx to protect filelist and openfiles */ williamr@2: williamr@2: /* williamr@2: * The socket operations are used a couple of places. williamr@2: * XXX: This is wrong, they should go through the operations vector for williamr@2: * XXX: sockets instead of going directly for the individual functions. /phk williamr@2: */ williamr@2: fo_rdwr_t soo_read; williamr@2: fo_rdwr_t soo_write; williamr@2: fo_ioctl_t soo_ioctl; williamr@2: fo_poll_t soo_poll; williamr@2: fo_kqfilter_t soo_kqfilter; williamr@2: fo_stat_t soo_stat; williamr@2: fo_close_t soo_close; williamr@2: williamr@2: /* Lock a file. */ williamr@2: #define FILE_LOCK(f) mtx_lock((f)->f_mtxp) williamr@2: #define FILE_UNLOCK(f) mtx_unlock((f)->f_mtxp) williamr@2: #define FILE_LOCKED(f) mtx_owned((f)->f_mtxp) williamr@2: #define FILE_LOCK_ASSERT(f, type) mtx_assert((f)->f_mtxp, (type)) williamr@2: williamr@2: #define fhold_locked(fp) \ williamr@2: do { \ williamr@2: FILE_LOCK_ASSERT(fp, MA_OWNED); \ williamr@2: (fp)->f_count++; \ williamr@2: } while (0) williamr@2: williamr@2: #define fhold(fp) \ williamr@2: do { \ williamr@2: FILE_LOCK(fp); \ williamr@2: (fp)->f_count++; \ williamr@2: FILE_UNLOCK(fp); \ williamr@2: } while (0) williamr@2: williamr@2: static __inline fo_rdwr_t fo_read; williamr@2: static __inline fo_rdwr_t fo_write; williamr@2: static __inline fo_ioctl_t fo_ioctl; williamr@2: static __inline fo_poll_t fo_poll; williamr@2: static __inline fo_kqfilter_t fo_kqfilter; williamr@2: static __inline fo_stat_t fo_stat; williamr@2: static __inline fo_close_t fo_close; williamr@2: williamr@2: static __inline int williamr@2: fo_read(fp, uio, active_cred, flags, td) williamr@2: struct file *fp; williamr@2: struct uio *uio; williamr@2: struct ucred *active_cred; williamr@2: int flags; williamr@2: struct thread *td; williamr@2: { williamr@2: williamr@2: return ((*fp->f_ops->fo_read)(fp, uio, active_cred, flags, td)); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fo_write(fp, uio, active_cred, flags, td) williamr@2: struct file *fp; williamr@2: struct uio *uio; williamr@2: struct ucred *active_cred; williamr@2: int flags; williamr@2: struct thread *td; williamr@2: { williamr@2: williamr@2: return ((*fp->f_ops->fo_write)(fp, uio, active_cred, flags, td)); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fo_ioctl(fp, com, data, active_cred, td) williamr@2: struct file *fp; williamr@2: u_long com; williamr@2: void *data; williamr@2: struct ucred *active_cred; williamr@2: struct thread *td; williamr@2: { williamr@2: williamr@2: return ((*fp->f_ops->fo_ioctl)(fp, com, data, active_cred, td)); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fo_poll(fp, events, active_cred, td) williamr@2: struct file *fp; williamr@2: int events; williamr@2: struct ucred *active_cred; williamr@2: struct thread *td; williamr@2: { williamr@2: williamr@2: return ((*fp->f_ops->fo_poll)(fp, events, active_cred, td)); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fo_stat(fp, sb, active_cred, td) williamr@2: struct file *fp; williamr@2: struct stat *sb; williamr@2: struct ucred *active_cred; williamr@2: struct thread *td; williamr@2: { williamr@2: williamr@2: return ((*fp->f_ops->fo_stat)(fp, sb, active_cred, td)); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fo_close(fp, td) williamr@2: struct file *fp; williamr@2: struct thread *td; williamr@2: { williamr@2: williamr@2: return ((*fp->f_ops->fo_close)(fp, td)); williamr@2: } williamr@2: williamr@2: static __inline int williamr@2: fo_kqfilter(fp, kn) williamr@2: struct file *fp; williamr@2: struct knote *kn; williamr@2: { williamr@2: williamr@2: return ((*fp->f_ops->fo_kqfilter)(fp, kn)); williamr@2: } williamr@2: williamr@2: #endif /* _KERNEL */ williamr@2: williamr@2: #endif /* !SYS_FILE_H */