xref: /original-bsd/sys/ufs/ffs/ufs_vnops.c (revision a304ca22)
1 /*	ufs_vnops.c	4.19	82/03/12	*/
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  */
23 fstat()
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.  This version does not follow links.
43  */
44 stat()
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, 0);
54 	if (ip == NULL)
55 		return;
56 	stat1(ip, uap->sb);
57 	iput(ip);
58 }
59 
60 /*
61  * Lstat system call.  This version does follow links.
62  */
63 lstat()
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);
76 	iput(ip);
77 }
78 
79 /*
80  * The basic routine for fstat and stat:
81  * get the inode and pass appropriate parts back.
82  */
83 stat1(ip, ub)
84 	register struct inode *ip;
85 	struct stat *ub;
86 {
87 	register struct dinode *dp;
88 	register struct buf *bp;
89 	struct stat ds;
90 
91 	IUPDAT(ip, &time, &time, 0);
92 	/*
93 	 * First copy from inode table
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;
102 	ds.st_size = ip->i_size;
103 	/*
104 	 * next the dates in the disk
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 /*
118  * Return target name of a symbolic link
119  */
120 readlink()
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);
142 out:
143 	iput(ip);
144 	u.u_r.r_val1 = uap->count - u.u_count;
145 }
146 
147 /*
148  * symlink -- make a symbolic link
149  */
150 symlink()
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.
191  */
192 dup()
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);
205 	if (fp == NULL)
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 		}
216 		u.u_r.r_val1 = i;
217 	}
218 	if (i != uap->fdes) {
219 		if (u.u_ofile[i]!=NULL)
220 			closef(u.u_ofile[i], 0);
221 		if (u.u_error)
222 			return;
223 		u.u_ofile[i] = fp;
224 		fp->f_count++;
225 	}
226 }
227 
228 /*
229  * Mount system call.
230  */
231 smount()
232 {
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;
244 	register char *cp;
245 
246 	uap = (struct a *)u.u_ap;
247 	dev = getmdev();
248 	if (u.u_error)
249 		return;
250 	u.u_dirp = (caddr_t)uap->freg;
251 	ip = namei(uchar, 0, 1);
252 	if (ip == NULL)
253 		return;
254 	if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR)
255 		goto out;
256 	smp = NULL;
257 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
258 		if (mp->m_bufp != NULL) {
259 			if (dev == mp->m_dev)
260 				goto out;
261 		} else
262 		if (smp == NULL)
263 			smp = mp;
264 	}
265 	mp = smp;
266 	if (mp == NULL)
267 		goto out;
268 	(*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
269 	if (u.u_error)
270 		goto out;
271 	bp = bread(dev, SUPERB);
272 	if (u.u_error) {
273 		brelse(bp);
274 		goto out1;
275 	}
276 	mp->m_inodp = ip;
277 	mp->m_dev = dev;
278 	bp->b_flags |= B_LOCKED;
279 	mp->m_bufp = bp;
280 	fp = bp->b_un.b_filsys;
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;
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;
291 	brelse(bp);
292 	ip->i_flag |= IMOUNT;
293 	irele(ip);
294 	return;
295 
296 out:
297 	u.u_error = EBUSY;
298 out1:
299 	iput(ip);
300 }
301 
302 /*
303  * the umount system call.
304  */
305 sumount()
306 {
307 	dev_t dev;
308 	register struct inode *ip;
309 	register struct mount *mp;
310 	struct buf *bp;
311 	int stillopen, flag;
312 	register struct a {
313 		char	*fspec;
314 	};
315 
316 	dev = getmdev();
317 	if (u.u_error)
318 		return;
319 	xumount(dev);	/* remove unused sticky files from text table */
320 	update(0);
321 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
322 		if (mp->m_bufp != NULL && dev == mp->m_dev)
323 			goto found;
324 	u.u_error = EINVAL;
325 	return;
326 
327 found:
328 	stillopen = 0;
329 	for (ip = inode; ip < inodeNINODE; ip++)
330 		if (ip->i_number != 0 && dev == ip->i_dev) {
331 			u.u_error = EBUSY;
332 			return;
333 		} else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK &&
334 		    ip->i_un.i_rdev == dev)
335 			stillopen++;
336 	ip = mp->m_inodp;
337 	ip->i_flag &= ~IMOUNT;
338 	ilock(ip);
339 	iput(ip);
340 	if ((bp = getblk(dev, SUPERB)) != mp->m_bufp)
341 		panic("umount");
342 	bp->b_flags &= ~B_LOCKED;
343 	flag = !bp->b_un.b_filsys->s_ronly;
344 	mp->m_bufp = NULL;
345 	brelse(bp);
346 	mpurge(mp - &mount[0]);
347 	if (!stillopen) {
348 		(*bdevsw[major(dev)].d_close)(dev, flag);
349 		binval(dev);
350 	}
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  */
358 dev_t
359 getmdev()
360 {
361 	dev_t dev;
362 	register struct inode *ip;
363 
364 	if (!suser())
365 		return(NODEV);
366 	ip = namei(uchar, 0, 1);
367 	if (ip == NULL)
368 		return(NODEV);
369 	if ((ip->i_mode&IFMT) != IFBLK)
370 		u.u_error = ENOTBLK;
371 	dev = (dev_t)ip->i_un.i_rdev;
372 	if (major(dev) >= nblkdev)
373 		u.u_error = ENXIO;
374 	iput(ip);
375 	return(dev);
376 }
377