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