1 /* $NetBSD: cd9660_util.c,v 1.2 2003/08/07 16:31:35 agc Exp $ */ 2 3 /*- 4 * Copyright (c) 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley 8 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 9 * Support code is derived from software contributed to Berkeley 10 * by Atsushi Murai (amurai@spec.co.jp). 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)cd9660_util.c 8.3 (Berkeley) 12/5/94 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: cd9660_util.c,v 1.2 2003/08/07 16:31:35 agc Exp $"); 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/namei.h> 45 #include <sys/resourcevar.h> 46 #include <sys/kernel.h> 47 #include <sys/file.h> 48 #include <sys/stat.h> 49 #include <sys/buf.h> 50 #include <sys/proc.h> 51 #include <sys/mount.h> 52 #include <sys/vnode.h> 53 #include <sys/malloc.h> 54 #include <sys/dirent.h> 55 56 #include <fs/cd9660/iso.h> 57 #include <fs/cd9660/cd9660_extern.h> 58 59 /* 60 * Get one character out of an iso filename 61 * Return number of bytes consumed 62 */ 63 int 64 isochar(isofn, isoend, joliet_level, c) 65 const u_char *isofn; 66 const u_char *isoend; 67 int joliet_level; 68 u_char *c; 69 { 70 *c = *isofn++; 71 if (joliet_level == 0 || isofn == isoend) 72 /* (00) and (01) are one byte in Joliet, too */ 73 return 1; 74 75 /* No Unicode support yet :-( */ 76 switch (*c) { 77 default: 78 *c = '?'; 79 break; 80 case '\0': 81 *c = *isofn; 82 break; 83 } 84 return 2; 85 } 86 87 /* 88 * translate and compare a filename 89 * Note: Version number plus ';' may be omitted. 90 */ 91 int 92 isofncmp(fn, fnlen, isofn, isolen, joliet_level) 93 const u_char *fn, *isofn; 94 int fnlen, isolen, joliet_level; 95 { 96 int i, j; 97 char c; 98 const u_char *isoend = isofn + isolen; 99 100 while (--fnlen >= 0) { 101 if (isofn == isoend) 102 return *fn; 103 isofn += isochar(isofn, isoend, joliet_level, &c); 104 if (c == ';') { 105 switch (*fn++) { 106 default: 107 return *--fn; 108 case 0: 109 return 0; 110 case ';': 111 break; 112 } 113 for (i = 0; --fnlen >= 0; i = i * 10 + *fn++ - '0') { 114 if (*fn < '0' || *fn > '9') { 115 return -1; 116 } 117 } 118 for (j = 0; isofn != isoend; j = j * 10 + c - '0') 119 isofn += isochar(isofn, isoend, 120 joliet_level, &c); 121 return i - j; 122 } 123 if (((u_char) c) != *fn) { 124 if (c >= 'A' && c <= 'Z') { 125 if (c + ('a' - 'A') != *fn) { 126 if (*fn >= 'a' && *fn <= 'z') 127 return *fn - ('a' - 'A') - c; 128 else 129 return *fn - c; 130 } 131 } else 132 return *fn - c; 133 } 134 fn++; 135 } 136 if (isofn != isoend) { 137 isofn += isochar(isofn, isoend, joliet_level, &c); 138 switch (c) { 139 default: 140 return -1; 141 case '.': 142 if (isofn != isoend) { 143 isochar(isofn, isoend, joliet_level, &c); 144 if (c == ';') 145 return 0; 146 } 147 return -1; 148 case ';': 149 return 0; 150 } 151 } 152 return 0; 153 } 154 155 /* 156 * translate a filename 157 */ 158 void 159 isofntrans(infn, infnlen, outfn, outfnlen, original, casetrans, assoc, joliet_level) 160 u_char *infn, *outfn; 161 int infnlen; 162 u_short *outfnlen; 163 int original; 164 int casetrans; 165 int assoc; 166 int joliet_level; 167 { 168 int fnidx = 0; 169 u_char *infnend = infn + infnlen; 170 171 if (assoc) { 172 *outfn++ = ASSOCCHAR; 173 fnidx++; 174 } 175 for (; infn != infnend; fnidx++) { 176 char c; 177 178 infn += isochar(infn, infnend, joliet_level, &c); 179 180 if (casetrans && joliet_level == 0 && c >= 'A' && c <= 'Z') 181 *outfn++ = c + ('a' - 'A'); 182 else if (!original && c == ';') { 183 if (fnidx > 0 && outfn[-1] == '.') 184 fnidx--; 185 break; 186 } else 187 *outfn++ = c; 188 } 189 *outfnlen = fnidx; 190 } 191