Commit | Line | Data |
---|---|---|
831e498e | 1 | /* lfs_vnops.c 3.4 %G% */ |
d67a03eb BJ |
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" | |
0737b714 | 16 | #include "../h/inline.h" |
d67a03eb BJ |
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 | ||
0737b714 | 68 | IUPDAT(ip, &time, &time); |
d67a03eb BJ |
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 | } | |
831e498e | 233 | mpurge(mp - &mount[0]); |
d67a03eb BJ |
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 | } |