2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* $NetBSD: cd9660_util.c,v 1.8 1994/12/13 22:33:25 mycroft Exp $ */
32 * The Regents of the University of California. All rights reserved.
34 * This code is derived from software contributed to Berkeley
35 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
36 * Support code is derived from software contributed to Berkeley
37 * by Atsushi Murai (amurai@spec.co.jp).
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. All advertising materials mentioning features or use of this software
48 * must display the following acknowledgement:
49 * This product includes software developed by the University of
50 * California, Berkeley and its contributors.
51 * 4. Neither the name of the University nor the names of its contributors
52 * may be used to endorse or promote products derived from this software
53 * without specific prior written permission.
55 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67 * @(#)cd9660_util.c 8.3 (Berkeley) 12/5/94
70 * 7-Dec-98 Add ATTR_VOL_MOUNTFLAGS attribute support - djb
71 * 18-Nov-98 Add support for volfs - djb
74 #include <sys/param.h>
75 #include <sys/systm.h>
76 #include <sys/vnode.h>
77 #include <sys/mount.h>
78 #include <sys/namei.h>
79 #include <sys/resourcevar.h>
80 #include <sys/kernel.h>
85 #include <sys/kauth.h>
87 #include <sys/utfconv.h>
88 #include <miscfs/specfs/specdev.h> /* XXX */
89 #include <miscfs/fifofs/fifo.h> /* XXX */
90 #include <sys/malloc.h>
93 #include <kern/assert.h>
95 #include <isofs/cd9660/iso.h>
96 #include <isofs/cd9660/cd9660_node.h>
97 #include <isofs/cd9660/iso_rrip.h>
99 #include <libkern/OSByteOrder.h>
102 * translate and compare a filename
103 * Note: Version number plus ';' may be omitted.
106 isofncmp(u_char
*fn
, int fnlen
, u_char
*isofn
, int isolen
)
111 while (--fnlen
>= 0) {
114 if ((c
= *isofn
++) == ';') {
123 for (i
= 0; --fnlen
>= 0; i
= i
* 10 + *fn
++ - '0') {
124 if (*fn
< '0' || *fn
> '9') {
128 for (j
= 0; --isolen
>= 0; j
= j
* 10 + *isofn
++ - '0');
131 /* if raw comparison fails, check if char was mapped */
133 if (c
>= 'A' && c
<= 'Z') {
134 if (c
+ ('a' - 'A') != *fn
) {
135 if (*fn
>= 'a' && *fn
<= 'z')
136 return *fn
- ('a' - 'A') - c
;
140 } else if (c
== '/') {
143 } else if (c
> 0 || *fn
!= '_')
164 * translate and compare a UCS-2 filename
165 * Note: Version number plus ';' may be omitted.
167 * The name pointed to by "fn" is the search name, whose characters are
168 * in native endian order. The name "ucsfn" is the on-disk name, whose
169 * characters are in big endian order.
173 ucsfncmp(u_int16_t
*fn
, int fnlen
, u_int16_t
*ucsfn
, int ucslen
)
178 /* convert byte count to char count */
182 while (--fnlen
>= 0) {
185 if ((c
= OSSwapBigToHostInt16(*ucsfn
++)) == UCS_SEPARATOR2
) {
194 for (i
= 0; --fnlen
>= 0; i
= i
* 10 + *fn
++ - '0') {
195 if (*fn
< '0' || *fn
> '9') {
199 for (j
= 0; --ucslen
>= 0; j
= j
* 10 + OSSwapBigToHostInt16(*ucsfn
++) - '0');
210 case OSSwapHostToBigConstInt16(UCS_SEPARATOR1
):
211 if (ucsfn
[1] != OSSwapHostToBigConstInt16(UCS_SEPARATOR2
))
213 case OSSwapHostToBigConstInt16(UCS_SEPARATOR2
):
222 * translate a filename
225 isofntrans(u_char
*infn
, int infnlen
, u_char
*outfn
, u_short
*outfnlen
,
226 int original
, int assoc
)
231 * Add a "._" prefix for associated files
234 *outfn
++ = ASSOCCHAR1
;
235 *outfn
++ = ASSOCCHAR2
;
239 for (; fnidx
< infnlen
; fnidx
++) {
243 * Some ISO 9600 CD names contain 8-bit chars.
244 * These chars are mapped to '_' because there
245 * is no context for mapping them to UTF-8.
246 * In addition '/' is mapped to ':'.
248 * isofncmp accounts for these mappings.
255 else if (c
== '.' && *infn
== ';')
268 * translate a UCS-2 filename to UTF-8
271 ucsfntrans(u_int16_t
*infn
, int infnlen
, u_char
*outfn
, u_short
*outfnlen
,
277 if (*(u_char
*)infn
== 0)
279 else if (*(u_char
*)infn
== 1)
290 * Add a "._" prefix for associated files
293 *outfn
++ = ASSOCCHAR1
;
294 *outfn
++ = ASSOCCHAR2
;
297 /* strip file version number */
298 for (fnidx
--; fnidx
> 0; fnidx
--) {
299 /* stop when ';' is found */
300 if (infn
[fnidx
] == OSSwapHostToBigConstInt16(UCS_SEPARATOR2
)) {
301 /* drop dangling dot */
302 if (fnidx
> 0 && infn
[fnidx
-1] == OSSwapHostToBigConstInt16(UCS_SEPARATOR1
))
311 flags
= UTF_NO_NULL_TERM
| UTF_DECOMPOSED
| UTF_BIG_ENDIAN
;
313 (void) utf8_encodestr(infn
, fnidx
* 2, outfn
, &outbytes
, ISO_JOLIET_NAMEMAX
, 0, flags
);
314 *outfnlen
= assoc
? outbytes
+ 2 : outbytes
;
320 * count the number of children by enumerating the directory
323 isochildcount(struct vnode
*vdp
, int *dircnt
, int *filcnt
)
326 struct buf
*bp
= NULL
;
328 struct iso_directory_record
*ep
;
339 bmask
= imp
->im_sector_size
- 1;
340 logblksize
= imp
->im_sector_size
;
341 blkoffset
= diroffset
= 0;
344 while (diroffset
< dp
->i_size
) {
346 * If offset is on a block boundary, read the next
347 * directory block. Release previous if it exists.
349 if ((diroffset
& bmask
) == 0) {
352 if ( (error
= cd9660_blkatoff(vdp
, SECTOFF(imp
, diroffset
), NULL
, &bp
)) )
357 ep
= (struct iso_directory_record
*)
358 (buf_dataptr(bp
) + blkoffset
);
360 reclen
= isonum_711(ep
->length
);
362 /* skip to next block, if any */
364 (diroffset
& ~bmask
) + logblksize
;
368 if ((reclen
< ISO_DIRECTORY_RECORD_SIZE
) ||
369 (blkoffset
+ reclen
> logblksize
) ||
370 (reclen
< ISO_DIRECTORY_RECORD_SIZE
+ isonum_711(ep
->name_len
))){
371 /* illegal, so give up */
376 * Some poorly mastered discs have an incorrect directory
377 * file size. If the '.' entry has a better size (bigger)
378 * then use that instead.
380 if ((diroffset
== 0) && (isonum_733(ep
->size
) > dp
->i_size
)) {
381 dp
->i_size
= isonum_733(ep
->size
);
384 if ( isonum_711(ep
->flags
) & directoryBit
)
386 else if ((isonum_711(ep
->flags
) & associatedBit
) == 0)
404 DerivePermissionSummary(uid_t owner
, gid_t group
, mode_t obj_mode
, __unused
struct iso_mnt
*imp
)
406 kauth_cred_t cred
= kauth_cred_get();
407 uint32_t permissions
;
410 /* User id 0 (root) always gets access. */
411 if (!suser(cred
, NULL
)) {
412 permissions
= R_OK
| X_OK
;
416 /* Otherwise, check the owner. */
417 if (owner
== kauth_cred_getuid(cred
)) {
418 permissions
= ((uint32_t)obj_mode
& S_IRWXU
) >> 6;
422 /* Otherwise, check the groups. */
423 if (kauth_cred_ismember_gid(cred
, group
, &is_member
) == 0 && is_member
) {
424 permissions
= ((uint32_t)obj_mode
& S_IRWXG
) >> 3;
428 /* Otherwise, settle for 'others' access. */
429 permissions
= (uint32_t)obj_mode
& S_IRWXO
;
432 return permissions
& ~W_OK
; /* Write access is always impossible */