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