This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / sys / isofs / isofs_vnops.c
CommitLineData
15637ed4 1/*
fde1aeb2 2 * $Id: isofs_vnops.c,v 1.3 1993/11/25 01:32:31 wollman Exp $
15637ed4
RG
3 */
4#include "param.h"
5#include "systm.h"
6#include "namei.h"
7#include "resourcevar.h"
8#include "kernel.h"
9#include "file.h"
10#include "stat.h"
11#include "buf.h"
12#include "proc.h"
13#include "conf.h"
14#include "mount.h"
15#include "vnode.h"
16#include "specdev.h"
17#include "fifo.h"
18#include "malloc.h"
19#include "dir.h"
20
21#include "iso.h"
22#include "isofs_node.h"
584fddaa 23#include "iso_rrip.h"
15637ed4
RG
24
25/*
26 * Open called.
27 *
28 * Nothing to do.
29 */
30/* ARGSUSED */
4c45483e 31int
15637ed4
RG
32isofs_open(vp, mode, cred, p)
33 struct vnode *vp;
34 int mode;
35 struct ucred *cred;
36 struct proc *p;
37{
38 return (0);
39}
40
41/*
42 * Close called
43 *
44 * Update the times on the inode on writeable file systems.
45 */
46/* ARGSUSED */
4c45483e 47int
15637ed4
RG
48isofs_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 */
4c45483e 62int
15637ed4
RG
63isofs_access(vp, mode, cred, p)
64 struct vnode *vp;
65 register int mode;
66 struct ucred *cred;
67 struct proc *p;
68{
69 return (0);
70}
71
72/* ARGSUSED */
4c45483e 73int
15637ed4
RG
74isofs_getattr(vp, vap, cred, p)
75 struct vnode *vp;
76 register struct vattr *vap;
77 struct ucred *cred;
78 struct proc *p;
79{
80 register struct iso_node *ip = VTOI(vp);
15637ed4
RG
81 int i;
82
15637ed4
RG
83 vap->va_fsid = ip->i_dev;
84 vap->va_fileid = ip->i_number;
15637ed4
RG
85 if (vp->v_type == VDIR)
86 vap->va_nlink = 2;
87 else
88 vap->va_nlink = 1;
584fddaa
JH
89
90 vap->va_mode = ip->inode.iso_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
15637ed4
RG
97 vap->va_rdev = 0;
98 vap->va_size = ip->i_size;
99 vap->va_size_rsv = 0;
15637ed4
RG
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 */
4c45483e 113int
15637ed4
RG
114isofs_read(vp, uio, ioflag, cred)
115 struct vnode *vp;
116 register struct uio *uio;
117 int ioflag;
118 struct ucred *cred;
119{
120 register struct iso_node *ip = VTOI(vp);
121 register struct iso_mnt *imp;
122 struct buf *bp;
123 daddr_t lbn, bn, rablock;
124 int size, diff, error = 0;
125 long n, on, type;
126
127#ifdef DIAGNOSTICx
128 if (uio->uio_rw != UIO_READ)
129 panic("isofs_read mode");
130 type = ip->i_mode & IFMT;
131 if (type != IFDIR && type != IFREG && type != IFLNK)
132 panic("isofs_read type");
133#endif
134 if (uio->uio_resid == 0)
135 return (0);
136 if (uio->uio_offset < 0)
137 return (EINVAL);
138 ip->i_flag |= IACC;
139 imp = ip->i_mnt;
140 do {
141 lbn = iso_lblkno(imp, uio->uio_offset);
142 on = iso_blkoff(imp, uio->uio_offset);
143 n = MIN((unsigned)(imp->im_bsize - on), uio->uio_resid);
144 diff = ip->i_size - uio->uio_offset;
145 if (diff <= 0)
146 return (0);
147 if (diff < n)
148 n = diff;
149 size = iso_blksize(imp, ip, lbn);
150 rablock = lbn + 1;
151 if (vp->v_lastr + 1 == lbn &&
152 iso_lblktosize(imp, rablock) < ip->i_size)
153 error = breada(ITOV(ip), lbn, size, rablock,
154 iso_blksize(imp, ip, rablock), NOCRED, &bp);
155 else
156 error = bread(ITOV(ip), lbn, size, NOCRED, &bp);
157 vp->v_lastr = lbn;
158 n = MIN(n, size - bp->b_resid);
159 if (error) {
160 brelse(bp);
161 return (error);
162 }
163
164 error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
165 if (n + on == imp->im_bsize || uio->uio_offset == ip->i_size)
166 bp->b_flags |= B_AGE;
167 brelse(bp);
168 } while (error == 0 && uio->uio_resid > 0 && n != 0);
169 return (error);
170}
171
172/* ARGSUSED */
4c45483e 173int
15637ed4
RG
174isofs_ioctl(vp, com, data, fflag, cred, p)
175 struct vnode *vp;
176 int com;
177 caddr_t data;
178 int fflag;
179 struct ucred *cred;
180 struct proc *p;
181{
182 return (ENOTTY);
183}
184
185/* ARGSUSED */
4c45483e 186int
15637ed4
RG
187isofs_select(vp, which, fflags, cred, p)
188 struct vnode *vp;
189 int which, fflags;
190 struct ucred *cred;
191 struct proc *p;
192{
193
194 /*
195 * We should really check to see if I/O is possible.
196 */
197 return (1);
198}
199
200/*
201 * Mmap a file
202 *
203 * NB Currently unsupported.
204 */
205/* ARGSUSED */
4c45483e 206int
15637ed4
RG
207isofs_mmap(vp, fflags, cred, p)
208 struct vnode *vp;
209 int fflags;
210 struct ucred *cred;
211 struct proc *p;
212{
213
214 return (EINVAL);
215}
216
217/*
218 * Seek on a file
219 *
220 * Nothing to do, so just return.
221 */
222/* ARGSUSED */
4c45483e 223int
15637ed4
RG
224isofs_seek(vp, oldoff, newoff, cred)
225 struct vnode *vp;
226 off_t oldoff, newoff;
227 struct ucred *cred;
228{
229
230 return (0);
231}
232
233/*
234 * Vnode op for readdir
235 */
4c45483e 236int
15637ed4
RG
237isofs_readdir(vp, uio, cred, eofflagp)
238 struct vnode *vp;
239 register struct uio *uio;
240 struct ucred *cred;
241 int *eofflagp;
242{
243 struct dirent dirent;
244 int iso_offset;
245 int entryoffsetinblock;
246 int error = 0;
247 int endsearch;
248 struct iso_directory_record *ep;
249 int reclen;
250 struct iso_mnt *imp;
251 struct iso_node *ip;
252 struct buf *bp = NULL;
253 int i;
254 int end_flag = 0;
584fddaa 255 ISO_RRIP_ANALYZE ana;
15637ed4
RG
256
257 ip = VTOI (vp);
258 imp = ip->i_mnt;
259
260 iso_offset = uio->uio_offset;
261
262 entryoffsetinblock = iso_blkoff(imp, iso_offset);
263 if (entryoffsetinblock != 0) {
264 if (error = iso_blkatoff(ip, iso_offset, (char **)0, &bp))
265 return (error);
266 }
267
268 endsearch = ip->i_size;
269
270 while (iso_offset < endsearch && uio->uio_resid > 0) {
271 /*
272 * If offset is on a block boundary,
273 * read the next directory block.
274 * Release previous if it exists.
275 */
276
277 if (iso_blkoff(imp, iso_offset) == 0) {
278 if (bp != NULL)
279 brelse(bp);
280 if (error = iso_blkatoff(ip, iso_offset,
281 (char **)0, &bp))
282 return (error);
283 entryoffsetinblock = 0;
284 }
285 /*
286 * Get pointer to next entry.
287 */
288
289 ep = (struct iso_directory_record *)
290 (bp->b_un.b_addr + entryoffsetinblock);
291
292 reclen = isonum_711 (ep->length);
293 if (reclen == 0) {
294 /* skip to next block, if any */
295 iso_offset = roundup (iso_offset,
296 imp->logical_block_size);
297 continue;
298 }
299
300 if (reclen < sizeof (struct iso_directory_record))
301 /* illegal entry, stop */
302 break;
303
304/* 10 Aug 92*/ if (entryoffsetinblock + reclen -1 >= imp->logical_block_size)
305 /* illegal directory, so stop looking */
306 break;
307
308 dirent.d_fileno = isonum_733 (ep->extent);
309 dirent.d_namlen = isonum_711 (ep->name_len);
310
311 if (reclen < sizeof (struct iso_directory_record)
312 + dirent.d_namlen)
313 /* illegal entry, stop */
314 break;
315
584fddaa
JH
316 /*
317 *
318 */
319 switch (ep->name[0]) {
fde1aeb2
GW
320 case 0:
321 dirent.d_name[0] = '.';
322 dirent.d_namlen = 1;
323 break;
324 case 1:
325 dirent.d_name[0] = '.';
326 dirent.d_name[1] = '.';
327 dirent.d_namlen = 2;
328 break;
329 default:
330 switch ( imp->iso_ftype ) {
331 case ISO_FTYPE_RRIP:
332 isofs_rrip_getname( ep, dirent.d_name, &dirent.d_namlen );
15637ed4 333 break;
fde1aeb2
GW
334 case ISO_FTYPE_9660:
335 {
336 int namelen = dirent.d_namlen;
337 isofntrans(ep->name, dirent.d_namlen,
338 dirent.d_name, &namelen);
339 dirent.d_namlen = namelen;
584fddaa 340 break;
fde1aeb2 341 }
584fddaa 342 default:
584fddaa 343 break;
fde1aeb2
GW
344 }
345 break;
15637ed4 346 }
584fddaa 347
15637ed4
RG
348 dirent.d_name[dirent.d_namlen] = 0;
349 dirent.d_reclen = DIRSIZ (&dirent);
350
351 if (uio->uio_resid < dirent.d_reclen)
352 break;
353
354 if (error = uiomove (&dirent, dirent.d_reclen, uio))
355 break;
356
357 iso_offset += reclen;
358 entryoffsetinblock += reclen;
359 }
360
361 if (bp)
362 brelse (bp);
363
364 if (end_flag || (VTOI(vp)->i_size - iso_offset) <= 0)
365 *eofflagp = 1;
366 else
367 *eofflagp = 0;
368
369 uio->uio_offset = iso_offset;
370
371 return (error);
372}
373
584fddaa
JH
374/*
375 * Return target name of a symbolic link
376 */
377typedef struct iso_directory_record ISODIR;
378typedef struct iso_node ISONODE;
379typedef struct iso_mnt ISOMNT;
380int isofs_readlink(vp, uio, cred)
381struct vnode *vp;
382struct uio *uio;
383struct ucred *cred;
384{
385 ISONODE *ip;
386 ISODIR *dirp;
387 ISOMNT *imp;
388 struct buf *bp;
389 int symlen;
390 int error;
391 char symname[NAME_MAX];
392
393 ip = VTOI( vp );
394 imp = ip->i_mnt;
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 if ( isofs_rrip_getsymname( vp, dirp, symname, &symlen ) == 0 ) {
445 brelse ( bp );
446 return( EINVAL );
447 }
448 /*
449 * Don't forget before you leave from home ;-)
450 */
451 brelse( bp );
452
453 /*
454 * return with the Symbolick name to caller's.
455 */
456 return ( uiomove( symname, symlen, uio ) );
457}
458
15637ed4
RG
459/*
460 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
461 * done. If a buffer has been saved in anticipation of a CREATE, delete it.
462 */
463/* ARGSUSED */
4c45483e 464int
15637ed4
RG
465isofs_abortop(ndp)
466 struct nameidata *ndp;
467{
468
469 if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
470 FREE(ndp->ni_pnbuf, M_NAMEI);
471 return (0);
472}
473
474/*
475 * Lock an inode.
476 */
4c45483e 477int
15637ed4
RG
478isofs_lock(vp)
479 struct vnode *vp;
480{
481 register struct iso_node *ip = VTOI(vp);
482
483 ISO_ILOCK(ip);
484 return (0);
485}
486
487/*
488 * Unlock an inode.
489 */
4c45483e 490int
15637ed4
RG
491isofs_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 */
4c45483e 505int
15637ed4
RG
506isofs_islocked(vp)
507 struct vnode *vp;
508{
509
510 if (VTOI(vp)->i_flag & ILOCKED)
511 return (1);
512 return (0);
513}
514
515/*
516 * Calculate the logical to physical mapping if not done already,
517 * then call the device strategy routine.
518 */
519
4c45483e 520int
15637ed4
RG
521isofs_strategy(bp)
522 register struct buf *bp;
523{
524 register struct iso_node *ip = VTOI(bp->b_vp);
525 struct vnode *vp;
526 int error;
527
528 if (bp->b_vp->v_type == VBLK || bp->b_vp->v_type == VCHR)
529 panic("isofs_strategy: spec");
530 if (bp->b_blkno == bp->b_lblkno) {
531 if (error = iso_bmap(ip, bp->b_lblkno, &bp->b_blkno))
532 return (error);
533 if ((long)bp->b_blkno == -1)
534 clrbuf(bp);
535 }
536 if ((long)bp->b_blkno == -1) {
537 biodone(bp);
538 return (0);
539 }
540 vp = ip->i_devvp;
541 bp->b_dev = vp->v_rdev;
542 (*(vp->v_op->vop_strategy))(bp);
543 return (0);
544}
545
546/*
547 * Print out the contents of an inode.
548 */
4c45483e 549void
15637ed4
RG
550isofs_print(vp)
551 struct vnode *vp;
552{
584fddaa 553 printf ("tag VT_ISOFS, isofs vnode\n");
15637ed4
RG
554}
555
556extern int enodev ();
557
558/*
559 * Global vfs data structures for isofs
560 */
561struct vnodeops isofs_vnodeops = {
562 isofs_lookup, /* lookup */
563 (void *)enodev, /* create */
564 (void *)enodev, /* mknod */
565 isofs_open, /* open */
566 isofs_close, /* close */
567 isofs_access, /* access */
568 isofs_getattr, /* getattr */
569 (void *)enodev, /* setattr */
570 isofs_read, /* read */
571 (void *)enodev, /* write */
572 isofs_ioctl, /* ioctl */
573 isofs_select, /* select */
574 isofs_mmap, /* mmap */
575 (void *)nullop, /* fsync */
576 isofs_seek, /* seek */
577 (void *)enodev, /* remove */
578 (void *)enodev, /* link */
579 (void *)enodev, /* rename */
580 (void *)enodev, /* mkdir */
581 (void *)enodev, /* rmdir */
582 (void *)enodev, /* symlink */
583 isofs_readdir, /* readdir */
584fddaa 584 isofs_readlink, /* readlink */
15637ed4
RG
585 isofs_abortop, /* abortop */
586 isofs_inactive, /* inactive */
587 isofs_reclaim, /* reclaim */
588 isofs_lock, /* lock */
589 isofs_unlock, /* unlock */
590 (void *)enodev, /* bmap */
591 isofs_strategy, /* strategy */
592 isofs_print, /* print */
593 isofs_islocked, /* islocked */
594 (void *)enodev, /* advlock */
595};