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