1df8bae1dSRodney W. Grimes /*-
251369649SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
351369649SPedro F. Giffuni *
4df8bae1dSRodney W. Grimes * Copyright (c) 1994
5df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved.
6df8bae1dSRodney W. Grimes *
7df8bae1dSRodney W. Grimes * This code is derived from software contributed to Berkeley
8df8bae1dSRodney W. Grimes * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
9df8bae1dSRodney W. Grimes * Support code is derived from software contributed to Berkeley
1044e568e2SDaniel C. Sobral * by Atsushi Murai (amurai@spec.co.jp). Joliet support was added by
1144e568e2SDaniel C. Sobral * Joachim Kuebart (joki@kuebart.stuttgart.netsurf.de).
12df8bae1dSRodney W. Grimes *
13df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without
14df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions
15df8bae1dSRodney W. Grimes * are met:
16df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright
17df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer.
18df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright
19df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the
20df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution.
21fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
22df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software
23df8bae1dSRodney W. Grimes * without specific prior written permission.
24df8bae1dSRodney W. Grimes *
25df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35df8bae1dSRodney W. Grimes * SUCH DAMAGE.
36df8bae1dSRodney W. Grimes */
37df8bae1dSRodney W. Grimes
38df8bae1dSRodney W. Grimes #include <sys/param.h>
3944127115SJeff Roberson #include <sys/systm.h>
40df8bae1dSRodney W. Grimes #include <sys/mount.h>
41df8bae1dSRodney W. Grimes #include <sys/vnode.h>
42c4f02a89SMax Khon #include <sys/iconv.h>
43df8bae1dSRodney W. Grimes
44a8d36d0dSCraig Rodrigues #include <fs/cd9660/iso.h>
45a8d36d0dSCraig Rodrigues #include <fs/cd9660/cd9660_mount.h>
46df8bae1dSRodney W. Grimes
47c4f02a89SMax Khon extern struct iconv_functions *cd9660_iconv;
48c4fefc48SMaxim Sobolev
49c4fefc48SMaxim Sobolev /*
5044e568e2SDaniel C. Sobral * Get one character out of an iso filename
5144e568e2SDaniel C. Sobral * Obey joliet_level
5244e568e2SDaniel C. Sobral * Return number of bytes consumed
5344e568e2SDaniel C. Sobral */
5444e568e2SDaniel C. Sobral int
isochar(u_char * isofn,u_char * isoend,int joliet_level,u_short * c,int * clen,int flags,void * handle)55*a5f59e85SEd Maste isochar(u_char *isofn, u_char *isoend, int joliet_level, u_short *c, int *clen,
56*a5f59e85SEd Maste int flags, void *handle)
5744e568e2SDaniel C. Sobral {
58c4f02a89SMax Khon size_t i, j, len;
59c4f02a89SMax Khon char inbuf[3], outbuf[3], *inp, *outp;
60c4f02a89SMax Khon
6144e568e2SDaniel C. Sobral *c = *isofn++;
62c4f02a89SMax Khon if (clen) *clen = 1;
6344e568e2SDaniel C. Sobral if (joliet_level == 0 || isofn == isoend)
6444e568e2SDaniel C. Sobral /* (00) and (01) are one byte in Joliet, too */
6544e568e2SDaniel C. Sobral return 1;
6644e568e2SDaniel C. Sobral
67c4f02a89SMax Khon if (flags & ISOFSMNT_KICONV && cd9660_iconv) {
68c4f02a89SMax Khon i = j = len = 2;
69c4f02a89SMax Khon inbuf[0]=(char)*(isofn - 1);
70c4f02a89SMax Khon inbuf[1]=(char)*isofn;
71c4f02a89SMax Khon inbuf[2]='\0';
72c4f02a89SMax Khon inp = inbuf;
73c4f02a89SMax Khon outp = outbuf;
7403ce3d72SDimitry Andric cd9660_iconv->convchr(handle, __DECONST(const char **, &inp), &i,
7503ce3d72SDimitry Andric &outp, &j);
76c4f02a89SMax Khon len -= j;
77c4f02a89SMax Khon if (clen) *clen = len;
78c4f02a89SMax Khon *c = '\0';
79c4f02a89SMax Khon while(len--)
80c4f02a89SMax Khon *c |= (*(outp - len - 1) & 0xff) << (len << 3);
81c4f02a89SMax Khon } else {
8244e568e2SDaniel C. Sobral switch (*c) {
8344e568e2SDaniel C. Sobral default:
8444e568e2SDaniel C. Sobral *c = '?';
8544e568e2SDaniel C. Sobral break;
8644e568e2SDaniel C. Sobral case '\0':
8744e568e2SDaniel C. Sobral *c = *isofn;
8844e568e2SDaniel C. Sobral break;
8944e568e2SDaniel C. Sobral }
90c4f02a89SMax Khon }
91c4fefc48SMaxim Sobolev
9244e568e2SDaniel C. Sobral return 2;
9344e568e2SDaniel C. Sobral }
9444e568e2SDaniel C. Sobral
9544e568e2SDaniel C. Sobral /*
96df8bae1dSRodney W. Grimes * translate and compare a filename
9744e568e2SDaniel C. Sobral * returns (fn - isofn)
98df8bae1dSRodney W. Grimes * Note: Version number plus ';' may be omitted.
99df8bae1dSRodney W. Grimes */
100df8bae1dSRodney W. Grimes int
isofncmp(u_char * fn,int fnlen,u_char * isofn,int isolen,int joliet_level,int flags,void * handle,void * lhandle)101*a5f59e85SEd Maste isofncmp(u_char *fn, int fnlen, u_char *isofn, int isolen, int joliet_level,
102*a5f59e85SEd Maste int flags, void *handle, void *lhandle)
103df8bae1dSRodney W. Grimes {
104df8bae1dSRodney W. Grimes int i, j;
105c4f02a89SMax Khon u_short c, d;
106c4f02a89SMax Khon u_char *fnend = fn + fnlen, *isoend = isofn + isolen;
107df8bae1dSRodney W. Grimes
108c4f02a89SMax Khon for (; fn < fnend; ) {
10903ce3d72SDimitry Andric d = sgetrune(fn, fnend - fn, __DECONST(const char **, &fn),
11003ce3d72SDimitry Andric flags, lhandle);
11144e568e2SDaniel C. Sobral if (isofn == isoend)
112c4f02a89SMax Khon return d;
113c4f02a89SMax Khon isofn += isochar(isofn, isoend, joliet_level, &c, NULL, flags, handle);
11444e568e2SDaniel C. Sobral if (c == ';') {
115c4f02a89SMax Khon if (d != ';')
116c4f02a89SMax Khon return d;
117c4f02a89SMax Khon for (i = 0; fn < fnend; i = i * 10 + *fn++ - '0') {
118df8bae1dSRodney W. Grimes if (*fn < '0' || *fn > '9') {
119df8bae1dSRodney W. Grimes return -1;
120df8bae1dSRodney W. Grimes }
121df8bae1dSRodney W. Grimes }
12244e568e2SDaniel C. Sobral for (j = 0; isofn != isoend; j = j * 10 + c - '0')
12344e568e2SDaniel C. Sobral isofn += isochar(isofn, isoend,
124c4f02a89SMax Khon joliet_level, &c,
125c4f02a89SMax Khon NULL, flags, handle);
126df8bae1dSRodney W. Grimes return i - j;
127df8bae1dSRodney W. Grimes }
128c4f02a89SMax Khon if (c != d) {
129df8bae1dSRodney W. Grimes if (c >= 'A' && c <= 'Z') {
130c4f02a89SMax Khon if (c + ('a' - 'A') != d) {
131c4f02a89SMax Khon if (d >= 'a' && d <= 'z')
132c4f02a89SMax Khon return d - ('a' - 'A') - c;
133df8bae1dSRodney W. Grimes else
134c4f02a89SMax Khon return d - c;
135df8bae1dSRodney W. Grimes }
136df8bae1dSRodney W. Grimes } else
137c4f02a89SMax Khon return d - c;
138df8bae1dSRodney W. Grimes }
139df8bae1dSRodney W. Grimes }
14044e568e2SDaniel C. Sobral if (isofn != isoend) {
141c4f02a89SMax Khon isofn += isochar(isofn, isoend, joliet_level, &c, NULL, flags, handle);
14244e568e2SDaniel C. Sobral switch (c) {
143df8bae1dSRodney W. Grimes default:
14444e568e2SDaniel C. Sobral return -c;
145df8bae1dSRodney W. Grimes case '.':
14644e568e2SDaniel C. Sobral if (isofn != isoend) {
147c4f02a89SMax Khon isochar(isofn, isoend, joliet_level, &c,
148c4f02a89SMax Khon NULL, flags, handle);
14944e568e2SDaniel C. Sobral if (c == ';')
15044e568e2SDaniel C. Sobral return 0;
15144e568e2SDaniel C. Sobral }
152df8bae1dSRodney W. Grimes return -1;
153df8bae1dSRodney W. Grimes case ';':
154df8bae1dSRodney W. Grimes return 0;
155df8bae1dSRodney W. Grimes }
156df8bae1dSRodney W. Grimes }
157df8bae1dSRodney W. Grimes return 0;
158df8bae1dSRodney W. Grimes }
159df8bae1dSRodney W. Grimes
160df8bae1dSRodney W. Grimes /*
16144e568e2SDaniel C. Sobral * translate a filename of length > 0
162df8bae1dSRodney W. Grimes */
163df8bae1dSRodney W. Grimes void
isofntrans(u_char * infn,int infnlen,u_char * outfn,u_short * outfnlen,int original,int assoc,int joliet_level,int flags,void * handle)164*a5f59e85SEd Maste isofntrans(u_char *infn, int infnlen, u_char *outfn, u_short *outfnlen,
165*a5f59e85SEd Maste int original, int assoc, int joliet_level, int flags, void *handle)
166df8bae1dSRodney W. Grimes {
167c4f02a89SMax Khon u_short c, d = '\0';
168c4f02a89SMax Khon u_char *outp = outfn, *infnend = infn + infnlen;
169c4f02a89SMax Khon int clen;
170df8bae1dSRodney W. Grimes
171df8bae1dSRodney W. Grimes if (assoc) {
172c4f02a89SMax Khon *outp++ = ASSOCCHAR;
173df8bae1dSRodney W. Grimes }
174c4f02a89SMax Khon for (; infn != infnend; ) {
175c4f02a89SMax Khon infn += isochar(infn, infnend, joliet_level, &c, &clen, flags, handle);
176df8bae1dSRodney W. Grimes
177a5eec775SDaniel C. Sobral if (!original && !joliet_level && c >= 'A' && c <= 'Z')
178c4f02a89SMax Khon c += ('a' - 'A');
17944e568e2SDaniel C. Sobral else if (!original && c == ';') {
180c4f02a89SMax Khon outp -= (d == '.');
181df8bae1dSRodney W. Grimes break;
182df8bae1dSRodney W. Grimes }
183c4f02a89SMax Khon d = c;
184c4f02a89SMax Khon while(clen--)
185c4f02a89SMax Khon *outp++ = c >> (clen << 3);
186c4f02a89SMax Khon }
187c4f02a89SMax Khon *outfnlen = outp - outfn;
188c4f02a89SMax Khon }
189c4f02a89SMax Khon
190c4f02a89SMax Khon /*
191c4f02a89SMax Khon * same as sgetrune(3)
192c4f02a89SMax Khon */
193c4f02a89SMax Khon u_short
sgetrune(const char * string,size_t n,char const ** result,int flags,void * handle)194*a5f59e85SEd Maste sgetrune(const char *string, size_t n, char const **result, int flags,
195*a5f59e85SEd Maste void *handle)
196c4f02a89SMax Khon {
197c4f02a89SMax Khon size_t i, j, len;
198c4f02a89SMax Khon char outbuf[3], *outp;
199c4f02a89SMax Khon u_short c = '\0';
200c4f02a89SMax Khon
201c4f02a89SMax Khon len = i = (n < 2) ? n : 2;
202c4f02a89SMax Khon j = 2;
203c4f02a89SMax Khon outp = outbuf;
204c4f02a89SMax Khon
205c4f02a89SMax Khon if (flags & ISOFSMNT_KICONV && cd9660_iconv) {
206c4f02a89SMax Khon cd9660_iconv->convchr(handle, (const char **)&string,
207c4f02a89SMax Khon &i, &outp, &j);
208c4f02a89SMax Khon len -= i;
209c4f02a89SMax Khon } else {
210c4f02a89SMax Khon len = 1;
211c4f02a89SMax Khon string++;
212c4f02a89SMax Khon }
213c4f02a89SMax Khon
214c4f02a89SMax Khon if (result) *result = string;
215c4f02a89SMax Khon while(len--) c |= (*(string - len - 1) & 0xff) << (len << 3);
216c4f02a89SMax Khon return (c);
217df8bae1dSRodney W. Grimes }
218