Commit | Line | Data |
---|---|---|
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 */ | |
27 | isofs_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 */ | |
42 | isofs_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 | */ | |
56 | isofs_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 */ | |
66 | isofs_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 */ | |
141 | isofs_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 */ | |
200 | isofs_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 */ | |
212 | isofs_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 */ | |
231 | isofs_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 */ | |
247 | isofs_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 | */ | |
259 | isofs_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 */ | |
382 | isofs_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 | */ | |
394 | isofs_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 | */ | |
406 | isofs_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 | */ | |
420 | isofs_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 | ||
434 | isofs_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 | */ | |
462 | isofs_print(vp) | |
463 | struct vnode *vp; | |
464 | { | |
465 | printf ("isoprint\n"); | |
466 | } | |
467 | ||
468 | extern int enodev (); | |
469 | ||
470 | /* | |
471 | * Global vfs data structures for isofs | |
472 | */ | |
473 | struct 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 |