cd9660_util.c revision 120492
11541Srgrimes/*-
21541Srgrimes * Copyright (c) 1994
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * This code is derived from software contributed to Berkeley
61541Srgrimes * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
71541Srgrimes * Support code is derived from software contributed to Berkeley
845773Sdcs * by Atsushi Murai (amurai@spec.co.jp). Joliet support was added by
945773Sdcs * Joachim Kuebart (joki@kuebart.stuttgart.netsurf.de).
101541Srgrimes *
111541Srgrimes * Redistribution and use in source and binary forms, with or without
121541Srgrimes * modification, are permitted provided that the following conditions
131541Srgrimes * are met:
141541Srgrimes * 1. Redistributions of source code must retain the above copyright
151541Srgrimes *    notice, this list of conditions and the following disclaimer.
161541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
171541Srgrimes *    notice, this list of conditions and the following disclaimer in the
181541Srgrimes *    documentation and/or other materials provided with the distribution.
191541Srgrimes * 3. All advertising materials mentioning features or use of this software
201541Srgrimes *    must display the following acknowledgement:
211541Srgrimes *	This product includes software developed by the University of
221541Srgrimes *	California, Berkeley and its contributors.
231541Srgrimes * 4. Neither the name of the University nor the names of its contributors
241541Srgrimes *    may be used to endorse or promote products derived from this software
251541Srgrimes *    without specific prior written permission.
261541Srgrimes *
271541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
281541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
291541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
301541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
311541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
321541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
331541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
341541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
351541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
361541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
371541Srgrimes * SUCH DAMAGE.
381541Srgrimes *
3922521Sdyson *	@(#)cd9660_util.c	8.3 (Berkeley) 12/5/94
401541Srgrimes */
411541Srgrimes
42116181Sobrien#include <sys/cdefs.h>
43116181Sobrien__FBSDID("$FreeBSD: head/sys/fs/cd9660/cd9660_util.c 120492 2003-09-26 20:26:25Z fjoe $");
44116181Sobrien
451541Srgrimes#include <sys/param.h>
4696009Sjeff#include <sys/systm.h>
471541Srgrimes#include <sys/mount.h>
481541Srgrimes#include <sys/vnode.h>
49120492Sfjoe#include <sys/iconv.h>
501541Srgrimes
511541Srgrimes#include <isofs/cd9660/iso.h>
52120492Sfjoe#include <isofs/cd9660/cd9660_mount.h>
531541Srgrimes
54120492Sfjoeextern struct iconv_functions *cd9660_iconv;
5572435Ssobomax
5672435Ssobomax/*
5745773Sdcs * Get one character out of an iso filename
5845773Sdcs * Obey joliet_level
5945773Sdcs * Return number of bytes consumed
6045773Sdcs */
6145773Sdcsint
62120492Sfjoeisochar(isofn, isoend, joliet_level, c, clen, flags, handle)
6345773Sdcs      u_char *isofn;
6445773Sdcs      u_char *isoend;
6545773Sdcs      int joliet_level;
66120492Sfjoe      u_short *c;
67120492Sfjoe      int *clen;
68120492Sfjoe      int flags;
69120492Sfjoe      void *handle;
7045773Sdcs{
71120492Sfjoe      size_t i, j, len;
72120492Sfjoe      char inbuf[3], outbuf[3], *inp, *outp;
73120492Sfjoe
7445773Sdcs      *c = *isofn++;
75120492Sfjoe      if (clen) *clen = 1;
7645773Sdcs      if (joliet_level == 0 || isofn == isoend)
7745773Sdcs              /* (00) and (01) are one byte in Joliet, too */
7845773Sdcs              return 1;
7945773Sdcs
80120492Sfjoe      if (flags & ISOFSMNT_KICONV && cd9660_iconv) {
81120492Sfjoe              i = j = len = 2;
82120492Sfjoe              inbuf[0]=(char)*(isofn - 1);
83120492Sfjoe              inbuf[1]=(char)*isofn;
84120492Sfjoe              inbuf[2]='\0';
85120492Sfjoe              inp = inbuf;
86120492Sfjoe              outp = outbuf;
87120492Sfjoe              cd9660_iconv->convchr(handle, (const char **)&inp, &i, &outp, &j);
88120492Sfjoe              len -= j;
89120492Sfjoe              if (clen) *clen = len;
90120492Sfjoe              *c = '\0';
91120492Sfjoe              while(len--)
92120492Sfjoe                      *c |= (*(outp - len - 1) & 0xff) << (len << 3);
93120492Sfjoe      } else {
94120492Sfjoe              switch (*c) {
95120492Sfjoe              default:
96120492Sfjoe                      *c = '?';
97120492Sfjoe                      break;
98120492Sfjoe              case '\0':
99120492Sfjoe                      *c = *isofn;
100120492Sfjoe                      break;
101120492Sfjoe              }
10245773Sdcs      }
10372435Ssobomax
10445773Sdcs      return 2;
10545773Sdcs}
10645773Sdcs
10745773Sdcs/*
1081541Srgrimes * translate and compare a filename
10945773Sdcs * returns (fn - isofn)
1101541Srgrimes * Note: Version number plus ';' may be omitted.
1111541Srgrimes */
1121541Srgrimesint
113120492Sfjoeisofncmp(fn, fnlen, isofn, isolen, joliet_level, flags, handle, lhandle)
11422593Sbde	u_char *fn;
11522593Sbde	int fnlen;
11622593Sbde	u_char *isofn;
11722593Sbde	int isolen;
11845773Sdcs	int joliet_level;
119120492Sfjoe	int flags;
120120492Sfjoe	void *handle;
121120492Sfjoe	void *lhandle;
1221541Srgrimes{
1231541Srgrimes	int i, j;
124120492Sfjoe	u_short c, d;
125120492Sfjoe	u_char *fnend = fn + fnlen, *isoend = isofn + isolen;
1268876Srgrimes
127120492Sfjoe	for (; fn < fnend; ) {
128120492Sfjoe		d = sgetrune(fn, fnend - fn, (char const **)&fn, flags, lhandle);
12945773Sdcs		if (isofn == isoend)
130120492Sfjoe			return d;
131120492Sfjoe		isofn += isochar(isofn, isoend, joliet_level, &c, NULL, flags, handle);
13245773Sdcs		if (c == ';') {
133120492Sfjoe			if (d != ';')
134120492Sfjoe				return d;
135120492Sfjoe			for (i = 0; fn < fnend; i = i * 10 + *fn++ - '0') {
1361541Srgrimes				if (*fn < '0' || *fn > '9') {
1371541Srgrimes					return -1;
1381541Srgrimes				}
1391541Srgrimes			}
14045773Sdcs			for (j = 0; isofn != isoend; j = j * 10 + c - '0')
14145773Sdcs				isofn += isochar(isofn, isoend,
142120492Sfjoe						 joliet_level, &c,
143120492Sfjoe						 NULL, flags, handle);
1441541Srgrimes			return i - j;
1451541Srgrimes		}
146120492Sfjoe		if (c != d) {
1471541Srgrimes			if (c >= 'A' && c <= 'Z') {
148120492Sfjoe				if (c + ('a' - 'A') != d) {
149120492Sfjoe					if (d >= 'a' && d <= 'z')
150120492Sfjoe						return d - ('a' - 'A') - c;
1511541Srgrimes					else
152120492Sfjoe						return d - c;
1531541Srgrimes				}
1541541Srgrimes			} else
155120492Sfjoe				return d - c;
1561541Srgrimes		}
1571541Srgrimes	}
15845773Sdcs	if (isofn != isoend) {
159120492Sfjoe		isofn += isochar(isofn, isoend, joliet_level, &c, NULL, flags, handle);
16045773Sdcs		switch (c) {
1611541Srgrimes		default:
16245773Sdcs			return -c;
16345773Sdcs		case '.':
16445773Sdcs			if (isofn != isoend) {
165120492Sfjoe				isochar(isofn, isoend, joliet_level, &c,
166120492Sfjoe					NULL, flags, handle);
16745773Sdcs				if (c == ';')
16845773Sdcs					return 0;
16945773Sdcs			}
1701541Srgrimes			return -1;
1711541Srgrimes		case ';':
1721541Srgrimes			return 0;
1731541Srgrimes		}
1741541Srgrimes	}
1751541Srgrimes	return 0;
1761541Srgrimes}
1771541Srgrimes
1781541Srgrimes/*
17945773Sdcs * translate a filename of length > 0
1801541Srgrimes */
1811541Srgrimesvoid
182120492Sfjoeisofntrans(infn, infnlen, outfn, outfnlen, original, assoc, joliet_level, flags, handle)
18322593Sbde	u_char *infn;
18422521Sdyson	int infnlen;
18522593Sbde	u_char *outfn;
18622521Sdyson	u_short *outfnlen;
18722521Sdyson	int original;
18822521Sdyson	int assoc;
18945773Sdcs	int joliet_level;
190120492Sfjoe	int flags;
191120492Sfjoe	void *handle;
1921541Srgrimes{
193120492Sfjoe	u_short c, d = '\0';
194120492Sfjoe	u_char *outp = outfn, *infnend = infn + infnlen;
195120492Sfjoe	int clen;
1968876Srgrimes
1971541Srgrimes	if (assoc) {
198120492Sfjoe		*outp++ = ASSOCCHAR;
1991541Srgrimes	}
200120492Sfjoe	for (; infn != infnend; ) {
201120492Sfjoe		infn += isochar(infn, infnend, joliet_level, &c, &clen, flags, handle);
2028876Srgrimes
20346669Sdcs		if (!original && !joliet_level && c >= 'A' && c <= 'Z')
204120492Sfjoe			c += ('a' - 'A');
20545773Sdcs		else if (!original && c == ';') {
206120492Sfjoe			outp -= (d == '.');
2071541Srgrimes			break;
208120492Sfjoe		}
20945773Sdcs		d = c;
210120492Sfjoe		while(clen--)
211120492Sfjoe			*outp++ = c >> (clen << 3);
2121541Srgrimes	}
213120492Sfjoe	*outfnlen = outp - outfn;
2141541Srgrimes}
215120492Sfjoe
216120492Sfjoe/*
217120492Sfjoe * same as sgetrune(3)
218120492Sfjoe */
219120492Sfjoeu_short
220120492Sfjoesgetrune(string, n, result, flags, handle)
221120492Sfjoe	const char *string;
222120492Sfjoe	size_t n;
223120492Sfjoe	char const **result;
224120492Sfjoe	int flags;
225120492Sfjoe	void *handle;
226120492Sfjoe{
227120492Sfjoe	size_t i, j, len;
228120492Sfjoe	char outbuf[3], *outp;
229120492Sfjoe	u_short c = '\0';
230120492Sfjoe
231120492Sfjoe	len = i = (n < 2) ? n : 2;
232120492Sfjoe	j = 2;
233120492Sfjoe	outp = outbuf;
234120492Sfjoe
235120492Sfjoe	if (flags & ISOFSMNT_KICONV && cd9660_iconv) {
236120492Sfjoe		cd9660_iconv->convchr(handle, (const char **)&string,
237120492Sfjoe			&i, &outp, &j);
238120492Sfjoe		len -= i;
239120492Sfjoe	} else {
240120492Sfjoe		len = 1;
241120492Sfjoe		string++;
242120492Sfjoe	}
243120492Sfjoe
244120492Sfjoe	if (result) *result = string;
245120492Sfjoe	while(len--) c |= (*(string - len - 1) & 0xff) << (len << 3);
246120492Sfjoe	return (c);
247120492Sfjoe}
248