]> git.saurik.com Git - apple/xnu.git/blob - bsd/isofs/cd9660/cd9660_util.c
ace849705dcfff08fa2ea7dbe4b52e34ef5c08be
[apple/xnu.git] / bsd / isofs / cd9660 / cd9660_util.c
1 /*
2 * Copyright (c) 2000-2001 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)
220 u_char *infn, *outfn;
221 int infnlen;
222 u_short *outfnlen;
223 int original;
224 {
225 int fnidx = 0;
226
227 for (; fnidx < infnlen; fnidx++) {
228 char c = *infn++;
229
230 /*
231 * Some ISO 9600 CD names contain 8-bit chars.
232 * These chars are mapped to '_' because there
233 * is no context for mapping them to UTF-8.
234 * In addition '/' is mapped to ':'.
235 *
236 * isofncmp accounts for these mappings.
237 */
238 if (!original) {
239 if (c < 0)
240 c = '_';
241 else if (c == '/')
242 c = ':';
243 else if (c == '.' && *infn == ';')
244 break;
245 else if (c == ';')
246 break;
247 }
248 *outfn++ = c;
249 }
250 *outfnlen = fnidx;
251 }
252
253
254
255 /*
256 * translate a UCS-2 filename to UTF-8
257 */
258 void
259 ucsfntrans(infn, infnlen, outfn, outfnlen, dir)
260 u_int16_t *infn;
261 int infnlen;
262 u_char *outfn;
263 u_short *outfnlen;
264 int dir;
265 {
266 if (infnlen == 1) {
267 strcpy(outfn, "..");
268
269 if (*(u_char*)infn == 0)
270 *outfnlen = 1;
271 else if (*(u_char*)infn == 1)
272 *outfnlen = 2;
273 } else {
274 int fnidx;
275 size_t outbytes;
276 int flags;
277
278 fnidx = infnlen/2;
279 flags = 0;
280
281 if (!dir) {
282 /* strip file version number */
283 for (fnidx--; fnidx > 0; fnidx--) {
284 /* stop when ';' is found */
285 if (infn[fnidx] == UCS_SEPARATOR2) {
286 /* drop dangling dot */
287 if (fnidx > 0 && infn[fnidx-1] == UCS_SEPARATOR1)
288 fnidx--;
289 break;
290 }
291 }
292 if (fnidx <= 0)
293 fnidx = infnlen/2;
294 }
295
296 flags = UTF_NO_NULL_TERM | UTF_DECOMPOSED;
297 if (BYTE_ORDER != BIG_ENDIAN)
298 flags |= UTF_REVERSE_ENDIAN;
299
300 (void) utf8_encodestr(infn, fnidx * 2, outfn, &outbytes, ISO_JOLIET_NAMEMAX, 0, flags);
301 *outfnlen = outbytes;
302 }
303 }
304
305
306 /*
307 * count the number of children by enumerating the directory
308 */
309 static int
310 isochildcount(vdp, dircnt, filcnt)
311 struct vnode *vdp;
312 int *dircnt;
313 int *filcnt;
314 {
315 struct iso_node *dp;
316 struct buf *bp = NULL;
317 struct iso_directory_record *ep;
318 u_long bmask;
319 int error = 0;
320 int reclen;
321 int dirs, files;
322 int blkoffset;
323 int logblksize;
324 long diroffset;
325
326 dp = VTOI(vdp);
327 bmask = dp->i_mnt->im_bmask;
328 logblksize = dp->i_mnt->logical_block_size;
329 blkoffset = diroffset = 0;
330 dirs = files = 0;
331
332 while (diroffset < dp->i_size) {
333 /*
334 * If offset is on a block boundary, read the next
335 * directory block. Release previous if it exists.
336 */
337 if ((diroffset & bmask) == 0) {
338 if (bp != NULL)
339 brelse(bp);
340 if ( (error = VOP_BLKATOFF(vdp, diroffset, NULL, &bp)) )
341 break;
342 blkoffset = 0;
343 }
344
345 ep = (struct iso_directory_record *)
346 ((char *)bp->b_data + blkoffset);
347
348 reclen = isonum_711(ep->length);
349 if (reclen == 0) {
350 /* skip to next block, if any */
351 diroffset =
352 (diroffset & ~bmask) + logblksize;
353 continue;
354 }
355
356 if ((reclen < ISO_DIRECTORY_RECORD_SIZE) ||
357 (blkoffset + reclen > logblksize) ||
358 (reclen < ISO_DIRECTORY_RECORD_SIZE + isonum_711(ep->name_len))){
359 /* illegal, so give up */
360 break;
361 }
362
363 if ( isonum_711(ep->flags) & directoryBit )
364 dirs++;
365 else if ((isonum_711(ep->flags) & associatedBit) == 0)
366 files++;
367
368 diroffset += reclen;
369 blkoffset += reclen;
370 }
371
372 if (bp)
373 brelse (bp);
374
375 *dircnt = dirs;
376 *filcnt = files;
377
378 return (error);
379 }
380
381
382 /*
383 * There are two ways to qualify for ownership rights on an object:
384 *
385 * 1. Your UID matches the UID of the vnode
386 * 2. You are root
387 *
388 */
389 static int cd9660_owner_rights(uid_t owner, struct iso_mnt *imp, struct ucred *cred, struct proc *p, int invokesuperuserstatus) {
390 return ((cred->cr_uid == owner) || /* [1] */
391 (invokesuperuserstatus && (suser(cred, &p->p_acflag) == 0))) ? 0 : EPERM; /* [2] */
392 }
393
394
395
396 static unsigned long DerivePermissionSummary(uid_t owner, gid_t group, mode_t obj_mode, struct iso_mnt *imp, struct ucred *cred, struct proc *p) {
397 register gid_t *gp;
398 unsigned long permissions;
399 int i;
400
401 /* User id 0 (root) always gets access. */
402 if (cred->cr_uid == 0) {
403 permissions = R_OK | X_OK;
404 goto Exit;
405 };
406
407 /* Otherwise, check the owner. */
408 if (cd9660_owner_rights(owner, imp, cred, p, 0) == 0) {
409 permissions = ((unsigned long)obj_mode & S_IRWXU) >> 6;
410 goto Exit;
411 }
412
413 /* Otherwise, check the groups. */
414 for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) {
415 if (group == *gp) {
416 permissions = ((unsigned long)obj_mode & S_IRWXG) >> 3;
417 goto Exit;
418 }
419 };
420
421 /* Otherwise, settle for 'others' access. */
422 permissions = (unsigned long)obj_mode & S_IRWXO;
423
424 Exit:
425 return permissions & ~W_OK; /* Write access is always impossible */
426 }
427
428
429 int
430 attrcalcsize(struct attrlist *attrlist)
431 {
432 int size;
433 attrgroup_t a;
434
435 #if ((ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID | ATTR_CMN_OBJTYPE | \
436 ATTR_CMN_OBJTAG | ATTR_CMN_OBJID | ATTR_CMN_OBJPERMANENTID | ATTR_CMN_PAROBJID | \
437 ATTR_CMN_SCRIPT | ATTR_CMN_CRTIME | ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | \
438 ATTR_CMN_ACCTIME | ATTR_CMN_BKUPTIME | ATTR_CMN_FNDRINFO | ATTR_CMN_OWNERID | \
439 ATTR_CMN_GRPID | ATTR_CMN_ACCESSMASK | ATTR_CMN_NAMEDATTRCOUNT | ATTR_CMN_NAMEDATTRLIST| \
440 ATTR_CMN_FLAGS | ATTR_CMN_USERACCESS) != ATTR_CMN_VALIDMASK)
441 #error AttributeBlockSize: Missing bits in common mask computation!
442 #endif
443 assert((attrlist->commonattr & ~ATTR_CMN_VALIDMASK) == 0);
444
445 #if ((ATTR_VOL_FSTYPE | ATTR_VOL_SIGNATURE | ATTR_VOL_SIZE | ATTR_VOL_SPACEFREE | \
446 ATTR_VOL_SPACEAVAIL | ATTR_VOL_MINALLOCATION | ATTR_VOL_ALLOCATIONCLUMP | ATTR_VOL_IOBLOCKSIZE | \
447 ATTR_VOL_OBJCOUNT | ATTR_VOL_FILECOUNT | ATTR_VOL_DIRCOUNT | ATTR_VOL_MAXOBJCOUNT | \
448 ATTR_VOL_MOUNTPOINT | ATTR_VOL_NAME | ATTR_VOL_MOUNTFLAGS | ATTR_VOL_INFO | \
449 ATTR_VOL_MOUNTEDDEVICE| ATTR_VOL_ENCODINGSUSED | ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES) != ATTR_VOL_VALIDMASK)
450 #error AttributeBlockSize: Missing bits in volume mask computation!
451 #endif
452 assert((attrlist->volattr & ~ATTR_VOL_VALIDMASK) == 0);
453
454 #if ((ATTR_DIR_LINKCOUNT | ATTR_DIR_ENTRYCOUNT | ATTR_DIR_MOUNTSTATUS) != ATTR_DIR_VALIDMASK)
455 #error AttributeBlockSize: Missing bits in directory mask computation!
456 #endif
457 assert((attrlist->dirattr & ~ATTR_DIR_VALIDMASK) == 0);
458 #if ((ATTR_FILE_LINKCOUNT | ATTR_FILE_TOTALSIZE | ATTR_FILE_ALLOCSIZE | ATTR_FILE_IOBLOCKSIZE | \
459 ATTR_FILE_CLUMPSIZE | ATTR_FILE_DEVTYPE | ATTR_FILE_FILETYPE | ATTR_FILE_FORKCOUNT | \
460 ATTR_FILE_FORKLIST | ATTR_FILE_DATALENGTH | ATTR_FILE_DATAALLOCSIZE | ATTR_FILE_DATAEXTENTS | \
461 ATTR_FILE_RSRCLENGTH | ATTR_FILE_RSRCALLOCSIZE | ATTR_FILE_RSRCEXTENTS) != ATTR_FILE_VALIDMASK)
462 #error AttributeBlockSize: Missing bits in file mask computation!
463 #endif
464 assert((attrlist->fileattr & ~ATTR_FILE_VALIDMASK) == 0);
465
466 #if ((ATTR_FORK_TOTALSIZE | ATTR_FORK_ALLOCSIZE) != ATTR_FORK_VALIDMASK)
467 #error AttributeBlockSize: Missing bits in fork mask computation!
468 #endif
469 assert((attrlist->forkattr & ~ATTR_FORK_VALIDMASK) == 0);
470
471 size = 0;
472
473 if ((a = attrlist->commonattr) != 0) {
474 if (a & ATTR_CMN_NAME) size += sizeof(struct attrreference);
475 if (a & ATTR_CMN_DEVID) size += sizeof(dev_t);
476 if (a & ATTR_CMN_FSID) size += sizeof(fsid_t);
477 if (a & ATTR_CMN_OBJTYPE) size += sizeof(fsobj_type_t);
478 if (a & ATTR_CMN_OBJTAG) size += sizeof(fsobj_tag_t);
479 if (a & ATTR_CMN_OBJID) size += sizeof(fsobj_id_t);
480 if (a & ATTR_CMN_OBJPERMANENTID) size += sizeof(fsobj_id_t);
481 if (a & ATTR_CMN_PAROBJID) size += sizeof(fsobj_id_t);
482 if (a & ATTR_CMN_SCRIPT) size += sizeof(text_encoding_t);
483 if (a & ATTR_CMN_CRTIME) size += sizeof(struct timespec);
484 if (a & ATTR_CMN_MODTIME) size += sizeof(struct timespec);
485 if (a & ATTR_CMN_CHGTIME) size += sizeof(struct timespec);
486 if (a & ATTR_CMN_ACCTIME) size += sizeof(struct timespec);
487 if (a & ATTR_CMN_BKUPTIME) size += sizeof(struct timespec);
488 if (a & ATTR_CMN_FNDRINFO) size += 32 * sizeof(u_int8_t);
489 if (a & ATTR_CMN_OWNERID) size += sizeof(uid_t);
490 if (a & ATTR_CMN_GRPID) size += sizeof(gid_t);
491 if (a & ATTR_CMN_ACCESSMASK) size += sizeof(u_long);
492 if (a & ATTR_CMN_NAMEDATTRCOUNT) size += sizeof(u_long);
493 if (a & ATTR_CMN_NAMEDATTRLIST) size += sizeof(struct attrreference);
494 if (a & ATTR_CMN_FLAGS) size += sizeof(u_long);
495 if (a & ATTR_CMN_USERACCESS) size += sizeof(u_long);
496 };
497 if ((a = attrlist->volattr) != 0) {
498 if (a & ATTR_VOL_FSTYPE) size += sizeof(u_long);
499 if (a & ATTR_VOL_SIGNATURE) size += sizeof(u_long);
500 if (a & ATTR_VOL_SIZE) size += sizeof(off_t);
501 if (a & ATTR_VOL_SPACEFREE) size += sizeof(off_t);
502 if (a & ATTR_VOL_SPACEAVAIL) size += sizeof(off_t);
503 if (a & ATTR_VOL_MINALLOCATION) size += sizeof(off_t);
504 if (a & ATTR_VOL_ALLOCATIONCLUMP) size += sizeof(off_t);
505 if (a & ATTR_VOL_IOBLOCKSIZE) size += sizeof(size_t);
506 if (a & ATTR_VOL_OBJCOUNT) size += sizeof(u_long);
507 if (a & ATTR_VOL_FILECOUNT) size += sizeof(u_long);
508 if (a & ATTR_VOL_DIRCOUNT) size += sizeof(u_long);
509 if (a & ATTR_VOL_MAXOBJCOUNT) size += sizeof(u_long);
510 if (a & ATTR_VOL_MOUNTPOINT) size += sizeof(struct attrreference);
511 if (a & ATTR_VOL_NAME) size += sizeof(struct attrreference);
512 if (a & ATTR_VOL_MOUNTFLAGS) size += sizeof(u_long);
513 if (a & ATTR_VOL_MOUNTEDDEVICE) size += sizeof(struct attrreference);
514 if (a & ATTR_VOL_ENCODINGSUSED) size += sizeof(unsigned long long);
515 if (a & ATTR_VOL_CAPABILITIES) size += sizeof(vol_capabilities_attr_t);
516 if (a & ATTR_VOL_ATTRIBUTES) size += sizeof(vol_attributes_attr_t);
517 };
518 if ((a = attrlist->dirattr) != 0) {
519 if (a & ATTR_DIR_LINKCOUNT) size += sizeof(u_long);
520 if (a & ATTR_DIR_ENTRYCOUNT) size += sizeof(u_long);
521 if (a & ATTR_DIR_MOUNTSTATUS) size += sizeof(u_long);
522 };
523 if ((a = attrlist->fileattr) != 0) {
524 if (a & ATTR_FILE_LINKCOUNT) size += sizeof(u_long);
525 if (a & ATTR_FILE_TOTALSIZE) size += sizeof(off_t);
526 if (a & ATTR_FILE_ALLOCSIZE) size += sizeof(off_t);
527 if (a & ATTR_FILE_IOBLOCKSIZE) size += sizeof(size_t);
528 if (a & ATTR_FILE_CLUMPSIZE) size += sizeof(off_t);
529 if (a & ATTR_FILE_DEVTYPE) size += sizeof(u_long);
530 if (a & ATTR_FILE_FILETYPE) size += sizeof(u_long);
531 if (a & ATTR_FILE_FORKCOUNT) size += sizeof(u_long);
532 if (a & ATTR_FILE_FORKLIST) size += sizeof(struct attrreference);
533 if (a & ATTR_FILE_DATALENGTH) size += sizeof(off_t);
534 if (a & ATTR_FILE_DATAALLOCSIZE) size += sizeof(off_t);
535 if (a & ATTR_FILE_DATAEXTENTS) size += sizeof(extentrecord);
536 if (a & ATTR_FILE_RSRCLENGTH) size += sizeof(off_t);
537 if (a & ATTR_FILE_RSRCALLOCSIZE) size += sizeof(off_t);
538 if (a & ATTR_FILE_RSRCEXTENTS) size += sizeof(extentrecord);
539 };
540 if ((a = attrlist->forkattr) != 0) {
541 if (a & ATTR_FORK_TOTALSIZE) size += sizeof(off_t);
542 if (a & ATTR_FORK_ALLOCSIZE) size += sizeof(off_t);
543 };
544
545 return size;
546 }
547
548
549
550 void
551 packvolattr (struct attrlist *alist,
552 struct iso_node *ip, /* ip for root directory */
553 void **attrbufptrptr,
554 void **varbufptrptr)
555 {
556 void *attrbufptr;
557 void *varbufptr;
558 struct iso_mnt *imp;
559 struct mount *mp;
560 attrgroup_t a;
561 u_long attrlength;
562
563 attrbufptr = *attrbufptrptr;
564 varbufptr = *varbufptrptr;
565 imp = ip->i_mnt;
566 mp = imp->im_mountp;
567
568 if ((a = alist->commonattr) != 0) {
569 if (a & ATTR_CMN_NAME) {
570 attrlength = strlen( imp->volume_id ) + 1;
571 ((struct attrreference *)attrbufptr)->attr_dataoffset = (u_int8_t *)varbufptr - (u_int8_t *)attrbufptr;
572 ((struct attrreference *)attrbufptr)->attr_length = attrlength;
573 (void) strncpy((unsigned char *)varbufptr, imp->volume_id, attrlength);
574
575 /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
576 (u_int8_t *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
577 ++((struct attrreference *)attrbufptr);
578 };
579 if (a & ATTR_CMN_DEVID) *((dev_t *)attrbufptr)++ = imp->im_devvp->v_rdev;
580 if (a & ATTR_CMN_FSID) *((fsid_t *)attrbufptr)++ = ITOV(ip)->v_mount->mnt_stat.f_fsid;
581 if (a & ATTR_CMN_OBJTYPE) *((fsobj_type_t *)attrbufptr)++ = 0;
582 if (a & ATTR_CMN_OBJTAG) *((fsobj_tag_t *)attrbufptr)++ = VT_ISOFS;
583 if (a & ATTR_CMN_OBJID) {
584 ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
585 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
586 ++((fsobj_id_t *)attrbufptr);
587 };
588 if (a & ATTR_CMN_OBJPERMANENTID) {
589 ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
590 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
591 ++((fsobj_id_t *)attrbufptr);
592 };
593 if (a & ATTR_CMN_PAROBJID) {
594 ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
595 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
596 ++((fsobj_id_t *)attrbufptr);
597 };
598 if (a & ATTR_CMN_SCRIPT) *((text_encoding_t *)attrbufptr)++ = 0;
599 if (a & ATTR_CMN_CRTIME) *((struct timespec *)attrbufptr)++ = imp->creation_date;
600 if (a & ATTR_CMN_MODTIME) *((struct timespec *)attrbufptr)++ = imp->modification_date;
601 if (a & ATTR_CMN_CHGTIME) *((struct timespec *)attrbufptr)++ = imp->modification_date;
602 if (a & ATTR_CMN_ACCTIME) *((struct timespec *)attrbufptr)++ = imp->modification_date;
603 if (a & ATTR_CMN_BKUPTIME) {
604 ((struct timespec *)attrbufptr)->tv_sec = 0;
605 ((struct timespec *)attrbufptr)->tv_nsec = 0;
606 ++((struct timespec *)attrbufptr);
607 };
608 if (a & ATTR_CMN_FNDRINFO) {
609 bzero (attrbufptr, 32 * sizeof(u_int8_t));
610 (u_int8_t *)attrbufptr += 32 * sizeof(u_int8_t);
611 };
612 if (a & ATTR_CMN_OWNERID) *((uid_t *)attrbufptr)++ = ip->inode.iso_uid;
613 if (a & ATTR_CMN_GRPID) *((gid_t *)attrbufptr)++ = ip->inode.iso_gid;
614 if (a & ATTR_CMN_ACCESSMASK) *((u_long *)attrbufptr)++ = (u_long)ip->inode.iso_mode;
615 if (a & ATTR_CMN_FLAGS) *((u_long *)attrbufptr)++ = 0;
616 if (a & ATTR_CMN_USERACCESS) {
617 *((u_long *)attrbufptr)++ =
618 DerivePermissionSummary(ip->inode.iso_uid,
619 ip->inode.iso_gid,
620 ip->inode.iso_mode,
621 imp,
622 current_proc()->p_ucred,
623 current_proc());
624 };
625 };
626
627 if ((a = alist->volattr) != 0) {
628 off_t blocksize = (off_t)imp->logical_block_size;
629
630 if (a & ATTR_VOL_FSTYPE) *((u_long *)attrbufptr)++ = (u_long)imp->im_mountp->mnt_vfc->vfc_typenum;
631 if (a & ATTR_VOL_SIGNATURE) *((u_long *)attrbufptr)++ = (u_long)ISO9660SIGNATURE;
632 if (a & ATTR_VOL_SIZE) *((off_t *)attrbufptr)++ = (off_t)imp->volume_space_size * blocksize;
633 if (a & ATTR_VOL_SPACEFREE) *((off_t *)attrbufptr)++ = 0;
634 if (a & ATTR_VOL_SPACEAVAIL) *((off_t *)attrbufptr)++ = 0;
635 if (a & ATTR_VOL_MINALLOCATION) *((off_t *)attrbufptr)++ = blocksize;
636 if (a & ATTR_VOL_ALLOCATIONCLUMP) *((off_t *)attrbufptr)++ = blocksize;
637 if (a & ATTR_VOL_IOBLOCKSIZE) *((size_t *)attrbufptr)++ = blocksize;
638 if (a & ATTR_VOL_OBJCOUNT) *((u_long *)attrbufptr)++ = 0;
639 if (a & ATTR_VOL_FILECOUNT) *((u_long *)attrbufptr)++ = 0;
640 if (a & ATTR_VOL_DIRCOUNT) *((u_long *)attrbufptr)++ = 0;
641 if (a & ATTR_VOL_MAXOBJCOUNT) *((u_long *)attrbufptr)++ = 0xFFFFFFFF;
642 if (a & ATTR_VOL_NAME) {
643 attrlength = strlen( imp->volume_id ) + 1;
644 ((struct attrreference *)attrbufptr)->attr_dataoffset = (u_int8_t *)varbufptr - (u_int8_t *)attrbufptr;
645 ((struct attrreference *)attrbufptr)->attr_length = attrlength;
646 (void) strncpy((unsigned char *)varbufptr, imp->volume_id, attrlength);
647
648 /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
649 (u_int8_t *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
650 ++((struct attrreference *)attrbufptr);
651 };
652 if (a & ATTR_VOL_MOUNTFLAGS) *((u_long *)attrbufptr)++ = (u_long)imp->im_mountp->mnt_flag;
653 if (a & ATTR_VOL_MOUNTEDDEVICE) {
654 ((struct attrreference *)attrbufptr)->attr_dataoffset = (u_int8_t *)varbufptr - (u_int8_t *)attrbufptr;
655 ((struct attrreference *)attrbufptr)->attr_length = strlen(mp->mnt_stat.f_mntfromname) + 1;
656 attrlength = ((struct attrreference *)attrbufptr)->attr_length;
657 attrlength = attrlength + ((4 - (attrlength & 3)) & 3); /* round up to the next 4-byte boundary: */
658 (void) bcopy(mp->mnt_stat.f_mntfromname, varbufptr, attrlength);
659
660 /* Advance beyond the space just allocated: */
661 (u_int8_t *)varbufptr += attrlength;
662 ++((struct attrreference *)attrbufptr);
663 };
664 if (a & ATTR_VOL_ENCODINGSUSED) *((unsigned long long *)attrbufptr)++ = (unsigned long long)0;
665 if (a & ATTR_VOL_CAPABILITIES) {
666 ((vol_capabilities_attr_t *)attrbufptr)->capabilities[VOL_CAPABILITIES_FORMAT] = VOL_CAP_FMT_PERSISTENTOBJECTIDS;
667 ((vol_capabilities_attr_t *)attrbufptr)->capabilities[VOL_CAPABILITIES_INTERFACES] =
668 VOL_CAP_INT_ATTRLIST | VOL_CAP_INT_NFSEXPORT;
669 ((vol_capabilities_attr_t *)attrbufptr)->capabilities[VOL_CAPABILITIES_RESERVED1] = 0;
670 ((vol_capabilities_attr_t *)attrbufptr)->capabilities[VOL_CAPABILITIES_RESERVED2] = 0;
671
672 ((vol_capabilities_attr_t *)attrbufptr)->valid[VOL_CAPABILITIES_FORMAT] =
673 VOL_CAP_FMT_PERSISTENTOBJECTIDS | VOL_CAP_FMT_SYMBOLICLINKS | VOL_CAP_FMT_HARDLINKS;
674 ((vol_capabilities_attr_t *)attrbufptr)->valid[VOL_CAPABILITIES_INTERFACES] =
675 VOL_CAP_INT_SEARCHFS | VOL_CAP_INT_ATTRLIST | VOL_CAP_INT_NFSEXPORT;
676 ((vol_capabilities_attr_t *)attrbufptr)->valid[VOL_CAPABILITIES_RESERVED1] = 0;
677 ((vol_capabilities_attr_t *)attrbufptr)->valid[VOL_CAPABILITIES_RESERVED2] = 0;
678
679 ++((vol_capabilities_attr_t *)attrbufptr);
680 };
681 if (a & ATTR_VOL_ATTRIBUTES) {
682 ((vol_attributes_attr_t *)attrbufptr)->validattr.commonattr = ATTR_CMN_VALIDMASK;
683 ((vol_attributes_attr_t *)attrbufptr)->validattr.volattr = ATTR_VOL_VALIDMASK;
684 ((vol_attributes_attr_t *)attrbufptr)->validattr.dirattr = ATTR_DIR_VALIDMASK;
685 ((vol_attributes_attr_t *)attrbufptr)->validattr.fileattr = ATTR_FILE_VALIDMASK;
686 ((vol_attributes_attr_t *)attrbufptr)->validattr.forkattr = ATTR_FORK_VALIDMASK;
687
688 ((vol_attributes_attr_t *)attrbufptr)->nativeattr.commonattr = ATTR_CMN_VALIDMASK;
689 ((vol_attributes_attr_t *)attrbufptr)->nativeattr.volattr = ATTR_VOL_VALIDMASK;
690 ((vol_attributes_attr_t *)attrbufptr)->nativeattr.dirattr = ATTR_DIR_VALIDMASK;
691 ((vol_attributes_attr_t *)attrbufptr)->nativeattr.fileattr = ATTR_FILE_VALIDMASK;
692 ((vol_attributes_attr_t *)attrbufptr)->nativeattr.forkattr = ATTR_FORK_VALIDMASK;
693
694 ++((vol_attributes_attr_t *)attrbufptr);
695 };
696 };
697
698 *attrbufptrptr = attrbufptr;
699 *varbufptrptr = varbufptr;
700 }
701
702
703 void
704 packcommonattr (struct attrlist *alist,
705 struct iso_node *ip,
706 void **attrbufptrptr,
707 void **varbufptrptr)
708 {
709 void *attrbufptr;
710 void *varbufptr;
711 attrgroup_t a;
712 u_long attrlength;
713
714 attrbufptr = *attrbufptrptr;
715 varbufptr = *varbufptrptr;
716
717 if ((a = alist->commonattr) != 0) {
718 struct iso_mnt *imp = ip->i_mnt;
719
720 if (a & ATTR_CMN_NAME) {
721 /* special case root since we know how to get it's name */
722 if (ITOV(ip)->v_flag & VROOT) {
723 attrlength = strlen( imp->volume_id ) + 1;
724 (void) strncpy((unsigned char *)varbufptr, imp->volume_id, attrlength);
725 } else {
726 attrlength = strlen(ip->i_namep) + 1;
727 (void) strncpy((unsigned char *)varbufptr, ip->i_namep, attrlength);
728 }
729
730 ((struct attrreference *)attrbufptr)->attr_dataoffset = (u_int8_t *)varbufptr - (u_int8_t *)attrbufptr;
731 ((struct attrreference *)attrbufptr)->attr_length = attrlength;
732 /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
733 (u_int8_t *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
734 ++((struct attrreference *)attrbufptr);
735 };
736 if (a & ATTR_CMN_DEVID) *((dev_t *)attrbufptr)++ = ip->i_dev;
737 if (a & ATTR_CMN_FSID) *((fsid_t *)attrbufptr)++ = ITOV(ip)->v_mount->mnt_stat.f_fsid;
738 if (a & ATTR_CMN_OBJTYPE) *((fsobj_type_t *)attrbufptr)++ = ITOV(ip)->v_type;
739 if (a & ATTR_CMN_OBJTAG) *((fsobj_tag_t *)attrbufptr)++ = ITOV(ip)->v_tag;
740 if (a & ATTR_CMN_OBJID) {
741 if (ITOV(ip)->v_flag & VROOT)
742 ((fsobj_id_t *)attrbufptr)->fid_objno = 2; /* force root to be 2 */
743 else
744 ((fsobj_id_t *)attrbufptr)->fid_objno = ip->i_number;
745 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
746 ++((fsobj_id_t *)attrbufptr);
747 };
748 if (a & ATTR_CMN_OBJPERMANENTID) {
749 if (ITOV(ip)->v_flag & VROOT)
750 ((fsobj_id_t *)attrbufptr)->fid_objno = 2; /* force root to be 2 */
751 else
752 ((fsobj_id_t *)attrbufptr)->fid_objno = ip->i_number;
753 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
754 ++((fsobj_id_t *)attrbufptr);
755 };
756 if (a & ATTR_CMN_PAROBJID) {
757 struct iso_directory_record *dp = (struct iso_directory_record *)imp->root;
758 ino_t rootino = isodirino(dp, imp);
759
760 if (ip->i_number == rootino)
761 ((fsobj_id_t *)attrbufptr)->fid_objno = 1; /* force root parent to be 1 */
762 else if (ip->i_parent == rootino)
763 ((fsobj_id_t *)attrbufptr)->fid_objno = 2; /* force root to be 2 */
764 else
765 ((fsobj_id_t *)attrbufptr)->fid_objno = ip->i_parent;
766 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
767 ++((fsobj_id_t *)attrbufptr);
768 };
769 if (a & ATTR_CMN_SCRIPT) *((text_encoding_t *)attrbufptr)++ = 0;
770 if (a & ATTR_CMN_CRTIME) *((struct timespec *)attrbufptr)++ = ip->inode.iso_mtime;
771 if (a & ATTR_CMN_MODTIME) *((struct timespec *)attrbufptr)++ = ip->inode.iso_mtime;
772 if (a & ATTR_CMN_CHGTIME) *((struct timespec *)attrbufptr)++ = ip->inode.iso_ctime;
773 if (a & ATTR_CMN_ACCTIME) *((struct timespec *)attrbufptr)++ = ip->inode.iso_atime;
774 if (a & ATTR_CMN_BKUPTIME) {
775 ((struct timespec *)attrbufptr)->tv_sec = 0;
776 ((struct timespec *)attrbufptr)->tv_nsec = 0;
777 ++((struct timespec *)attrbufptr);
778 };
779 if (a & ATTR_CMN_FNDRINFO) {
780 struct finder_info finfo = {0};
781
782 finfo.fdFlags = ip->i_FinderFlags;
783 finfo.fdLocation.v = -1;
784 finfo.fdLocation.h = -1;
785 if (ITOV(ip)->v_type == VREG) {
786 finfo.fdType = ip->i_FileType;
787 finfo.fdCreator = ip->i_Creator;
788 }
789 bcopy (&finfo, attrbufptr, sizeof(finfo));
790 (u_int8_t *)attrbufptr += sizeof(finfo);
791 bzero (attrbufptr, EXTFNDRINFOSIZE);
792 (u_int8_t *)attrbufptr += EXTFNDRINFOSIZE;
793 };
794 if (a & ATTR_CMN_OWNERID) *((uid_t *)attrbufptr)++ = ip->inode.iso_uid;
795 if (a & ATTR_CMN_GRPID) *((gid_t *)attrbufptr)++ = ip->inode.iso_gid;
796 if (a & ATTR_CMN_ACCESSMASK) *((u_long *)attrbufptr)++ = (u_long)ip->inode.iso_mode;
797 if (a & ATTR_CMN_FLAGS) *((u_long *)attrbufptr)++ = 0; /* could also use ip->i_flag */
798 if (a & ATTR_CMN_USERACCESS) {
799 *((u_long *)attrbufptr)++ =
800 DerivePermissionSummary(ip->inode.iso_uid,
801 ip->inode.iso_gid,
802 ip->inode.iso_mode,
803 imp,
804 current_proc()->p_ucred,
805 current_proc());
806 };
807 };
808
809 *attrbufptrptr = attrbufptr;
810 *varbufptrptr = varbufptr;
811 }
812
813
814 void
815 packdirattr(struct attrlist *alist,
816 struct iso_node *ip,
817 void **attrbufptrptr,
818 void **varbufptrptr)
819 {
820 void *attrbufptr;
821 attrgroup_t a;
822 int filcnt, dircnt;
823
824 attrbufptr = *attrbufptrptr;
825 filcnt = dircnt = 0;
826
827 a = alist->dirattr;
828 if ((ITOV(ip)->v_type == VDIR) && (a != 0)) {
829 /*
830 * if we haven't counted our children yet, do it now...
831 */
832 if ((ip->i_entries == 0) &&
833 (a & (ATTR_DIR_LINKCOUNT | ATTR_DIR_ENTRYCOUNT))) {
834 (void) isochildcount(ITOV(ip), &dircnt, &filcnt);
835
836 if ((ip->inode.iso_links == 1) && (dircnt != 0))
837 ip->inode.iso_links = dircnt;
838 if ((filcnt + dircnt) > 0)
839 ip->i_entries = dircnt + filcnt;
840 }
841
842 if (a & ATTR_DIR_LINKCOUNT) {
843 *((u_long *)attrbufptr)++ = ip->inode.iso_links;
844 }
845 if (a & ATTR_DIR_ENTRYCOUNT) {
846 /* exclude '.' and '..' from total caount */
847 *((u_long *)attrbufptr)++ = ((ip->i_entries <= 2) ? 0 : (ip->i_entries - 2));
848 }
849 if (a & ATTR_DIR_MOUNTSTATUS) {
850 if (ITOV(ip)->v_mountedhere) {
851 *((u_long *)attrbufptr)++ = DIR_MNTSTATUS_MNTPOINT;
852 } else {
853 *((u_long *)attrbufptr)++ = 0;
854 };
855 };
856 };
857
858 *attrbufptrptr = attrbufptr;
859 }
860
861
862 void
863 packfileattr(struct attrlist *alist,
864 struct iso_node *ip,
865 void **attrbufptrptr,
866 void **varbufptrptr)
867 {
868 void *attrbufptr = *attrbufptrptr;
869 void *varbufptr = *varbufptrptr;
870 attrgroup_t a = alist->fileattr;
871
872 if ((ITOV(ip)->v_type == VREG) && (a != 0)) {
873 if (a & ATTR_FILE_LINKCOUNT)
874 *((u_long *)attrbufptr)++ = ip->inode.iso_links;
875 if (a & ATTR_FILE_TOTALSIZE)
876 *((off_t *)attrbufptr)++ = (off_t)ip->i_size;
877 if (a & ATTR_FILE_ALLOCSIZE)
878 *((off_t *)attrbufptr)++ = (off_t)ip->i_size;
879 if (a & ATTR_FILE_IOBLOCKSIZE)
880 *((u_long *)attrbufptr)++ = ip->i_mnt->logical_block_size;
881 if (a & ATTR_FILE_CLUMPSIZE)
882 *((u_long *)attrbufptr)++ = ip->i_mnt->logical_block_size;
883 if (a & ATTR_FILE_DEVTYPE)
884 *((u_long *)attrbufptr)++ = (u_long)ip->inode.iso_rdev;
885 if (a & ATTR_FILE_DATALENGTH)
886 *((off_t *)attrbufptr)++ = (off_t)ip->i_size;
887 if (a & ATTR_FILE_DATAALLOCSIZE)
888 *((off_t *)attrbufptr)++ = (off_t)ip->i_size;
889 if (a & ATTR_FILE_RSRCLENGTH)
890 *((off_t *)attrbufptr)++ = (off_t)ip->i_rsrcsize;
891 if (a & ATTR_FILE_RSRCALLOCSIZE)
892 *((off_t *)attrbufptr)++ = (off_t)ip->i_rsrcsize;
893 }
894
895 *attrbufptrptr = attrbufptr;
896 *varbufptrptr = varbufptr;
897 }
898
899
900 void
901 packattrblk(struct attrlist *alist,
902 struct vnode *vp,
903 void **attrbufptrptr,
904 void **varbufptrptr)
905 {
906 struct iso_node *ip = VTOI(vp);
907
908 if (alist->volattr != 0) {
909 packvolattr(alist, ip, attrbufptrptr, varbufptrptr);
910 } else {
911 packcommonattr(alist, ip, attrbufptrptr, varbufptrptr);
912
913 switch (ITOV(ip)->v_type) {
914 case VDIR:
915 packdirattr(alist, ip, attrbufptrptr, varbufptrptr);
916 break;
917
918 case VREG:
919 packfileattr(alist, ip, attrbufptrptr, varbufptrptr);
920 break;
921
922 /* Without this the compiler complains about VNON,VBLK,VCHR,VLNK,VSOCK,VFIFO,VBAD and VSTR
923 not being handled...
924 */
925 default:
926 break;
927 };
928 };
929 };