xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 6246)
1 /*	vfs_syscalls.c	4.20	82/03/16	*/
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 	if (u.u_error)
179 		return;
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.
193  */
194 dup()
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);
207 	if (fp == NULL)
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 		}
218 		u.u_r.r_val1 = i;
219 	}
220 	if (i != uap->fdes) {
221 		if (u.u_ofile[i]!=NULL)
222 			closef(u.u_ofile[i], 0);
223 		if (u.u_error)
224 			return;
225 		u.u_ofile[i] = fp;
226 		fp->f_count++;
227 	}
228 }
229 
230 /*
231  * Mount system call.
232  */
233 smount()
234 {
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;
246 	register char *cp;
247 
248 	uap = (struct a *)u.u_ap;
249 	dev = getmdev();
250 	if (u.u_error)
251 		return;
252 	u.u_dirp = (caddr_t)uap->freg;
253 	ip = namei(uchar, 0, 1);
254 	if (ip == NULL)
255 		return;
256 	if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR)
257 		goto out;
258 	smp = NULL;
259 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
260 		if (mp->m_bufp != NULL) {
261 			if (dev == mp->m_dev)
262 				goto out;
263 		} else
264 		if (smp == NULL)
265 			smp = mp;
266 	}
267 	mp = smp;
268 	if (mp == NULL)
269 		goto out;
270 	(*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
271 	if (u.u_error)
272 		goto out;
273 	bp = bread(dev, SUPERB);
274 	if (u.u_error) {
275 		brelse(bp);
276 		goto out1;
277 	}
278 	mp->m_inodp = ip;
279 	mp->m_dev = dev;
280 	bp->b_flags |= B_LOCKED;
281 	mp->m_bufp = bp;
282 	fp = bp->b_un.b_filsys;
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;
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;
293 	brelse(bp);
294 	ip->i_flag |= IMOUNT;
295 	irele(ip);
296 	return;
297 
298 out:
299 	u.u_error = EBUSY;
300 out1:
301 	iput(ip);
302 }
303 
304 /*
305  * the umount system call.
306  */
307 sumount()
308 {
309 	dev_t dev;
310 	register struct inode *ip;
311 	register struct mount *mp;
312 	struct buf *bp;
313 	int stillopen, flag;
314 	register struct a {
315 		char	*fspec;
316 	};
317 
318 	dev = getmdev();
319 	if (u.u_error)
320 		return;
321 	xumount(dev);	/* remove unused sticky files from text table */
322 	update(0);
323 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
324 		if (mp->m_bufp != NULL && dev == mp->m_dev)
325 			goto found;
326 	u.u_error = EINVAL;
327 	return;
328 
329 found:
330 	stillopen = 0;
331 	for (ip = inode; ip < inodeNINODE; ip++)
332 		if (ip->i_number != 0 && dev == ip->i_dev) {
333 			u.u_error = EBUSY;
334 			return;
335 		} else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK &&
336 		    ip->i_un.i_rdev == dev)
337 			stillopen++;
338 	ip = mp->m_inodp;
339 	ip->i_flag &= ~IMOUNT;
340 	ilock(ip);
341 	iput(ip);
342 	if ((bp = getblk(dev, SUPERB)) != mp->m_bufp)
343 		panic("umount");
344 	bp->b_flags &= ~B_LOCKED;
345 	flag = !bp->b_un.b_filsys->s_ronly;
346 	mp->m_bufp = NULL;
347 	brelse(bp);
348 	mpurge(mp - &mount[0]);
349 	if (!stillopen) {
350 		(*bdevsw[major(dev)].d_close)(dev, flag);
351 		binval(dev);
352 	}
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  */
360 dev_t
361 getmdev()
362 {
363 	dev_t dev;
364 	register struct inode *ip;
365 
366 	if (!suser())
367 		return(NODEV);
368 	ip = namei(uchar, 0, 1);
369 	if (ip == NULL)
370 		return(NODEV);
371 	if ((ip->i_mode&IFMT) != IFBLK)
372 		u.u_error = ENOTBLK;
373 	dev = (dev_t)ip->i_un.i_rdev;
374 	if (major(dev) >= nblkdev)
375 		u.u_error = ENXIO;
376 	iput(ip);
377 	return(dev);
378 }
379