a1c7f59500721331b14cd84731f60522e121786e
[openafs.git] / src / afs / HPUX / osi_inode.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  * HPUX inode operations
12  *
13  * Implements:
14  *
15  */
16 #include "../afs/param.h"       /* Should be always first */
17 #include <afsconfig.h>
18
19 RCSID("$Header$");
20
21 #include "../afs/sysincludes.h" /* Standard vendor system headers */
22 #include "../afs/afsincludes.h" /* Afs-based standard headers */
23 #include "../afs/osi_inode.h"
24 #include "../afs/afs_stats.h" /* statistics stuff */
25 #include <sys/mount.h>
26
27
28 static struct inode *
29 getinode(struct vfs *vfsp, dev_t dev, ino_t inode, int *perror)
30 {
31    struct mount *mp = (vfsp ? VFSTOM(vfsp) : 0);
32    struct inode *pip;
33    *perror = 0;
34     
35    if (!mp && !(mp = getmp(dev))) {
36       u.u_error = ENXIO;
37       return((struct inode *)0);
38    }
39    pip=iget(dev,mp,inode);
40    if(!pip)
41         *perror = BAD_IGET;
42    return(pip);
43 }
44
45 struct inode *
46 igetinode(struct vfs *vfsp, dev_t dev, ino_t inode, int *perror)
47 {
48         struct inode *pip, *ip;
49         extern struct osi_dev cacheDev;
50         register int code = 0;
51
52         *perror = 0;
53         AFS_STATCNT(igetinode);
54         ip = getinode(vfsp, dev, inode,perror);
55         if (ip == NULL) {
56             *perror = BAD_IGET;
57             u.u_error = ENOENT;         /* Well... */
58             return;
59         }
60         if (ip->i_mode == 0) {
61             /* Not an allocated inode */
62             iforget(ip);            
63             u.u_error = ENOENT;
64             return;
65         }
66         if (ip->i_nlink == 0 || (ip->i_mode&IFMT) != IFREG) {
67             iput(ip);
68             u.u_error = ENOENT;
69             return;
70         }
71         return ip;
72 }
73
74 iforget(ip)
75      struct inode *ip;
76 {
77    idrop(ip);
78 }
79
80 afs_syscall_icreate(dev, near_inode, param1, param2, param3, param4)
81 long dev, near_inode, param1, param2, param3, param4;
82 {
83         int dummy, err=0;
84         struct inode *ip, *newip;
85
86         AFS_STATCNT(afs_syscall_icreate);
87
88         if (!afs_suser()) {
89             u.u_error = EPERM;
90             goto out;
91         }
92
93         ip = getinode(0, (dev_t)dev, 2,&dummy);
94         if (ip == NULL) {
95             u.u_error = ENOENT; /* Well... */
96             goto out;
97         }
98
99         newip = (struct inode *)ialloc(ip, near_inode, 0);
100         iput(ip);
101         if  (newip == NULL)
102             goto out;
103
104         newip->i_flag |= IACC|IUPD|ICHG;
105         newip->i_nlink = 1;
106         newip->i_mode = IFREG;
107         newip->i_vnode.v_type = VREG;
108         newip->i_vicemagic = VICEMAGIC;
109         newip->i_vicep1 = param1;
110         newip->i_vicep2 = param2;
111         I_VICE3(newip) = param3;
112         newip->i_vicep4 = param4; 
113         u.u_r.r_val1 = newip->i_number;
114
115         iput(newip);
116
117 out:
118         return err;
119 }
120
121 afs_syscall_iopen(dev, inode, usrmod)
122 int dev, inode, usrmod;
123 {
124         struct file *fp;
125         struct inode *ip;
126         struct vnode *vp = (struct vnode *)0;
127         int dummy;
128         extern struct fileops vnodefops;
129         register int code;
130
131         AFS_STATCNT(afs_syscall_iopen);
132
133         if (!afs_suser()) {
134             u.u_error = EPERM;
135             goto out;
136         }
137
138         ip = igetinode(0, (dev_t)dev, (ino_t)inode,&dummy);
139         if (u.u_error)
140             goto out;
141         fp = falloc();
142         if (!fp) {
143             iput(ip);
144             goto out;
145         }
146         iunlock(ip);
147
148         fp->f_ops = &vnodefops;
149         vp = ITOV(ip);
150         fp->f_data = (char *)vp;
151         fp->f_type = DTYPE_VNODE;
152         fp->f_flag = (usrmod+1) & (FMASK);
153
154         /* Obtained from hp kernel sys/vfs_scalls.c: copen().
155          * Otherwise we panic because the v_writecount
156          * goes less than 0 during close.
157          */
158         if ((vp->v_type == VREG) && (fp->f_flag & FWRITE)) {
159            VN_INC_WRITECOUNT(vp);
160         }
161
162         /* fp->f_count, f_msgcount are set by falloc */
163         /* fp->f_offset zeroed by falloc */
164         /* f_cred set by falloc */
165
166         /*
167          * Obtained from hp kernel sys/vfs_scalls.c: copen() does
168          * a PUTF() (defined earlier in the file) before returning,
169          * so we parrot what it does.  If this is not done, then
170          * threaded processes will get EBADF errors when they try
171          * to use the resulting file descriptor (e.g. with lseek()).
172          *
173          * Note: u.u_r.r_val1 is set by ufalloc(), which is
174          * called by falloc(), which is called above.
175          */
176         if (is_multithreaded(u.u_procp)) {
177            int fd = (int)u.u_r.r_val1;
178            putf(fd);
179         }
180
181 out:
182         return;
183 }
184
185 afs_syscall_iincdec(dev, inode, inode_p1, amount)
186 int dev, inode, inode_p1, amount;
187 {
188         int dummy;
189         struct inode *ip;
190         register afs_int32 code;
191
192         if (!afs_suser()) {
193             u.u_error = EPERM;
194             goto out;
195         }
196
197         ip = igetinode(0, (dev_t)dev, (ino_t)inode,&dummy);
198         if (u.u_error) {
199             goto out;
200         }
201
202         if (!IS_VICEMAGIC(ip))
203             u.u_error = EPERM;
204         else if (ip->i_vicep1 != inode_p1)
205             u.u_error = ENXIO;
206         else {
207             ip->i_nlink += amount;
208             if (ip->i_nlink == 0) {
209                 CLEAR_VICEMAGIC(ip);
210             }
211             ip->i_flag |= ICHG;
212         }
213
214         iput(ip);
215
216 out:
217     return;
218 }