only allow ``brk'' back to beginning of monitor data area
[unix-history] / usr / src / sys / ufs / lfs / lfs_vnops.c
CommitLineData
32f555bf 1/* lfs_vnops.c 4.20 82/03/16 */
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/*
5485e062 42 * Stat system call. This version does not follow links.
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;
5485e062 53 ip = namei(uchar, 0, 0);
e92a04af 54 if (ip == NULL)
d67a03eb 55 return;
a3aa7f92 56 stat1(ip, uap->sb);
d67a03eb
BJ
57 iput(ip);
58}
59
5485e062
BJ
60/*
61 * Lstat system call. This version does follow links.
62 */
63lstat()
64{
65 register struct inode *ip;
66 register struct a {
67 char *fname;
68 struct stat *sb;
69 } *uap;
70
71 uap = (struct a *)u.u_ap;
72 ip = namei(uchar, 0, 1);
73 if (ip == NULL)
74 return;
019b08c9 75 stat1(ip, uap->sb);
5485e062
BJ
76 iput(ip);
77}
78
d67a03eb
BJ
79/*
80 * The basic routine for fstat and stat:
81 * get the inode and pass appropriate parts back.
82 */
a3aa7f92 83stat1(ip, ub)
e92a04af
BJ
84 register struct inode *ip;
85 struct stat *ub;
d67a03eb
BJ
86{
87 register struct dinode *dp;
88 register struct buf *bp;
89 struct stat ds;
90
c0bb1685 91 IUPDAT(ip, &time, &time, 0);
d67a03eb 92 /*
e92a04af 93 * First copy from inode table
d67a03eb
BJ
94 */
95 ds.st_dev = ip->i_dev;
96 ds.st_ino = ip->i_number;
97 ds.st_mode = ip->i_mode;
98 ds.st_nlink = ip->i_nlink;
99 ds.st_uid = ip->i_uid;
100 ds.st_gid = ip->i_gid;
101 ds.st_rdev = (dev_t)ip->i_un.i_rdev;
a3aa7f92 102 ds.st_size = ip->i_size;
d67a03eb 103 /*
5485e062 104 * next the dates in the disk
d67a03eb
BJ
105 */
106 bp = bread(ip->i_dev, itod(ip->i_number));
107 dp = bp->b_un.b_dino;
108 dp += itoo(ip->i_number);
109 ds.st_atime = dp->di_atime;
110 ds.st_mtime = dp->di_mtime;
111 ds.st_ctime = dp->di_ctime;
112 brelse(bp);
113 if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
114 u.u_error = EFAULT;
115}
116
117/*
5485e062
BJ
118 * Return target name of a symbolic link
119 */
120readlink()
121{
122 register struct inode *ip;
123 register struct a {
124 char *name;
125 char *buf;
126 int count;
127 } *uap;
128
129 ip = namei(uchar, 0, 0);
130 if (ip == NULL)
131 return;
132 if ((ip->i_mode&IFMT) != IFLNK) {
133 u.u_error = ENXIO;
134 goto out;
135 }
136 uap = (struct a *)u.u_ap;
137 u.u_offset = 0;
138 u.u_base = uap->buf;
139 u.u_count = uap->count;
140 u.u_segflg = 0;
141 readi(ip);
142out:
143 iput(ip);
144 u.u_r.r_val1 = uap->count - u.u_count;
145}
146
147/*
148 * symlink -- make a symbolic link
149 */
150symlink()
151{
152 register struct a {
153 char *target;
154 char *linkname;
155 } *uap;
156 register struct inode *ip;
157 register char *tp;
158 register c, nc;
159
160 uap = (struct a *)u.u_ap;
161 tp = uap->target;
162 nc = 0;
163 while (c = fubyte(tp)) {
164 if (c < 0) {
165 u.u_error = EFAULT;
166 return;
167 }
168 tp++;
169 nc++;
170 }
171 u.u_dirp = uap->linkname;
172 ip = namei(uchar, 1, 0);
173 if (ip) {
174 iput(ip);
175 u.u_error = EEXIST;
176 return;
177 }
32f555bf
BJ
178 if (u.u_error)
179 return;
5485e062
BJ
180 ip = maknode(IFLNK | 0777);
181 if (ip == NULL)
182 return;
183 u.u_base = uap->target;
184 u.u_count = nc;
185 u.u_offset = 0;
186 u.u_segflg = 0;
187 writei(ip);
188 iput(ip);
189}
190
191/*
192 * the dup system call.
d67a03eb
BJ
193 */
194dup()
195{
196 register struct file *fp;
197 register struct a {
198 int fdes;
199 int fdes2;
200 } *uap;
201 register i, m;
202
203 uap = (struct a *)u.u_ap;
204 m = uap->fdes & ~077;
205 uap->fdes &= 077;
206 fp = getf(uap->fdes);
e92a04af 207 if (fp == NULL)
d67a03eb
BJ
208 return;
209 if ((m&0100) == 0) {
210 if ((i = ufalloc()) < 0)
211 return;
212 } else {
213 i = uap->fdes2;
214 if (i<0 || i>=NOFILE) {
215 u.u_error = EBADF;
216 return;
217 }
d67a03eb
BJ
218 u.u_r.r_val1 = i;
219 }
e92a04af 220 if (i != uap->fdes) {
d67a03eb 221 if (u.u_ofile[i]!=NULL)
f3156a73
BJ
222 closef(u.u_ofile[i], 0);
223 if (u.u_error)
224 return;
d67a03eb
BJ
225 u.u_ofile[i] = fp;
226 fp->f_count++;
227 }
228}
229
230/*
e92a04af 231 * Mount system call.
d67a03eb 232 */
e92a04af
BJ
233smount()
234{
d67a03eb
BJ
235 dev_t dev;
236 register struct inode *ip;
237 register struct mount *mp;
238 struct mount *smp;
239 register struct filsys *fp;
240 struct buf *bp;
241 register struct a {
242 char *fspec;
243 char *freg;
244 int ronly;
245 } *uap;
1e608f17 246 register char *cp;
d67a03eb
BJ
247
248 uap = (struct a *)u.u_ap;
249 dev = getmdev();
e92a04af 250 if (u.u_error)
d67a03eb
BJ
251 return;
252 u.u_dirp = (caddr_t)uap->freg;
5485e062 253 ip = namei(uchar, 0, 1);
e92a04af 254 if (ip == NULL)
d67a03eb 255 return;
e92a04af 256 if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR)
d67a03eb
BJ
257 goto out;
258 smp = NULL;
e92a04af
BJ
259 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
260 if (mp->m_bufp != NULL) {
261 if (dev == mp->m_dev)
d67a03eb
BJ
262 goto out;
263 } else
e92a04af 264 if (smp == NULL)
d67a03eb
BJ
265 smp = mp;
266 }
267 mp = smp;
e92a04af 268 if (mp == NULL)
d67a03eb
BJ
269 goto out;
270 (*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
e92a04af 271 if (u.u_error)
d67a03eb
BJ
272 goto out;
273 bp = bread(dev, SUPERB);
e92a04af 274 if (u.u_error) {
d67a03eb
BJ
275 brelse(bp);
276 goto out1;
277 }
278 mp->m_inodp = ip;
279 mp->m_dev = dev;
2c3059b1
BJ
280 bp->b_flags |= B_LOCKED;
281 mp->m_bufp = bp;
282 fp = bp->b_un.b_filsys;
d67a03eb
BJ
283 fp->s_ilock = 0;
284 fp->s_flock = 0;
285 fp->s_ronly = uap->ronly & 1;
286 fp->s_nbehind = 0;
287 fp->s_lasti = 1;
1e608f17
BJ
288 u.u_dirp = uap->freg;
289 for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; )
290 if ((*cp++ = uchar()) == 0)
291 u.u_dirp--; /* get 0 again */
292 *cp = 0;
d67a03eb
BJ
293 brelse(bp);
294 ip->i_flag |= IMOUNT;
e92a04af 295 irele(ip);
d67a03eb
BJ
296 return;
297
298out:
299 u.u_error = EBUSY;
300out1:
301 iput(ip);
302}
303
304/*
305 * the umount system call.
306 */
307sumount()
308{
309 dev_t dev;
310 register struct inode *ip;
311 register struct mount *mp;
312 struct buf *bp;
2c3059b1 313 int stillopen, flag;
d67a03eb
BJ
314 register struct a {
315 char *fspec;
316 };
317
318 dev = getmdev();
e92a04af 319 if (u.u_error)
d67a03eb
BJ
320 return;
321 xumount(dev); /* remove unused sticky files from text table */
68503f9a 322 update(0);
e92a04af
BJ
323 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
324 if (mp->m_bufp != NULL && dev == mp->m_dev)
d67a03eb
BJ
325 goto found;
326 u.u_error = EINVAL;
327 return;
328
329found:
9491f93d 330 stillopen = 0;
e92a04af 331 for (ip = inode; ip < inodeNINODE; ip++)
2c3059b1 332 if (ip->i_number != 0 && dev == ip->i_dev) {
d67a03eb
BJ
333 u.u_error = EBUSY;
334 return;
2c3059b1
BJ
335 } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK &&
336 ip->i_un.i_rdev == dev)
337 stillopen++;
d67a03eb
BJ
338 ip = mp->m_inodp;
339 ip->i_flag &= ~IMOUNT;
e92a04af 340 ilock(ip);
d67a03eb 341 iput(ip);
2c3059b1
BJ
342 if ((bp = getblk(dev, SUPERB)) != mp->m_bufp)
343 panic("umount");
344 bp->b_flags &= ~B_LOCKED;
4a18fb8e 345 flag = !bp->b_un.b_filsys->s_ronly;
d67a03eb
BJ
346 mp->m_bufp = NULL;
347 brelse(bp);
aa250f32 348 mpurge(mp - &mount[0]);
4a18fb8e 349 if (!stillopen) {
4a18fb8e
RE
350 (*bdevsw[major(dev)].d_close)(dev, flag);
351 binval(dev);
352 }
d67a03eb
BJ
353}
354
355/*
356 * Common code for mount and umount.
357 * Check that the user's argument is a reasonable
358 * thing on which to mount, and return the device number if so.
359 */
360dev_t
361getmdev()
362{
363 dev_t dev;
364 register struct inode *ip;
365
d67a03eb
BJ
366 if (!suser())
367 return(NODEV);
5485e062 368 ip = namei(uchar, 0, 1);
e92a04af 369 if (ip == NULL)
d67a03eb 370 return(NODEV);
e92a04af 371 if ((ip->i_mode&IFMT) != IFBLK)
d67a03eb
BJ
372 u.u_error = ENOTBLK;
373 dev = (dev_t)ip->i_un.i_rdev;
e92a04af 374 if (major(dev) >= nblkdev)
d67a03eb
BJ
375 u.u_error = ENXIO;
376 iput(ip);
377 return(dev);
378}