dread-do-validation-20041012
[openafs.git] / src / afs / VNOPS / afs_vnop_open.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * Implements:
12  * afs_open
13  *
14  */
15
16
17 #include <afsconfig.h>
18 #include "afs/param.h"
19
20 RCSID
21     ("$Header$");
22
23 #include "afs/sysincludes.h"    /* Standard vendor system headers */
24 #include "afsincludes.h"        /* Afs-based standard headers */
25 #include "afs/afs_stats.h"      /* statistics */
26 #include "afs/afs_cbqueue.h"
27 #include "afs/nfsclient.h"
28 #include "afs/afs_osidnlc.h"
29
30
31
32 /* given a vnode ptr, open flags and credentials, open the file.  No access
33  * checks are done here, instead they're done by afs_create or afs_access,
34  * both called by the vn_open call.
35  */
36 int
37 #ifdef AFS_SGI64_ENV
38 afs_open(bhv_desc_t * bhv, struct vcache **avcp, afs_int32 aflags,
39          struct AFS_UCRED *acred)
40 #else
41 afs_open(struct vcache **avcp, afs_int32 aflags, struct AFS_UCRED *acred)
42 #endif
43 {
44     register afs_int32 code;
45     struct vrequest treq;
46     struct vcache *tvc;
47     int writing;
48     struct afs_fakestat_state fakestate;
49
50     AFS_STATCNT(afs_open);
51     if ((code = afs_InitReq(&treq, acred)))
52         return code;
53 #ifdef AFS_SGI64_ENV
54     /* avcpp can be, but is not necesarily, bhp's vnode. */
55     tvc = VTOAFS(BHV_TO_VNODE(bhv));
56 #else
57     tvc = *avcp;
58 #endif
59     afs_Trace2(afs_iclSetp, CM_TRACE_OPEN, ICL_TYPE_POINTER, tvc,
60                ICL_TYPE_INT32, aflags);
61     afs_InitFakeStat(&fakestate);
62     code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
63     if (code)
64         goto done;
65     code = afs_VerifyVCache(tvc, &treq);
66     if (code)
67         goto done;
68     if (aflags & (FWRITE | FTRUNC))
69         writing = 1;
70     else
71         writing = 0;
72     if (vType(tvc) == VDIR) {
73         /* directory */
74         if (writing) {
75             code = EISDIR;
76             goto done;
77         } else {
78             if (!afs_AccessOK
79                 (tvc, ((tvc->states & CForeign) ? PRSFS_READ : PRSFS_LOOKUP),
80                  &treq, CHECK_MODE_BITS)) {
81                 code = EACCES;
82                 goto done;
83             }
84         }
85     } else {
86 #ifdef  AFS_SUN5_ENV
87         if (AFS_NFSXLATORREQ(acred) && (aflags & FREAD)) {
88             if (!afs_AccessOK
89                 (tvc, PRSFS_READ, &treq,
90                  CHECK_MODE_BITS | CMB_ALLOW_EXEC_AS_READ)) {
91                 code = EACCES;
92                 goto done;
93             }
94         }
95 #endif
96 #ifdef  AFS_AIX41_ENV
97         if (aflags & FRSHARE) {
98             /*
99              * Hack for AIX 4.1:
100              *  Apparently it is possible for a file to get mapped without
101              *  either VNOP_MAP or VNOP_RDWR being called, if (1) it is a
102              *  sharable library, and (2) it has already been loaded.  We must
103              *  ensure that the credp is up to date.  We detect the situation
104              *  by checking for O_RSHARE at open time.
105              */
106             /*
107              * We keep the caller's credentials since an async daemon will
108              * handle the request at some point. We assume that the same
109              * credentials will be used.
110              */
111             ObtainWriteLock(&tvc->lock, 140);
112             if (!tvc->credp || (tvc->credp != acred)) {
113                 crhold(acred);
114                 if (tvc->credp) {
115                     struct ucred *crp = tvc->credp;
116                     tvc->credp = NULL;
117                     crfree(crp);
118                 }
119                 tvc->credp = acred;
120             }
121             ReleaseWriteLock(&tvc->lock);
122         }
123 #endif
124         /* normal file or symlink */
125         osi_FlushText(tvc);     /* only needed to flush text if text locked last time */
126 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
127         afs_BozonLock(&tvc->pvnLock, tvc);
128 #endif
129         osi_FlushPages(tvc, acred);
130 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
131         afs_BozonUnlock(&tvc->pvnLock, tvc);
132 #endif
133     }
134     /* set date on file if open in O_TRUNC mode */
135     if (aflags & FTRUNC) {
136         /* this fixes touch */
137         ObtainWriteLock(&tvc->lock, 123);
138         tvc->m.Date = osi_Time();
139         tvc->states |= CDirty;
140         ReleaseWriteLock(&tvc->lock);
141     }
142     ObtainReadLock(&tvc->lock);
143     if (writing)
144         tvc->execsOrWriters++;
145     tvc->opens++;
146 #if defined(AFS_SGI_ENV)
147     if (writing && tvc->cred == NULL) {
148         crhold(acred);
149         tvc->cred = acred;
150     }
151 #endif
152     ReleaseReadLock(&tvc->lock);
153   done:
154     afs_PutFakeStat(&fakestate);
155     code = afs_CheckCode(code, &treq, 4);       /* avoid AIX -O bug */
156
157     afs_Trace2(afs_iclSetp, CM_TRACE_OPEN, ICL_TYPE_POINTER, tvc,
158                ICL_TYPE_INT32, 999999);
159
160     return code;
161 }