xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 5416)
1 /*	vfs_syscalls.c	4.16	82/01/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.
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);
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  */
64 stat1(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  */
101 dup()
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  */
138 smount()
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 
203 out:
204 	u.u_error = EBUSY;
205 out1:
206 	iput(ip);
207 }
208 
209 /*
210  * the umount system call.
211  */
212 sumount()
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(0);
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 
234 found:
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  */
265 dev_t
266 getmdev()
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 }
284