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