Commit | Line | Data |
---|---|---|
32f555bf | 1 | /* ufs_vnops.c 4.20 82/03/16 */ |
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; | |
019b08c9 | 75 | stat1(ip, uap->sb); |
5485e062 BJ |
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 | } | |
32f555bf BJ |
178 | if (u.u_error) |
179 | return; | |
5485e062 BJ |
180 | ip = maknode(IFLNK | 0777); |
181 | if (ip == NULL) | |
182 | return; | |
183 | u.u_base = uap->target; | |
184 | u.u_count = nc; | |
185 | u.u_offset = 0; | |
186 | u.u_segflg = 0; | |
187 | writei(ip); | |
188 | iput(ip); | |
189 | } | |
190 | ||
191 | /* | |
192 | * the dup system call. | |
d67a03eb BJ |
193 | */ |
194 | dup() | |
195 | { | |
196 | register struct file *fp; | |
197 | register struct a { | |
198 | int fdes; | |
199 | int fdes2; | |
200 | } *uap; | |
201 | register i, m; | |
202 | ||
203 | uap = (struct a *)u.u_ap; | |
204 | m = uap->fdes & ~077; | |
205 | uap->fdes &= 077; | |
206 | fp = getf(uap->fdes); | |
e92a04af | 207 | if (fp == NULL) |
d67a03eb BJ |
208 | return; |
209 | if ((m&0100) == 0) { | |
210 | if ((i = ufalloc()) < 0) | |
211 | return; | |
212 | } else { | |
213 | i = uap->fdes2; | |
214 | if (i<0 || i>=NOFILE) { | |
215 | u.u_error = EBADF; | |
216 | return; | |
217 | } | |
d67a03eb BJ |
218 | u.u_r.r_val1 = i; |
219 | } | |
e92a04af | 220 | if (i != uap->fdes) { |
d67a03eb | 221 | if (u.u_ofile[i]!=NULL) |
f3156a73 BJ |
222 | closef(u.u_ofile[i], 0); |
223 | if (u.u_error) | |
224 | return; | |
d67a03eb BJ |
225 | u.u_ofile[i] = fp; |
226 | fp->f_count++; | |
227 | } | |
228 | } | |
229 | ||
230 | /* | |
e92a04af | 231 | * Mount system call. |
d67a03eb | 232 | */ |
e92a04af BJ |
233 | smount() |
234 | { | |
d67a03eb BJ |
235 | dev_t dev; |
236 | register struct inode *ip; | |
237 | register struct mount *mp; | |
238 | struct mount *smp; | |
239 | register struct filsys *fp; | |
240 | struct buf *bp; | |
241 | register struct a { | |
242 | char *fspec; | |
243 | char *freg; | |
244 | int ronly; | |
245 | } *uap; | |
1e608f17 | 246 | register char *cp; |
d67a03eb BJ |
247 | |
248 | uap = (struct a *)u.u_ap; | |
249 | dev = getmdev(); | |
e92a04af | 250 | if (u.u_error) |
d67a03eb BJ |
251 | return; |
252 | u.u_dirp = (caddr_t)uap->freg; | |
5485e062 | 253 | ip = namei(uchar, 0, 1); |
e92a04af | 254 | if (ip == NULL) |
d67a03eb | 255 | return; |
e92a04af | 256 | if (ip->i_count!=1 || (ip->i_mode&IFMT) != IFDIR) |
d67a03eb BJ |
257 | goto out; |
258 | smp = NULL; | |
e92a04af BJ |
259 | for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) { |
260 | if (mp->m_bufp != NULL) { | |
261 | if (dev == mp->m_dev) | |
d67a03eb BJ |
262 | goto out; |
263 | } else | |
e92a04af | 264 | if (smp == NULL) |
d67a03eb BJ |
265 | smp = mp; |
266 | } | |
267 | mp = smp; | |
e92a04af | 268 | if (mp == NULL) |
d67a03eb BJ |
269 | goto out; |
270 | (*bdevsw[major(dev)].d_open)(dev, !uap->ronly); | |
e92a04af | 271 | if (u.u_error) |
d67a03eb BJ |
272 | goto out; |
273 | bp = bread(dev, SUPERB); | |
e92a04af | 274 | if (u.u_error) { |
d67a03eb BJ |
275 | brelse(bp); |
276 | goto out1; | |
277 | } | |
278 | mp->m_inodp = ip; | |
279 | mp->m_dev = dev; | |
2c3059b1 BJ |
280 | bp->b_flags |= B_LOCKED; |
281 | mp->m_bufp = bp; | |
282 | fp = bp->b_un.b_filsys; | |
d67a03eb BJ |
283 | fp->s_ilock = 0; |
284 | fp->s_flock = 0; | |
285 | fp->s_ronly = uap->ronly & 1; | |
286 | fp->s_nbehind = 0; | |
287 | fp->s_lasti = 1; | |
1e608f17 BJ |
288 | u.u_dirp = uap->freg; |
289 | for (cp = fp->s_fsmnt; cp < &fp->s_fsmnt[sizeof (fp->s_fsmnt) - 1]; ) | |
290 | if ((*cp++ = uchar()) == 0) | |
291 | u.u_dirp--; /* get 0 again */ | |
292 | *cp = 0; | |
d67a03eb BJ |
293 | brelse(bp); |
294 | ip->i_flag |= IMOUNT; | |
e92a04af | 295 | irele(ip); |
d67a03eb BJ |
296 | return; |
297 | ||
298 | out: | |
299 | u.u_error = EBUSY; | |
300 | out1: | |
301 | iput(ip); | |
302 | } | |
303 | ||
304 | /* | |
305 | * the umount system call. | |
306 | */ | |
307 | sumount() | |
308 | { | |
309 | dev_t dev; | |
310 | register struct inode *ip; | |
311 | register struct mount *mp; | |
312 | struct buf *bp; | |
2c3059b1 | 313 | int stillopen, flag; |
d67a03eb BJ |
314 | register struct a { |
315 | char *fspec; | |
316 | }; | |
317 | ||
318 | dev = getmdev(); | |
e92a04af | 319 | if (u.u_error) |
d67a03eb BJ |
320 | return; |
321 | xumount(dev); /* remove unused sticky files from text table */ | |
68503f9a | 322 | update(0); |
e92a04af BJ |
323 | for (mp = &mount[0]; mp < &mount[NMOUNT]; mp++) |
324 | if (mp->m_bufp != NULL && dev == mp->m_dev) | |
d67a03eb BJ |
325 | goto found; |
326 | u.u_error = EINVAL; | |
327 | return; | |
328 | ||
329 | found: | |
9491f93d | 330 | stillopen = 0; |
e92a04af | 331 | for (ip = inode; ip < inodeNINODE; ip++) |
2c3059b1 | 332 | if (ip->i_number != 0 && dev == ip->i_dev) { |
d67a03eb BJ |
333 | u.u_error = EBUSY; |
334 | return; | |
2c3059b1 BJ |
335 | } else if (ip->i_number != 0 && (ip->i_mode&IFMT) == IFBLK && |
336 | ip->i_un.i_rdev == dev) | |
337 | stillopen++; | |
d67a03eb BJ |
338 | ip = mp->m_inodp; |
339 | ip->i_flag &= ~IMOUNT; | |
e92a04af | 340 | ilock(ip); |
d67a03eb | 341 | iput(ip); |
2c3059b1 BJ |
342 | if ((bp = getblk(dev, SUPERB)) != mp->m_bufp) |
343 | panic("umount"); | |
344 | bp->b_flags &= ~B_LOCKED; | |
4a18fb8e | 345 | flag = !bp->b_un.b_filsys->s_ronly; |
d67a03eb BJ |
346 | mp->m_bufp = NULL; |
347 | brelse(bp); | |
aa250f32 | 348 | mpurge(mp - &mount[0]); |
4a18fb8e | 349 | if (!stillopen) { |
4a18fb8e RE |
350 | (*bdevsw[major(dev)].d_close)(dev, flag); |
351 | binval(dev); | |
352 | } | |
d67a03eb BJ |
353 | } |
354 | ||
355 | /* | |
356 | * Common code for mount and umount. | |
357 | * Check that the user's argument is a reasonable | |
358 | * thing on which to mount, and return the device number if so. | |
359 | */ | |
360 | dev_t | |
361 | getmdev() | |
362 | { | |
363 | dev_t dev; | |
364 | register struct inode *ip; | |
365 | ||
d67a03eb BJ |
366 | if (!suser()) |
367 | return(NODEV); | |
5485e062 | 368 | ip = namei(uchar, 0, 1); |
e92a04af | 369 | if (ip == NULL) |
d67a03eb | 370 | return(NODEV); |
e92a04af | 371 | if ((ip->i_mode&IFMT) != IFBLK) |
d67a03eb BJ |
372 | u.u_error = ENOTBLK; |
373 | dev = (dev_t)ip->i_un.i_rdev; | |
e92a04af | 374 | if (major(dev) >= nblkdev) |
d67a03eb BJ |
375 | u.u_error = ENXIO; |
376 | iput(ip); | |
377 | return(dev); | |
378 | } |