]> git.saurik.com Git - apple/xnu.git/blob - bsd/isofs/cd9660/cd9660_util.c
xnu-517.7.7.tar.gz
[apple/xnu.git] / bsd / isofs / cd9660 / cd9660_util.c
1 /*
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /* $NetBSD: cd9660_util.c,v 1.8 1994/12/13 22:33:25 mycroft Exp $ */
23
24 /*-
25 * Copyright (c) 1994
26 * The Regents of the University of California. All rights reserved.
27 *
28 * This code is derived from software contributed to Berkeley
29 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
30 * Support code is derived from software contributed to Berkeley
31 * by Atsushi Murai (amurai@spec.co.jp).
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * @(#)cd9660_util.c 8.3 (Berkeley) 12/5/94
62 *
63 * HISTORY
64 * 7-Dec-98 Add ATTR_VOL_MOUNTFLAGS attribute support - djb
65 * 18-Nov-98 Add support for volfs - djb
66 */
67
68 #include <sys/param.h>
69 #include <sys/systm.h>
70 #include <sys/vnode.h>
71 #include <sys/mount.h>
72 #include <sys/namei.h>
73 #include <sys/resourcevar.h>
74 #include <sys/kernel.h>
75 #include <sys/file.h>
76 #include <sys/stat.h>
77 #include <sys/buf.h>
78 #include <sys/proc.h>
79 #include <sys/conf.h>
80 #include <sys/utfconv.h>
81 #include <miscfs/specfs/specdev.h> /* XXX */
82 #include <miscfs/fifofs/fifo.h> /* XXX */
83 #include <sys/malloc.h>
84 #include <sys/dir.h>
85 #include <sys/attr.h>
86 #include <kern/assert.h>
87 #include <architecture/byte_order.h>
88
89 #include <isofs/cd9660/iso.h>
90 #include <isofs/cd9660/cd9660_node.h>
91 #include <isofs/cd9660/iso_rrip.h>
92
93 /*
94 * translate and compare a filename
95 * Note: Version number plus ';' may be omitted.
96 */
97 int
98 isofncmp(fn, fnlen, isofn, isolen)
99 u_char *fn, *isofn;
100 int fnlen, isolen;
101 {
102 int i, j;
103 char c;
104
105 while (--fnlen >= 0) {
106 if (--isolen < 0)
107 return *fn;
108 if ((c = *isofn++) == ';') {
109 switch (*fn++) {
110 default:
111 return *--fn;
112 case 0:
113 return 0;
114 case ';':
115 break;
116 }
117 for (i = 0; --fnlen >= 0; i = i * 10 + *fn++ - '0') {
118 if (*fn < '0' || *fn > '9') {
119 return -1;
120 }
121 }
122 for (j = 0; --isolen >= 0; j = j * 10 + *isofn++ - '0');
123 return i - j;
124 }
125 /* if raw comparison fails, check if char was mapped */
126 if (c != *fn) {
127 if (c >= 'A' && c <= 'Z') {
128 if (c + ('a' - 'A') != *fn) {
129 if (*fn >= 'a' && *fn <= 'z')
130 return *fn - ('a' - 'A') - c;
131 else
132 return *fn - c;
133 }
134 } else if (c == '/') {
135 if (*fn != ':')
136 return *fn - c;
137 } else if (c > 0 || *fn != '_')
138 return *fn - c;
139 }
140 fn++;
141 }
142 if (isolen > 0) {
143 switch (*isofn) {
144 default:
145 return -1;
146 case '.':
147 if (isofn[1] != ';')
148 return -1;
149 case ';':
150 return 0;
151 }
152 }
153 return 0;
154 }
155
156
157 /*
158 * translate and compare a UCS-2 filename
159 * Note: Version number plus ';' may be omitted.
160 */
161
162 int
163 ucsfncmp(fn, fnlen, ucsfn, ucslen)
164 u_int16_t *fn;
165 int fnlen;
166 u_int16_t *ucsfn;
167 int ucslen;
168 {
169 int i, j;
170 u_int16_t c;
171
172 /* convert byte count to char count */
173 ucslen /= 2;
174 fnlen /= 2;
175
176 while (--fnlen >= 0) {
177 if (--ucslen < 0)
178 return *fn;
179 if ((c = *ucsfn++) == UCS_SEPARATOR2) {
180 switch (*fn++) {
181 default:
182 return *--fn;
183 case 0:
184 return 0;
185 case UCS_SEPARATOR2:
186 break;
187 }
188 for (i = 0; --fnlen >= 0; i = i * 10 + *fn++ - '0') {
189 if (*fn < '0' || *fn > '9') {
190 return -1;
191 }
192 }
193 for (j = 0; --ucslen >= 0; j = j * 10 + *ucsfn++ - '0');
194 return i - j;
195 }
196 if (c != *fn)
197 return *fn - c;
198 fn++;
199 }
200 if (ucslen > 0) {
201 switch (*ucsfn) {
202 default:
203 return -1;
204 case UCS_SEPARATOR1:
205 if (ucsfn[1] != UCS_SEPARATOR2)
206 return -1;
207 case UCS_SEPARATOR2:
208 return 0;
209 }
210 }
211 return 0;
212 }
213
214
215 /*
216 * translate a filename
217 */
218 void
219 isofntrans(infn, infnlen, outfn, outfnlen, original, assoc)
220 u_char *infn, *outfn;
221 int infnlen;
222 u_short *outfnlen;
223 int original;
224 int assoc;
225 {
226 int fnidx = 0;
227
228 /*
229 * Add a "._" prefix for associated files
230 */
231 if (assoc) {
232 *outfn++ = ASSOCCHAR1;
233 *outfn++ = ASSOCCHAR2;
234 fnidx += 2;
235 infnlen +=2;
236 }
237 for (; fnidx < infnlen; fnidx++) {
238 char c = *infn++;
239
240 /*
241 * Some ISO 9600 CD names contain 8-bit chars.
242 * These chars are mapped to '_' because there
243 * is no context for mapping them to UTF-8.
244 * In addition '/' is mapped to ':'.
245 *
246 * isofncmp accounts for these mappings.
247 */
248 if (!original) {
249 if (c < 0)
250 c = '_';
251 else if (c == '/')
252 c = ':';
253 else if (c == '.' && *infn == ';')
254 break;
255 else if (c == ';')
256 break;
257 }
258 *outfn++ = c;
259 }
260 *outfnlen = fnidx;
261 }
262
263
264
265 /*
266 * translate a UCS-2 filename to UTF-8
267 */
268 void
269 ucsfntrans(infn, infnlen, outfn, outfnlen, dir, assoc)
270 u_int16_t *infn;
271 int infnlen;
272 u_char *outfn;
273 u_short *outfnlen;
274 int dir;
275 int assoc;
276 {
277 if (infnlen == 1) {
278 strcpy(outfn, "..");
279
280 if (*(u_char*)infn == 0)
281 *outfnlen = 1;
282 else if (*(u_char*)infn == 1)
283 *outfnlen = 2;
284 } else {
285 int fnidx;
286 size_t outbytes;
287 int flags;
288
289 fnidx = infnlen/2;
290 flags = 0;
291
292 /*
293 * Add a "._" prefix for associated files
294 */
295 if (assoc) {
296 *outfn++ = ASSOCCHAR1;
297 *outfn++ = ASSOCCHAR2;
298 }
299 if (!dir) {
300 /* strip file version number */
301 for (fnidx--; fnidx > 0; fnidx--) {
302 /* stop when ';' is found */
303 if (infn[fnidx] == UCS_SEPARATOR2) {
304 /* drop dangling dot */
305 if (fnidx > 0 && infn[fnidx-1] == UCS_SEPARATOR1)
306 fnidx--;
307 break;
308 }
309 }
310 if (fnidx <= 0)
311 fnidx = infnlen/2;
312 }
313
314 flags = UTF_NO_NULL_TERM | UTF_DECOMPOSED;
315 if (BYTE_ORDER != BIG_ENDIAN)
316 flags |= UTF_REVERSE_ENDIAN;
317
318 (void) utf8_encodestr(infn, fnidx * 2, outfn, &outbytes, ISO_JOLIET_NAMEMAX, 0, flags);
319 *outfnlen = assoc ? outbytes + 2 : outbytes;
320 }
321 }
322
323
324 /*
325 * count the number of children by enumerating the directory
326 */
327 static int
328 isochildcount(vdp, dircnt, filcnt)
329 struct vnode *vdp;
330 int *dircnt;
331 int *filcnt;
332 {
333 struct iso_node *dp;
334 struct buf *bp = NULL;
335 struct iso_mnt *imp;
336 struct iso_directory_record *ep;
337 u_long bmask;
338 int error = 0;
339 int reclen;
340 int dirs, files;
341 int blkoffset;
342 int logblksize;
343 long diroffset;
344
345 dp = VTOI(vdp);
346 imp = dp->i_mnt;
347 bmask = imp->im_sector_size - 1;
348 logblksize = imp->im_sector_size;
349 blkoffset = diroffset = 0;
350 dirs = files = 0;
351
352 while (diroffset < dp->i_size) {
353 /*
354 * If offset is on a block boundary, read the next
355 * directory block. Release previous if it exists.
356 */
357 if ((diroffset & bmask) == 0) {
358 if (bp != NULL)
359 brelse(bp);
360 if ( (error = VOP_BLKATOFF(vdp, SECTOFF(imp, diroffset), NULL, &bp)) )
361 break;
362 blkoffset = 0;
363 }
364
365 ep = (struct iso_directory_record *)
366 ((char *)bp->b_data + blkoffset);
367
368 reclen = isonum_711(ep->length);
369 if (reclen == 0) {
370 /* skip to next block, if any */
371 diroffset =
372 (diroffset & ~bmask) + logblksize;
373 continue;
374 }
375
376 if ((reclen < ISO_DIRECTORY_RECORD_SIZE) ||
377 (blkoffset + reclen > logblksize) ||
378 (reclen < ISO_DIRECTORY_RECORD_SIZE + isonum_711(ep->name_len))){
379 /* illegal, so give up */
380 break;
381 }
382
383 /*
384 * Some poorly mastered discs have an incorrect directory
385 * file size. If the '.' entry has a better size (bigger)
386 * then use that instead.
387 */
388 if ((diroffset == 0) && (isonum_733(ep->size) > dp->i_size)) {
389 dp->i_size = isonum_733(ep->size);
390 }
391
392 if ( isonum_711(ep->flags) & directoryBit )
393 dirs++;
394 else if ((isonum_711(ep->flags) & associatedBit) == 0)
395 files++;
396
397 diroffset += reclen;
398 blkoffset += reclen;
399 }
400
401 if (bp)
402 brelse (bp);
403
404 *dircnt = dirs;
405 *filcnt = files;
406
407 return (error);
408 }
409
410
411 /*
412 * There are two ways to qualify for ownership rights on an object:
413 *
414 * 1. Your UID matches the UID of the vnode
415 * 2. You are root
416 *
417 */
418 static int cd9660_owner_rights(uid_t owner, struct iso_mnt *imp, struct ucred *cred, struct proc *p, int invokesuperuserstatus) {
419 return ((cred->cr_uid == owner) || /* [1] */
420 (invokesuperuserstatus && (suser(cred, &p->p_acflag) == 0))) ? 0 : EPERM; /* [2] */
421 }
422
423
424
425 static unsigned long DerivePermissionSummary(uid_t owner, gid_t group, mode_t obj_mode, struct iso_mnt *imp, struct ucred *cred, struct proc *p) {
426 register gid_t *gp;
427 unsigned long permissions;
428 int i;
429
430 /* User id 0 (root) always gets access. */
431 if (cred->cr_uid == 0) {
432 permissions = R_OK | X_OK;
433 goto Exit;
434 };
435
436 /* Otherwise, check the owner. */
437 if (cd9660_owner_rights(owner, imp, cred, p, 0) == 0) {
438 permissions = ((unsigned long)obj_mode & S_IRWXU) >> 6;
439 goto Exit;
440 }
441
442 /* Otherwise, check the groups. */
443 for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) {
444 if (group == *gp) {
445 permissions = ((unsigned long)obj_mode & S_IRWXG) >> 3;
446 goto Exit;
447 }
448 };
449
450 /* Otherwise, settle for 'others' access. */
451 permissions = (unsigned long)obj_mode & S_IRWXO;
452
453 Exit:
454 return permissions & ~W_OK; /* Write access is always impossible */
455 }
456
457
458 int
459 attrcalcsize(struct attrlist *attrlist)
460 {
461 int size;
462 attrgroup_t a;
463
464 #if ((ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID | ATTR_CMN_OBJTYPE | \
465 ATTR_CMN_OBJTAG | ATTR_CMN_OBJID | ATTR_CMN_OBJPERMANENTID | ATTR_CMN_PAROBJID | \
466 ATTR_CMN_SCRIPT | ATTR_CMN_CRTIME | ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | \
467 ATTR_CMN_ACCTIME | ATTR_CMN_BKUPTIME | ATTR_CMN_FNDRINFO | ATTR_CMN_OWNERID | \
468 ATTR_CMN_GRPID | ATTR_CMN_ACCESSMASK | ATTR_CMN_NAMEDATTRCOUNT | ATTR_CMN_NAMEDATTRLIST| \
469 ATTR_CMN_FLAGS | ATTR_CMN_USERACCESS) != ATTR_CMN_VALIDMASK)
470 #error AttributeBlockSize: Missing bits in common mask computation!
471 #endif
472 assert((attrlist->commonattr & ~ATTR_CMN_VALIDMASK) == 0);
473
474 #if ((ATTR_VOL_FSTYPE | ATTR_VOL_SIGNATURE | ATTR_VOL_SIZE | ATTR_VOL_SPACEFREE | \
475 ATTR_VOL_SPACEAVAIL | ATTR_VOL_MINALLOCATION | ATTR_VOL_ALLOCATIONCLUMP | ATTR_VOL_IOBLOCKSIZE | \
476 ATTR_VOL_OBJCOUNT | ATTR_VOL_FILECOUNT | ATTR_VOL_DIRCOUNT | ATTR_VOL_MAXOBJCOUNT | \
477 ATTR_VOL_MOUNTPOINT | ATTR_VOL_NAME | ATTR_VOL_MOUNTFLAGS | ATTR_VOL_INFO | \
478 ATTR_VOL_MOUNTEDDEVICE| ATTR_VOL_ENCODINGSUSED | ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES) != ATTR_VOL_VALIDMASK)
479 #error AttributeBlockSize: Missing bits in volume mask computation!
480 #endif
481 assert((attrlist->volattr & ~ATTR_VOL_VALIDMASK) == 0);
482
483 #if ((ATTR_DIR_LINKCOUNT | ATTR_DIR_ENTRYCOUNT | ATTR_DIR_MOUNTSTATUS) != ATTR_DIR_VALIDMASK)
484 #error AttributeBlockSize: Missing bits in directory mask computation!
485 #endif
486 assert((attrlist->dirattr & ~ATTR_DIR_VALIDMASK) == 0);
487 #if ((ATTR_FILE_LINKCOUNT | ATTR_FILE_TOTALSIZE | ATTR_FILE_ALLOCSIZE | ATTR_FILE_IOBLOCKSIZE | \
488 ATTR_FILE_CLUMPSIZE | ATTR_FILE_DEVTYPE | ATTR_FILE_FILETYPE | ATTR_FILE_FORKCOUNT | \
489 ATTR_FILE_FORKLIST | ATTR_FILE_DATALENGTH | ATTR_FILE_DATAALLOCSIZE | ATTR_FILE_DATAEXTENTS | \
490 ATTR_FILE_RSRCLENGTH | ATTR_FILE_RSRCALLOCSIZE | ATTR_FILE_RSRCEXTENTS) != ATTR_FILE_VALIDMASK)
491 #error AttributeBlockSize: Missing bits in file mask computation!
492 #endif
493 assert((attrlist->fileattr & ~ATTR_FILE_VALIDMASK) == 0);
494
495 #if ((ATTR_FORK_TOTALSIZE | ATTR_FORK_ALLOCSIZE) != ATTR_FORK_VALIDMASK)
496 #error AttributeBlockSize: Missing bits in fork mask computation!
497 #endif
498 assert((attrlist->forkattr & ~ATTR_FORK_VALIDMASK) == 0);
499
500 size = 0;
501
502 if ((a = attrlist->commonattr) != 0) {
503 if (a & ATTR_CMN_NAME) size += sizeof(struct attrreference);
504 if (a & ATTR_CMN_DEVID) size += sizeof(dev_t);
505 if (a & ATTR_CMN_FSID) size += sizeof(fsid_t);
506 if (a & ATTR_CMN_OBJTYPE) size += sizeof(fsobj_type_t);
507 if (a & ATTR_CMN_OBJTAG) size += sizeof(fsobj_tag_t);
508 if (a & ATTR_CMN_OBJID) size += sizeof(fsobj_id_t);
509 if (a & ATTR_CMN_OBJPERMANENTID) size += sizeof(fsobj_id_t);
510 if (a & ATTR_CMN_PAROBJID) size += sizeof(fsobj_id_t);
511 if (a & ATTR_CMN_SCRIPT) size += sizeof(text_encoding_t);
512 if (a & ATTR_CMN_CRTIME) size += sizeof(struct timespec);
513 if (a & ATTR_CMN_MODTIME) size += sizeof(struct timespec);
514 if (a & ATTR_CMN_CHGTIME) size += sizeof(struct timespec);
515 if (a & ATTR_CMN_ACCTIME) size += sizeof(struct timespec);
516 if (a & ATTR_CMN_BKUPTIME) size += sizeof(struct timespec);
517 if (a & ATTR_CMN_FNDRINFO) size += 32 * sizeof(u_int8_t);
518 if (a & ATTR_CMN_OWNERID) size += sizeof(uid_t);
519 if (a & ATTR_CMN_GRPID) size += sizeof(gid_t);
520 if (a & ATTR_CMN_ACCESSMASK) size += sizeof(u_long);
521 if (a & ATTR_CMN_NAMEDATTRCOUNT) size += sizeof(u_long);
522 if (a & ATTR_CMN_NAMEDATTRLIST) size += sizeof(struct attrreference);
523 if (a & ATTR_CMN_FLAGS) size += sizeof(u_long);
524 if (a & ATTR_CMN_USERACCESS) size += sizeof(u_long);
525 };
526 if ((a = attrlist->volattr) != 0) {
527 if (a & ATTR_VOL_FSTYPE) size += sizeof(u_long);
528 if (a & ATTR_VOL_SIGNATURE) size += sizeof(u_long);
529 if (a & ATTR_VOL_SIZE) size += sizeof(off_t);
530 if (a & ATTR_VOL_SPACEFREE) size += sizeof(off_t);
531 if (a & ATTR_VOL_SPACEAVAIL) size += sizeof(off_t);
532 if (a & ATTR_VOL_MINALLOCATION) size += sizeof(off_t);
533 if (a & ATTR_VOL_ALLOCATIONCLUMP) size += sizeof(off_t);
534 if (a & ATTR_VOL_IOBLOCKSIZE) size += sizeof(size_t);
535 if (a & ATTR_VOL_OBJCOUNT) size += sizeof(u_long);
536 if (a & ATTR_VOL_FILECOUNT) size += sizeof(u_long);
537 if (a & ATTR_VOL_DIRCOUNT) size += sizeof(u_long);
538 if (a & ATTR_VOL_MAXOBJCOUNT) size += sizeof(u_long);
539 if (a & ATTR_VOL_MOUNTPOINT) size += sizeof(struct attrreference);
540 if (a & ATTR_VOL_NAME) size += sizeof(struct attrreference);
541 if (a & ATTR_VOL_MOUNTFLAGS) size += sizeof(u_long);
542 if (a & ATTR_VOL_MOUNTEDDEVICE) size += sizeof(struct attrreference);
543 if (a & ATTR_VOL_ENCODINGSUSED) size += sizeof(unsigned long long);
544 if (a & ATTR_VOL_CAPABILITIES) size += sizeof(vol_capabilities_attr_t);
545 if (a & ATTR_VOL_ATTRIBUTES) size += sizeof(vol_attributes_attr_t);
546 };
547 if ((a = attrlist->dirattr) != 0) {
548 if (a & ATTR_DIR_LINKCOUNT) size += sizeof(u_long);
549 if (a & ATTR_DIR_ENTRYCOUNT) size += sizeof(u_long);
550 if (a & ATTR_DIR_MOUNTSTATUS) size += sizeof(u_long);
551 };
552 if ((a = attrlist->fileattr) != 0) {
553 if (a & ATTR_FILE_LINKCOUNT) size += sizeof(u_long);
554 if (a & ATTR_FILE_TOTALSIZE) size += sizeof(off_t);
555 if (a & ATTR_FILE_ALLOCSIZE) size += sizeof(off_t);
556 if (a & ATTR_FILE_IOBLOCKSIZE) size += sizeof(size_t);
557 if (a & ATTR_FILE_CLUMPSIZE) size += sizeof(off_t);
558 if (a & ATTR_FILE_DEVTYPE) size += sizeof(u_long);
559 if (a & ATTR_FILE_FILETYPE) size += sizeof(u_long);
560 if (a & ATTR_FILE_FORKCOUNT) size += sizeof(u_long);
561 if (a & ATTR_FILE_FORKLIST) size += sizeof(struct attrreference);
562 if (a & ATTR_FILE_DATALENGTH) size += sizeof(off_t);
563 if (a & ATTR_FILE_DATAALLOCSIZE) size += sizeof(off_t);
564 if (a & ATTR_FILE_DATAEXTENTS) size += sizeof(extentrecord);
565 if (a & ATTR_FILE_RSRCLENGTH) size += sizeof(off_t);
566 if (a & ATTR_FILE_RSRCALLOCSIZE) size += sizeof(off_t);
567 if (a & ATTR_FILE_RSRCEXTENTS) size += sizeof(extentrecord);
568 };
569 if ((a = attrlist->forkattr) != 0) {
570 if (a & ATTR_FORK_TOTALSIZE) size += sizeof(off_t);
571 if (a & ATTR_FORK_ALLOCSIZE) size += sizeof(off_t);
572 };
573
574 return size;
575 }
576
577
578
579 void
580 packvolattr (struct attrlist *alist,
581 struct iso_node *ip, /* ip for root directory */
582 void **attrbufptrptr,
583 void **varbufptrptr)
584 {
585 void *attrbufptr;
586 void *varbufptr;
587 struct iso_mnt *imp;
588 struct mount *mp;
589 attrgroup_t a;
590 u_long attrlength;
591
592 attrbufptr = *attrbufptrptr;
593 varbufptr = *varbufptrptr;
594 imp = ip->i_mnt;
595 mp = imp->im_mountp;
596
597 if ((a = alist->commonattr) != 0) {
598 if (a & ATTR_CMN_NAME) {
599 attrlength = strlen( imp->volume_id ) + 1;
600 ((struct attrreference *)attrbufptr)->attr_dataoffset = (u_int8_t *)varbufptr - (u_int8_t *)attrbufptr;
601 ((struct attrreference *)attrbufptr)->attr_length = attrlength;
602 (void) strncpy((unsigned char *)varbufptr, imp->volume_id, attrlength);
603
604 /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
605 (u_int8_t *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
606 ++((struct attrreference *)attrbufptr);
607 };
608 if (a & ATTR_CMN_DEVID) *((dev_t *)attrbufptr)++ = imp->im_devvp->v_rdev;
609 if (a & ATTR_CMN_FSID) *((fsid_t *)attrbufptr)++ = ITOV(ip)->v_mount->mnt_stat.f_fsid;
610 if (a & ATTR_CMN_OBJTYPE) *((fsobj_type_t *)attrbufptr)++ = 0;
611 if (a & ATTR_CMN_OBJTAG) *((fsobj_tag_t *)attrbufptr)++ = VT_ISOFS;
612 if (a & ATTR_CMN_OBJID) {
613 ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
614 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
615 ++((fsobj_id_t *)attrbufptr);
616 };
617 if (a & ATTR_CMN_OBJPERMANENTID) {
618 ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
619 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
620 ++((fsobj_id_t *)attrbufptr);
621 };
622 if (a & ATTR_CMN_PAROBJID) {
623 ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
624 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
625 ++((fsobj_id_t *)attrbufptr);
626 };
627 if (a & ATTR_CMN_SCRIPT) *((text_encoding_t *)attrbufptr)++ = 0;
628 if (a & ATTR_CMN_CRTIME) *((struct timespec *)attrbufptr)++ = imp->creation_date;
629 if (a & ATTR_CMN_MODTIME) *((struct timespec *)attrbufptr)++ = imp->modification_date;
630 if (a & ATTR_CMN_CHGTIME) *((struct timespec *)attrbufptr)++ = imp->modification_date;
631 if (a & ATTR_CMN_ACCTIME) *((struct timespec *)attrbufptr)++ = imp->modification_date;
632 if (a & ATTR_CMN_BKUPTIME) {
633 ((struct timespec *)attrbufptr)->tv_sec = 0;
634 ((struct timespec *)attrbufptr)->tv_nsec = 0;
635 ++((struct timespec *)attrbufptr);
636 };
637 if (a & ATTR_CMN_FNDRINFO) {
638 bzero (attrbufptr, 32 * sizeof(u_int8_t));
639 (u_int8_t *)attrbufptr += 32 * sizeof(u_int8_t);
640 };
641 if (a & ATTR_CMN_OWNERID) *((uid_t *)attrbufptr)++ = ip->inode.iso_uid;
642 if (a & ATTR_CMN_GRPID) *((gid_t *)attrbufptr)++ = ip->inode.iso_gid;
643 if (a & ATTR_CMN_ACCESSMASK) *((u_long *)attrbufptr)++ = (u_long)ip->inode.iso_mode;
644 if (a & ATTR_CMN_FLAGS) *((u_long *)attrbufptr)++ = 0;
645 if (a & ATTR_CMN_USERACCESS) {
646 *((u_long *)attrbufptr)++ =
647 DerivePermissionSummary(ip->inode.iso_uid,
648 ip->inode.iso_gid,
649 ip->inode.iso_mode,
650 imp,
651 current_proc()->p_ucred,
652 current_proc());
653 };
654 };
655
656 if ((a = alist->volattr) != 0) {
657 off_t blocksize = (off_t)imp->logical_block_size;
658
659 if (a & ATTR_VOL_FSTYPE) *((u_long *)attrbufptr)++ = (u_long)imp->im_mountp->mnt_vfc->vfc_typenum;
660 if (a & ATTR_VOL_SIGNATURE) *((u_long *)attrbufptr)++ = (u_long)ISO9660SIGNATURE;
661 if (a & ATTR_VOL_SIZE) *((off_t *)attrbufptr)++ = (off_t)imp->volume_space_size * blocksize;
662 if (a & ATTR_VOL_SPACEFREE) *((off_t *)attrbufptr)++ = 0;
663 if (a & ATTR_VOL_SPACEAVAIL) *((off_t *)attrbufptr)++ = 0;
664 if (a & ATTR_VOL_MINALLOCATION) *((off_t *)attrbufptr)++ = blocksize;
665 if (a & ATTR_VOL_ALLOCATIONCLUMP) *((off_t *)attrbufptr)++ = blocksize;
666 if (a & ATTR_VOL_IOBLOCKSIZE) *((size_t *)attrbufptr)++ = blocksize;
667 if (a & ATTR_VOL_OBJCOUNT) *((u_long *)attrbufptr)++ = 0;
668 if (a & ATTR_VOL_FILECOUNT) *((u_long *)attrbufptr)++ = 0;
669 if (a & ATTR_VOL_DIRCOUNT) *((u_long *)attrbufptr)++ = 0;
670 if (a & ATTR_VOL_MAXOBJCOUNT) *((u_long *)attrbufptr)++ = 0xFFFFFFFF;
671 if (a & ATTR_VOL_NAME) {
672 attrlength = strlen( imp->volume_id ) + 1;
673 ((struct attrreference *)attrbufptr)->attr_dataoffset = (u_int8_t *)varbufptr - (u_int8_t *)attrbufptr;
674 ((struct attrreference *)attrbufptr)->attr_length = attrlength;
675 (void) strncpy((unsigned char *)varbufptr, imp->volume_id, attrlength);
676
677 /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
678 (u_int8_t *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
679 ++((struct attrreference *)attrbufptr);
680 };
681 if (a & ATTR_VOL_MOUNTFLAGS) *((u_long *)attrbufptr)++ = (u_long)imp->im_mountp->mnt_flag;
682 if (a & ATTR_VOL_MOUNTEDDEVICE) {
683 ((struct attrreference *)attrbufptr)->attr_dataoffset = (u_int8_t *)varbufptr - (u_int8_t *)attrbufptr;
684 ((struct attrreference *)attrbufptr)->attr_length = strlen(mp->mnt_stat.f_mntfromname) + 1;
685 attrlength = ((struct attrreference *)attrbufptr)->attr_length;
686 attrlength = attrlength + ((4 - (attrlength & 3)) & 3); /* round up to the next 4-byte boundary: */
687 (void) bcopy(mp->mnt_stat.f_mntfromname, varbufptr, attrlength);
688
689 /* Advance beyond the space just allocated: */
690 (u_int8_t *)varbufptr += attrlength;
691 ++((struct attrreference *)attrbufptr);
692 };
693 if (a & ATTR_VOL_ENCODINGSUSED) *((unsigned long long *)attrbufptr)++ = (unsigned long long)0;
694 if (a & ATTR_VOL_CAPABILITIES) {
695 ((vol_capabilities_attr_t *)attrbufptr)->capabilities[VOL_CAPABILITIES_FORMAT] =
696 (imp->iso_ftype == ISO_FTYPE_RRIP ? VOL_CAP_FMT_SYMBOLICLINKS : 0) |
697 (imp->iso_ftype == ISO_FTYPE_RRIP ? VOL_CAP_FMT_HARDLINKS : 0) |
698 (imp->iso_ftype == ISO_FTYPE_RRIP || imp->iso_ftype == ISO_FTYPE_JOLIET
699 ? VOL_CAP_FMT_CASE_SENSITIVE : 0) |
700 VOL_CAP_FMT_CASE_PRESERVING |
701 VOL_CAP_FMT_FAST_STATFS;
702 ((vol_capabilities_attr_t *)attrbufptr)->capabilities[VOL_CAPABILITIES_INTERFACES] =
703 VOL_CAP_INT_ATTRLIST |
704 VOL_CAP_INT_NFSEXPORT;
705 ((vol_capabilities_attr_t *)attrbufptr)->capabilities[VOL_CAPABILITIES_RESERVED1] = 0;
706 ((vol_capabilities_attr_t *)attrbufptr)->capabilities[VOL_CAPABILITIES_RESERVED2] = 0;
707
708 ((vol_capabilities_attr_t *)attrbufptr)->valid[VOL_CAPABILITIES_FORMAT] =
709 VOL_CAP_FMT_PERSISTENTOBJECTIDS |
710 VOL_CAP_FMT_SYMBOLICLINKS |
711 VOL_CAP_FMT_HARDLINKS |
712 VOL_CAP_FMT_JOURNAL |
713 VOL_CAP_FMT_JOURNAL_ACTIVE |
714 VOL_CAP_FMT_NO_ROOT_TIMES |
715 VOL_CAP_FMT_SPARSE_FILES |
716 VOL_CAP_FMT_ZERO_RUNS |
717 VOL_CAP_FMT_CASE_SENSITIVE |
718 VOL_CAP_FMT_CASE_PRESERVING |
719 VOL_CAP_FMT_FAST_STATFS;
720 ((vol_capabilities_attr_t *)attrbufptr)->valid[VOL_CAPABILITIES_INTERFACES] =
721 VOL_CAP_INT_SEARCHFS |
722 VOL_CAP_INT_ATTRLIST |
723 VOL_CAP_INT_NFSEXPORT |
724 VOL_CAP_INT_READDIRATTR |
725 VOL_CAP_INT_EXCHANGEDATA |
726 VOL_CAP_INT_COPYFILE |
727 VOL_CAP_INT_ALLOCATE |
728 VOL_CAP_INT_VOL_RENAME |
729 VOL_CAP_INT_ADVLOCK |
730 VOL_CAP_INT_FLOCK;
731 ((vol_capabilities_attr_t *)attrbufptr)->valid[VOL_CAPABILITIES_RESERVED1] = 0;
732 ((vol_capabilities_attr_t *)attrbufptr)->valid[VOL_CAPABILITIES_RESERVED2] = 0;
733
734 ++((vol_capabilities_attr_t *)attrbufptr);
735 };
736 if (a & ATTR_VOL_ATTRIBUTES) {
737 ((vol_attributes_attr_t *)attrbufptr)->validattr.commonattr = ATTR_CMN_VALIDMASK;
738 ((vol_attributes_attr_t *)attrbufptr)->validattr.volattr = ATTR_VOL_VALIDMASK;
739 ((vol_attributes_attr_t *)attrbufptr)->validattr.dirattr = ATTR_DIR_VALIDMASK;
740 ((vol_attributes_attr_t *)attrbufptr)->validattr.fileattr = ATTR_FILE_VALIDMASK;
741 ((vol_attributes_attr_t *)attrbufptr)->validattr.forkattr = ATTR_FORK_VALIDMASK;
742
743 ((vol_attributes_attr_t *)attrbufptr)->nativeattr.commonattr = ATTR_CMN_VALIDMASK;
744 ((vol_attributes_attr_t *)attrbufptr)->nativeattr.volattr = ATTR_VOL_VALIDMASK;
745 ((vol_attributes_attr_t *)attrbufptr)->nativeattr.dirattr = ATTR_DIR_VALIDMASK;
746 ((vol_attributes_attr_t *)attrbufptr)->nativeattr.fileattr = ATTR_FILE_VALIDMASK;
747 ((vol_attributes_attr_t *)attrbufptr)->nativeattr.forkattr = ATTR_FORK_VALIDMASK;
748
749 ++((vol_attributes_attr_t *)attrbufptr);
750 };
751 };
752
753 *attrbufptrptr = attrbufptr;
754 *varbufptrptr = varbufptr;
755 }
756
757
758 void
759 packcommonattr (struct attrlist *alist,
760 struct iso_node *ip,
761 void **attrbufptrptr,
762 void **varbufptrptr)
763 {
764 void *attrbufptr;
765 void *varbufptr;
766 attrgroup_t a;
767 u_long attrlength;
768
769 attrbufptr = *attrbufptrptr;
770 varbufptr = *varbufptrptr;
771
772 if ((a = alist->commonattr) != 0) {
773 struct iso_mnt *imp = ip->i_mnt;
774
775 if (a & ATTR_CMN_NAME) {
776 /* special case root since we know how to get it's name */
777 if (ITOV(ip)->v_flag & VROOT) {
778 attrlength = strlen( imp->volume_id ) + 1;
779 (void) strncpy((unsigned char *)varbufptr, imp->volume_id, attrlength);
780 } else {
781 attrlength = strlen(ip->i_namep) + 1;
782 (void) strncpy((unsigned char *)varbufptr, ip->i_namep, attrlength);
783 }
784
785 ((struct attrreference *)attrbufptr)->attr_dataoffset = (u_int8_t *)varbufptr - (u_int8_t *)attrbufptr;
786 ((struct attrreference *)attrbufptr)->attr_length = attrlength;
787 /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
788 (u_int8_t *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
789 ++((struct attrreference *)attrbufptr);
790 };
791 if (a & ATTR_CMN_DEVID) *((dev_t *)attrbufptr)++ = ip->i_dev;
792 if (a & ATTR_CMN_FSID) *((fsid_t *)attrbufptr)++ = ITOV(ip)->v_mount->mnt_stat.f_fsid;
793 if (a & ATTR_CMN_OBJTYPE) *((fsobj_type_t *)attrbufptr)++ = ITOV(ip)->v_type;
794 if (a & ATTR_CMN_OBJTAG) *((fsobj_tag_t *)attrbufptr)++ = ITOV(ip)->v_tag;
795 if (a & ATTR_CMN_OBJID) {
796 if (ITOV(ip)->v_flag & VROOT)
797 ((fsobj_id_t *)attrbufptr)->fid_objno = 2; /* force root to be 2 */
798 else
799 ((fsobj_id_t *)attrbufptr)->fid_objno = ip->i_number;
800 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
801 ++((fsobj_id_t *)attrbufptr);
802 };
803 if (a & ATTR_CMN_OBJPERMANENTID) {
804 if (ITOV(ip)->v_flag & VROOT)
805 ((fsobj_id_t *)attrbufptr)->fid_objno = 2; /* force root to be 2 */
806 else
807 ((fsobj_id_t *)attrbufptr)->fid_objno = ip->i_number;
808 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
809 ++((fsobj_id_t *)attrbufptr);
810 };
811 if (a & ATTR_CMN_PAROBJID) {
812 struct iso_directory_record *dp = (struct iso_directory_record *)imp->root;
813 ino_t rootino = isodirino(dp, imp);
814
815 if (ip->i_number == rootino)
816 ((fsobj_id_t *)attrbufptr)->fid_objno = 1; /* force root parent to be 1 */
817 else if (ip->i_parent == rootino)
818 ((fsobj_id_t *)attrbufptr)->fid_objno = 2; /* force root to be 2 */
819 else
820 ((fsobj_id_t *)attrbufptr)->fid_objno = ip->i_parent;
821 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
822 ++((fsobj_id_t *)attrbufptr);
823 };
824 if (a & ATTR_CMN_SCRIPT) *((text_encoding_t *)attrbufptr)++ = 0;
825 if (a & ATTR_CMN_CRTIME) *((struct timespec *)attrbufptr)++ = ip->inode.iso_mtime;
826 if (a & ATTR_CMN_MODTIME) *((struct timespec *)attrbufptr)++ = ip->inode.iso_mtime;
827 if (a & ATTR_CMN_CHGTIME) *((struct timespec *)attrbufptr)++ = ip->inode.iso_ctime;
828 if (a & ATTR_CMN_ACCTIME) *((struct timespec *)attrbufptr)++ = ip->inode.iso_atime;
829 if (a & ATTR_CMN_BKUPTIME) {
830 ((struct timespec *)attrbufptr)->tv_sec = 0;
831 ((struct timespec *)attrbufptr)->tv_nsec = 0;
832 ++((struct timespec *)attrbufptr);
833 };
834 if (a & ATTR_CMN_FNDRINFO) {
835 struct finder_info finfo = {0};
836
837 finfo.fdFlags = ip->i_FinderFlags;
838 finfo.fdLocation.v = -1;
839 finfo.fdLocation.h = -1;
840 if (ITOV(ip)->v_type == VREG) {
841 finfo.fdType = ip->i_FileType;
842 finfo.fdCreator = ip->i_Creator;
843 }
844 bcopy (&finfo, attrbufptr, sizeof(finfo));
845 (u_int8_t *)attrbufptr += sizeof(finfo);
846 bzero (attrbufptr, EXTFNDRINFOSIZE);
847 (u_int8_t *)attrbufptr += EXTFNDRINFOSIZE;
848 };
849 if (a & ATTR_CMN_OWNERID) *((uid_t *)attrbufptr)++ = ip->inode.iso_uid;
850 if (a & ATTR_CMN_GRPID) *((gid_t *)attrbufptr)++ = ip->inode.iso_gid;
851 if (a & ATTR_CMN_ACCESSMASK) *((u_long *)attrbufptr)++ = (u_long)ip->inode.iso_mode;
852 if (a & ATTR_CMN_FLAGS) *((u_long *)attrbufptr)++ = 0; /* could also use ip->i_flag */
853 if (a & ATTR_CMN_USERACCESS) {
854 *((u_long *)attrbufptr)++ =
855 DerivePermissionSummary(ip->inode.iso_uid,
856 ip->inode.iso_gid,
857 ip->inode.iso_mode,
858 imp,
859 current_proc()->p_ucred,
860 current_proc());
861 };
862 };
863
864 *attrbufptrptr = attrbufptr;
865 *varbufptrptr = varbufptr;
866 }
867
868
869 void
870 packdirattr(struct attrlist *alist,
871 struct iso_node *ip,
872 void **attrbufptrptr,
873 void **varbufptrptr)
874 {
875 void *attrbufptr;
876 attrgroup_t a;
877 int filcnt, dircnt;
878
879 attrbufptr = *attrbufptrptr;
880 filcnt = dircnt = 0;
881
882 a = alist->dirattr;
883 if ((ITOV(ip)->v_type == VDIR) && (a != 0)) {
884 /*
885 * if we haven't counted our children yet, do it now...
886 */
887 if ((ip->i_entries == 0) &&
888 (a & (ATTR_DIR_LINKCOUNT | ATTR_DIR_ENTRYCOUNT))) {
889 (void) isochildcount(ITOV(ip), &dircnt, &filcnt);
890
891 if ((ip->inode.iso_links == 1) && (dircnt != 0))
892 ip->inode.iso_links = dircnt;
893 if ((filcnt + dircnt) > 0)
894 ip->i_entries = dircnt + filcnt;
895 }
896
897 if (a & ATTR_DIR_LINKCOUNT) {
898 *((u_long *)attrbufptr)++ = ip->inode.iso_links;
899 }
900 if (a & ATTR_DIR_ENTRYCOUNT) {
901 /* exclude '.' and '..' from total caount */
902 *((u_long *)attrbufptr)++ = ((ip->i_entries <= 2) ? 0 : (ip->i_entries - 2));
903 }
904 if (a & ATTR_DIR_MOUNTSTATUS) {
905 if (ITOV(ip)->v_mountedhere) {
906 *((u_long *)attrbufptr)++ = DIR_MNTSTATUS_MNTPOINT;
907 } else {
908 *((u_long *)attrbufptr)++ = 0;
909 };
910 };
911 };
912
913 *attrbufptrptr = attrbufptr;
914 }
915
916
917 void
918 packfileattr(struct attrlist *alist,
919 struct iso_node *ip,
920 void **attrbufptrptr,
921 void **varbufptrptr)
922 {
923 void *attrbufptr = *attrbufptrptr;
924 void *varbufptr = *varbufptrptr;
925 attrgroup_t a = alist->fileattr;
926
927 if ((ITOV(ip)->v_type == VREG) && (a != 0)) {
928 if (a & ATTR_FILE_LINKCOUNT)
929 *((u_long *)attrbufptr)++ = ip->inode.iso_links;
930 if (a & ATTR_FILE_TOTALSIZE)
931 *((off_t *)attrbufptr)++ = (off_t)ip->i_size;
932 if (a & ATTR_FILE_ALLOCSIZE)
933 *((off_t *)attrbufptr)++ = (off_t)ip->i_size;
934 if (a & ATTR_FILE_IOBLOCKSIZE)
935 *((u_long *)attrbufptr)++ = ip->i_mnt->logical_block_size;
936 if (a & ATTR_FILE_CLUMPSIZE)
937 *((u_long *)attrbufptr)++ = ip->i_mnt->logical_block_size;
938 if (a & ATTR_FILE_DEVTYPE)
939 *((u_long *)attrbufptr)++ = (u_long)ip->inode.iso_rdev;
940 if (a & ATTR_FILE_DATALENGTH)
941 *((off_t *)attrbufptr)++ = (off_t)ip->i_size;
942 if (a & ATTR_FILE_DATAALLOCSIZE)
943 *((off_t *)attrbufptr)++ = (off_t)ip->i_size;
944 if (a & ATTR_FILE_RSRCLENGTH)
945 *((off_t *)attrbufptr)++ = (off_t)ip->i_rsrcsize;
946 if (a & ATTR_FILE_RSRCALLOCSIZE)
947 *((off_t *)attrbufptr)++ = (off_t)ip->i_rsrcsize;
948 }
949
950 *attrbufptrptr = attrbufptr;
951 *varbufptrptr = varbufptr;
952 }
953
954
955 void
956 packattrblk(struct attrlist *alist,
957 struct vnode *vp,
958 void **attrbufptrptr,
959 void **varbufptrptr)
960 {
961 struct iso_node *ip = VTOI(vp);
962
963 if (alist->volattr != 0) {
964 packvolattr(alist, ip, attrbufptrptr, varbufptrptr);
965 } else {
966 packcommonattr(alist, ip, attrbufptrptr, varbufptrptr);
967
968 switch (ITOV(ip)->v_type) {
969 case VDIR:
970 packdirattr(alist, ip, attrbufptrptr, varbufptrptr);
971 break;
972
973 case VREG:
974 packfileattr(alist, ip, attrbufptrptr, varbufptrptr);
975 break;
976
977 /* Without this the compiler complains about VNON,VBLK,VCHR,VLNK,VSOCK,VFIFO,VBAD and VSTR
978 not being handled...
979 */
980 default:
981 break;
982 };
983 };
984 };