be more paranoid about errors from recursive calls to rvalue().
[unix-history] / usr / src / sys / ufs / ffs / ufs_vnops.c
CommitLineData
2b4b57cd 1/* ufs_vnops.c 4.15 81/11/18 */
d67a03eb
BJ
2
3#include "../h/param.h"
4#include "../h/systm.h"
5#include "../h/mount.h"
6#include "../h/ino.h"
7#include "../h/reg.h"
8#include "../h/buf.h"
9#include "../h/filsys.h"
10#include "../h/dir.h"
11#include "../h/user.h"
12#include "../h/inode.h"
13#include "../h/file.h"
14#include "../h/conf.h"
15#include "../h/stat.h"
0737b714 16#include "../h/inline.h"
ae921915
BJ
17#include "../h/socket.h"
18#include "../h/socketvar.h"
d67a03eb
BJ
19
20/*
21 * the fstat system call.
22 */
23fstat()
24{
25 register struct file *fp;
26 register struct a {
27 int fdes;
28 struct stat *sb;
29 } *uap;
30
31 uap = (struct a *)u.u_ap;
32 fp = getf(uap->fdes);
e92a04af 33 if (fp == NULL)
d67a03eb 34 return;
e92a04af 35 if (fp->f_flag & FSOCKET)
cc15ab5d 36 u.u_error = sostat(fp->f_socket, uap->sb);
e92a04af
BJ
37 else
38 stat1(fp->f_inode, uap->sb);
d67a03eb
BJ
39}
40
41/*
e92a04af 42 * Stat system call.
d67a03eb
BJ
43 */
44stat()
45{
46 register struct inode *ip;
47 register struct a {
48 char *fname;
49 struct stat *sb;
50 } *uap;
51
52 uap = (struct a *)u.u_ap;
53 ip = namei(uchar, 0);
e92a04af 54 if (ip == NULL)
d67a03eb 55 return;
a3aa7f92 56 stat1(ip, uap->sb);
d67a03eb
BJ
57 iput(ip);
58}
59
60/*
61 * The basic routine for fstat and stat:
62 * get the inode and pass appropriate parts back.
63 */
a3aa7f92 64stat1(ip, ub)
e92a04af
BJ
65 register struct inode *ip;
66 struct stat *ub;
d67a03eb
BJ
67{
68 register struct dinode *dp;
69 register struct buf *bp;
70 struct stat ds;
71
c0bb1685 72 IUPDAT(ip, &time, &time, 0);
d67a03eb 73 /*
e92a04af 74 * First copy from inode table
d67a03eb
BJ
75 */
76 ds.st_dev = ip->i_dev;
77 ds.st_ino = ip->i_number;
78 ds.st_mode = ip->i_mode;
79 ds.st_nlink = ip->i_nlink;
80 ds.st_uid = ip->i_uid;
81 ds.st_gid = ip->i_gid;
82 ds.st_rdev = (dev_t)ip->i_un.i_rdev;
a3aa7f92 83 ds.st_size = ip->i_size;
d67a03eb 84 /*
e92a04af 85 * Next the dates in the disk
d67a03eb
BJ
86 */
87 bp = bread(ip->i_dev, itod(ip->i_number));
88 dp = bp->b_un.b_dino;
89 dp += itoo(ip->i_number);
90 ds.st_atime = dp->di_atime;
91 ds.st_mtime = dp->di_mtime;
92 ds.st_ctime = dp->di_ctime;
93 brelse(bp);
94 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
95 u.u_error = EFAULT;
96}
97
98/*
e92a04af 99 * Dup system call.
d67a03eb
BJ
100 */
101dup()
102{
103 register struct file *fp;
104 register struct a {
105 int fdes;
106 int fdes2;
107 } *uap;
108 register i, m;
109
110 uap = (struct a *)u.u_ap;
111 m = uap->fdes & ~077;
112 uap->fdes &= 077;
113 fp = getf(uap->fdes);
e92a04af 114 if (fp == NULL)
d67a03eb
BJ
115 return;
116 if ((m&0100) == 0) {
117 if ((i = ufalloc()) < 0)
118 return;
119 } else {
120 i = uap->fdes2;
121 if (i<0 || i>=NOFILE) {
122 u.u_error = EBADF;
123 return;
124 }
d67a03eb
BJ
125 u.u_r.r_val1 = i;
126 }
e92a04af 127 if (i != uap->fdes) {
d67a03eb
BJ
128 if (u.u_ofile[i]!=NULL)
129 closef(u.u_ofile[i]);
130 u.u_ofile[i] = fp;
131 fp->f_count++;
132 }
133}
134
135/*
e92a04af 136 * Mount system call.
d67a03eb 137 */
e92a04af
BJ
138smount()
139{
d67a03eb
BJ
140 dev_t dev;
141 register struct inode *ip;
142 register struct mount *mp;
143 struct mount *smp;
144 register struct filsys *fp;
145 struct buf *bp;
146 register struct a {
147 char *fspec;
148 char *freg;
149 int ronly;
150 } *uap;
1e608f17 151 register char *cp;
d67a03eb
BJ
152
153 uap = (struct a *)u.u_ap;
154 dev = getmdev();
e92a04af 155 if (u.u_error)
d67a03eb
BJ
156 return;
157 u.u_dirp = (caddr_t)uap->freg;
158 ip = namei(uchar, 0);
e92a04af 159 if (ip == NULL)
d67a03eb 160 return;
e92a04af 161 if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR)
d67a03eb
BJ
162 goto out;
163 smp = NULL;
e92a04af
BJ
164 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
165 if (mp->m_bufp != NULL) {
166 if (dev == mp->m_dev)
d67a03eb
BJ
167 goto out;
168 } else
e92a04af 169 if (smp == NULL)
d67a03eb
BJ
170 smp = mp;
171 }
172 mp = smp;
e92a04af 173 if (mp == NULL)
d67a03eb
BJ
174 goto out;
175 (*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
e92a04af 176 if (u.u_error)
d67a03eb
BJ
177 goto out;
178 bp = bread(dev, SUPERB);
e92a04af 179 if (u.u_error) {
d67a03eb
BJ
180 brelse(bp);
181 goto out1;
182 }
183 mp->m_inodp = ip;
184 mp->m_dev = dev;
2c3059b1
BJ
185 bp->b_flags |= B_LOCKED;
186 mp->m_bufp = bp;
187 fp = bp->b_un.b_filsys;
d67a03eb
BJ
188 fp->s_ilock = 0;
189 fp->s_flock = 0;
190 fp->s_ronly = uap->ronly & 1;
191 fp->s_nbehind = 0;
192 fp->s_lasti = 1;
1e608f17
BJ
193 u.u_dirp = uap->freg;
194 for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; )
195 if ((*cp++ = uchar()) == 0)
196 u.u_dirp--; /* get 0 again */
197 *cp = 0;
d67a03eb
BJ
198 brelse(bp);
199 ip->i_flag |= IMOUNT;
e92a04af 200 irele(ip);
d67a03eb
BJ
201 return;
202
203out:
204 u.u_error = EBUSY;
205out1:
206 iput(ip);
207}
208
209/*
210 * the umount system call.
211 */
212sumount()
213{
214 dev_t dev;
215 register struct inode *ip;
216 register struct mount *mp;
217 struct buf *bp;
2c3059b1 218 int stillopen, flag;
d67a03eb
BJ
219 register struct a {
220 char *fspec;
221 };
222
223 dev = getmdev();
e92a04af 224 if (u.u_error)
d67a03eb
BJ
225 return;
226 xumount(dev); /* remove unused sticky files from text table */
227 update();
e92a04af
BJ
228 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
229 if (mp->m_bufp != NULL && dev == mp->m_dev)
d67a03eb
BJ
230 goto found;
231 u.u_error = EINVAL;
232 return;
233
234found:
9491f93d 235 stillopen = 0;
e92a04af 236 for (ip = inode; ip < inodeNINODE; ip++)
2c3059b1 237 if (ip->i_number != 0 && dev == ip->i_dev) {
d67a03eb
BJ
238 u.u_error = EBUSY;
239 return;
2c3059b1
BJ
240 } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK &&
241 ip->i_un.i_rdev == dev)
242 stillopen++;
d67a03eb
BJ
243 ip = mp->m_inodp;
244 ip->i_flag &= ~IMOUNT;
e92a04af 245 ilock(ip);
d67a03eb 246 iput(ip);
2c3059b1
BJ
247 if ((bp = getblk(dev, SUPERB)) != mp->m_bufp)
248 panic("umount");
249 bp->b_flags &= ~B_LOCKED;
4a18fb8e 250 flag = !bp->b_un.b_filsys->s_ronly;
d67a03eb
BJ
251 mp->m_bufp = NULL;
252 brelse(bp);
aa250f32 253 mpurge(mp - &mount[0]);
4a18fb8e 254 if (!stillopen) {
4a18fb8e
RE
255 (*bdevsw[major(dev)].d_close)(dev, flag);
256 binval(dev);
257 }
d67a03eb
BJ
258}
259
260/*
261 * Common code for mount and umount.
262 * Check that the user's argument is a reasonable
263 * thing on which to mount, and return the device number if so.
264 */
265dev_t
266getmdev()
267{
268 dev_t dev;
269 register struct inode *ip;
270
d67a03eb
BJ
271 if (!suser())
272 return(NODEV);
d67a03eb 273 ip = namei(uchar, 0);
e92a04af 274 if (ip == NULL)
d67a03eb 275 return(NODEV);
e92a04af 276 if ((ip->i_mode&IFMT) != IFBLK)
d67a03eb
BJ
277 u.u_error = ENOTBLK;
278 dev = (dev_t)ip->i_un.i_rdev;
e92a04af 279 if (major(dev) >= nblkdev)
d67a03eb
BJ
280 u.u_error = ENXIO;
281 iput(ip);
282 return(dev);
283}