xref: /openbsd-src/sys/isofs/cd9660/cd9660_node.c (revision 4f12c8ab063383cd7d25f15b13b7a1240c0c5dc3)
1*4f12c8abSsemarie /*	$OpenBSD: cd9660_node.c,v 1.38 2021/10/19 06:11:45 semarie Exp $	*/
2053e05a2Sniklas /*	$NetBSD: cd9660_node.c,v 1.17 1997/05/05 07:13:57 mycroft Exp $	*/
3df930be7Sderaadt 
4df930be7Sderaadt /*-
5df930be7Sderaadt  * Copyright (c) 1982, 1986, 1989, 1994
6df930be7Sderaadt  *	The Regents of the University of California.  All rights reserved.
7df930be7Sderaadt  *
8df930be7Sderaadt  * This code is derived from software contributed to Berkeley
9df930be7Sderaadt  * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
10df930be7Sderaadt  * Support code is derived from software contributed to Berkeley
11df930be7Sderaadt  * by Atsushi Murai (amurai@spec.co.jp).
12df930be7Sderaadt  *
13df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
14df930be7Sderaadt  * modification, are permitted provided that the following conditions
15df930be7Sderaadt  * are met:
16df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
17df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
18df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
19df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
20df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
2129295d1cSmillert  * 3. Neither the name of the University nor the names of its contributors
22df930be7Sderaadt  *    may be used to endorse or promote products derived from this software
23df930be7Sderaadt  *    without specific prior written permission.
24df930be7Sderaadt  *
25df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35df930be7Sderaadt  * SUCH DAMAGE.
36df930be7Sderaadt  *
37df930be7Sderaadt  *	@(#)cd9660_node.c	8.5 (Berkeley) 12/5/94
38df930be7Sderaadt  */
39df930be7Sderaadt 
40df930be7Sderaadt #include <sys/param.h>
41df930be7Sderaadt #include <sys/systm.h>
42df930be7Sderaadt #include <sys/mount.h>
43df930be7Sderaadt #include <sys/buf.h>
44df930be7Sderaadt #include <sys/vnode.h>
45fde894e5Stedu #include <sys/lock.h>
469d71829cSniklas #include <sys/namei.h>
47df930be7Sderaadt #include <sys/kernel.h>
48df930be7Sderaadt #include <sys/malloc.h>
49df930be7Sderaadt #include <sys/stat.h>
50df930be7Sderaadt 
519dc9bb81Sdlg #include <crypto/siphash.h>
529dc9bb81Sdlg 
53df930be7Sderaadt #include <isofs/cd9660/iso.h>
54053e05a2Sniklas #include <isofs/cd9660/cd9660_extern.h>
55df930be7Sderaadt #include <isofs/cd9660/cd9660_node.h>
56df930be7Sderaadt 
57df930be7Sderaadt /*
58df930be7Sderaadt  * Structures associated with iso_node caching.
59df930be7Sderaadt  */
609dc9bb81Sdlg u_int cd9660_isohash(dev_t, cdino_t);
619dc9bb81Sdlg 
62df930be7Sderaadt struct iso_node **isohashtbl;
63df930be7Sderaadt u_long isohash;
649dc9bb81Sdlg SIPHASH_KEY isohashkey;
659dc9bb81Sdlg #define	INOHASH(device, inum) cd9660_isohash((device), (inum))
66df930be7Sderaadt 
6782be8208Sjason extern int prtactive;	/* 1 => print out reclaim of active vnodes */
68df930be7Sderaadt 
69c4071fd1Smillert static u_int cd9660_chars2ui(u_char *, int);
70053e05a2Sniklas 
71df930be7Sderaadt /*
72df930be7Sderaadt  * Initialize hash links for inodes and dnodes.
73df930be7Sderaadt  */
7407feb63cScsapuntz int
cd9660_init(struct vfsconf * vfsp)751bf87d88Sjsg cd9660_init(struct vfsconf *vfsp)
76df930be7Sderaadt {
77df930be7Sderaadt 
786dfb9ddeStedu 	isohashtbl = hashinit(initialvnodes, M_ISOFSMNT, M_WAITOK, &isohash);
799dc9bb81Sdlg 	arc4random_buf(&isohashkey, sizeof(isohashkey));
8007feb63cScsapuntz 	return (0);
81df930be7Sderaadt }
82df930be7Sderaadt 
839dc9bb81Sdlg u_int
cd9660_isohash(dev_t device,cdino_t inum)849dc9bb81Sdlg cd9660_isohash(dev_t device, cdino_t inum)
859dc9bb81Sdlg {
869dc9bb81Sdlg 	SIPHASH_CTX ctx;
879dc9bb81Sdlg 
889dc9bb81Sdlg 	SipHash24_Init(&ctx, &isohashkey);
899dc9bb81Sdlg 	SipHash24_Update(&ctx, &device, sizeof(device));
909dc9bb81Sdlg 	SipHash24_Update(&ctx, &inum, sizeof(inum));
919dc9bb81Sdlg 	return (SipHash24_End(&ctx) & isohash);
929dc9bb81Sdlg }
939dc9bb81Sdlg 
94df930be7Sderaadt /*
95df930be7Sderaadt  * Use the device/inum pair to find the incore inode, and return a pointer
96df930be7Sderaadt  * to it. If it is in core, but locked, wait for it.
97df930be7Sderaadt  */
98df930be7Sderaadt struct vnode *
cd9660_ihashget(dev_t dev,cdino_t inum)991bf87d88Sjsg cd9660_ihashget(dev_t dev, cdino_t inum)
100df930be7Sderaadt {
10107feb63cScsapuntz 	struct iso_node *ip;
102df930be7Sderaadt 	struct vnode *vp;
103df930be7Sderaadt 
10407feb63cScsapuntz loop:
1055deff29eSoga 	/* XXX locking lock hash list? */
10607feb63cScsapuntz        for (ip = isohashtbl[INOHASH(dev, inum)]; ip; ip = ip->i_next) {
10707feb63cScsapuntz                if (inum == ip->i_number && dev == ip->i_dev) {
108f6d35f95Sderaadt                        vp = ITOV(ip);
1095deff29eSoga 			/* XXX locking unlock hash list? */
11008107a0bSvisa                        if (vget(vp, LK_EXCLUSIVE))
11107feb63cScsapuntz                                goto loop;
112f6d35f95Sderaadt                        return (vp);
113f6d35f95Sderaadt 	       }
114f6d35f95Sderaadt        }
1155deff29eSoga 	/* XXX locking unlock hash list? */
11607feb63cScsapuntz        return (NULL);
117df930be7Sderaadt }
118df930be7Sderaadt 
119df930be7Sderaadt /*
120df930be7Sderaadt  * Insert the inode into the hash table, and return it locked.
121df930be7Sderaadt  */
122d91bc836Scsapuntz int
cd9660_ihashins(struct iso_node * ip)1231bf87d88Sjsg cd9660_ihashins(struct iso_node *ip)
124df930be7Sderaadt {
125df930be7Sderaadt 	struct iso_node **ipp, *iq;
126df930be7Sderaadt 
1275deff29eSoga 	/* XXX locking lock hash list? */
128df930be7Sderaadt 	ipp = &isohashtbl[INOHASH(ip->i_dev, ip->i_number)];
129d91bc836Scsapuntz 
130d91bc836Scsapuntz 	for (iq = *ipp; iq; iq = iq->i_next) {
131d91bc836Scsapuntz 		if (iq->i_dev == ip->i_dev &&
132d91bc836Scsapuntz 		    iq->i_number == ip->i_number)
133d91bc836Scsapuntz 			return (EEXIST);
134d91bc836Scsapuntz 	}
135d91bc836Scsapuntz 
1369d71829cSniklas 	if ((iq = *ipp) != NULL)
137df930be7Sderaadt 		iq->i_prev = &ip->i_next;
138df930be7Sderaadt 	ip->i_next = iq;
139df930be7Sderaadt 	ip->i_prev = ipp;
140df930be7Sderaadt 	*ipp = ip;
1415deff29eSoga 	/* XXX locking unlock hash list? */
14207feb63cScsapuntz 
143*4f12c8abSsemarie 	VOP_LOCK(ITOV(ip), LK_EXCLUSIVE);
1442752fedbSpedro 
145d91bc836Scsapuntz 	return (0);
146df930be7Sderaadt }
147df930be7Sderaadt 
148df930be7Sderaadt /*
149df930be7Sderaadt  * Remove the inode from the hash table.
150df930be7Sderaadt  */
151df930be7Sderaadt void
cd9660_ihashrem(struct iso_node * ip)1521bf87d88Sjsg cd9660_ihashrem(struct iso_node *ip)
153df930be7Sderaadt {
154b2acc587Sjsg 	struct iso_node *iq;
155df930be7Sderaadt 
156d91bc836Scsapuntz 	if (ip->i_prev == NULL)
157d91bc836Scsapuntz 		return;
158d91bc836Scsapuntz 
1595deff29eSoga 	/* XXX locking lock hash list? */
1609d71829cSniklas 	if ((iq = ip->i_next) != NULL)
161df930be7Sderaadt 		iq->i_prev = ip->i_prev;
162df930be7Sderaadt 	*ip->i_prev = iq;
163df930be7Sderaadt #ifdef DIAGNOSTIC
164df930be7Sderaadt 	ip->i_next = NULL;
165df930be7Sderaadt 	ip->i_prev = NULL;
166df930be7Sderaadt #endif
1675deff29eSoga 	/* XXX locking unlock hash list? */
168df930be7Sderaadt }
169df930be7Sderaadt 
170df930be7Sderaadt /*
171df930be7Sderaadt  * Last reference to an inode, write the inode out and if necessary,
172df930be7Sderaadt  * truncate and deallocate the file.
173df930be7Sderaadt  */
174df930be7Sderaadt int
cd9660_inactive(void * v)1751bf87d88Sjsg cd9660_inactive(void *v)
1769d71829cSniklas {
17799bc9d31Sderaadt 	struct vop_inactive_args *ap = v;
178df930be7Sderaadt 	struct vnode *vp = ap->a_vp;
179b2acc587Sjsg 	struct iso_node *ip = VTOI(vp);
180df930be7Sderaadt 	int error = 0;
181df930be7Sderaadt 
1824df17c52Spedro #ifdef DIAGNOSTIC
183df930be7Sderaadt 	if (prtactive && vp->v_usecount != 0)
184df930be7Sderaadt 		vprint("cd9660_inactive: pushing active", vp);
1854df17c52Spedro #endif
186df930be7Sderaadt 
187df930be7Sderaadt 	ip->i_flag = 0;
18836bb23f1Svisa 	VOP_UNLOCK(vp);
189df930be7Sderaadt 	/*
190df930be7Sderaadt 	 * If we are done with the inode, reclaim it
191df930be7Sderaadt 	 * so that it can be reused immediately.
192df930be7Sderaadt 	 */
19307feb63cScsapuntz 	if (ip->inode.iso_mode == 0)
194db7aa982Smpi 		vrecycle(vp, ap->a_p);
19507feb63cScsapuntz 
196053e05a2Sniklas 	return (error);
197df930be7Sderaadt }
198df930be7Sderaadt 
199df930be7Sderaadt /*
200df930be7Sderaadt  * Reclaim an inode so that it can be used for other purposes.
201df930be7Sderaadt  */
202df930be7Sderaadt int
cd9660_reclaim(void * v)2031bf87d88Sjsg cd9660_reclaim(void *v)
2049d71829cSniklas {
20599bc9d31Sderaadt 	struct vop_reclaim_args *ap = v;
206b2acc587Sjsg 	struct vnode *vp = ap->a_vp;
207b2acc587Sjsg 	struct iso_node *ip = VTOI(vp);
208df930be7Sderaadt 
2094df17c52Spedro #ifdef DIAGNOSTIC
210df930be7Sderaadt 	if (prtactive && vp->v_usecount != 0)
211df930be7Sderaadt 		vprint("cd9660_reclaim: pushing active", vp);
2124df17c52Spedro #endif
2134df17c52Spedro 
214df930be7Sderaadt 	/*
215df930be7Sderaadt 	 * Remove the inode from its hash chain.
216df930be7Sderaadt 	 */
217df930be7Sderaadt 	cd9660_ihashrem(ip);
218df930be7Sderaadt 	/*
219df930be7Sderaadt 	 * Purge old data structures associated with the inode.
220df930be7Sderaadt 	 */
221df930be7Sderaadt 	cache_purge(vp);
222df930be7Sderaadt 	if (ip->i_devvp) {
223df930be7Sderaadt 		vrele(ip->i_devvp);
224df930be7Sderaadt 		ip->i_devvp = 0;
225df930be7Sderaadt 	}
2260e5ae731Stedu 	free(vp->v_data, M_ISOFSNODE, 0);
227df930be7Sderaadt 	vp->v_data = NULL;
228df930be7Sderaadt 	return (0);
229df930be7Sderaadt }
230df930be7Sderaadt 
231df930be7Sderaadt /*
232df930be7Sderaadt  * File attributes
233df930be7Sderaadt  */
234df930be7Sderaadt void
cd9660_defattr(struct iso_directory_record * isodir,struct iso_node * inop,struct buf * bp)2351bf87d88Sjsg cd9660_defattr(struct iso_directory_record *isodir, struct iso_node *inop,
2361bf87d88Sjsg     struct buf *bp)
237df930be7Sderaadt {
238df930be7Sderaadt 	struct buf *bp2 = NULL;
239df930be7Sderaadt 	struct iso_mnt *imp;
240df930be7Sderaadt 	struct iso_extended_attributes *ap = NULL;
241df930be7Sderaadt 	int off;
242df930be7Sderaadt 
243df930be7Sderaadt 	if (isonum_711(isodir->flags)&2) {
244df930be7Sderaadt 		inop->inode.iso_mode = S_IFDIR;
245df930be7Sderaadt 		/*
246df930be7Sderaadt 		 * If we return 2, fts() will assume there are no subdirectories
247df930be7Sderaadt 		 * (just links for the path and .), so instead we return 1.
248df930be7Sderaadt 		 */
249df930be7Sderaadt 		inop->inode.iso_links = 1;
250df930be7Sderaadt 	} else {
251df930be7Sderaadt 		inop->inode.iso_mode = S_IFREG;
252df930be7Sderaadt 		inop->inode.iso_links = 1;
253df930be7Sderaadt 	}
254df930be7Sderaadt 	if (!bp
255df930be7Sderaadt 	    && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT)
256df930be7Sderaadt 	    && (off = isonum_711(isodir->ext_attr_length))) {
257574066a2Scsapuntz 		cd9660_bufatoff(inop, (off_t)-(off << imp->im_bshift), NULL,
258df930be7Sderaadt 			     &bp2);
259df930be7Sderaadt 		bp = bp2;
260df930be7Sderaadt 	}
261df930be7Sderaadt 	if (bp) {
262df930be7Sderaadt 		ap = (struct iso_extended_attributes *)bp->b_data;
263df930be7Sderaadt 
264df930be7Sderaadt 		if (isonum_711(ap->version) == 1) {
265df930be7Sderaadt 			if (!(ap->perm[1]&0x10))
26693de0522Smillert 				inop->inode.iso_mode |= S_IRUSR;
26793de0522Smillert 			if (!(ap->perm[1]&0x40))
26893de0522Smillert 				inop->inode.iso_mode |= S_IXUSR;
26993de0522Smillert 			if (!(ap->perm[0]&0x01))
27093de0522Smillert 				inop->inode.iso_mode |= S_IRGRP;
27193de0522Smillert 			if (!(ap->perm[0]&0x04))
27293de0522Smillert 				inop->inode.iso_mode |= S_IXGRP;
27393de0522Smillert 			if (!(ap->perm[0]&0x10))
27493de0522Smillert 				inop->inode.iso_mode |= S_IROTH;
27593de0522Smillert 			if (!(ap->perm[0]&0x40))
27693de0522Smillert 				inop->inode.iso_mode |= S_IXOTH;
277df930be7Sderaadt 			inop->inode.iso_uid = isonum_723(ap->owner); /* what about 0? */
278df930be7Sderaadt 			inop->inode.iso_gid = isonum_723(ap->group); /* what about 0? */
279df930be7Sderaadt 		} else
280df930be7Sderaadt 			ap = NULL;
281df930be7Sderaadt 	}
282df930be7Sderaadt 	if (!ap) {
28393de0522Smillert 		inop->inode.iso_mode |=
28493de0522Smillert 		    S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
285df930be7Sderaadt 		inop->inode.iso_uid = (uid_t)0;
286df930be7Sderaadt 		inop->inode.iso_gid = (gid_t)0;
287df930be7Sderaadt 	}
288df930be7Sderaadt 	if (bp2)
289df930be7Sderaadt 		brelse(bp2);
290df930be7Sderaadt }
291df930be7Sderaadt 
292df930be7Sderaadt /*
293df930be7Sderaadt  * Time stamps
294df930be7Sderaadt  */
295df930be7Sderaadt void
cd9660_deftstamp(struct iso_directory_record * isodir,struct iso_node * inop,struct buf * bp)2961bf87d88Sjsg cd9660_deftstamp(struct iso_directory_record *isodir, struct iso_node *inop,
2971bf87d88Sjsg     struct buf *bp)
298df930be7Sderaadt {
299df930be7Sderaadt 	struct buf *bp2 = NULL;
300df930be7Sderaadt 	struct iso_mnt *imp;
301df930be7Sderaadt 	struct iso_extended_attributes *ap = NULL;
302df930be7Sderaadt 	int off;
303df930be7Sderaadt 
304df930be7Sderaadt 	if (!bp
305df930be7Sderaadt 	    && ((imp = inop->i_mnt)->im_flags & ISOFSMNT_EXTATT)
306df930be7Sderaadt 	    && (off = isonum_711(isodir->ext_attr_length))) {
307574066a2Scsapuntz 		cd9660_bufatoff(inop, (off_t)-(off << imp->im_bshift), NULL,
308df930be7Sderaadt 			     &bp2);
309df930be7Sderaadt 		bp = bp2;
310df930be7Sderaadt 	}
311df930be7Sderaadt 	if (bp) {
312df930be7Sderaadt 		ap = (struct iso_extended_attributes *)bp->b_data;
313df930be7Sderaadt 
314df930be7Sderaadt 		if (isonum_711(ap->version) == 1) {
315df930be7Sderaadt 			if (!cd9660_tstamp_conv17(ap->ftime,&inop->inode.iso_atime))
316df930be7Sderaadt 				cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_atime);
317df930be7Sderaadt 			if (!cd9660_tstamp_conv17(ap->ctime,&inop->inode.iso_ctime))
318df930be7Sderaadt 				inop->inode.iso_ctime = inop->inode.iso_atime;
319df930be7Sderaadt 			if (!cd9660_tstamp_conv17(ap->mtime,&inop->inode.iso_mtime))
320df930be7Sderaadt 				inop->inode.iso_mtime = inop->inode.iso_ctime;
321df930be7Sderaadt 		} else
322df930be7Sderaadt 			ap = NULL;
323df930be7Sderaadt 	}
324df930be7Sderaadt 	if (!ap) {
325df930be7Sderaadt 		cd9660_tstamp_conv7(isodir->date,&inop->inode.iso_ctime);
326df930be7Sderaadt 		inop->inode.iso_atime = inop->inode.iso_ctime;
327df930be7Sderaadt 		inop->inode.iso_mtime = inop->inode.iso_ctime;
328df930be7Sderaadt 	}
329df930be7Sderaadt 	if (bp2)
330df930be7Sderaadt 		brelse(bp2);
331df930be7Sderaadt }
332df930be7Sderaadt 
333df930be7Sderaadt int
cd9660_tstamp_conv7(u_char * pi,struct timespec * pu)3341bf87d88Sjsg cd9660_tstamp_conv7(u_char *pi, struct timespec *pu)
335df930be7Sderaadt {
336df930be7Sderaadt 	int crtime, days;
3371009d266Sderaadt 	int y, m, d, hour, minute, second;
3381009d266Sderaadt 	signed char tz;
339df930be7Sderaadt 
340df930be7Sderaadt 	y = pi[0] + 1900;
341df930be7Sderaadt 	m = pi[1];
342df930be7Sderaadt 	d = pi[2];
343df930be7Sderaadt 	hour = pi[3];
344df930be7Sderaadt 	minute = pi[4];
345df930be7Sderaadt 	second = pi[5];
3461009d266Sderaadt 	tz = (signed char) pi[6];
347df930be7Sderaadt 
348df930be7Sderaadt 	if (y < 1970) {
3499d71829cSniklas 		pu->tv_sec  = 0;
3509d71829cSniklas 		pu->tv_nsec = 0;
351053e05a2Sniklas 		return (0);
352df930be7Sderaadt 	} else {
353df930be7Sderaadt #ifdef	ORIGINAL
354df930be7Sderaadt 		/* computes day number relative to Sept. 19th,1989 */
355df930be7Sderaadt 		/* don't even *THINK* about changing formula. It works! */
356df930be7Sderaadt 		days = 367*(y-1980)-7*(y+(m+9)/12)/4-3*((y+(m-9)/7)/100+1)/4+275*m/9+d-100;
357df930be7Sderaadt #else
358df930be7Sderaadt 		/*
359df930be7Sderaadt 		 * Changed :-) to make it relative to Jan. 1st, 1970
360df930be7Sderaadt 		 * and to disambiguate negative division
361df930be7Sderaadt 		 */
362df930be7Sderaadt 		days = 367*(y-1960)-7*(y+(m+9)/12)/4-3*((y+(m+9)/12-1)/100+1)/4+275*m/9+d-239;
363df930be7Sderaadt #endif
364df930be7Sderaadt 		crtime = ((((days * 24) + hour) * 60 + minute) * 60) + second;
365df930be7Sderaadt 
366df930be7Sderaadt 		/* timezone offset is unreliable on some disks */
367df930be7Sderaadt 		if (-48 <= tz && tz <= 52)
368df930be7Sderaadt 			crtime -= tz * 15 * 60;
369df930be7Sderaadt 	}
3709d71829cSniklas 	pu->tv_sec  = crtime;
3719d71829cSniklas 	pu->tv_nsec = 0;
372053e05a2Sniklas 	return (1);
373df930be7Sderaadt }
374df930be7Sderaadt 
375df930be7Sderaadt static u_int
cd9660_chars2ui(u_char * begin,int len)3761bf87d88Sjsg cd9660_chars2ui(u_char *begin, int len)
377df930be7Sderaadt {
378df930be7Sderaadt 	u_int rc;
379df930be7Sderaadt 
380df930be7Sderaadt 	for (rc = 0; --len >= 0;) {
381df930be7Sderaadt 		rc *= 10;
382df930be7Sderaadt 		rc += *begin++ - '0';
383df930be7Sderaadt 	}
384053e05a2Sniklas 	return (rc);
385df930be7Sderaadt }
386df930be7Sderaadt 
387df930be7Sderaadt int
cd9660_tstamp_conv17(u_char * pi,struct timespec * pu)3881bf87d88Sjsg cd9660_tstamp_conv17(u_char *pi, struct timespec *pu)
389df930be7Sderaadt {
390df930be7Sderaadt 	u_char buf[7];
391df930be7Sderaadt 
392df930be7Sderaadt 	/* year:"0001"-"9999" -> -1900  */
393df930be7Sderaadt 	buf[0] = cd9660_chars2ui(pi,4) - 1900;
394df930be7Sderaadt 
395df930be7Sderaadt 	/* month: " 1"-"12"      -> 1 - 12 */
396df930be7Sderaadt 	buf[1] = cd9660_chars2ui(pi + 4,2);
397df930be7Sderaadt 
398df930be7Sderaadt 	/* day:   " 1"-"31"      -> 1 - 31 */
399df930be7Sderaadt 	buf[2] = cd9660_chars2ui(pi + 6,2);
400df930be7Sderaadt 
401df930be7Sderaadt 	/* hour:  " 0"-"23"      -> 0 - 23 */
402df930be7Sderaadt 	buf[3] = cd9660_chars2ui(pi + 8,2);
403df930be7Sderaadt 
404df930be7Sderaadt 	/* minute:" 0"-"59"      -> 0 - 59 */
405df930be7Sderaadt 	buf[4] = cd9660_chars2ui(pi + 10,2);
406df930be7Sderaadt 
407df930be7Sderaadt 	/* second:" 0"-"59"      -> 0 - 59 */
408df930be7Sderaadt 	buf[5] = cd9660_chars2ui(pi + 12,2);
409df930be7Sderaadt 
410df930be7Sderaadt 	/* difference of GMT */
411df930be7Sderaadt 	buf[6] = pi[16];
412df930be7Sderaadt 
413053e05a2Sniklas 	return (cd9660_tstamp_conv7(buf,pu));
414df930be7Sderaadt }
415df930be7Sderaadt 
4160cad8b22Sguenther cdino_t
isodirino(struct iso_directory_record * isodir,struct iso_mnt * imp)4171bf87d88Sjsg isodirino(struct iso_directory_record *isodir, struct iso_mnt *imp)
418df930be7Sderaadt {
4190cad8b22Sguenther 	cdino_t ino;
420df930be7Sderaadt 
421053e05a2Sniklas 	ino = (isonum_733(isodir->extent) +
422053e05a2Sniklas 	    isonum_711(isodir->ext_attr_length)) << imp->im_bshift;
423df930be7Sderaadt 	return (ino);
424df930be7Sderaadt }
425