1 /*
2 * $Id: $
3 */
4 #include "sys/param.h"
5 #include "systm.h"
6 #include "kernel.h"
7 #include "sys/file.h"
8 #include "sys/stat.h"
9 #include "sys/errno.h"
10 #include "buf.h"
11 #include "proc.h"
12 #include "resourcevar.h"
13 #include "sys/mount.h"
14 #include "uio.h"
15 #include "namei.h"
16 #include "vnode.h"
17 #include "specdev.h"
18 #include "fifo.h"
19 #include "malloc.h"
20 #include "sys/dir.h"
21 #include "prototypes.h"
22
23 #include "iso.h"
24 #include "isofs_node.h"
25 #include "iso_rrip.h"
26
27 /*
28 * Open called.
29 *
30 * Nothing to do.
31 */
32 /* ARGSUSED */
33 isofs_open(vp, mode, cred, p)
34 struct vnode *vp;
35 int mode;
36 struct ucred *cred;
37 struct proc *p;
38 {
39 return (0);
40 }
41
42 /*
43 * Close called
44 *
45 * Update the times on the inode on writeable file systems.
46 */
47 /* ARGSUSED */
48 isofs_close(vp, fflag, cred, p)
49 struct vnode *vp;
50 int fflag;
51 struct ucred *cred;
52 struct proc *p;
53 {
54 return (0);
55 }
56
57 /*
58 * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
59 * The mode is shifted to select the owner/group/other fields. The
60 * super user is granted all permissions.
61 */
62 isofs_access(vp, mode, cred, p)
63 struct vnode *vp;
64 register int mode;
65 struct ucred *cred;
66 struct proc *p;
67 {
68 return (0);
69 }
70
71 /* ARGSUSED */
72 isofs_getattr(vp, vap, cred, p)
73 struct vnode *vp;
74 register struct vattr *vap;
75 struct ucred *cred;
76 struct proc *p;
77 {
78 register struct iso_node *ip = VTOI(vp);
79 int i;
80
81 vap->va_fsid = ip->i_dev;
82 vap->va_fileid = ip->i_number;
83 /*if (vp->v_type == VDIR)
84 vap->va_nlink = 2;
85 else
86 vap->va_nlink = 1; */
87
88 vap->va_nlink = ip->inode.iso_links;
89 vap->va_mode = ip->inode.iso_mode;
90 /*printf("getattr mode %x ", vap->va_mode);*/
91 vap->va_uid = ip->inode.iso_uid;
92 vap->va_gid = ip->inode.iso_gid;
93 vap->va_atime= ip->inode.iso_atime;
94 vap->va_mtime= ip->inode.iso_mtime;
95 vap->va_ctime= ip->inode.iso_ctime;
96
97 vap->va_rdev = ip->inode.iso_dev;
98 vap->va_size = ip->i_size;
99 vap->va_size_rsv = 0;
100 vap->va_flags = 0;
101 vap->va_gen = 1;
102 vap->va_blocksize = ip->i_mnt->logical_block_size;
103 vap->va_bytes = ip->i_size;
104 vap->va_bytes_rsv = 0;
105 vap->va_type = vp->v_type;
106 return (0);
107 }
108
109 /*
110 * Vnode op for reading.
111 */
112 /* ARGSUSED */
113 isofs_read(vp, uio, ioflag, cred)
114 struct vnode *vp;
115 register struct uio *uio;
116 int ioflag;
117 struct ucred *cred;
118 {
119 register struct iso_node *ip = VTOI(vp);
120 register struct iso_mnt *imp;
121 struct buf *bp;
122 daddr_t lbn, bn, rablock;
123 int size, diff, error = 0;
124 long n, on, type;
125
126 #ifdef DIAGNOSTICx
127 if (uio->uio_rw != UIO_READ)
128 panic("isofs_read mode");
129 type = ip->i_mode & IFMT;
130 if (type != IFDIR && type != IFREG && type != IFLNK)
131 panic("isofs_read type");
132 #endif
133 if (uio->uio_resid == 0)
134 return (0);
135 if (uio->uio_offset < 0)
136 return (EINVAL);
137 ip->i_flag |= IACC;
138 imp = ip->i_mnt;
139 do {
140 lbn = iso_lblkno(imp, uio->uio_offset);
141 on = iso_blkoff(imp, uio->uio_offset);
142 n = min((unsigned)(imp->im_bsize - on), uio->uio_resid);
143 diff = ip->i_size - uio->uio_offset;
144 if (diff <= 0)
145 return (0);
146 if (diff < n)
147 n = diff;
148 size = iso_blksize(imp, ip, lbn);
149 rablock = lbn + 1;
150 if (vp->v_lastr + 1 == lbn &&
151 iso_lblktosize(imp, rablock) < ip->i_size)
152 error = breada(ITOV(ip), lbn, size, rablock,
153 iso_blksize(imp, ip, rablock), NOCRED, &bp);
154 else
155 error = bread(ITOV(ip), lbn, size, NOCRED, &bp);
156 vp->v_lastr = lbn;
157 n = min(n, size - bp->b_resid);
158 if (error) {
159 brelse(bp);
160 return (error);
161 }
162
163 error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
164 if (n + on == imp->im_bsize || uio->uio_offset == ip->i_size)
165 bp->b_flags |= B_AGE;
166 brelse(bp);
167 } while (error == 0 && uio->uio_resid > 0 && n != 0);
168 return (error);
169 }
170
171 /* ARGSUSED */
172 isofs_ioctl(vp, com, data, fflag, cred, p)
173 struct vnode *vp;
174 int com;
175 caddr_t data;
176 int fflag;
177 struct ucred *cred;
178 struct proc *p;
179 {
180 return (ENOTTY);
181 }
182
183 /* ARGSUSED */
184 isofs_select(vp, which, fflags, cred, p)
185 struct vnode *vp;
186 int which, fflags;
187 struct ucred *cred;
188 struct proc *p;
189 {
190
191 /*
192 * We should really check to see if I/O is possible.
193 */
194 return (1);
195 }
196
197 /*
198 * Mmap a file
199 *
200 * NB Currently unsupported.
201 */
202 /* ARGSUSED */
203 isofs_mmap(vp, fflags, cred, p)
204 struct vnode *vp;
205 int fflags;
206 struct ucred *cred;
207 struct proc *p;
208 {
209
210 return (EINVAL);
211 }
212
213 /*
214 * Seek on a file
215 *
216 * Nothing to do, so just return.
217 */
218 /* ARGSUSED */
219 isofs_seek(vp, oldoff, newoff, cred)
220 struct vnode *vp;
221 off_t oldoff, newoff;
222 struct ucred *cred;
223 {
224
225 return (0);
226 }
227
228 /*
229 * Vnode op for readdir
230 */
231 isofs_readdir(vp, uio, cred, eofflagp)
232 struct vnode *vp;
233 register struct uio *uio;
234 struct ucred *cred;
235 int *eofflagp;
236 {
237 struct dirent dirent;
238 int iso_offset;
239 int entryoffsetinblock;
240 int error = 0;
241 int endsearch;
242 struct iso_directory_record *ep;
243 int reclen;
244 struct iso_mnt *imp;
245 struct iso_node *ip;
246 struct buf *bp = NULL;
247 int i;
248 int end_flag = 0;
249 ISO_RRIP_ANALYZE ana;
250
251 ip = VTOI (vp);
252 imp = ip->i_mnt;
253
254 iso_offset = uio->uio_offset;
255
256 entryoffsetinblock = iso_blkoff(imp, iso_offset);
257 if (entryoffsetinblock != 0) {
258 if (error = iso_blkatoff(ip, iso_offset, (char **)0, &bp))
259 return (error);
260 }
261
262 endsearch = ip->i_size;
263
264 while (iso_offset < endsearch && uio->uio_resid > 0) {
265 /*
266 * If offset is on a block boundary,
267 * read the next directory block.
268 * Release previous if it exists.
269 */
270
271 if (iso_blkoff(imp, iso_offset) == 0) {
272 if (bp != NULL)
273 brelse(bp);
274 if (error = iso_blkatoff(ip, iso_offset,
275 (char **)0, &bp))
276 return (error);
277 entryoffsetinblock = 0;
278 }
279 /*
280 * Get pointer to next entry.
281 */
282
283 ep = (struct iso_directory_record *)
284 (bp->b_un.b_addr + entryoffsetinblock);
285
286 reclen = isonum_711 (ep->length);
287 if (reclen == 0) {
288 /* skip to next block, if any */
289 iso_offset = roundup (iso_offset,
290 imp->logical_block_size);
291 continue;
292 }
293
294 if (reclen < sizeof (struct iso_directory_record))
295 /* illegal entry, stop */
296 break;
297
298 /* 10 Aug 92*/ if (entryoffsetinblock + reclen -1 >= imp->logical_block_size)
299 /* illegal directory, so stop looking */
300 break;
301
302 /*
303 * if a directory, fake inode number on extent, otherwise
304 * make unique with entry offset
305 */
306 if(ep->flags[0] & 2)
307 dirent.d_fileno = iso_lblktosize(imp, isonum_733 (ep->extent));
308 else
309 dirent.d_fileno = iso_lblktosize(imp, isonum_733 (ep->extent))
310 + entryoffsetinblock;
311
312 dirent.d_namlen = isonum_711 (ep->name_len);
313
314 if (reclen < sizeof (struct iso_directory_record)
315 + dirent.d_namlen)
316 /* illegal entry, stop */
317 break;
318
319 /*
320 *
321 */
322 switch (ep->name[0]) {
323 case 0:
324 dirent.d_name[0] = '.';
325 dirent.d_namlen = 1;
326 break;
327 case 1:
328 dirent.d_name[0] = '.';
329 dirent.d_name[1] = '.';
330 dirent.d_namlen = 2;
331 break;
332 default:
333 switch ( imp->iso_ftype ) {
334 case ISO_FTYPE_RRIP:
335 isofs_rrip_getname( ep, dirent.d_name, &dirent.d_namlen );
336 break;
337 case ISO_FTYPE_9660:
338 isofntrans(ep->name, dirent.d_namlen, dirent.d_name, &dirent.d_namlen);
339 break;
340 default:
341 break;
342 }
343 break;
344 }
345
346 dirent.d_name[dirent.d_namlen] = 0;
347 dirent.d_reclen = DIRSIZ (&dirent);
348
349 if (uio->uio_resid < dirent.d_reclen)
350 break;
351
352 if (error = uiomove (&dirent, dirent.d_reclen, uio))
353 break;
354
355 iso_offset += reclen;
356 entryoffsetinblock += reclen;
357 }
358
359 if (bp)
360 brelse (bp);
361
362 if (end_flag || (VTOI(vp)->i_size - iso_offset) <= 0)
363 *eofflagp = 1;
364 else
365 *eofflagp = 0;
366
367 uio->uio_offset = iso_offset;
368
369 return (error);
370 }
371
372 /*
373 * Return target name of a symbolic link
374 */
375 typedef struct iso_directory_record ISODIR;
376 typedef struct iso_node ISONODE;
377 typedef struct iso_mnt ISOMNT;
isofs_readlink(vp,uio,cred)378 int isofs_readlink(vp, uio, cred)
379 struct vnode *vp;
380 struct uio *uio;
381 struct ucred *cred;
382 {
383 ISONODE *ip;
384 ISODIR *dirp;
385 ISOMNT *imp;
386 struct buf *bp;
387 int symlen;
388 int error, rv;
389
390 ip = VTOI( vp );
391 #ifdef nope
392 char symname[NAME_MAX];
393 imp = ip->i_mnt;
394 /*printf("readlink mode %x ", ip->inode.iso_mode);*/
395 /*
396 * Get parents directory record block that this inode included.
397 */
398 error = bread( imp->im_devvp,
399 (daddr_t)(( ip->iso_parent_ext + (ip->iso_parent >> 11 ) )
400 * imp->im_bsize / DEV_BSIZE ),
401 imp->im_bsize,
402 NOCRED,
403 &bp );
404 if ( error ) {
405 return( EINVAL );
406 }
407
408 /*
409 * Setup the directory pointer for this inode
410 */
411
412 dirp = (ISODIR *)(bp->b_un.b_addr + ( ip->iso_parent & 0x7ff ) );
413 #ifdef DEBUG
414 printf("lbn=%d[base=%d,off=%d,bsize=%d,DEV_BSIZE=%d], dirp= %08x, b_addr=%08x, offset=%08x(%08x)\n",
415 (daddr_t)(( ip->iso_parent_ext + (ip->iso_parent >> 12 ) ) * imp->im_bsize / DEV_BSIZE ),
416 ip->iso_parent_ext,
417 (ip->iso_parent >> 11 ),
418 imp->im_bsize,
419 DEV_BSIZE,
420 dirp,
421 bp->b_un.b_addr,
422 ip->iso_parent,
423 ip->iso_parent & 0x7ff );
424 #endif
425
426 /*
427 * Just make sure, we have a right one....
428 * 1: Check not cross boundary on block
429 * 2: Check number of inode
430 */
431 if ( (ip->iso_parent & 0x7ff) + isonum_711( dirp->length ) >=
432 imp->im_bsize ) {
433 brelse ( bp );
434 return( EINVAL );
435 }
436 /*if ( isonum_733(dirp->extent) != ip->i_number ) {
437 brelse ( bp );
438 return( EINVAL );
439 }*/
440
441 /*
442 * Ok, we just gathering a Symbolick name in SL record.
443 */
444 rv = isofs_rrip_getsymname(vp, dirp, symname, &symlen);
445 brelse (bp);
446
447 if (rv == 0)
448 return( EINVAL );
449
450 /*
451 * return with the Symbolic name to caller's.
452 */
453 return ( uiomove( symname, symlen, uio ) );
454 #else
455 if(ip->iso_sl == 0)
456 return(EINVAL);
457 else
458 return ( uiomove( ip->iso_sl, ip->iso_sl_len, uio ) );
459 #endif
460 }
461
462 /*
463 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
464 * done. If a buffer has been saved in anticipation of a CREATE, delete it.
465 */
466 /* ARGSUSED */
467 isofs_abortop(ndp)
468 struct nameidata *ndp;
469 {
470
471 if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
472 FREE(ndp->ni_pnbuf, M_NAMEI);
473 return (0);
474 }
475
476 /*
477 * Lock an inode.
478 */
479 isofs_lock(vp)
480 struct vnode *vp;
481 {
482 register struct iso_node *ip = VTOI(vp);
483
484 ISO_ILOCK(ip);
485 return (0);
486 }
487
488 /*
489 * Unlock an inode.
490 */
491 isofs_unlock(vp)
492 struct vnode *vp;
493 {
494 register struct iso_node *ip = VTOI(vp);
495
496 if (!(ip->i_flag & ILOCKED))
497 panic("isofs_unlock NOT LOCKED");
498 ISO_IUNLOCK(ip);
499 return (0);
500 }
501
502 /*
503 * Check for a locked inode.
504 */
505 isofs_islocked(vp)
506 struct vnode *vp;
507 {
508
509 if (VTOI(vp)->i_flag & ILOCKED)
510 return (1);
511 return (0);
512 }
513
514 /*
515 * Calculate the logical to physical mapping if not done already,
516 * then call the device strategy routine.
517 */
518
isofs_strategy(bp)519 isofs_strategy(bp)
520 register struct buf *bp;
521 {
522 register struct iso_node *ip = VTOI(bp->b_vp);
523 struct vnode *vp;
524 int error;
525
526 if (bp->b_vp->v_type == VBLK || bp->b_vp->v_type == VCHR)
527 panic("isofs_strategy: spec");
528 if (bp->b_blkno == bp->b_lblkno) {
529 if (error = iso_bmap(ip, bp->b_lblkno, &bp->b_blkno))
530 return (error);
531 if ((long)bp->b_blkno == -1)
532 clrbuf(bp);
533 }
534 if ((long)bp->b_blkno == -1) {
535 biodone(bp);
536 return (0);
537 }
538 vp = ip->i_devvp;
539 bp->b_dev = vp->v_rdev;
540 (*(vp->v_op->vop_strategy))(bp);
541 return (0);
542 }
543
544 /*
545 * Print out the contents of an inode.
546 */
547 isofs_print(vp)
548 struct vnode *vp;
549 {
550 printf ("tag VT_ISOFS, isofs vnode\n");
551 }
552
553 extern int _ENODEV_ (), nullop();
554
555 /*
556 * Global vfs data structures for isofs
557 */
558 struct vnodeops isofs_vnodeops = {
559 isofs_lookup, /* lookup */
560 (void *)_ENODEV_, /* create */
561 (void *)_ENODEV_, /* mknod */
562 isofs_open, /* open */
563 isofs_close, /* close */
564 isofs_access, /* access */
565 isofs_getattr, /* getattr */
566 (void *)_ENODEV_, /* setattr */
567 isofs_read, /* read */
568 (void *)_ENODEV_, /* write */
569 isofs_ioctl, /* ioctl */
570 isofs_select, /* select */
571 isofs_mmap, /* mmap */
572 (void *)nullop, /* fsync */
573 isofs_seek, /* seek */
574 (void *)_ENODEV_, /* remove */
575 (void *)_ENODEV_, /* link */
576 (void *)_ENODEV_, /* rename */
577 (void *)_ENODEV_, /* mkdir */
578 (void *)_ENODEV_, /* rmdir */
579 (void *)_ENODEV_, /* symlink */
580 isofs_readdir, /* readdir */
581 isofs_readlink, /* readlink */
582 isofs_abortop, /* abortop */
583 isofs_inactive, /* inactive */
584 isofs_reclaim, /* reclaim */
585 isofs_lock, /* lock */
586 isofs_unlock, /* unlock */
587 (void *)_ENODEV_, /* bmap */
588 isofs_strategy, /* strategy */
589 isofs_print, /* print */
590 isofs_islocked, /* islocked */
591 (void *)_ENODEV_, /* advlock */
592 };
593
594 struct vnodeops spec_isonodeops = {
595 spec_lookup, /* lookup */
596 spec_create, /* create */
597 spec_mknod, /* mknod */
598 spec_open, /* open */
599 spec_close, /* close */
600 isofs_access, /* access */
601 isofs_getattr, /* getattr */
602 (void *)nullop, /* setattr -- XXX not enodev so writable*/
603 spec_read, /* read */
604 spec_write, /* write */
605 spec_ioctl, /* ioctl */
606 spec_select, /* select */
607 spec_mmap, /* mmap */
608 spec_fsync, /* fsync */
609 spec_seek, /* seek */
610 spec_remove, /* remove */
611 spec_link, /* link */
612 spec_rename, /* rename */
613 spec_mkdir, /* mkdir */
614 spec_rmdir, /* rmdir */
615 spec_symlink, /* symlink */
616 spec_readdir, /* readdir */
617 spec_readlink, /* readlink */
618 spec_abortop, /* abortop */
619 isofs_inactive, /* inactive */
620 isofs_reclaim, /* reclaim */
621 isofs_lock, /* lock */
622 isofs_unlock, /* unlock */
623 spec_bmap, /* bmap */
624 spec_strategy, /* strategy */
625 isofs_print, /* print */
626 isofs_islocked, /* islocked */
627 spec_advlock, /* advlock */
628 };
629