xref: /csrg-svn/sys/ufs/lfs/lfs_vnops.c (revision 4828)
1 /*	lfs_vnops.c	4.12	81/11/08	*/
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 & FSOCKET)
34 		sostat(fp->f_socket);
35 	else
36 		stat1(fp->f_inode, uap->sb);
37 }
38 
39 /*
40  * Stat system call.
41  */
42 stat()
43 {
44 	register struct inode *ip;
45 	register struct a {
46 		char	*fname;
47 		struct stat *sb;
48 	} *uap;
49 
50 	uap = (struct a *)u.u_ap;
51 	ip = namei(uchar, 0);
52 	if (ip == NULL)
53 		return;
54 	stat1(ip, uap->sb);
55 	iput(ip);
56 }
57 
58 /*
59  * The basic routine for fstat and stat:
60  * get the inode and pass appropriate parts back.
61  */
62 stat1(ip, ub)
63 	register struct inode *ip;
64 	struct stat *ub;
65 {
66 	register struct dinode *dp;
67 	register struct buf *bp;
68 	struct stat ds;
69 
70 	IUPDAT(ip, &time, &time, 0);
71 	/*
72 	 * First copy from inode table
73 	 */
74 	ds.st_dev = ip->i_dev;
75 	ds.st_ino = ip->i_number;
76 	ds.st_mode = ip->i_mode;
77 	ds.st_nlink = ip->i_nlink;
78 	ds.st_uid = ip->i_uid;
79 	ds.st_gid = ip->i_gid;
80 	ds.st_rdev = (dev_t)ip->i_un.i_rdev;
81 	ds.st_size = ip->i_size;
82 	/*
83 	 * Next the dates in the disk
84 	 */
85 	bp = bread(ip->i_dev, itod(ip->i_number));
86 	dp = bp->b_un.b_dino;
87 	dp += itoo(ip->i_number);
88 	ds.st_atime = dp->di_atime;
89 	ds.st_mtime = dp->di_mtime;
90 	ds.st_ctime = dp->di_ctime;
91 	brelse(bp);
92 	if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
93 		u.u_error = EFAULT;
94 }
95 
96 /*
97  * Dup system call.
98  */
99 dup()
100 {
101 	register struct file *fp;
102 	register struct a {
103 		int	fdes;
104 		int	fdes2;
105 	} *uap;
106 	register i, m;
107 
108 	uap = (struct a *)u.u_ap;
109 	m = uap->fdes & ~077;
110 	uap->fdes &= 077;
111 	fp = getf(uap->fdes);
112 	if (fp == NULL)
113 		return;
114 	if ((m&0100) == 0) {
115 		if ((i = ufalloc()) < 0)
116 			return;
117 	} else {
118 		i = uap->fdes2;
119 		if (i<0 || i>=NOFILE) {
120 			u.u_error = EBADF;
121 			return;
122 		}
123 		u.u_r.r_val1 = i;
124 	}
125 	if (i != uap->fdes) {
126 		if (u.u_ofile[i]!=NULL)
127 			closef(u.u_ofile[i]);
128 		u.u_ofile[i] = fp;
129 		fp->f_count++;
130 	}
131 }
132 
133 /*
134  * Mount system call.
135  */
136 smount()
137 {
138 	dev_t dev;
139 	register struct inode *ip;
140 	register struct mount *mp;
141 	struct mount *smp;
142 	register struct filsys *fp;
143 	struct buf *bp;
144 	register struct a {
145 		char	*fspec;
146 		char	*freg;
147 		int	ronly;
148 	} *uap;
149 	register char *cp;
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&IFMT) != IFDIR)
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 	bp->b_flags |= B_LOCKED;
184 	mp->m_bufp = bp;
185 	fp = bp->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 	u.u_dirp = uap->freg;
192 	for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; )
193 		if ((*cp++ = uchar()) == 0)
194 			u.u_dirp--;		/* get 0 again */
195 	*cp = 0;
196 	brelse(bp);
197 	ip->i_flag |= IMOUNT;
198 	irele(ip);
199 	return;
200 
201 out:
202 	u.u_error = EBUSY;
203 out1:
204 	iput(ip);
205 }
206 
207 /*
208  * the umount system call.
209  */
210 sumount()
211 {
212 	dev_t dev;
213 	register struct inode *ip;
214 	register struct mount *mp;
215 	struct buf *bp;
216 	int stillopen, flag;
217 	register struct a {
218 		char	*fspec;
219 	};
220 
221 	dev = getmdev();
222 	if (u.u_error)
223 		return;
224 	xumount(dev);	/* remove unused sticky files from text table */
225 	update();
226 	for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
227 		if (mp->m_bufp != NULL && dev == mp->m_dev)
228 			goto found;
229 	u.u_error = EINVAL;
230 	return;
231 
232 found:
233 	stillopen = 0;
234 	for (ip = inode; ip < inodeNINODE; ip++)
235 		if (ip->i_number != 0 && dev == ip->i_dev) {
236 			u.u_error = EBUSY;
237 			return;
238 		} else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK &&
239 		    ip->i_un.i_rdev == dev)
240 			stillopen++;
241 	ip = mp->m_inodp;
242 	ip->i_flag &= ~IMOUNT;
243 	ilock(ip);
244 	iput(ip);
245 	if ((bp = getblk(dev, SUPERB)) != mp->m_bufp)
246 		panic("umount");
247 	bp->b_flags &= ~B_LOCKED;
248 	flag = !bp->b_un.b_filsys->s_ronly;
249 	mp->m_bufp = NULL;
250 	brelse(bp);
251 	mpurge(mp - &mount[0]);
252 	if (!stillopen) {
253 		(*bdevsw[major(dev)].d_close)(dev, flag);
254 		binval(dev);
255 	}
256 }
257 
258 /*
259  * Common code for mount and umount.
260  * Check that the user's argument is a reasonable
261  * thing on which to mount, and return the device number if so.
262  */
263 dev_t
264 getmdev()
265 {
266 	dev_t dev;
267 	register struct inode *ip;
268 
269 	if (!suser())
270 		return(NODEV);
271 	ip = namei(uchar, 0);
272 	if (ip == NULL)
273 		return(NODEV);
274 	if ((ip->i_mode&IFMT) != IFBLK)
275 		u.u_error = ENOTBLK;
276 	dev = (dev_t)ip->i_un.i_rdev;
277 	if (major(dev) >= nblkdev)
278 		u.u_error = ENXIO;
279 	iput(ip);
280 	return(dev);
281 }
282