Commit | Line | Data |
---|---|---|
c03d82b0 SB |
1 | /* |
2 | * | |
3 | * | |
4 | * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE | |
5 | * -------------------- ----- ---------------------- | |
6 | * CURRENT PATCH LEVEL: 1 00040 | |
7 | * -------------------- ----- ---------------------- | |
8 | * | |
9 | * 10 Aug 92 Scott Burris Fixed "delete from CD-ROM" bug | |
10 | */ | |
868e813d WJ |
11 | #include "param.h" |
12 | #include "systm.h" | |
13 | #include "namei.h" | |
14 | #include "resourcevar.h" | |
15 | #include "kernel.h" | |
16 | #include "file.h" | |
17 | #include "stat.h" | |
18 | #include "buf.h" | |
19 | #include "proc.h" | |
20 | #include "conf.h" | |
21 | #include "mount.h" | |
22 | #include "vnode.h" | |
23 | #include "specdev.h" | |
24 | #include "fifo.h" | |
25 | #include "malloc.h" | |
26 | #include "dir.h" | |
27 | ||
28 | #include "iso.h" | |
29 | #include "isofs_node.h" | |
30 | ||
31 | /* | |
32 | * Open called. | |
33 | * | |
34 | * Nothing to do. | |
35 | */ | |
36 | /* ARGSUSED */ | |
37 | isofs_open(vp, mode, cred, p) | |
38 | struct vnode *vp; | |
39 | int mode; | |
40 | struct ucred *cred; | |
41 | struct proc *p; | |
42 | { | |
43 | return (0); | |
44 | } | |
45 | ||
46 | /* | |
47 | * Close called | |
48 | * | |
49 | * Update the times on the inode on writeable file systems. | |
50 | */ | |
51 | /* ARGSUSED */ | |
52 | isofs_close(vp, fflag, cred, p) | |
53 | struct vnode *vp; | |
54 | int fflag; | |
55 | struct ucred *cred; | |
56 | struct proc *p; | |
57 | { | |
58 | return (0); | |
59 | } | |
60 | ||
61 | /* | |
62 | * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. | |
63 | * The mode is shifted to select the owner/group/other fields. The | |
64 | * super user is granted all permissions. | |
65 | */ | |
66 | isofs_access(vp, mode, cred, p) | |
67 | struct vnode *vp; | |
68 | register int mode; | |
69 | struct ucred *cred; | |
70 | struct proc *p; | |
71 | { | |
72 | return (0); | |
73 | } | |
74 | ||
75 | /* ARGSUSED */ | |
76 | isofs_getattr(vp, vap, cred, p) | |
77 | struct vnode *vp; | |
78 | register struct vattr *vap; | |
79 | struct ucred *cred; | |
80 | struct proc *p; | |
81 | { | |
82 | register struct iso_node *ip = VTOI(vp); | |
83 | int year, month, day, hour ,minute, second, tz; | |
84 | int crtime, days; | |
85 | int i; | |
86 | ||
87 | year = ip->iso_time[0] - 70; | |
88 | month = ip->iso_time[1]; | |
89 | day = ip->iso_time[2]; | |
90 | hour = ip->iso_time[3]; | |
91 | minute = ip->iso_time[4]; | |
92 | second = ip->iso_time[5]; | |
93 | tz = ip->iso_time[6]; | |
94 | ||
95 | if (year < 0) { | |
96 | crtime = 0; | |
97 | } else { | |
98 | int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; | |
99 | days = year * 365; | |
100 | if (year > 2) | |
101 | days += (year+2) / 4; | |
102 | for (i = 1; i < month; i++) | |
103 | days += monlen[i-1]; | |
104 | if (((year+2) % 4) == 0 && month > 2) | |
105 | days++; | |
106 | days += day - 1; | |
107 | crtime = ((((days * 24) + hour) * 60 + minute) * 60) | |
108 | + second; | |
109 | ||
110 | /* sign extend */ | |
111 | if (tz & 0x80) | |
112 | tz |= (-1 << 8); | |
113 | ||
114 | /* timezone offset is unreliable on some disks */ | |
115 | if (-48 <= tz && tz <= 52) | |
116 | crtime += tz * 15 * 60; | |
117 | } | |
118 | ||
119 | vap->va_fsid = ip->i_dev; | |
120 | vap->va_fileid = ip->i_number; | |
121 | vap->va_mode = VREAD|VEXEC; | |
122 | vap->va_mode |= (vap->va_mode >> 3) | (vap->va_mode >> 6); | |
123 | if (vp->v_type == VDIR) | |
124 | vap->va_nlink = 2; | |
125 | else | |
126 | vap->va_nlink = 1; | |
127 | vap->va_uid = 0; | |
128 | vap->va_gid = 0; | |
129 | vap->va_rdev = 0; | |
130 | vap->va_size = ip->i_size; | |
131 | vap->va_size_rsv = 0; | |
132 | vap->va_atime.tv_sec = crtime; | |
133 | vap->va_atime.tv_usec = 0; | |
134 | vap->va_mtime.tv_sec = crtime; | |
135 | vap->va_mtime.tv_usec = 0; | |
136 | vap->va_ctime.tv_sec = crtime; | |
137 | vap->va_ctime.tv_usec = 0; | |
138 | vap->va_flags = 0; | |
139 | vap->va_gen = 1; | |
140 | vap->va_blocksize = ip->i_mnt->logical_block_size; | |
141 | vap->va_bytes = ip->i_size; | |
142 | vap->va_bytes_rsv = 0; | |
143 | vap->va_type = vp->v_type; | |
144 | return (0); | |
145 | } | |
146 | ||
147 | /* | |
148 | * Vnode op for reading. | |
149 | */ | |
150 | /* ARGSUSED */ | |
151 | isofs_read(vp, uio, ioflag, cred) | |
152 | struct vnode *vp; | |
153 | register struct uio *uio; | |
154 | int ioflag; | |
155 | struct ucred *cred; | |
156 | { | |
157 | register struct iso_node *ip = VTOI(vp); | |
158 | register struct iso_mnt *imp; | |
159 | struct buf *bp; | |
160 | daddr_t lbn, bn, rablock; | |
161 | int size, diff, error = 0; | |
162 | long n, on, type; | |
163 | ||
164 | #ifdef DIAGNOSTICx | |
165 | if (uio->uio_rw != UIO_READ) | |
166 | panic("isofs_read mode"); | |
167 | type = ip->i_mode & IFMT; | |
168 | if (type != IFDIR && type != IFREG && type != IFLNK) | |
169 | panic("isofs_read type"); | |
170 | #endif | |
171 | if (uio->uio_resid == 0) | |
172 | return (0); | |
173 | if (uio->uio_offset < 0) | |
174 | return (EINVAL); | |
175 | ip->i_flag |= IACC; | |
176 | imp = ip->i_mnt; | |
177 | do { | |
178 | lbn = iso_lblkno(imp, uio->uio_offset); | |
179 | on = iso_blkoff(imp, uio->uio_offset); | |
180 | n = MIN((unsigned)(imp->im_bsize - on), uio->uio_resid); | |
181 | diff = ip->i_size - uio->uio_offset; | |
182 | if (diff <= 0) | |
183 | return (0); | |
184 | if (diff < n) | |
185 | n = diff; | |
186 | size = iso_blksize(imp, ip, lbn); | |
187 | rablock = lbn + 1; | |
188 | if (vp->v_lastr + 1 == lbn && | |
189 | iso_lblktosize(imp, rablock) < ip->i_size) | |
190 | error = breada(ITOV(ip), lbn, size, rablock, | |
191 | iso_blksize(imp, ip, rablock), NOCRED, &bp); | |
192 | else | |
193 | error = bread(ITOV(ip), lbn, size, NOCRED, &bp); | |
194 | vp->v_lastr = lbn; | |
195 | n = MIN(n, size - bp->b_resid); | |
196 | if (error) { | |
197 | brelse(bp); | |
198 | return (error); | |
199 | } | |
200 | ||
201 | error = uiomove(bp->b_un.b_addr + on, (int)n, uio); | |
202 | if (n + on == imp->im_bsize || uio->uio_offset == ip->i_size) | |
203 | bp->b_flags |= B_AGE; | |
204 | brelse(bp); | |
205 | } while (error == 0 && uio->uio_resid > 0 && n != 0); | |
206 | return (error); | |
207 | } | |
208 | ||
209 | /* ARGSUSED */ | |
210 | isofs_ioctl(vp, com, data, fflag, cred, p) | |
211 | struct vnode *vp; | |
212 | int com; | |
213 | caddr_t data; | |
214 | int fflag; | |
215 | struct ucred *cred; | |
216 | struct proc *p; | |
217 | { | |
218 | return (ENOTTY); | |
219 | } | |
220 | ||
221 | /* ARGSUSED */ | |
222 | isofs_select(vp, which, fflags, cred, p) | |
223 | struct vnode *vp; | |
224 | int which, fflags; | |
225 | struct ucred *cred; | |
226 | struct proc *p; | |
227 | { | |
228 | ||
229 | /* | |
230 | * We should really check to see if I/O is possible. | |
231 | */ | |
232 | return (1); | |
233 | } | |
234 | ||
235 | /* | |
236 | * Mmap a file | |
237 | * | |
238 | * NB Currently unsupported. | |
239 | */ | |
240 | /* ARGSUSED */ | |
241 | isofs_mmap(vp, fflags, cred, p) | |
242 | struct vnode *vp; | |
243 | int fflags; | |
244 | struct ucred *cred; | |
245 | struct proc *p; | |
246 | { | |
247 | ||
248 | return (EINVAL); | |
249 | } | |
250 | ||
251 | /* | |
252 | * Seek on a file | |
253 | * | |
254 | * Nothing to do, so just return. | |
255 | */ | |
256 | /* ARGSUSED */ | |
257 | isofs_seek(vp, oldoff, newoff, cred) | |
258 | struct vnode *vp; | |
259 | off_t oldoff, newoff; | |
260 | struct ucred *cred; | |
261 | { | |
262 | ||
263 | return (0); | |
264 | } | |
265 | ||
266 | /* | |
267 | * Vnode op for readdir | |
268 | */ | |
269 | isofs_readdir(vp, uio, cred, eofflagp) | |
270 | struct vnode *vp; | |
271 | register struct uio *uio; | |
272 | struct ucred *cred; | |
273 | int *eofflagp; | |
274 | { | |
275 | struct dirent dirent; | |
276 | int iso_offset; | |
277 | int entryoffsetinblock; | |
278 | int error = 0; | |
279 | int endsearch; | |
280 | struct iso_directory_record *ep; | |
281 | int reclen; | |
282 | struct iso_mnt *imp; | |
283 | struct iso_node *ip; | |
284 | struct buf *bp = NULL; | |
285 | int i; | |
286 | int end_flag = 0; | |
287 | ||
288 | ip = VTOI (vp); | |
289 | imp = ip->i_mnt; | |
290 | ||
291 | iso_offset = uio->uio_offset; | |
292 | ||
293 | entryoffsetinblock = iso_blkoff(imp, iso_offset); | |
294 | if (entryoffsetinblock != 0) { | |
295 | if (error = iso_blkatoff(ip, iso_offset, (char **)0, &bp)) | |
296 | return (error); | |
297 | } | |
298 | ||
299 | endsearch = ip->i_size; | |
300 | ||
301 | while (iso_offset < endsearch && uio->uio_resid > 0) { | |
302 | /* | |
303 | * If offset is on a block boundary, | |
304 | * read the next directory block. | |
305 | * Release previous if it exists. | |
306 | */ | |
307 | ||
308 | if (iso_blkoff(imp, iso_offset) == 0) { | |
309 | if (bp != NULL) | |
310 | brelse(bp); | |
311 | if (error = iso_blkatoff(ip, iso_offset, | |
312 | (char **)0, &bp)) | |
313 | return (error); | |
314 | entryoffsetinblock = 0; | |
315 | } | |
316 | /* | |
317 | * Get pointer to next entry. | |
318 | */ | |
319 | ||
320 | ep = (struct iso_directory_record *) | |
321 | (bp->b_un.b_addr + entryoffsetinblock); | |
322 | ||
323 | reclen = isonum_711 (ep->length); | |
324 | if (reclen == 0) { | |
325 | /* skip to next block, if any */ | |
326 | iso_offset = roundup (iso_offset, | |
327 | imp->logical_block_size); | |
328 | continue; | |
329 | } | |
330 | ||
331 | if (reclen < sizeof (struct iso_directory_record)) | |
332 | /* illegal entry, stop */ | |
333 | break; | |
334 | ||
c03d82b0 | 335 | /* 10 Aug 92*/ if (entryoffsetinblock + reclen -1 >= imp->logical_block_size) |
868e813d WJ |
336 | /* illegal directory, so stop looking */ |
337 | break; | |
338 | ||
339 | dirent.d_fileno = isonum_733 (ep->extent); | |
340 | dirent.d_namlen = isonum_711 (ep->name_len); | |
341 | ||
342 | if (reclen < sizeof (struct iso_directory_record) | |
343 | + dirent.d_namlen) | |
344 | /* illegal entry, stop */ | |
345 | break; | |
346 | ||
347 | /*bcopy (ep->name, dirent.d_name, dirent.d_namlen);*/ | |
348 | isofntrans(ep->name, dirent.d_namlen, | |
349 | dirent.d_name, &dirent.d_namlen); | |
350 | if (dirent.d_namlen == 1) { | |
351 | switch (dirent.d_name[0]) { | |
352 | case 0: | |
353 | dirent.d_name[0] = '.'; | |
354 | break; | |
355 | case 1: | |
356 | dirent.d_name[0] = '.'; | |
357 | dirent.d_name[1] = '.'; | |
358 | dirent.d_namlen = 2; | |
359 | } | |
360 | } | |
361 | dirent.d_name[dirent.d_namlen] = 0; | |
362 | dirent.d_reclen = DIRSIZ (&dirent); | |
363 | ||
364 | if (uio->uio_resid < dirent.d_reclen) | |
365 | break; | |
366 | ||
367 | if (error = uiomove (&dirent, dirent.d_reclen, uio)) | |
368 | break; | |
369 | ||
370 | iso_offset += reclen; | |
371 | entryoffsetinblock += reclen; | |
372 | } | |
373 | ||
374 | if (bp) | |
375 | brelse (bp); | |
376 | ||
377 | if (end_flag || (VTOI(vp)->i_size - iso_offset) <= 0) | |
378 | *eofflagp = 1; | |
379 | else | |
380 | *eofflagp = 0; | |
381 | ||
382 | uio->uio_offset = iso_offset; | |
383 | ||
384 | return (error); | |
385 | } | |
386 | ||
387 | /* | |
388 | * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually | |
389 | * done. If a buffer has been saved in anticipation of a CREATE, delete it. | |
390 | */ | |
391 | /* ARGSUSED */ | |
392 | isofs_abortop(ndp) | |
393 | struct nameidata *ndp; | |
394 | { | |
395 | ||
396 | if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF) | |
397 | FREE(ndp->ni_pnbuf, M_NAMEI); | |
398 | return (0); | |
399 | } | |
400 | ||
401 | /* | |
402 | * Lock an inode. | |
403 | */ | |
404 | isofs_lock(vp) | |
405 | struct vnode *vp; | |
406 | { | |
407 | register struct iso_node *ip = VTOI(vp); | |
408 | ||
409 | ISO_ILOCK(ip); | |
410 | return (0); | |
411 | } | |
412 | ||
413 | /* | |
414 | * Unlock an inode. | |
415 | */ | |
416 | isofs_unlock(vp) | |
417 | struct vnode *vp; | |
418 | { | |
419 | register struct iso_node *ip = VTOI(vp); | |
420 | ||
421 | if (!(ip->i_flag & ILOCKED)) | |
422 | panic("isofs_unlock NOT LOCKED"); | |
423 | ISO_IUNLOCK(ip); | |
424 | return (0); | |
425 | } | |
426 | ||
427 | /* | |
428 | * Check for a locked inode. | |
429 | */ | |
430 | isofs_islocked(vp) | |
431 | struct vnode *vp; | |
432 | { | |
433 | ||
434 | if (VTOI(vp)->i_flag & ILOCKED) | |
435 | return (1); | |
436 | return (0); | |
437 | } | |
438 | ||
439 | /* | |
440 | * Calculate the logical to physical mapping if not done already, | |
441 | * then call the device strategy routine. | |
442 | */ | |
443 | ||
444 | isofs_strategy(bp) | |
445 | register struct buf *bp; | |
446 | { | |
447 | register struct iso_node *ip = VTOI(bp->b_vp); | |
448 | struct vnode *vp; | |
449 | int error; | |
450 | ||
451 | if (bp->b_vp->v_type == VBLK || bp->b_vp->v_type == VCHR) | |
452 | panic("isofs_strategy: spec"); | |
453 | if (bp->b_blkno == bp->b_lblkno) { | |
454 | if (error = iso_bmap(ip, bp->b_lblkno, &bp->b_blkno)) | |
455 | return (error); | |
456 | if ((long)bp->b_blkno == -1) | |
457 | clrbuf(bp); | |
458 | } | |
459 | if ((long)bp->b_blkno == -1) { | |
460 | biodone(bp); | |
461 | return (0); | |
462 | } | |
463 | vp = ip->i_devvp; | |
464 | bp->b_dev = vp->v_rdev; | |
465 | (*(vp->v_op->vop_strategy))(bp); | |
466 | return (0); | |
467 | } | |
468 | ||
469 | /* | |
470 | * Print out the contents of an inode. | |
471 | */ | |
472 | isofs_print(vp) | |
473 | struct vnode *vp; | |
474 | { | |
475 | printf ("isoprint\n"); | |
476 | } | |
477 | ||
478 | extern int enodev (); | |
479 | ||
480 | /* | |
481 | * Global vfs data structures for isofs | |
482 | */ | |
483 | struct vnodeops isofs_vnodeops = { | |
484 | isofs_lookup, /* lookup */ | |
485 | (void *)enodev, /* create */ | |
486 | (void *)enodev, /* mknod */ | |
487 | isofs_open, /* open */ | |
488 | isofs_close, /* close */ | |
489 | isofs_access, /* access */ | |
490 | isofs_getattr, /* getattr */ | |
491 | (void *)enodev, /* setattr */ | |
492 | isofs_read, /* read */ | |
493 | (void *)enodev, /* write */ | |
494 | isofs_ioctl, /* ioctl */ | |
495 | isofs_select, /* select */ | |
496 | isofs_mmap, /* mmap */ | |
497 | (void *)nullop, /* fsync */ | |
498 | isofs_seek, /* seek */ | |
499 | (void *)enodev, /* remove */ | |
500 | (void *)enodev, /* link */ | |
501 | (void *)enodev, /* rename */ | |
502 | (void *)enodev, /* mkdir */ | |
503 | (void *)enodev, /* rmdir */ | |
504 | (void *)enodev, /* symlink */ | |
505 | isofs_readdir, /* readdir */ | |
506 | (void *)enodev, /* readlink */ | |
507 | isofs_abortop, /* abortop */ | |
508 | isofs_inactive, /* inactive */ | |
509 | isofs_reclaim, /* reclaim */ | |
510 | isofs_lock, /* lock */ | |
511 | isofs_unlock, /* unlock */ | |
512 | (void *)enodev, /* bmap */ | |
513 | isofs_strategy, /* strategy */ | |
514 | isofs_print, /* print */ | |
515 | isofs_islocked, /* islocked */ | |
516 | (void *)enodev, /* advlock */ | |
517 | }; | |
518 | ||
519 |