|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /* $NetBSD: cd9660_node.c,v 1.13 1994/12/24 15:30:07 cgd Exp $ */
26:
27: /*-
28: * Copyright (c) 1982, 1986, 1989, 1994
29: * The Regents of the University of California. All rights reserved.
30: *
31: * This code is derived from software contributed to Berkeley
32: * by Pace Willisson ([email protected]). The Rock Ridge Extension
33: * Support code is derived from software contributed to Berkeley
34: * by Atsushi Murai ([email protected]).
35: *
36: * Redistribution and use in source and binary forms, with or without
37: * modification, are permitted provided that the following conditions
38: * are met:
39: * 1. Redistributions of source code must retain the above copyright
40: * notice, this list of conditions and the following disclaimer.
41: * 2. Redistributions in binary form must reproduce the above copyright
42: * notice, this list of conditions and the following disclaimer in the
43: * documentation and/or other materials provided with the distribution.
44: * 3. All advertising materials mentioning features or use of this software
45: * must display the following acknowledgement:
46: * This product includes software developed by the University of
47: * California, Berkeley and its contributors.
48: * 4. Neither the name of the University nor the names of its contributors
49: * may be used to endorse or promote products derived from this software
50: * without specific prior written permission.
51: *
52: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62: * SUCH DAMAGE.
63: *
64: * @(#)cd9660_node.c 8.5 (Berkeley) 12/5/94
65: */
66:
67: #include <sys/param.h>
68: #include <sys/systm.h>
69: #include <sys/mount.h>
70: #include <sys/proc.h>
71: #include <sys/file.h>
72: #include <sys/buf.h>
73: #include <sys/vnode.h>
74: #include <sys/kernel.h>
75: #include <sys/malloc.h>
76: #include <sys/stat.h>
77: #include <sys/lock.h>
78:
79: #include <isofs/cd9660/iso.h>
80: #include <isofs/cd9660/cd9660_node.h>
81: #include <isofs/cd9660/iso_rrip.h>
82: #include <isofs/cd9660/cd9660_mount.h>
83:
84: /*
85: * Structures associated with iso_node caching.
86: */
87: struct iso_node **isohashtbl;
88: u_long isohash;
89: #define INOHASH(device, inum) (((device) + ((inum)>>12)) & isohash)
90:
91: #ifdef ISODEVMAP
92: struct iso_node **idvhashtbl;
93: u_long idvhash;
94: #define DNOHASH(device, inum) (((device) + ((inum)>>12)) & idvhash)
95: #endif
96:
97: /* defined in bsd/ufs/ufs/ufs_inode.c */
98: extern int prtactive; /* 1 => print out reclaim of active vnodes */
99:
100: extern void cache_purge (struct vnode *vp);
101:
102: /*
103: * Initialize hash links for inodes and dnodes.
104: */
105: int
106: cd9660_init()
107: {
108:
109: isohashtbl = hashinit(desiredvnodes, M_ISOFSMNT, &isohash);
110: #ifdef ISODEVMAP
111: idvhashtbl = hashinit(desiredvnodes / 8, M_ISOFSMNT, &idvhash);
112: #endif
113: return 0;
114: }
115:
116: #ifdef ISODEVMAP
117: /*
118: * Enter a new node into the device hash list
119: */
120: struct iso_dnode *
121: iso_dmap(device, inum, create)
122: dev_t device;
123: ino_t inum;
124: int create;
125: {
126: register struct iso_dnode **dpp, *dp, *dq;
127:
128: dpp = &idvhashtbl[DNOHASH(device, inum)];
129: for (dp = *dpp;; dp = dp->d_next) {
130: if (dp == NULL)
131: return (NULL);
132: if (inum == dp->i_number && device == dp->i_dev)
133: return (dp);
134:
135: if (!create)
136: return (NULL);
137:
138: MALLOC(dp, struct iso_dnode *, sizeof(struct iso_dnode), M_CACHE,
139: M_WAITOK);
140: dp->i_dev = dev;
141: dp->i_number = ino;
142:
143: if (dq = *dpp)
144: dq->d_prev = dp->d_next;
145: dp->d_next = dq;
146: dp->d_prev = dpp;
147: *dpp = dp;
148:
149: return (dp);
150: }
151:
152: void
153: iso_dunmap(device)
154: dev_t device;
155: {
156: struct iso_dnode **dpp, *dp, *dq;
157:
158: for (dpp = idvhashtbl; dpp <= idvhashtbl + idvhash; dpp++) {
159: for (dp = *dpp; dp != NULL; dp = dq)
160: dq = dp->d_next;
161: if (device == dp->i_dev) {
162: if (dq)
163: dq->d_prev = dp->d_prev;
164: *dp->d_prev = dq;
165: FREE(dp, M_CACHE);
166: }
167: }
168: }
169: }
170: #endif
171:
172: /*
173: * Use the device/inum pair to find the incore inode, and return a pointer
174: * to it. If it is in core, but locked, wait for it.
175: */
176: struct vnode *
177: cd9660_ihashget(device, inum, p)
178: dev_t device;
179: ino_t inum;
180: struct proc *p;
181: {
182: register struct iso_node *ip;
183: struct vnode *vp;
184:
185: for (;;)
186: for (ip = isohashtbl[INOHASH(device, inum)];; ip = ip->i_next) {
187: if (ip == NULL)
188: return (NULL);
189: if (inum == ip->i_number && device == ip->i_dev) {
190: /*
191: * This is my most dangerous change. I am not waiting for
192: * the inode lock anymore (ufs doesn't, why should we) and
193: * I'm worried because there is not lock on the hashtable,
194: * but there wasn't before so I'll let it go for now.
195: * -- chw --
196: */
197: vp = ITOV(ip);
198: simple_lock(&vp->v_interlock);
199: if (!vget(vp, LK_EXCLUSIVE | LK_INTERLOCK | LK_RETRY, p))
200: return (vp);
201: break;
202: }
203: }
204: /* NOTREACHED */
205: }
206:
207: /*
208: * Insert the inode into the hash table, and return it locked.
209: */
210: void
211: cd9660_ihashins(ip)
212: struct iso_node *ip;
213: {
214: struct iso_node **ipp, *iq;
215: struct proc *p = current_proc();
216:
217: /* lock the inode, then put it on the appropriate hash list */
218: lockmgr(&ip->i_lock, LK_EXCLUSIVE, (struct slock *)0, p);
219:
220: ipp = &isohashtbl[INOHASH(ip->i_dev, ip->i_number)];
221: if ((iq = *ipp))
222: iq->i_prev = &ip->i_next;
223: ip->i_next = iq;
224: ip->i_prev = ipp;
225: *ipp = ip;
226: }
227:
228: /*
229: * Remove the inode from the hash table.
230: */
231: void
232: cd9660_ihashrem(ip)
233: register struct iso_node *ip;
234: {
235: register struct iso_node *iq;
236:
237: if ((iq = ip->i_next))
238: iq->i_prev = ip->i_prev;
239: *ip->i_prev = iq;
240: #if 1 /* was ifdef DIAGNOSTIC */
241: ip->i_next = NULL;
242: ip->i_prev = NULL;
243: #endif
244: }
245:
246: /*
247: * Last reference to an inode, write the inode out and if necessary,
248: * truncate and deallocate the file.
249: */
250: int
251: cd9660_inactive(ap)
252: struct vop_inactive_args /* {
253: struct vnode *a_vp;
254: struct proc *a_p;
255: } */ *ap;
256: {
257: struct vnode *vp = ap->a_vp;
258: struct proc *p = ap->a_p;
259: register struct iso_node *ip = VTOI(vp);
260: int error = 0;
261:
262: if (prtactive && vp->v_usecount != 0)
263: vprint("cd9660_inactive: pushing active", vp);
264:
265: ip->i_flag = 0;
266:
267: /*
268: * We need to unlock the inode here. If we don't panics or
269: * hangs will ensue. Our callers expect us to take care of this.
270: */
271:
272: VOP_UNLOCK(vp,0,p);
273:
274: /*
275: * If we are done with the inode, reclaim it
276: * so that it can be reused immediately.
277: */
278: if (vp->v_usecount == 0 && ip->inode.iso_mode == 0)
279: vgone(vp);
280:
281: return error;
282: }
283:
284: /*
285: * Reclaim an inode so that it can be used for other purposes.
286: */
287: int
288: cd9660_reclaim(ap)
289: struct vop_reclaim_args /* {
290: struct vnode *a_vp;
291: } */ *ap;
292: {
293: register struct vnode *vp = ap->a_vp;
294: register struct iso_node *ip = VTOI(vp);
295:
296: if (prtactive && vp->v_usecount != 0)
297: vprint("cd9660_reclaim: pushing active", vp);
298: /*
299: * Remove the inode from its hash chain.
300: */
301: cd9660_ihashrem(ip);
302: /*
303: * Purge old data structures associated with the inode.
304: */
305: cache_purge(vp);
306: if (ip->i_devvp) {
307: vrele(ip->i_devvp);
308: ip->i_devvp = 0;
309: }
310: FREE(vp->v_data, M_ISOFSNODE);
311: vp->v_data = NULL;
312: return (0);
313: }
314:
315: /*
316: * File attributes
317: */
318: void
319: cd9660_defattr(isodir, inop, bp)
320: struct iso_directory_record *isodir;
321: struct iso_node *inop;
322: struct buf *bp;
323: {
324: struct buf *bp2 = NULL;
325: struct iso_mnt *imp;
326: struct iso_extended_attributes *ap = NULL;
327: int off;
328:
329: if ( isonum_711(isodir->flags) & directoryBit ) {
330: inop->inode.iso_mode = S_IFDIR;
331: /*
332: * If we return 2, fts() will assume there are no subdirectories
333: * (just links for the path and .), so instead we return 1.
334: */
335: inop->inode.iso_links = 1;
336: } else {
337: inop->inode.iso_mode = S_IFREG;
338: inop->inode.iso_links = 1;
339: }
340: if (!bp
341: && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT)
342: && (off = isonum_711(isodir->ext_attr_length))) {
343: VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL,
344: &bp2);
345: bp = bp2;
346: }
347: if (bp) {
348: ap = (struct iso_extended_attributes *)bp->b_data;
349:
350: if (isonum_711(ap->version) == 1) {
351: if (!(ap->perm[0]&0x40))
352: inop->inode.iso_mode |= VEXEC >> 6;
353: if (!(ap->perm[0]&0x10))
354: inop->inode.iso_mode |= VREAD >> 6;
355: if (!(ap->perm[0]&4))
356: inop->inode.iso_mode |= VEXEC >> 3;
357: if (!(ap->perm[0]&1))
358: inop->inode.iso_mode |= VREAD >> 3;
359: if (!(ap->perm[1]&0x40))
360: inop->inode.iso_mode |= VEXEC;
361: if (!(ap->perm[1]&0x10))
362: inop->inode.iso_mode |= VREAD;
363: inop->inode.iso_uid = isonum_723(ap->owner); /* what about 0? */
364: inop->inode.iso_gid = isonum_723(ap->group); /* what about 0? */
365: } else
366: ap = NULL;
367: }
368: if (!ap) {
369: inop->inode.iso_mode |= VREAD|VEXEC|(VREAD|VEXEC)>>3|(VREAD|VEXEC)>>6;
370: inop->inode.iso_uid = (uid_t)0;
371: inop->inode.iso_gid = (gid_t)0;
372: }
373: if (bp2)
374: brelse(bp2);
375: }
376:
377: /*
378: * Time stamps
379: */
380: void
381: cd9660_deftstamp(isodir,inop,bp)
382: struct iso_directory_record *isodir;
383: struct iso_node *inop;
384: struct buf *bp;
385: {
386: struct buf *bp2 = NULL;
387: struct iso_mnt *imp;
388: struct iso_extended_attributes *ap = NULL;
389: int off;
390:
391: if (!bp
392: && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT)
393: && (off = isonum_711(isodir->ext_attr_length))) {
394: VOP_BLKATOFF(ITOV(inop), (off_t)-(off << imp->im_bshift), NULL,
395: &bp2);
396: bp = bp2;
397: }
398: if (bp) {
399: ap = (struct iso_extended_attributes *)bp->b_data;
400:
401: if (isonum_711(ap->version) == 1) {
402: if (!cd9660_tstamp_conv17(ap->ftime,&inop->inode.iso_atime))
403: cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_atime);
404: if (!cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime))
405: inop->inode.iso_ctime = inop->inode.iso_atime;
406: if (!cd9660_tstamp_conv17(ap->mtime,&inop->inode.iso_mtime))
407: inop->inode.iso_mtime = inop->inode.iso_ctime;
408: } else
409: ap = NULL;
410: }
411: if (!ap) {
412: cd9660_tstamp_conv7(isodir->date,&inop->inode.iso_ctime);
413: inop->inode.iso_atime = inop->inode.iso_ctime;
414: inop->inode.iso_mtime = inop->inode.iso_ctime;
415: }
416: if (bp2)
417: brelse(bp2);
418: }
419:
420: int
421: cd9660_tstamp_conv7(pi,pu)
422: u_char *pi;
423: struct timespec *pu;
424: {
425: int crtime, days;
426: int y, m, d, hour, minute, second, tz;
427:
428: y = pi[0] + 1900;
429: m = pi[1];
430: d = pi[2];
431: hour = pi[3];
432: minute = pi[4];
433: second = pi[5];
434: tz = pi[6];
435:
436: if (y < 1970) {
437: pu->tv_sec = 0;
438: pu->tv_nsec = 0;
439: return 0;
440: } else {
441: #ifdef ORIGINAL
442: /* computes day number relative to Sept. 19th,1989 */
443: /* don't even *THINK* about changing formula. It works! */
444: days = 367*(y-1980)-7*(y+(m+9)/12)/4-3*((y+(m-9)/7)/100+1)/4+275*m/9+d-100;
445: #else
446: /*
447: * Changed :-) to make it relative to Jan. 1st, 1970
448: * and to disambiguate negative division
449: */
450: days = 367*(y-1960)-7*(y+(m+9)/12)/4-3*((y+(m+9)/12-1)/100+1)/4+275*m/9+d-239;
451: #endif
452: crtime = ((((days * 24) + hour) * 60 + minute) * 60) + second;
453:
454: /* timezone offset is unreliable on some disks */
455: if (-48 <= tz && tz <= 52)
456: crtime -= tz * 15 * 60;
457: }
458: pu->tv_sec = crtime;
459: pu->tv_nsec = 0;
460: return 1;
461: }
462:
463: static u_int
464: cd9660_chars2ui(begin,len)
465: u_char *begin;
466: int len;
467: {
468: u_int rc;
469:
470: for (rc = 0; --len >= 0;) {
471: rc *= 10;
472: rc += *begin++ - '0';
473: }
474: return rc;
475: }
476:
477: int
478: cd9660_tstamp_conv17(pi,pu)
479: u_char *pi;
480: struct timespec *pu;
481: {
482: u_char buf[7];
483:
484: /* year:"0001"-"9999" -> -1900 */
485: buf[0] = cd9660_chars2ui(pi,4) - 1900;
486:
487: /* month: " 1"-"12" -> 1 - 12 */
488: buf[1] = cd9660_chars2ui(pi + 4,2);
489:
490: /* day: " 1"-"31" -> 1 - 31 */
491: buf[2] = cd9660_chars2ui(pi + 6,2);
492:
493: /* hour: " 0"-"23" -> 0 - 23 */
494: buf[3] = cd9660_chars2ui(pi + 8,2);
495:
496: /* minute:" 0"-"59" -> 0 - 59 */
497: buf[4] = cd9660_chars2ui(pi + 10,2);
498:
499: /* second:" 0"-"59" -> 0 - 59 */
500: buf[5] = cd9660_chars2ui(pi + 12,2);
501:
502: /* difference of GMT */
503: buf[6] = pi[16];
504:
505: return cd9660_tstamp_conv7(buf,pu);
506: }
507:
508: ino_t
509: isodirino(isodir, imp)
510: struct iso_directory_record *isodir;
511: struct iso_mnt *imp;
512: {
513: ino_t ino;
514:
515: ino = (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length))
516: << imp->im_bshift;
517: return (ino);
518: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.