1/* 2 * Copyright (c) 2000-2001, Boris Popov 3 * All rights reserved. 4 * 5 * Portions Copyright (C) 2001 - 2013 Apple Inc. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Boris Popov. 18 * 4. Neither the name of the author nor the names of any co-contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 */ 35#ifndef _FS_SMBFS_NODE_H_ 36#define _FS_SMBFS_NODE_H_ 37 38/* 39 * OS X semantics expect that node id of 2 is the root of the share. 40 * If File IDs are supported by the SMB 2/3 server, then we need to return 2 41 * for the root vnode File ID . If some other item on the server has the 42 * File ID of 2, then we return the actual root File ID instead. 43 * When vget is supported, then if they ask for File ID of 2, we return the 44 * root vnode. If they ask for File ID that matches the actual root File ID, 45 * then we return the vnode that has the File ID of 2 on the server. 46 */ 47#define SMBFS_ROOT_INO 2 /* just like in UFS */ 48#define SMBFS_ROOT_PAR_INO 1 /* Maps to root vnode just like SMBFS_ROOT_INO */ 49 50/* Bits for smbnode.n_flag */ 51#define NREFPARENT 0x00001 /* node holds parent from recycling */ 52#define N_ISSTREAM 0x00002 /* Node is a stream */ 53#define N_ISRSRCFRK 0x00004 /* Special stream node! */ 54#define NISMAPPED 0x00008 /* This file has been mmapped */ 55#define NNEEDS_FLUSH 0x00010 /* Need to flush the file */ 56#define NNEEDS_EOF_SET 0x00020 /* Need to set the eof, ignore the eof from the server */ 57#define NATTRCHANGED 0x00040 /* Did we change the size of the file, clear cache on close */ 58#define NALLOC 0x00080 /* being created */ 59#define NWALLOC 0x00100 /* awaiting creation */ 60#define NTRANSIT 0x00200 /* being reclaimed */ 61#define NWTRANSIT 0x00400 /* awaiting reclaim */ 62#define NDELETEONCLOSE 0x00800 /* We need to delete this item on close */ 63#define NMARKEDFORDLETE 0x01000 /* This item will has been marked for deletion */ 64#define NNEGNCENTRIES 0x02000 /* Directory has negative name cache entries */ 65#define NWINDOWSYMLNK 0x04000 /* This is a Conrad/Steve Window's symbolic links */ 66#define N_POLLNOTIFY 0x08000 /* Change notify is not support, poll */ 67#define NO_EXTENDEDOPEN 0x10000 /* The server doesn't support the extended open reply */ 68#define NHAS_POSIXMODES 0x20000 /* This node has a Windows NFS ACE that contains posix modes */ 69 70#define UNKNOWNUID ((uid_t)99) 71#define UNKNOWNGID ((gid_t)99) 72 73struct smbfs_fctx; 74 75enum smbfslocktype {SMBFS_SHARED_LOCK = 1, SMBFS_EXCLUSIVE_LOCK = 2, SMBFS_RECLAIM_LOCK = 3}; 76 77/* Used in reconnect for open files. Look at openState. */ 78#define kNeedRevoke 0x01 79#define kNeedReopen 0x02 80#define kInReopen 0x04 // Reopen in progress, don't update metadata 81 82enum { 83 kAnyMatch = 1, 84 kCheckDenyOrLocks = 2, 85 kExactMatch = 3, 86 kPreflightOpen = 4 87}; 88 89/* Carbon Read/Write and Deny bits */ 90enum { 91 kAccessRead = 0x01, 92 kAccessWrite = 0x02, 93 kDenyRead = 0x10, 94 kDenyWrite = 0x20, 95 kOpenMask = 0x03, 96 kDenyMask = 0x30, 97 kAccessMask = 0x33 98}; 99 100struct ByteRangeLockEntry { 101 int64_t offset; 102 int64_t length; 103 uint32_t lck_pid; 104 struct ByteRangeLockEntry *next; 105}; 106 107/* Used for Open Deny */ 108struct fileRefEntry { 109 uint32_t refcnt; /* open file reference count */ 110 uint32_t mmapped; /* This entry has been mmaped */ 111 pid_t p_pid; /* proc that did the open */ 112 SMBFID fid; /* file handle, SMB 1 fid in volatile */ 113 uint16_t accessMode; /* access mode for this open */ 114 uint32_t rights; /* nt granted rights */ 115 struct proc *proc; /* used in cluster IO strategy function */ 116 struct ByteRangeLockEntry *lockList; 117 struct smb2_durable_handle dur_handle; 118 struct fileRefEntry *next; 119}; 120 121struct smb_open_dir { 122 uint32_t refcnt; 123 uint32_t kq_refcnt; 124 SMBFID fid; /* directory handle, SMB 1 fid in volatile */ 125 struct smbfs_fctx *fctx; /* ff context */ 126 void *nextEntry; /* directory entry that didn't fit */ 127 int32_t nextEntryLen; /* size of directory entry that didn't fit */ 128 int32_t nextEntryFlags; /* flags that the next entry was create with */ 129 off_t offset; /* last ff offset */ 130 uint32_t needReopen; /* Need to reopen the notification */ 131 uint32_t needsUpdate; 132 u_int32_t dirchangecnt; /* changes each insert/delete. used by readdirattr */ 133}; 134 135struct smb_open_file { 136 int32_t refcnt; /* open file reference count */ 137 SMBFID fid; /* file handle, SMB 1 fid in volatile */ 138 uint32_t rights; /* nt granted rights */ 139 uint16_t accessMode; /* access mode used when opening */ 140 uint32_t mmapMode; /* The mode we used when opening from mmap */ 141 int32_t needClose; /* we opened it in the read call */ 142 int32_t openRWCnt; /* number of rw opens */ 143 int32_t openRCnt; /* number of r opens */ 144 int32_t openWCnt; /* number of w opens */ 145 int32_t openTotalWriteCnt; /* nbr of w opens (shared and nonshared) */ 146 int32_t clusterCloseError; /* Error to be return on user close */ 147 uint32_t openState; /* Do we need to revoke or reopen the file */ 148 lck_mtx_t openStateLock; /* Locks the openState */ 149 lck_mtx_t clusterWriteLock; /* Used for cluster writes */ 150 lck_mtx_t openDenyListLock; /* Locks the open deny list */ 151 struct fileRefEntry *openDenyList; 152 struct smbfs_flock *smbflock; /* Our flock structure */ 153}; 154 155struct smbnode { 156 lck_rw_t n_rwlock; 157 void * n_lastvop; /* tracks last operation that locked the smbnode */ 158 void * n_activation; 159 uint32_t n_lockState; /* current lock state */ 160 uint32_t n_flag; 161 struct smbnode *n_parent; 162 vnode_t n_vnode; 163 struct smbmount *n_mount; 164 time_t attribute_cache_timer; /* attributes cache time */ 165 struct timespec n_crtime; /* create time */ 166 struct timespec n_mtime; /* modify time */ 167 struct timespec n_atime; /* last access time */ 168 struct timespec n_chtime; /* change time */ 169 struct timespec n_sizetime; 170 struct timespec n_rename_time; /* last rename time */ 171 u_quad_t n_size; /* stream size */ 172 uint8_t waitOnClusterWrite; 173 u_quad_t n_data_alloc; /* stream allocation size */ 174 int n_dosattr; 175 uint32_t n_flags_mask; /* When doing unix extensions the va_flags mask */ 176 uid_t n_uid; 177 gid_t n_gid; 178 mode_t n_mode; 179 mode_t create_va_mode; 180 uid_t n_nfs_uid; 181 gid_t n_nfs_gid; 182 int set_create_va_mode; 183 time_t finfo_cache_timer; /* finder info cache timer, only used by the data node */ 184 uint8_t finfo[FINDERINFOSIZE]; /* finder info , only used by the data node */ 185 time_t rfrk_cache_timer; /* resource stream size cache timer, only used by the data node */ 186 u_quad_t rfrk_size; /* resource stream size, only used by the data node */ 187 u_quad_t rfrk_alloc_size;/* resource stream alloc size */ 188 lck_mtx_t rfrkMetaLock; /* Locks the resource size and resource cache timer */ 189 uint64_t n_ino; 190 uint64_t n_nlinks; /* Currently only supported when using the new UNIX Extensions */ 191 SInt32 n_child_refcnt; /* Each child node holds a refcnt */ 192 union { 193 struct smb_open_dir dir; 194 struct smb_open_file file; 195 }open_type; 196 void *acl_cache_data; 197 time_t acl_cache_timer; 198 int acl_error; 199 size_t acl_cache_len; 200 lck_mtx_t f_ACLCacheLock; /* Locks the ACL Cache */ 201 lck_rw_t n_name_rwlock; /* Read/Write lock for n_name */ 202 lck_rw_t n_parent_rwlock; /* Read/Write lock for n_parent */ 203 char *n_name; /* node's file or directory name */ 204 size_t n_nmlen; /* node's name length */ 205 size_t n_snmlen; /* if a stream then the legnth of the stream name */ 206 char *n_sname; /* if a stream then the the name of the stream */ 207 LIST_ENTRY(smbnode) n_hash; 208 uint32_t maxAccessRights; 209 struct timespec maxAccessRightChTime; /* change time */ 210 uint32_t n_reparse_tag; 211 uint16_t n_fstatus; /* Does the node have any named streams */ 212 char *n_symlink_target; 213 size_t n_symlink_target_len; 214 time_t n_symlink_cache_timer; 215 struct timespec n_last_write_time; 216}; 217 218/* Directory items */ 219#define d_refcnt open_type.dir.refcnt 220#define d_kqrefcnt open_type.dir.kq_refcnt 221#define d_fctx open_type.dir.fctx 222#define d_nextEntry open_type.dir.nextEntry 223#define d_nextEntryFlags open_type.dir.nextEntryFlags 224#define d_nextEntryLen open_type.dir.nextEntryLen 225#define d_offset open_type.dir.offset 226#define d_needReopen open_type.dir.needReopen 227#define d_fid open_type.dir.fid 228#define d_needsUpdate open_type.dir.needsUpdate 229#define d_changecnt open_type.dir.dirchangecnt 230 231/* File items */ 232#define f_refcnt open_type.file.refcnt 233#define f_fid open_type.file.fid 234#define f_rights open_type.file.rights 235#define f_accessMode open_type.file.accessMode 236#define f_mmapMode open_type.file.mmapMode 237#define f_needClose open_type.file.needClose 238#define f_openRWCnt open_type.file.openRWCnt 239#define f_openRCnt open_type.file.openRCnt 240#define f_openWCnt open_type.file.openWCnt 241#define f_openTotalWCnt open_type.file.openTotalWriteCnt 242#define f_openDenyList open_type.file.openDenyList 243#define f_smbflock open_type.file.smbflock 244#define f_openState open_type.file.openState 245#define f_openStateLock open_type.file.openStateLock 246#define f_clusterWriteLock open_type.file.clusterWriteLock 247#define f_openDenyListLock open_type.file.openDenyListLock 248#define f_clusterCloseError open_type.file.clusterCloseError 249 250/* Attribute cache timeouts in seconds */ 251#define SMB_MINATTRTIMO 2 252#define SMB_MAXATTRTIMO 30 253 254/* 255 * Determine attrtimeo. It will be something between SMB_MINATTRTIMO and 256 * SMB_MAXATTRTIMO where recently modified files have a short timeout 257 * and files that haven't been modified in a long time have a long 258 * timeout. This is the same algorithm used by NFS. 259 */ 260#define SMB_CACHE_TIME(ts, np, attrtimeo) { \ 261 nanotime(&ts); \ 262 attrtimeo = (ts.tv_sec - np->n_mtime.tv_sec) / 10; \ 263 if (attrtimeo < SMB_MINATTRTIMO) \ 264 attrtimeo = SMB_MINATTRTIMO; \ 265 else if (attrtimeo > SMB_MAXATTRTIMO) \ 266 attrtimeo = SMB_MAXATTRTIMO; \ 267 nanouptime(&ts); \ 268} 269 270#define VTOSMB(vp) ((struct smbnode *)vnode_fsnode(vp)) 271#define SMBTOV(np) ((vnode_t )(np)->n_vnode) 272 273/* smbfs_nget flags */ 274typedef enum _SMBFS_NGET_FLAGS 275{ 276 SMBFS_NGET_CREATE_VNODE = 0x0001, 277 SMBFS_NGET_LOOKUP_ONLY = 0x0002, 278 SMBFS_NGET_NO_CACHE_UPDATE = 0x0004 279} _SMBFS_NGET_FLAGS; 280 281/* smb_get_uid_gid_mode flags */ 282typedef enum _SMBFS_GET_UGM_FLAGS 283{ 284 SMBFS_GET_UGM_IS_DIR = 0x0001, 285 SMBFS_GET_UGM_REMOVE_POSIX_MODES = 0x0002 286} _SMBFS_GET_UGM_FLAGS; 287 288extern lck_attr_t *smbfs_lock_attr; 289extern lck_grp_t *smbfs_mutex_group; 290extern lck_grp_t *smbfs_rwlock_group; 291 292struct smbfattr; 293 294int smbnode_lock(struct smbnode *np, enum smbfslocktype); 295int smbnode_lockpair(struct smbnode *np1, struct smbnode *np2, enum smbfslocktype); 296void smbnode_unlock(struct smbnode *np); 297void smbnode_unlockpair(struct smbnode *np1, struct smbnode *np2); 298uint64_t smbfs_hash(struct smb_share *share, uint64_t ino, 299 const char *name, size_t nmlen); 300void smb_vhashrem (struct smbnode *np); 301void smb_vhashadd(struct smbnode *np, uint64_t hashval); 302int smbfs_nget(struct smb_share *share, struct mount *mp, 303 vnode_t dvp, const char *name, size_t nmlen, 304 struct smbfattr *fap, vnode_t *vpp, 305 uint32_t cnflags, uint32_t flags, 306 vfs_context_t context); 307vnode_t smbfs_find_vgetstrm(struct smbmount *smp, struct smbnode *np, const char *sname, 308 size_t maxfilenamelen); 309int smbfs_vgetstrm(struct smb_share *share, struct smbmount *smp, vnode_t vp, 310 vnode_t *svpp, struct smbfattr *fap, const char *sname); 311int smb_get_rsrcfrk_size(struct smb_share *share, vnode_t vp, vfs_context_t context); 312vnode_t smb_update_rsrc_and_getparent(vnode_t vp, int setsize); 313int smb_check_posix_access(vfs_context_t context, struct smbnode * np, 314 mode_t rq_mode); 315Boolean node_isimmutable(struct smb_share *share, vnode_t vp, struct smbfattr *fap); 316void smbfs_attr_cacheenter(struct smb_share *share, vnode_t vp, struct smbfattr *fap, 317 int UpdateResourceParent, vfs_context_t context); 318int smbfs_attr_cachelookup(struct smb_share *share, vnode_t vp, struct vnode_attr *va, 319 vfs_context_t context, int useCacheDataOnly); 320void smbfs_attr_touchdir(struct smbnode *dnp, int fatShare); 321 322int smbfsIsCacheable(vnode_t vp); 323void smbfs_setsize(vnode_t vp, off_t size); 324int smbfs_update_size(struct smbnode *np, struct timespec * reqtime, u_quad_t new_size); 325int smbfs_update_name_par(struct smb_share *share, vnode_t dvp, vnode_t vp, 326 struct timespec *reqtime, 327 const char *new_name, size_t name_len); 328 329int FindByteRangeLockEntry(struct fileRefEntry *fndEntry, int64_t offset, 330 int64_t length, uint32_t lck_pid); 331void AddRemoveByteRangeLockEntry(struct fileRefEntry *fndEntry, int64_t offset, 332 int64_t length, int8_t unLock, uint32_t lck_pid); 333void AddFileRef(vnode_t vp, struct proc *p, uint16_t accessMode, uint32_t rights, 334 SMBFID fid, struct smb2_durable_handle dur_handle, struct fileRefEntry **fndEntry); 335int32_t FindFileEntryByFID(vnode_t vp, SMBFID fid, struct fileRefEntry **fndEntry); 336int32_t FindFileEntryByLeaseKey(vnode_t vp, uint64_t lease_key_hi, uint64_t lease_key_low, struct fileRefEntry **fndEntry); 337int32_t FindMappedFileRef(vnode_t vp, struct fileRefEntry **fndEntry, SMBFID *fid); 338int32_t FindFileRef(vnode_t vp, proc_t p, uint16_t accessMode, int32_t flags, 339 int64_t offset, int64_t length, 340 struct fileRefEntry **fndEntry, 341 SMBFID *fid); 342void RemoveFileRef(vnode_t vp, struct fileRefEntry *inEntry); 343void smb_get_uid_gid_mode(struct smb_share *share, struct smbmount *smp, 344 struct smbfattr *fap, uint32_t flags, 345 uid_t *uid, gid_t *gid, mode_t *mode); 346 347/* smbfs_io.c prototypes */ 348int smbfs_readvdir(vnode_t vp, uio_t uio, vfs_context_t context, int flags, 349 int32_t *numdirent); 350int smbfs_0extend(struct smb_share *share, SMBFID fid, u_quad_t from, 351 u_quad_t to, int ioflag, vfs_context_t context); 352int smbfs_doread(struct smb_share *share, off_t endOfFile, uio_t uiop, 353 SMBFID fid, vfs_context_t context); 354int smbfs_dowrite(struct smb_share *share, off_t endOfFile, uio_t uiop, 355 SMBFID fid, int ioflag, vfs_context_t context); 356void smbfs_reconnect(struct smbmount *smp); 357int32_t smbfs_IObusy(struct smbmount *smp); 358void smbfs_ClearChildren(struct smbmount *smp, struct smbnode * parent); 359int smbfs_handle_lease_break(struct smbmount *smp, uint64_t lease_key_hi, 360 uint64_t lease_key_low, uint32_t new_lease_state); 361 362#define smb_ubc_getsize(v) (vnode_vtype(v) == VREG ? ubc_getsize(v) : (off_t)0) 363 364#endif /* _FS_SMBFS_NODE_H_ */ 365