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