Add the source code for /usr/src/usr.bin from the Net/2 tape
[unix-history] / usr / src / sys.386bsd / isofs / isofs_vnops.c
CommitLineData
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 */
37isofs_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 */
52isofs_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 */
66isofs_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 */
76isofs_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 */
151isofs_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 */
210isofs_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 */
222isofs_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 */
241isofs_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 */
257isofs_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 */
269isofs_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 */
392isofs_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 */
404isofs_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 */
416isofs_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 */
430isofs_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
444isofs_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 */
472isofs_print(vp)
473 struct vnode *vp;
474{
475 printf ("isoprint\n");
476}
477
478extern int enodev ();
479
480/*
481 * Global vfs data structures for isofs
482 */
483struct 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