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