be more paranoid about errors from recursive calls to rvalue().
[unix-history] / usr / src / sys / ufs / lfs / lfs_vnops.c
... / ...
CommitLineData
1/* lfs_vnops.c 4.15 81/11/18 */
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"
16#include "../h/inline.h"
17#include "../h/socket.h"
18#include "../h/socketvar.h"
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);
33 if (fp == NULL)
34 return;
35 if (fp->f_flag & FSOCKET)
36 u.u_error = sostat(fp->f_socket, uap->sb);
37 else
38 stat1(fp->f_inode, uap->sb);
39}
40
41/*
42 * Stat system call.
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);
54 if (ip == NULL)
55 return;
56 stat1(ip, uap->sb);
57 iput(ip);
58}
59
60/*
61 * The basic routine for fstat and stat:
62 * get the inode and pass appropriate parts back.
63 */
64stat1(ip, ub)
65 register struct inode *ip;
66 struct stat *ub;
67{
68 register struct dinode *dp;
69 register struct buf *bp;
70 struct stat ds;
71
72 IUPDAT(ip, &time, &time, 0);
73 /*
74 * First copy from inode table
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;
83 ds.st_size = ip->i_size;
84 /*
85 * Next the dates in the disk
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/*
99 * Dup system call.
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);
114 if (fp == NULL)
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 }
125 u.u_r.r_val1 = i;
126 }
127 if (i != uap->fdes) {
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/*
136 * Mount system call.
137 */
138smount()
139{
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;
151 register char *cp;
152
153 uap = (struct a *)u.u_ap;
154 dev = getmdev();
155 if (u.u_error)
156 return;
157 u.u_dirp = (caddr_t)uap->freg;
158 ip = namei(uchar, 0);
159 if (ip == NULL)
160 return;
161 if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR)
162 goto out;
163 smp = NULL;
164 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
165 if (mp->m_bufp != NULL) {
166 if (dev == mp->m_dev)
167 goto out;
168 } else
169 if (smp == NULL)
170 smp = mp;
171 }
172 mp = smp;
173 if (mp == NULL)
174 goto out;
175 (*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
176 if (u.u_error)
177 goto out;
178 bp = bread(dev, SUPERB);
179 if (u.u_error) {
180 brelse(bp);
181 goto out1;
182 }
183 mp->m_inodp = ip;
184 mp->m_dev = dev;
185 bp->b_flags |= B_LOCKED;
186 mp->m_bufp = bp;
187 fp = bp->b_un.b_filsys;
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;
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;
198 brelse(bp);
199 ip->i_flag |= IMOUNT;
200 irele(ip);
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;
218 int stillopen, flag;
219 register struct a {
220 char *fspec;
221 };
222
223 dev = getmdev();
224 if (u.u_error)
225 return;
226 xumount(dev); /* remove unused sticky files from text table */
227 update();
228 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
229 if (mp->m_bufp != NULL && dev == mp->m_dev)
230 goto found;
231 u.u_error = EINVAL;
232 return;
233
234found:
235 stillopen = 0;
236 for (ip = inode; ip < inodeNINODE; ip++)
237 if (ip->i_number != 0 && dev == ip->i_dev) {
238 u.u_error = EBUSY;
239 return;
240 } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK &&
241 ip->i_un.i_rdev == dev)
242 stillopen++;
243 ip = mp->m_inodp;
244 ip->i_flag &= ~IMOUNT;
245 ilock(ip);
246 iput(ip);
247 if ((bp = getblk(dev, SUPERB)) != mp->m_bufp)
248 panic("umount");
249 bp->b_flags &= ~B_LOCKED;
250 flag = !bp->b_un.b_filsys->s_ronly;
251 mp->m_bufp = NULL;
252 brelse(bp);
253 mpurge(mp - &mount[0]);
254 if (!stillopen) {
255 (*bdevsw[major(dev)].d_close)(dev, flag);
256 binval(dev);
257 }
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
271 if (!suser())
272 return(NODEV);
273 ip = namei(uchar, 0);
274 if (ip == NULL)
275 return(NODEV);
276 if ((ip->i_mode&IFMT) != IFBLK)
277 u.u_error = ENOTBLK;
278 dev = (dev_t)ip->i_un.i_rdev;
279 if (major(dev) >= nblkdev)
280 u.u_error = ENXIO;
281 iput(ip);
282 return(dev);
283}