it figures.
[unix-history] / usr / src / sys / ufs / lfs / lfs_vnops.c
CommitLineData
5485e062 1/* lfs_vnops.c 4.18 82/02/27 */
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;
75 stat1(ip, uap->sb, (off_t)0);
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 }
178 ip = maknode(IFLNK | 0777);
179 if (ip == NULL)
180 return;
181 u.u_base = uap->target;
182 u.u_count = nc;
183 u.u_offset = 0;
184 u.u_segflg = 0;
185 writei(ip);
186 iput(ip);
187}
188
189/*
190 * the dup system call.
d67a03eb
BJ
191 */
192dup()
193{
194 register struct file *fp;
195 register struct a {
196 int fdes;
197 int fdes2;
198 } *uap;
199 register i, m;
200
201 uap = (struct a *)u.u_ap;
202 m = uap->fdes & ~077;
203 uap->fdes &= 077;
204 fp = getf(uap->fdes);
e92a04af 205 if (fp == NULL)
d67a03eb
BJ
206 return;
207 if ((m&0100) == 0) {
208 if ((i = ufalloc()) < 0)
209 return;
210 } else {
211 i = uap->fdes2;
212 if (i<0 || i>=NOFILE) {
213 u.u_error = EBADF;
214 return;
215 }
d67a03eb
BJ
216 u.u_r.r_val1 = i;
217 }
e92a04af 218 if (i != uap->fdes) {
d67a03eb 219 if (u.u_ofile[i]!=NULL)
f3156a73
BJ
220 closef(u.u_ofile[i], 0);
221 if (u.u_error)
222 return;
d67a03eb
BJ
223 u.u_ofile[i] = fp;
224 fp->f_count++;
225 }
226}
227
228/*
e92a04af 229 * Mount system call.
d67a03eb 230 */
e92a04af
BJ
231smount()
232{
d67a03eb
BJ
233 dev_t dev;
234 register struct inode *ip;
235 register struct mount *mp;
236 struct mount *smp;
237 register struct filsys *fp;
238 struct buf *bp;
239 register struct a {
240 char *fspec;
241 char *freg;
242 int ronly;
243 } *uap;
1e608f17 244 register char *cp;
d67a03eb
BJ
245
246 uap = (struct a *)u.u_ap;
247 dev = getmdev();
e92a04af 248 if (u.u_error)
d67a03eb
BJ
249 return;
250 u.u_dirp = (caddr_t)uap->freg;
5485e062 251 ip = namei(uchar, 0, 1);
e92a04af 252 if (ip == NULL)
d67a03eb 253 return;
e92a04af 254 if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR)
d67a03eb
BJ
255 goto out;
256 smp = NULL;
e92a04af
BJ
257 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
258 if (mp->m_bufp != NULL) {
259 if (dev == mp->m_dev)
d67a03eb
BJ
260 goto out;
261 } else
e92a04af 262 if (smp == NULL)
d67a03eb
BJ
263 smp = mp;
264 }
265 mp = smp;
e92a04af 266 if (mp == NULL)
d67a03eb
BJ
267 goto out;
268 (*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
e92a04af 269 if (u.u_error)
d67a03eb
BJ
270 goto out;
271 bp = bread(dev, SUPERB);
e92a04af 272 if (u.u_error) {
d67a03eb
BJ
273 brelse(bp);
274 goto out1;
275 }
276 mp->m_inodp = ip;
277 mp->m_dev = dev;
2c3059b1
BJ
278 bp->b_flags |= B_LOCKED;
279 mp->m_bufp = bp;
280 fp = bp->b_un.b_filsys;
d67a03eb
BJ
281 fp->s_ilock = 0;
282 fp->s_flock = 0;
283 fp->s_ronly = uap->ronly & 1;
284 fp->s_nbehind = 0;
285 fp->s_lasti = 1;
1e608f17
BJ
286 u.u_dirp = uap->freg;
287 for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; )
288 if ((*cp++ = uchar()) == 0)
289 u.u_dirp--; /* get 0 again */
290 *cp = 0;
d67a03eb
BJ
291 brelse(bp);
292 ip->i_flag |= IMOUNT;
e92a04af 293 irele(ip);
d67a03eb
BJ
294 return;
295
296out:
297 u.u_error = EBUSY;
298out1:
299 iput(ip);
300}
301
302/*
303 * the umount system call.
304 */
305sumount()
306{
307 dev_t dev;
308 register struct inode *ip;
309 register struct mount *mp;
310 struct buf *bp;
2c3059b1 311 int stillopen, flag;
d67a03eb
BJ
312 register struct a {
313 char *fspec;
314 };
315
316 dev = getmdev();
e92a04af 317 if (u.u_error)
d67a03eb
BJ
318 return;
319 xumount(dev); /* remove unused sticky files from text table */
68503f9a 320 update(0);
e92a04af
BJ
321 for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
322 if (mp->m_bufp != NULL && dev == mp->m_dev)
d67a03eb
BJ
323 goto found;
324 u.u_error = EINVAL;
325 return;
326
327found:
9491f93d 328 stillopen = 0;
e92a04af 329 for (ip = inode; ip < inodeNINODE; ip++)
2c3059b1 330 if (ip->i_number != 0 && dev == ip->i_dev) {
d67a03eb
BJ
331 u.u_error = EBUSY;
332 return;
2c3059b1
BJ
333 } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK &&
334 ip->i_un.i_rdev == dev)
335 stillopen++;
d67a03eb
BJ
336 ip = mp->m_inodp;
337 ip->i_flag &= ~IMOUNT;
e92a04af 338 ilock(ip);
d67a03eb 339 iput(ip);
2c3059b1
BJ
340 if ((bp = getblk(dev, SUPERB)) != mp->m_bufp)
341 panic("umount");
342 bp->b_flags &= ~B_LOCKED;
4a18fb8e 343 flag = !bp->b_un.b_filsys->s_ronly;
d67a03eb
BJ
344 mp->m_bufp = NULL;
345 brelse(bp);
aa250f32 346 mpurge(mp - &mount[0]);
4a18fb8e 347 if (!stillopen) {
4a18fb8e
RE
348 (*bdevsw[major(dev)].d_close)(dev, flag);
349 binval(dev);
350 }
d67a03eb
BJ
351}
352
353/*
354 * Common code for mount and umount.
355 * Check that the user's argument is a reasonable
356 * thing on which to mount, and return the device number if so.
357 */
358dev_t
359getmdev()
360{
361 dev_t dev;
362 register struct inode *ip;
363
d67a03eb
BJ
364 if (!suser())
365 return(NODEV);
5485e062 366 ip = namei(uchar, 0, 1);
e92a04af 367 if (ip == NULL)
d67a03eb 368 return(NODEV);
e92a04af 369 if ((ip->i_mode&IFMT) != IFBLK)
d67a03eb
BJ
370 u.u_error = ENOTBLK;
371 dev = (dev_t)ip->i_un.i_rdev;
e92a04af 372 if (major(dev) >= nblkdev)
d67a03eb
BJ
373 u.u_error = ENXIO;
374 iput(ip);
375 return(dev);
376}