Commit | Line | Data |
---|---|---|
5485e062 | 1 | /* lfs_vnops.c 4.18 82/02/27 */ |
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" |
ae921915 BJ |
17 | #include "../h/socket.h" |
18 | #include "../h/socketvar.h" | |
d67a03eb BJ |
19 | |
20 | /* | |
21 | * the fstat system call. | |
22 | */ | |
23 | fstat() | |
24 | { | |
25 | register struct file *fp; | |
26 | register struct a { | |
27 | int fdes; | |
28 | struct stat *sb; | |
29 | } *uap; | |
30 | ||
31 | uap = (struct a *)u.u_ap; | |
32 | fp = getf(uap->fdes); | |
e92a04af | 33 | if (fp == NULL) |
d67a03eb | 34 | return; |
e92a04af | 35 | if (fp->f_flag & FSOCKET) |
cc15ab5d | 36 | u.u_error = sostat(fp->f_socket, uap->sb); |
e92a04af BJ |
37 | else |
38 | stat1(fp->f_inode, uap->sb); | |
d67a03eb BJ |
39 | } |
40 | ||
41 | /* | |
5485e062 | 42 | * Stat system call. This version does not follow links. |
d67a03eb BJ |
43 | */ |
44 | stat() | |
45 | { | |
46 | register struct inode *ip; | |
47 | register struct a { | |
48 | char *fname; | |
49 | struct stat *sb; | |
50 | } *uap; | |
51 | ||
52 | uap = (struct a *)u.u_ap; | |
5485e062 | 53 | ip = namei(uchar, 0, 0); |
e92a04af | 54 | if (ip == NULL) |
d67a03eb | 55 | return; |
a3aa7f92 | 56 | stat1(ip, uap->sb); |
d67a03eb BJ |
57 | iput(ip); |
58 | } | |
59 | ||
5485e062 BJ |
60 | /* |
61 | * Lstat system call. This version does follow links. | |
62 | */ | |
63 | lstat() | |
64 | { | |
65 | register struct inode *ip; | |
66 | register struct a { | |
67 | char *fname; | |
68 | struct stat *sb; | |
69 | } *uap; | |
70 | ||
71 | uap = (struct a *)u.u_ap; | |
72 | ip = namei(uchar, 0, 1); | |
73 | if (ip == NULL) | |
74 | return; | |
75 | stat1(ip, uap->sb, (off_t)0); | |
76 | iput(ip); | |
77 | } | |
78 | ||
d67a03eb BJ |
79 | /* |
80 | * The basic routine for fstat and stat: | |
81 | * get the inode and pass appropriate parts back. | |
82 | */ | |
a3aa7f92 | 83 | stat1(ip, ub) |
e92a04af BJ |
84 | register struct inode *ip; |
85 | struct stat *ub; | |
d67a03eb BJ |
86 | { |
87 | register struct dinode *dp; | |
88 | register struct buf *bp; | |
89 | struct stat ds; | |
90 | ||
c0bb1685 | 91 | IUPDAT(ip, &time, &time, 0); |
d67a03eb | 92 | /* |
e92a04af | 93 | * First copy from inode table |
d67a03eb BJ |
94 | */ |
95 | ds.st_dev = ip->i_dev; | |
96 | ds.st_ino = ip->i_number; | |
97 | ds.st_mode = ip->i_mode; | |
98 | ds.st_nlink = ip->i_nlink; | |
99 | ds.st_uid = ip->i_uid; | |
100 | ds.st_gid = ip->i_gid; | |
101 | ds.st_rdev = (dev_t)ip->i_un.i_rdev; | |
a3aa7f92 | 102 | ds.st_size = ip->i_size; |
d67a03eb | 103 | /* |
5485e062 | 104 | * next the dates in the disk |
d67a03eb BJ |
105 | */ |
106 | bp = bread(ip->i_dev, itod(ip->i_number)); | |
107 | dp = bp->b_un.b_dino; | |
108 | dp += itoo(ip->i_number); | |
109 | ds.st_atime = dp->di_atime; | |
110 | ds.st_mtime = dp->di_mtime; | |
111 | ds.st_ctime = dp->di_ctime; | |
112 | brelse(bp); | |
113 | if (copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0) | |
114 | u.u_error = EFAULT; | |
115 | } | |
116 | ||
117 | /* | |
5485e062 BJ |
118 | * Return target name of a symbolic link |
119 | */ | |
120 | readlink() | |
121 | { | |
122 | register struct inode *ip; | |
123 | register struct a { | |
124 | char *name; | |
125 | char *buf; | |
126 | int count; | |
127 | } *uap; | |
128 | ||
129 | ip = namei(uchar, 0, 0); | |
130 | if (ip == NULL) | |
131 | return; | |
132 | if ((ip->i_mode&IFMT) != IFLNK) { | |
133 | u.u_error = ENXIO; | |
134 | goto out; | |
135 | } | |
136 | uap = (struct a *)u.u_ap; | |
137 | u.u_offset = 0; | |
138 | u.u_base = uap->buf; | |
139 | u.u_count = uap->count; | |
140 | u.u_segflg = 0; | |
141 | readi(ip); | |
142 | out: | |
143 | iput(ip); | |
144 | u.u_r.r_val1 = uap->count - u.u_count; | |
145 | } | |
146 | ||
147 | /* | |
148 | * symlink -- make a symbolic link | |
149 | */ | |
150 | symlink() | |
151 | { | |
152 | register struct a { | |
153 | char *target; | |
154 | char *linkname; | |
155 | } *uap; | |
156 | register struct inode *ip; | |
157 | register char *tp; | |
158 | register c, nc; | |
159 | ||
160 | uap = (struct a *)u.u_ap; | |
161 | tp = uap->target; | |
162 | nc = 0; | |
163 | while (c = fubyte(tp)) { | |
164 | if (c < 0) { | |
165 | u.u_error = EFAULT; | |
166 | return; | |
167 | } | |
168 | tp++; | |
169 | nc++; | |
170 | } | |
171 | u.u_dirp = uap->linkname; | |
172 | ip = namei(uchar, 1, 0); | |
173 | if (ip) { | |
174 | iput(ip); | |
175 | u.u_error = EEXIST; | |
176 | return; | |
177 | } | |
178 | ip = maknode(IFLNK | 0777); | |
179 | if (ip == NULL) | |
180 | return; | |
181 | u.u_base = uap->target; | |
182 | u.u_count = nc; | |
183 | u.u_offset = 0; | |
184 | u.u_segflg = 0; | |
185 | writei(ip); | |
186 | iput(ip); | |
187 | } | |
188 | ||
189 | /* | |
190 | * the dup system call. | |
d67a03eb BJ |
191 | */ |
192 | dup() | |
193 | { | |
194 | register struct file *fp; | |
195 | register struct a { | |
196 | int fdes; | |
197 | int fdes2; | |
198 | } *uap; | |
199 | register i, m; | |
200 | ||
201 | uap = (struct a *)u.u_ap; | |
202 | m = uap->fdes & ~077; | |
203 | uap->fdes &= 077; | |
204 | fp = getf(uap->fdes); | |
e92a04af | 205 | if (fp == NULL) |
d67a03eb BJ |
206 | return; |
207 | if ((m&0100) == 0) { | |
208 | if ((i = ufalloc()) < 0) | |
209 | return; | |
210 | } else { | |
211 | i = uap->fdes2; | |
212 | if (i<0 || i>=NOFILE) { | |
213 | u.u_error = EBADF; | |
214 | return; | |
215 | } | |
d67a03eb BJ |
216 | u.u_r.r_val1 = i; |
217 | } | |
e92a04af | 218 | if (i != uap->fdes) { |
d67a03eb | 219 | if (u.u_ofile[i]!=NULL) |
f3156a73 BJ |
220 | closef(u.u_ofile[i], 0); |
221 | if (u.u_error) | |
222 | return; | |
d67a03eb BJ |
223 | u.u_ofile[i] = fp; |
224 | fp->f_count++; | |
225 | } | |
226 | } | |
227 | ||
228 | /* | |
e92a04af | 229 | * Mount system call. |
d67a03eb | 230 | */ |
e92a04af BJ |
231 | smount() |
232 | { | |
d67a03eb BJ |
233 | dev_t dev; |
234 | register struct inode *ip; | |
235 | register struct mount *mp; | |
236 | struct mount *smp; | |
237 | register struct filsys *fp; | |
238 | struct buf *bp; | |
239 | register struct a { | |
240 | char *fspec; | |
241 | char *freg; | |
242 | int ronly; | |
243 | } *uap; | |
1e608f17 | 244 | register char *cp; |
d67a03eb BJ |
245 | |
246 | uap = (struct a *)u.u_ap; | |
247 | dev = getmdev(); | |
e92a04af | 248 | if (u.u_error) |
d67a03eb BJ |
249 | return; |
250 | u.u_dirp = (caddr_t)uap->freg; | |
5485e062 | 251 | ip = namei(uchar, 0, 1); |
e92a04af | 252 | if (ip == NULL) |
d67a03eb | 253 | return; |
e92a04af | 254 | if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR) |
d67a03eb BJ |
255 | goto out; |
256 | smp = NULL; | |
e92a04af BJ |
257 | for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { |
258 | if (mp->m_bufp != NULL) { | |
259 | if (dev == mp->m_dev) | |
d67a03eb BJ |
260 | goto out; |
261 | } else | |
e92a04af | 262 | if (smp == NULL) |
d67a03eb BJ |
263 | smp = mp; |
264 | } | |
265 | mp = smp; | |
e92a04af | 266 | if (mp == NULL) |
d67a03eb BJ |
267 | goto out; |
268 | (*bdevsw[major(dev)].d_open)(dev, !uap->ronly); | |
e92a04af | 269 | if (u.u_error) |
d67a03eb BJ |
270 | goto out; |
271 | bp = bread(dev, SUPERB); | |
e92a04af | 272 | if (u.u_error) { |
d67a03eb BJ |
273 | brelse(bp); |
274 | goto out1; | |
275 | } | |
276 | mp->m_inodp = ip; | |
277 | mp->m_dev = dev; | |
2c3059b1 BJ |
278 | bp->b_flags |= B_LOCKED; |
279 | mp->m_bufp = bp; | |
280 | fp = bp->b_un.b_filsys; | |
d67a03eb BJ |
281 | fp->s_ilock = 0; |
282 | fp->s_flock = 0; | |
283 | fp->s_ronly = uap->ronly & 1; | |
284 | fp->s_nbehind = 0; | |
285 | fp->s_lasti = 1; | |
1e608f17 BJ |
286 | u.u_dirp = uap->freg; |
287 | for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; ) | |
288 | if ((*cp++ = uchar()) == 0) | |
289 | u.u_dirp--; /* get 0 again */ | |
290 | *cp = 0; | |
d67a03eb BJ |
291 | brelse(bp); |
292 | ip->i_flag |= IMOUNT; | |
e92a04af | 293 | irele(ip); |
d67a03eb BJ |
294 | return; |
295 | ||
296 | out: | |
297 | u.u_error = EBUSY; | |
298 | out1: | |
299 | iput(ip); | |
300 | } | |
301 | ||
302 | /* | |
303 | * the umount system call. | |
304 | */ | |
305 | sumount() | |
306 | { | |
307 | dev_t dev; | |
308 | register struct inode *ip; | |
309 | register struct mount *mp; | |
310 | struct buf *bp; | |
2c3059b1 | 311 | int stillopen, flag; |
d67a03eb BJ |
312 | register struct a { |
313 | char *fspec; | |
314 | }; | |
315 | ||
316 | dev = getmdev(); | |
e92a04af | 317 | if (u.u_error) |
d67a03eb BJ |
318 | return; |
319 | xumount(dev); /* remove unused sticky files from text table */ | |
68503f9a | 320 | update(0); |
e92a04af BJ |
321 | for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) |
322 | if (mp->m_bufp != NULL && dev == mp->m_dev) | |
d67a03eb BJ |
323 | goto found; |
324 | u.u_error = EINVAL; | |
325 | return; | |
326 | ||
327 | found: | |
9491f93d | 328 | stillopen = 0; |
e92a04af | 329 | for (ip = inode; ip < inodeNINODE; ip++) |
2c3059b1 | 330 | if (ip->i_number != 0 && dev == ip->i_dev) { |
d67a03eb BJ |
331 | u.u_error = EBUSY; |
332 | return; | |
2c3059b1 BJ |
333 | } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK && |
334 | ip->i_un.i_rdev == dev) | |
335 | stillopen++; | |
d67a03eb BJ |
336 | ip = mp->m_inodp; |
337 | ip->i_flag &= ~IMOUNT; | |
e92a04af | 338 | ilock(ip); |
d67a03eb | 339 | iput(ip); |
2c3059b1 BJ |
340 | if ((bp = getblk(dev, SUPERB)) != mp->m_bufp) |
341 | panic("umount"); | |
342 | bp->b_flags &= ~B_LOCKED; | |
4a18fb8e | 343 | flag = !bp->b_un.b_filsys->s_ronly; |
d67a03eb BJ |
344 | mp->m_bufp = NULL; |
345 | brelse(bp); | |
aa250f32 | 346 | mpurge(mp - &mount[0]); |
4a18fb8e | 347 | if (!stillopen) { |
4a18fb8e RE |
348 | (*bdevsw[major(dev)].d_close)(dev, flag); |
349 | binval(dev); | |
350 | } | |
d67a03eb BJ |
351 | } |
352 | ||
353 | /* | |
354 | * Common code for mount and umount. | |
355 | * Check that the user's argument is a reasonable | |
356 | * thing on which to mount, and return the device number if so. | |
357 | */ | |
358 | dev_t | |
359 | getmdev() | |
360 | { | |
361 | dev_t dev; | |
362 | register struct inode *ip; | |
363 | ||
d67a03eb BJ |
364 | if (!suser()) |
365 | return(NODEV); | |
5485e062 | 366 | ip = namei(uchar, 0, 1); |
e92a04af | 367 | if (ip == NULL) |
d67a03eb | 368 | return(NODEV); |
e92a04af | 369 | if ((ip->i_mode&IFMT) != IFBLK) |
d67a03eb BJ |
370 | u.u_error = ENOTBLK; |
371 | dev = (dev_t)ip->i_un.i_rdev; | |
e92a04af | 372 | if (major(dev) >= nblkdev) |
d67a03eb BJ |
373 | u.u_error = ENXIO; |
374 | iput(ip); | |
375 | return(dev); | |
376 | } |