xref: /csrg-svn/sys/kern/vfs_syscalls.c (revision 4125)
1 /*	vfs_syscalls.c	4.11	81/08/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 
18 /*
19  * the fstat system call.
20  */
21 fstat()
22 {
23 	register struct file *fp;
24 	register struct a {
25 		int	fdes;
26 		struct stat *sb;
27 	} *uap;
28 
29 	uap = (struct a *)u.u_ap;
30 	fp = getf(uap->fdes);
31 	if(fp == NULL)
32 		return;
33 	if (fp->f_flag&FPORT) {
34 		ptstat(fp);
35 		return;
36 	}
37 #ifdef BBNNET
38 	if (fp->f_flag&FNET) {
39 	    	u.u_error = EINVAL;
40 		return;
41 	}
42 #endif
43 	stat1(fp->f_inode, uap->sb);
44 }
45 
46 /*
47  * the stat system call.
48  */
49 stat()
50 {
51 	register struct inode *ip;
52 	register struct a {
53 		char	*fname;
54 		struct stat *sb;
55 	} *uap;
56 
57 	uap = (struct a *)u.u_ap;
58 	ip = namei(uchar, 0);
59 	if(ip == NULL)
60 		return;
61 	stat1(ip, uap->sb);
62 	iput(ip);
63 }
64 
65 /*
66  * The basic routine for fstat and stat:
67  * get the inode and pass appropriate parts back.
68  */
69 stat1(ip, ub)
70 register struct inode *ip;
71 struct stat *ub;
72 {
73 	register struct dinode *dp;
74 	register struct buf *bp;
75 	struct stat ds;
76 
77 	IUPDAT(ip, &time, &time, 0);
78 	/*
79 	 * first copy from inode table
80 	 */
81 	ds.st_dev = ip->i_dev;
82 	ds.st_ino = ip->i_number;
83 	ds.st_mode = ip->i_mode;
84 	ds.st_nlink = ip->i_nlink;
85 	ds.st_uid = ip->i_uid;
86 	ds.st_gid = ip->i_gid;
87 	ds.st_rdev = (dev_t)ip->i_un.i_rdev;
88 	ds.st_size = ip->i_size;
89 	/*
90 	 * next the dates in the disk
91 	 */
92 	bp = bread(ip->i_dev, itod(ip->i_number));
93 	dp = bp->b_un.b_dino;
94 	dp += itoo(ip->i_number);
95 	ds.st_atime = dp->di_atime;
96 	ds.st_mtime = dp->di_mtime;
97 	ds.st_ctime = dp->di_ctime;
98 	brelse(bp);
99 	if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
100 		u.u_error = EFAULT;
101 }
102 
103 /*
104  * the dup system call.
105  */
106 dup()
107 {
108 	register struct file *fp;
109 	register struct a {
110 		int	fdes;
111 		int	fdes2;
112 	} *uap;
113 	register i, m;
114 
115 	uap = (struct a *)u.u_ap;
116 	m = uap->fdes & ~077;
117 	uap->fdes &= 077;
118 	fp = getf(uap->fdes);
119 	if(fp == NULL)
120 		return;
121 	if ((m&0100) == 0) {
122 		if ((i = ufalloc()) < 0)
123 			return;
124 	} else {
125 		i = uap->fdes2;
126 		if (i<0 || i>=NOFILE) {
127 			u.u_error = EBADF;
128 			return;
129 		}
130 		if (u.u_vrpages[i]) {
131 			u.u_error = ETXTBSY;
132 			return;
133 		}
134 		u.u_r.r_val1 = i;
135 	}
136 	if (i!=uap->fdes) {
137 		if (u.u_ofile[i]!=NULL)
138 			closef(u.u_ofile[i]);
139 		u.u_ofile[i] = fp;
140 		fp->f_count++;
141 	}
142 }
143 
144 /*
145  * the mount system call.
146  */
147 smount() {
148 	dev_t dev;
149 	register struct inode *ip;
150 	register struct mount *mp;
151 	struct mount *smp;
152 	register struct filsys *fp;
153 	struct buf *bp;
154 	register struct a {
155 		char	*fspec;
156 		char	*freg;
157 		int	ronly;
158 	} *uap;
159 	register char *cp;
160 
161 	uap = (struct a *)u.u_ap;
162 	dev = getmdev();
163 	if(u.u_error)
164 		return;
165 	u.u_dirp = (caddr_t)uap->freg;
166 	ip = namei(uchar, 0);
167 	if(ip == NULL)
168 		return;
169 	if(ip->i_count!=1 || (ip->i_mode&(IFBLK&IFCHR))!=0)
170 		goto out;
171 	smp = NULL;
172 	for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++) {
173 		if(mp->m_bufp != NULL) {
174 			if(dev == mp->m_dev)
175 				goto out;
176 		} else
177 		if(smp == NULL)
178 			smp = mp;
179 	}
180 	mp = smp;
181 	if(mp == NULL)
182 		goto out;
183 	(*bdevsw[major(dev)].d_open)(dev, !uap->ronly);
184 	if(u.u_error)
185 		goto out;
186 	bp = bread(dev, SUPERB);
187 	if(u.u_error) {
188 		brelse(bp);
189 		goto out1;
190 	}
191 	mp->m_inodp = ip;
192 	mp->m_dev = dev;
193 	bp->b_flags |= B_LOCKED;
194 	mp->m_bufp = bp;
195 	fp = bp->b_un.b_filsys;
196 	fp->s_ilock = 0;
197 	fp->s_flock = 0;
198 	fp->s_ronly = uap->ronly & 1;
199 	fp->s_nbehind = 0;
200 	fp->s_lasti = 1;
201 	u.u_dirp = uap->freg;
202 	for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; )
203 		if ((*cp++ = uchar()) == 0)
204 			u.u_dirp--;		/* get 0 again */
205 	*cp = 0;
206 	brelse(bp);
207 	ip->i_flag |= IMOUNT;
208 	prele(ip);
209 	return;
210 
211 out:
212 	u.u_error = EBUSY;
213 out1:
214 	iput(ip);
215 }
216 
217 /*
218  * the umount system call.
219  */
220 sumount()
221 {
222 	dev_t dev;
223 	register struct inode *ip;
224 	register struct mount *mp;
225 	struct buf *bp;
226 	int stillopen, flag;
227 	register struct a {
228 		char	*fspec;
229 	};
230 
231 	dev = getmdev();
232 	if(u.u_error)
233 		return;
234 	xumount(dev);	/* remove unused sticky files from text table */
235 	update();
236 	for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
237 		if(mp->m_bufp != NULL && dev == mp->m_dev)
238 			goto found;
239 	u.u_error = EINVAL;
240 	return;
241 
242 found:
243 	stillopen = 0;
244 	for(ip = inode; ip < inodeNINODE; ip++)
245 		if (ip->i_number != 0 && dev == ip->i_dev) {
246 			u.u_error = EBUSY;
247 			return;
248 		} else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK &&
249 		    ip->i_un.i_rdev == dev)
250 			stillopen++;
251 	ip = mp->m_inodp;
252 	ip->i_flag &= ~IMOUNT;
253 	plock(ip);
254 	iput(ip);
255 	if ((bp = getblk(dev, SUPERB)) != mp->m_bufp)
256 		panic("umount");
257 	bp->b_flags &= ~B_LOCKED;
258 	flag = !bp->b_un.b_filsys->s_ronly;
259 	mp->m_bufp = NULL;
260 	brelse(bp);
261 	mpurge(mp - &mount[0]);
262 	if (!stillopen) {
263 		(*bdevsw[major(dev)].d_close)(dev, flag);
264 		binval(dev);
265 	}
266 }
267 
268 /*
269  * Common code for mount and umount.
270  * Check that the user's argument is a reasonable
271  * thing on which to mount, and return the device number if so.
272  */
273 dev_t
274 getmdev()
275 {
276 	dev_t dev;
277 	register struct inode *ip;
278 
279 	if (!suser())
280 		return(NODEV);
281 	ip = namei(uchar, 0);
282 	if(ip == NULL)
283 		return(NODEV);
284 	if((ip->i_mode&IFMT) != IFBLK)
285 		u.u_error = ENOTBLK;
286 	dev = (dev_t)ip->i_un.i_rdev;
287 	if(major(dev) >= nblkdev)
288 		u.u_error = ENXIO;
289 	iput(ip);
290 	return(dev);
291 }
292