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