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