xref: /original-bsd/sys/ufs/ufs/ufs_vnops.c (revision 56abee86)
1 /*	ufs_vnops.c	4.9	81/03/09	*/
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 	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 	register char *cp;
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 	bp->b_flags |= B_LOCKED;
185 	mp->m_bufp = bp;
186 	fp = bp->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 	u.u_dirp = uap->freg;
193 	for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; )
194 		if ((*cp++ = uchar()) == 0)
195 			u.u_dirp--;		/* get 0 again */
196 	*cp = 0;
197 	brelse(bp);
198 	ip->i_flag |= IMOUNT;
199 	prele(ip);
200 	return;
201 
202 out:
203 	u.u_error = EBUSY;
204 out1:
205 	iput(ip);
206 }
207 
208 /*
209  * the umount system call.
210  */
211 sumount()
212 {
213 	dev_t dev;
214 	register struct inode *ip;
215 	register struct mount *mp;
216 	struct buf *bp;
217 	int stillopen, flag;
218 	register struct a {
219 		char	*fspec;
220 	};
221 
222 	dev = getmdev();
223 	if(u.u_error)
224 		return;
225 	xumount(dev);	/* remove unused sticky files from text table */
226 	update();
227 	for(mp = &mount[0]; mp < &mount[NMOUNT]; mp++)
228 		if(mp->m_bufp != NULL && dev == mp->m_dev)
229 			goto found;
230 	u.u_error = EINVAL;
231 	return;
232 
233 found:
234 	stillopen = 0;
235 	for(ip = inode; ip < inodeNINODE; ip++)
236 		if (ip->i_number != 0 && dev == ip->i_dev) {
237 			u.u_error = EBUSY;
238 			return;
239 		} else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK &&
240 		    ip->i_un.i_rdev == dev)
241 			stillopen++;
242 	ip = mp->m_inodp;
243 	ip->i_flag &= ~IMOUNT;
244 	plock(ip);
245 	iput(ip);
246 	if ((bp = getblk(dev, SUPERB)) != mp->m_bufp)
247 		panic("umount");
248 	bp->b_flags &= ~B_LOCKED;
249 	flag = !bp->b_un.b_filsys->s_ronly;
250 	mp->m_bufp = NULL;
251 	brelse(bp);
252 	mpurge(mp - &mount[0]);
253 	if (!stillopen) {
254 		(*bdevsw[major(dev)].d_close)(dev, flag);
255 		binval(dev);
256 	}
257 }
258 
259 /*
260  * Common code for mount and umount.
261  * Check that the user's argument is a reasonable
262  * thing on which to mount, and return the device number if so.
263  */
264 dev_t
265 getmdev()
266 {
267 	dev_t dev;
268 	register struct inode *ip;
269 
270 	if (!suser())
271 		return(NODEV);
272 	ip = namei(uchar, 0);
273 	if(ip == NULL)
274 		return(NODEV);
275 	if((ip->i_mode&IFMT) != IFBLK)
276 		u.u_error = ENOTBLK;
277 	dev = (dev_t)ip->i_un.i_rdev;
278 	if(major(dev) >= nblkdev)
279 		u.u_error = ENXIO;
280 	iput(ip);
281 	return(dev);
282 }
283