remove unnecessary offset_t casts of 0
[unleashed.git] / kernel / fs / udfs / udf_subr.c
blob24f311d77043688db583e6d4fe0448989691e551
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/types.h>
26 #include <sys/t_lock.h>
27 #include <sys/param.h>
28 #include <sys/time.h>
29 #include <sys/systm.h>
30 #include <sys/sysmacros.h>
31 #include <sys/resource.h>
32 #include <sys/signal.h>
33 #include <sys/cred.h>
34 #include <sys/user.h>
35 #include <sys/buf.h>
36 #include <sys/vfs.h>
37 #include <sys/stat.h>
38 #include <sys/vnode.h>
39 #include <sys/mode.h>
40 #include <sys/proc.h>
41 #include <sys/disp.h>
42 #include <sys/file.h>
43 #include <sys/fcntl.h>
44 #include <sys/flock.h>
45 #include <sys/kmem.h>
46 #include <sys/uio.h>
47 #include <sys/dnlc.h>
48 #include <sys/conf.h>
49 #include <sys/errno.h>
50 #include <sys/mman.h>
51 #include <sys/fbuf.h>
52 #include <sys/pathname.h>
53 #include <sys/debug.h>
54 #include <sys/vmsystm.h>
55 #include <sys/cmn_err.h>
56 #include <sys/dirent.h>
57 #include <sys/errno.h>
58 #include <sys/modctl.h>
59 #include <sys/statvfs.h>
60 #include <sys/mount.h>
61 #include <sys/sunddi.h>
62 #include <sys/bootconf.h>
63 #include <sys/policy.h>
65 #include <vm/hat.h>
66 #include <vm/page.h>
67 #include <vm/pvn.h>
68 #include <vm/as.h>
69 #include <vm/seg.h>
70 #include <vm/seg_map.h>
71 #include <vm/seg_kmem.h>
72 #include <vm/seg_vn.h>
73 #include <vm/rm.h>
74 #include <vm/page.h>
75 #include <sys/swap.h>
78 #include <sys/fs_subr.h>
81 #include <sys/fs/udf_volume.h>
82 #include <sys/fs/udf_inode.h>
84 int32_t ud_trace;
87 * HASH chains and mutex
89 extern union ihead ud_ihead[UD_HASH_SZ];
90 extern kmutex_t ud_icache_lock;
93 extern kmutex_t ud_sync_busy;
95 * udf_vfs list manipulation routines
97 extern kmutex_t udf_vfs_mutex;
98 extern struct udf_vfs *udf_vfs_instances;
101 * Used to verify that a given entry on the udf_instances list (see below)
102 * still refers to a mounted file system.
104 * XXX: This is a crock that substitutes for proper locking to coordinate
105 * updates to and uses of the entries in udf_instances.
107 struct check_node {
108 struct vfs *vfsp;
109 struct udf_vfs *udf_vfs;
110 dev_t vfs_dev;
113 vfs_t *ud_still_mounted(struct check_node *);
114 void ud_checkclean(struct vfs *,
115 struct udf_vfs *, dev_t, time_t);
116 int32_t ud_icheck(struct udf_vfs *);
117 void ud_flushi(int32_t);
120 * Link udf_vfsp in at the head of the list of udf_vfs_instances.
122 void
123 ud_vfs_add(struct udf_vfs *udf_vfsp)
125 mutex_enter(&udf_vfs_mutex);
126 udf_vfsp->udf_next = udf_vfs_instances;
127 udf_vfs_instances = udf_vfsp;
128 mutex_exit(&udf_vfs_mutex);
132 * Remove udf_vfsp from the list of udf_vfs_instances.
134 * Does no error checking; udf_vfsp is assumed to actually be on the list.
136 void
137 ud_vfs_remove(struct udf_vfs *udf_vfsp)
139 struct udf_vfs **delpt = &udf_vfs_instances;
141 mutex_enter(&udf_vfs_mutex);
142 for (; *delpt != NULL; delpt = &((*delpt)->udf_next)) {
143 if (*delpt == udf_vfsp) {
144 *delpt = udf_vfsp->udf_next;
145 udf_vfsp->udf_next = NULL;
146 break;
149 mutex_exit(&udf_vfs_mutex);
153 * Search for the prn in the array
154 * of partitions and translate
155 * to the disk block number
157 daddr_t
158 ud_xlate_to_daddr(struct udf_vfs *udf_vfsp,
159 uint16_t prn, uint32_t blkno, int32_t nblks, uint32_t *count)
161 int32_t i;
162 struct ud_map *map;
163 struct ud_part *ud_parts;
164 uint32_t lblkno, retblkno = 0, *addr;
165 uint32_t begin_req, end_req;
166 uint32_t begin_bad, end_bad;
168 ud_printf("ud_xlate_to_daddr\n");
170 /* Is prn valid */
171 if (prn < udf_vfsp->udf_nmaps) {
172 map = &(udf_vfsp->udf_maps[prn]);
174 if (map->udm_flags == UDM_MAP_VPM) {
176 * Map is Virtual Parition Map
177 * first check for the appropriate
178 * table and then return the converted
179 * block number
181 for (i = 0; i < map->udm_nent; i++) {
182 if (blkno < map->udm_count[i]) {
183 addr = map->udm_addr[i];
184 lblkno = SWAP_32(addr[blkno]);
185 *count = 1;
186 break;
187 } else {
188 blkno -= map->udm_count[i];
191 } else if (map->udm_flags == UDM_MAP_SPM) {
192 struct stbl *stbl;
193 struct stbl_entry *te;
194 int32_t entry_count;
197 * Map type is Sparable Parition Map
198 * if the block is in the map
199 * return the translated block
200 * other wise use the regular
201 * partition stuff
203 begin_req = blkno;
204 end_req = begin_req + nblks;
206 stbl = (struct stbl *)map->udm_spaddr[0];
207 te = (struct stbl_entry *)&stbl->stbl_entry;
208 entry_count = SWAP_16(stbl->stbl_len);
210 for (i = 0; i < entry_count; i++, te++) {
211 begin_bad = SWAP_32(te->sent_ol);
212 end_bad = begin_bad + map->udm_plen;
215 * Either unmapped or reserved
216 * or defective. need not consider
218 if (begin_bad >= (uint32_t)0xFFFFFFF0) {
219 continue;
221 if ((end_req < begin_bad) ||
222 (begin_req >= end_bad)) {
223 continue;
226 if (begin_req < begin_bad) {
227 ASSERT(end_req >= begin_bad);
228 end_req = begin_bad;
229 } else {
230 retblkno = SWAP_32(te->sent_ml) +
231 begin_req - begin_bad;
232 if (end_req < end_bad) {
233 *count = end_req - begin_req;
234 } else {
235 *count = end_bad - begin_req;
237 goto end;
241 lblkno = blkno;
242 *count = end_req - begin_req;
243 } else {
245 * regular partition
247 lblkno = blkno;
248 *count = nblks;
250 ud_parts = udf_vfsp->udf_parts;
251 for (i = 0; i < udf_vfsp->udf_npart; i++) {
252 if (map->udm_pn == ud_parts->udp_number) {
254 * Check if the block is inside
255 * the partition or not
257 if (lblkno >= ud_parts->udp_length) {
258 retblkno = 0;
259 } else {
260 retblkno = ud_parts->udp_start + lblkno;
262 goto end;
264 ud_parts ++;
268 end:
269 return (retblkno);
272 #ifdef UNDEF
273 uint32_t
274 ud_xlate_to_addr(struct udf_vfs *udf_vfsp,
275 uint16_t prn, daddr_t blkno, int32_t lad)
277 int32_t i;
278 struct ud_part *ud_parts;
280 ud_printf("ud_xlate_to_addr\n");
282 if (lad == 0) {
283 return (blkno);
285 ud_parts = udf_vfsp->udf_parts;
286 for (i = 0; i < udf_vfsp->udf_npart; i++) {
287 if (prn == ud_parts->udp_number) {
288 return (blkno - ud_parts->udp_start);
291 return (0);
293 #endif
296 * Directories do not have holes
298 int32_t
299 ud_ip_off2bno(struct ud_inode *ip, uint32_t offset, uint32_t *bno)
301 int32_t i, error;
302 struct icb_ext *iext;
304 ASSERT(ip->i_type == VDIR);
306 if (ip->i_desc_type == ICB_FLAG_ONE_AD) {
307 *bno = ip->i_icb_block;
308 return (0);
311 if ((error = ud_read_icb_till_off(ip, (uoff_t)offset)) != 0) {
312 return (error);
315 for (i = 0; i < ip->i_ext_used; i++) {
316 iext = &ip->i_ext[i];
317 if ((iext->ib_offset <= offset) &&
318 (offset < (iext->ib_offset + iext->ib_count))) {
319 *bno = iext->ib_block +
320 ((offset - iext->ib_offset) >>
321 ip->i_udf->udf_l2b_shift);
322 break;
325 return (0);
328 static uint32_t cum_sec[] = {
329 0x0, 0x28de80, 0x4dc880, 0x76a700, 0x9e3400, 0xc71280,
330 0xee9f80, 0x1177e00, 0x1405c80, 0x167e980, 0x190c800, 0x1b85500
332 static uint32_t cum_sec_leap[] = {
333 0x0, 0x28de80, 0x4f1a00, 0x77f880, 0x9f8580, 0xc86400,
334 0xeff100, 0x118cf80, 0x141ae00, 0x1693b00, 0x1921980, 0x1b9a680
337 #define DAYS_PER_YEAR 365
339 #define SEC_PER_DAY 0x15180
340 #define SEC_PER_YEAR 0x1e13380
343 /* This holds good till yr 2100 */
344 void
345 ud_dtime2utime(struct timespec32 *utime,
346 struct tstamp const *dtime)
348 int16_t year, tzone;
349 int32_t sec;
350 uint32_t *cp;
352 ud_printf("ud_dtime2utime\n");
354 year = SWAP_16(dtime->ts_year);
355 cp = (year % 4) ? cum_sec : cum_sec_leap;
357 utime->tv_sec = cp[dtime->ts_month - 1];
358 utime->tv_sec += (dtime->ts_day - 1) * SEC_PER_DAY;
359 utime->tv_sec += ((dtime->ts_hour * 60) +
360 dtime->ts_min) * 60 +
361 dtime->ts_sec;
363 tzone = SWAP_16(dtime->ts_tzone);
364 if ((tzone & TMODE) == 0x1000) {
365 /* Local time */
366 if ((tzone & TINVALID) != TINVALID) {
367 if (tzone & TSIGN) {
369 * Sign extend the tzone
371 sec = tzone | 0xFFFFF000;
372 } else {
373 sec = tzone & TOFFSET;
375 sec *= 60;
376 utime->tv_sec -= sec;
380 utime->tv_nsec = ((((dtime->ts_csec * 100) +
381 dtime->ts_husec) * 100) +
382 dtime->ts_usec) * 1000;
383 if (year >= 1970) {
384 utime->tv_sec += (year - 1970) * SEC_PER_YEAR;
385 utime->tv_sec += ((year - 1969) / 4) * SEC_PER_DAY;
386 } else {
387 utime->tv_sec = ((1970 - year) * SEC_PER_YEAR +
388 ((1972 - year) / 4) * SEC_PER_DAY -
389 utime->tv_sec) * -1;
390 if (utime->tv_nsec) {
391 utime->tv_sec++;
392 utime->tv_nsec = 1000 * 1000 * 1000 - utime->tv_nsec;
397 void
398 ud_utime2dtime(struct timespec32 const *utime,
399 struct tstamp *dtime)
401 time32_t sec = utime->tv_sec;
402 int32_t usec = utime->tv_nsec / 1000;
403 uint32_t lyrs, nyrs, dummy;
404 uint32_t *cp;
405 int32_t before = 0;
407 ud_printf("ud_utime2dtime\n");
409 if (sec < 0) {
410 before = 1;
411 sec = sec * -1;
412 if (usec) {
413 sec = sec + 1;
414 usec = 1000 * 1000 - usec;
418 dtime->ts_csec = usec / 10000;
419 usec %= 10000;
420 dtime->ts_husec = usec / 100;
421 dtime->ts_usec = usec % 100;
423 nyrs = sec / SEC_PER_YEAR;
424 if (before == 0) {
425 lyrs = (nyrs + 1) / 4;
426 } else {
427 lyrs = (nyrs + 2) / 4;
429 if (nyrs != ((sec - (lyrs * SEC_PER_DAY)) / SEC_PER_YEAR)) {
430 nyrs--;
431 if (before == 0) {
432 lyrs = (nyrs + 1) / 4;
433 } else {
434 lyrs = (nyrs + 2) / 4;
437 sec -= nyrs * SEC_PER_YEAR + lyrs * SEC_PER_DAY;
439 if (before == 1) {
440 nyrs = 1970 - nyrs;
441 if (sec != 0) {
442 nyrs --;
443 if ((nyrs % 4) == 0) {
444 sec = SEC_PER_YEAR + SEC_PER_DAY - sec;
445 } else {
446 sec = SEC_PER_YEAR - sec;
449 } else {
450 nyrs += 1970;
452 cp = (nyrs % 4) ? cum_sec : cum_sec_leap;
453 dummy = sec / (SEC_PER_DAY * 29);
454 if (dummy > 11) {
455 dummy = 11;
457 if (sec < cp[dummy]) {
458 dummy--;
460 dtime->ts_year = SWAP_16(nyrs);
461 dtime->ts_month = dummy;
462 sec -= cp[dtime->ts_month];
463 dtime->ts_month++;
464 dtime->ts_day = sec / SEC_PER_DAY;
465 sec -= dtime->ts_day * SEC_PER_DAY;
466 dtime->ts_day++;
467 dtime->ts_hour = sec / SECS_PER_HOUR;
468 sec -= dtime->ts_hour * SECS_PER_HOUR;
469 dtime->ts_min = sec / SECS_PER_MIN;
470 sec -= dtime->ts_min * SECS_PER_MIN;
471 dtime->ts_sec = (uint8_t)sec;
473 /* GMT offset is 0 */
474 dtime->ts_tzone = SWAP_16(0x1000);
478 int32_t
479 ud_syncip(struct ud_inode *ip, int32_t flags, int32_t waitfor)
481 int32_t error;
482 struct vnode *vp = ITOV(ip);
484 ud_printf("ud_syncip\n");
486 if (ip->i_udf == NULL) {
487 return (0);
490 if (!vn_has_cached_data(vp) || (vp->v_type == VCHR)) {
491 error = 0;
492 } else {
493 rw_exit(&ip->i_contents);
494 error = fop_putpage(vp, 0,
495 (uint32_t)0, flags, CRED(), NULL);
496 rw_enter(&ip->i_contents, RW_WRITER);
499 if (ip->i_flag & (IUPD |IACC | ICHG | IMOD)) {
500 ud_iupdat(ip, waitfor);
503 return (error);
507 /* ARGSUSED */
508 int32_t
509 ud_fbwrite(struct fbuf *fbp, struct ud_inode *ip)
511 ud_printf("ud_fbwrite\n");
513 ASSERT(fbp != NULL);
515 return (fbwrite(fbp));
519 void
520 ud_sbwrite(struct udf_vfs *udf_vfsp)
522 struct log_vol_int_desc *lvid;
523 struct ud_part *ud_part;
524 struct lvid_iu *iu;
525 uint32_t *temp;
526 int32_t i, c;
528 ud_printf("ud_sbwrite\n");
529 ASSERT(udf_vfsp);
530 ASSERT(MUTEX_HELD(&udf_vfsp->udf_lock));
533 * updatable information in the superblock
534 * integrity type, udf_maxuniq, udf_nfiles, udf_ndirs
535 * udp_nfree in lvid
537 lvid = (struct log_vol_int_desc *)udf_vfsp->udf_lvid;
538 if (udf_vfsp->udf_clean == UDF_DIRTY) {
539 lvid->lvid_int_type = SWAP_32(LOG_VOL_OPEN_INT);
540 } else {
541 lvid->lvid_int_type = SWAP_32(LOG_VOL_CLOSE_INT);
543 lvid->lvid_uniqid = SWAP_64(udf_vfsp->udf_maxuniq);
544 temp = lvid->lvid_fst;
545 c = SWAP_32(lvid->lvid_npart);
546 ud_part = udf_vfsp->udf_parts;
547 for (i = 0; i < c; i++) {
548 temp[i] = SWAP_32(ud_part->udp_nfree);
549 ud_part++;
551 iu = (struct lvid_iu *)(temp + c * 2);
552 iu->lvidiu_nfiles = SWAP_32(udf_vfsp->udf_nfiles);
553 iu->lvidiu_ndirs = SWAP_32(udf_vfsp->udf_ndirs);
555 ud_update_regid(&iu->lvidiu_regid);
557 ud_make_tag(udf_vfsp, &lvid->lvid_tag,
558 UD_LOG_VOL_INT, udf_vfsp->udf_iseq_loc,
559 sizeof (struct log_vol_int_desc) - 8 +
560 8 * udf_vfsp->udf_npart +
561 SWAP_32(lvid->lvid_liu));
564 * Don't release the buffer after writing to the disk
566 bwrite2(udf_vfsp->udf_iseq);
570 int32_t
571 ud_sync_indir(struct ud_inode *ip)
573 int32_t elen;
575 ud_printf("ud_sync_indir\n");
577 if (ip->i_desc_type == ICB_FLAG_ONE_AD) {
578 return (0);
579 } else if (ip->i_desc_type == ICB_FLAG_SHORT_AD) {
580 elen = sizeof (struct short_ad);
581 } else if (ip->i_desc_type == ICB_FLAG_LONG_AD) {
582 elen = sizeof (struct long_ad);
583 } else {
584 return (EINVAL);
587 if (ip->i_astrat == STRAT_TYPE4) {
588 int32_t ndentry;
590 ndentry = ip->i_max_emb / elen;
591 if (ip->i_ext_used < ndentry) {
592 return (0);
594 ASSERT(ip->i_con);
595 } else {
596 cmn_err(CE_WARN, "unsupported strategy type\n");
597 return (EINVAL);
600 return (0);
603 void
604 ud_update(int32_t flag)
606 struct vfs *vfsp;
607 struct udf_vfs *udfsp, *udfsnext, *update_list = NULL;
608 int32_t check_cnt = 0;
609 size_t check_size;
610 struct check_node *check_list, *ptr;
611 time_t start_time;
613 ud_printf("ud_update\n");
615 mutex_enter(&ud_sync_busy);
617 * Examine all udf_vfs structures and add those that we can lock to the
618 * update list. This is so that we don't hold the list lock for a
619 * long time. If vfs_lock fails for a file system instance, then skip
620 * it because somebody is doing a unmount on it.
622 mutex_enter(&udf_vfs_mutex);
623 for (udfsp = udf_vfs_instances;
624 udfsp != NULL; udfsp = udfsp->udf_next) {
625 vfsp = udfsp->udf_vfs;
626 if (vfs_lock(vfsp) != 0) {
627 continue;
629 udfsp->udf_wnext = update_list;
630 update_list = udfsp;
631 check_cnt++;
633 mutex_exit(&udf_vfs_mutex);
635 if (update_list == NULL) {
636 mutex_exit(&ud_sync_busy);
637 return;
640 check_size = sizeof (struct check_node) * check_cnt;
641 check_list = ptr = kmem_alloc(check_size, KM_NOSLEEP);
644 * Write back modified superblocks.
645 * Consistency check that the superblock of
646 * each file system is still in the buffer cache.
648 * Note that the update_list traversal is done without the protection
649 * of an overall list lock, so it's necessary to rely on the fact that
650 * each entry of the list is vfs_locked when moving from one entry to
651 * the next. This works because a concurrent attempt to add an entry
652 * to another thread's update_list won't find it, since it'll already
653 * be locked.
655 check_cnt = 0;
656 for (udfsp = update_list; udfsp != NULL; udfsp = udfsnext) {
658 * Need to grab the next ptr before we unlock this one so
659 * another thread doesn't grab it and change it before we move
660 * on to the next vfs. (Once we unlock it, it's ok if another
661 * thread finds it to add it to its own update_list; we don't
662 * attempt to refer to it through our list any more.)
664 udfsnext = udfsp->udf_wnext;
665 vfsp = udfsp->udf_vfs;
667 if (!vfsp->vfs_data) {
668 vfs_unlock(vfsp);
669 continue;
671 mutex_enter(&udfsp->udf_lock);
674 * Build up the STABLE check list, so we can unlock the vfs
675 * until we do the actual checking.
677 if (check_list != NULL) {
678 if ((udfsp->udf_flags & UDF_FL_RDONLY) == 0) {
679 ptr->vfsp = vfsp;
680 ptr->udf_vfs = udfsp;
681 ptr->vfs_dev = vfsp->vfs_dev;
682 ptr++;
683 check_cnt++;
688 * superblock is not modified
690 if (udfsp->udf_mod == 0) {
691 mutex_exit(&udfsp->udf_lock);
692 vfs_unlock(vfsp);
693 continue;
695 if ((udfsp->udf_flags & UDF_FL_RDONLY) == 0) {
696 mutex_exit(&udfsp->udf_lock);
697 mutex_exit(&ud_sync_busy);
698 cmn_err(CE_WARN, "update ro udfs mod\n");
699 return;
701 udfsp->udf_mod = 0;
702 mutex_exit(&udfsp->udf_lock);
704 ud_update_superblock(vfsp);
705 vfs_unlock(vfsp);
708 ud_flushi(flag);
710 * Force stale buffer cache information to be flushed,
711 * for all devices. This should cause any remaining control
712 * information (e.g., inode info) to be flushed back.
714 bflush((dev_t)NODEV);
716 if (check_list == NULL) {
717 mutex_exit(&ud_sync_busy);
718 return;
722 * For each udf filesystem in the STABLE check_list, update
723 * the clean flag if warranted.
725 start_time = gethrestime_sec();
726 for (ptr = check_list; check_cnt > 0; check_cnt--, ptr++) {
728 * ud_still_mounted() returns with vfsp and the vfs_reflock
729 * held if ptr refers to a vfs that is still mounted.
731 if ((vfsp = ud_still_mounted(ptr)) == NULL) {
732 continue;
734 ud_checkclean(vfsp, ptr->udf_vfs, ptr->vfs_dev, start_time);
735 vfs_unlock(vfsp);
737 mutex_exit(&ud_sync_busy);
738 kmem_free(check_list, check_size);
743 * Returns vfsp and hold the lock if the vfs is still being mounted.
744 * Otherwise, returns 0.
746 * For our purposes, "still mounted" means that the file system still appears
747 * on the list of UFS file system instances.
749 vfs_t *
750 ud_still_mounted(struct check_node *checkp)
752 struct vfs *vfsp;
753 struct udf_vfs *udf_vfsp;
755 ud_printf("ud_still_mounted\n");
757 mutex_enter(&udf_vfs_mutex);
758 for (udf_vfsp = udf_vfs_instances;
759 udf_vfsp != NULL; udf_vfsp = udf_vfsp->udf_next) {
760 if (udf_vfsp != checkp->udf_vfs) {
761 continue;
764 * Tentative match: verify it and try to lock. (It's not at
765 * all clear how the verification could fail, given that we've
766 * gotten this far. We would have had to reallocate the
767 * ufsvfs struct at hand for a new incarnation; is that really
768 * possible in the interval from constructing the check_node
769 * to here?)
771 vfsp = udf_vfsp->udf_vfs;
772 if (vfsp != checkp->vfsp) {
773 continue;
775 if (vfsp->vfs_dev != checkp->vfs_dev) {
776 continue;
778 if (vfs_lock(vfsp) != 0) {
779 continue;
781 mutex_exit(&udf_vfs_mutex);
782 return (vfsp);
784 mutex_exit(&udf_vfs_mutex);
785 return (NULL);
788 /* ARGSUSED */
789 void
790 ud_checkclean(struct vfs *vfsp,
791 struct udf_vfs *udf_vfsp, dev_t dev, time_t timev)
793 ud_printf("ud_checkclean\n");
794 udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
796 * ignore if buffers or inodes are busy
798 if ((bcheck(dev, udf_vfsp->udf_iseq)) ||
799 (ud_icheck(udf_vfsp))) {
800 return;
802 mutex_enter(&udf_vfsp->udf_lock);
803 ud_sbwrite(udf_vfsp);
804 mutex_exit(&udf_vfsp->udf_lock);
807 int32_t
808 ud_icheck(struct udf_vfs *udf_vfsp)
810 int32_t index, error = 0;
811 union ihead *ih;
812 struct ud_inode *ip;
814 mutex_enter(&ud_icache_lock);
815 for (index = 0; index < UD_HASH_SZ; index++) {
816 ih = &ud_ihead[index];
817 for (ip = ih->ih_chain[0];
818 ip != (struct ud_inode *)ih; ip = ip->i_forw) {
819 if ((ip->i_udf == udf_vfsp) &&
820 ((ip->i_flag & (IMOD|IUPD|ICHG)) ||
821 (RW_ISWRITER(&ip->i_rwlock)) ||
822 ((ip->i_nlink <= 0) && (ip->i_flag & IREF)))) {
823 error = 1;
824 goto end;
828 end:
829 mutex_exit(&ud_icache_lock);
830 return (error);
833 void
834 ud_flushi(int32_t flag)
836 struct ud_inode *ip, *lip;
837 struct vnode *vp;
838 int cheap = flag & SYNC_ATTR;
839 int32_t index;
840 union ihead *ih;
843 * Write back each (modified) inode,
844 * but don't sync back pages if vnode is
845 * part of the virtual swap device.
847 mutex_enter(&ud_icache_lock);
848 for (index = 0; index < UD_HASH_SZ; index++) {
849 ih = &ud_ihead[index];
850 lip = NULL;
852 for (ip = ih->ih_chain[0], lip = NULL;
853 ip && ip != (struct ud_inode *)ih;
854 ip = ip->i_forw) {
855 int flag = ip->i_flag;
857 vp = ITOV(ip);
859 * Skip locked & inactive inodes.
860 * Skip vnodes w/ no cached data and no inode changes.
861 * Skip read-only vnodes
863 if ((flag & IREF) == 0 ||
864 (!vn_has_cached_data(vp) &&
865 ((flag & (IMOD|IACC|IUPD|ICHG)) == 0)) ||
866 (vp->v_vfsp == NULL) || vn_is_readonly(vp)) {
867 continue;
870 if (!rw_tryenter(&ip->i_contents, RW_WRITER)) {
871 continue;
874 VN_HOLD(vp);
876 if (lip != NULL) {
877 ITIMES(lip);
878 VN_RELE(ITOV(lip));
880 lip = ip;
883 * If this is an inode sync for file system hardening
884 * or this is a full sync but file is a swap file,
885 * don't sync pages but make sure the inode is up
886 * to date. In other cases, push everything out.
888 if (cheap || IS_SWAPVP(vp)) {
889 ud_iupdat(ip, 0);
890 } else {
891 (void) ud_syncip(ip, B_ASYNC, I_SYNC);
893 rw_exit(&ip->i_contents);
895 if (lip != NULL) {
896 ITIMES(lip);
897 VN_RELE(ITOV(lip));
900 mutex_exit(&ud_icache_lock);
904 void
905 ud_update_regid(struct regid *reg)
907 ud_printf("ud_update_regid\n");
909 bzero(reg->reg_id, 23);
910 (void) strncpy(reg->reg_id, SUN_IMPL_ID, SUN_IMPL_ID_LEN);
911 reg->reg_ids[0] = SUN_OS_CLASS;
912 reg->reg_ids[1] = SUN_OS_ID;
915 /* ARGSUSED4 */
916 void
917 ud_make_tag(struct udf_vfs *udf_vfsp,
918 struct tag *tag, uint16_t tag_id, uint32_t blkno, uint16_t crc_len)
920 int32_t i;
921 uint16_t crc;
922 uint8_t *addr, cksum = 0;
924 ud_printf("ud_make_tag\n");
926 ASSERT(crc_len > 0x10);
927 addr = (uint8_t *)tag;
928 crc_len -= sizeof (struct tag);
929 crc = ud_crc(addr + 0x10, crc_len);
931 tag->tag_id = SWAP_16(tag_id);
932 tag->tag_desc_ver = SWAP_16(2);
933 tag->tag_cksum = 0;
934 tag->tag_res = 0;
935 tag->tag_sno = SWAP_16(udf_vfsp->udf_tsno);
936 tag->tag_crc = SWAP_16(crc);
938 tag->tag_crc_len = SWAP_16(crc_len);
939 tag->tag_loc = SWAP_32(blkno);
941 addr = (uint8_t *)tag;
942 for (i = 0; i <= 15; i++) {
943 cksum += addr[i];
945 tag->tag_cksum = cksum;
948 int32_t
949 ud_make_dev_spec_ear(struct dev_spec_ear *ds,
950 major_t major, minor_t minor)
952 int32_t attr_len;
954 ud_printf("ud_make_dev_spec_ear\n");
956 bzero(ds, sizeof (struct dev_spec_ear));
958 attr_len = sizeof (struct dev_spec_ear);
959 ds->ds_atype = SWAP_32(12);
960 ds->ds_astype = 1;
961 ds->ds_attr_len = SWAP_32(attr_len);
962 ds->ds_iu_len = 0;
963 ds->ds_major_id = SWAP_32(major);
964 ds->ds_minor_id = SWAP_32(minor);
966 return (attr_len);
970 int32_t
971 ud_get_next_fid(struct ud_inode *ip, struct fbuf **fbp, uint32_t offset,
972 struct file_id **fid, uint8_t **name, uint8_t *buf)
974 struct vnode *vp = ITOV(ip);
975 caddr_t beg, end;
976 int32_t error, lbsize, lbmask, sz, iulen, idlen, copied = 0;
977 struct udf_vfs *udf_vfsp;
978 uint8_t *obuf;
979 int32_t count;
980 uint32_t tbno;
981 uint16_t crc_len;
982 uint32_t len;
984 ud_printf("ud_get_next_fid\n");
986 obuf = buf;
987 udf_vfsp = ip->i_udf;
988 lbsize = udf_vfsp->udf_lbsize;
989 lbmask = udf_vfsp->udf_lbmask;
991 if ((error = ud_ip_off2bno(ip, offset, &tbno)) != 0) {
992 return (error);
994 /* First time read */
995 if (*fbp == NULL) {
996 if ((error = fbread(vp, (offset_t)(offset & ~lbmask),
997 lbsize, S_READ, fbp)) != 0) {
998 return (error);
1002 end = (*fbp)->fb_addr + (*fbp)->fb_count;
1003 beg = (*fbp)->fb_addr + (offset & lbmask);
1006 if ((offset % lbsize) ||
1007 (offset == 0)) {
1008 sz = end - beg;
1009 } else {
1010 sz = 0;
1014 if (F_LEN <= sz) {
1015 *fid = (struct file_id *)beg;
1016 beg += F_LEN;
1017 } else {
1018 copied = 1;
1019 bcopy(beg, buf, sz);
1020 fbrelse(*fbp, S_OTHER);
1021 *fbp = NULL;
1023 /* Skip to next block */
1024 if (offset & lbmask) {
1025 offset = (offset & ~lbmask) + lbsize;
1027 if ((error = fbread(vp, (offset_t)offset,
1028 lbsize, S_READ, fbp)) != 0) {
1029 return (error);
1031 end = (*fbp)->fb_addr + (*fbp)->fb_count;
1032 beg = (*fbp)->fb_addr;
1034 bcopy(beg, buf + sz, F_LEN - sz);
1035 beg = beg + F_LEN - sz;
1036 *fid = (struct file_id *)buf;
1038 buf += F_LEN;
1043 * Check if this a valid file_identifier
1045 if (ud_verify_tag_and_desc(&(*fid)->fid_tag, UD_FILE_ID_DESC,
1046 tbno, 0, lbsize) != 0) {
1048 * Either end of directory or corrupted
1050 return (EINVAL);
1053 crc_len = SWAP_16((*fid)->fid_tag.tag_crc_len);
1054 if (crc_len > udf_vfsp->udf_lbsize) {
1056 * Entries cannot be larger than
1057 * blocksize
1059 return (EINVAL);
1062 if (crc_len < (F_LEN - sizeof (struct tag))) {
1063 iulen = SWAP_16((*fid)->fid_iulen);
1064 idlen = FID_LEN(*fid) - F_LEN;
1065 goto use_id_iu_len;
1069 * By now beg points to the start fo the file name
1072 sz = end - beg;
1073 len = crc_len + sizeof (struct tag) - (F_LEN);
1074 if (len <= sz) {
1075 if (copied == 1) {
1076 bcopy(beg, buf, len);
1077 buf += len;
1079 beg += len;
1080 } else {
1081 copied = 1;
1083 * We are releasing the
1084 * old buffer so copy fid to buf
1086 if (obuf == buf) {
1087 count = F_LEN + sz;
1088 bcopy(*fid, buf, count);
1089 *fid = (struct file_id *)buf;
1090 buf += count;
1091 } else {
1092 bcopy(beg, buf, sz);
1093 *fid = (struct file_id *)buf;
1094 buf += sz;
1096 fbrelse(*fbp, S_OTHER);
1097 *fbp = NULL;
1099 /* Skip to next block */
1100 if (offset & lbmask) {
1101 offset = (offset & ~lbmask) + lbsize;
1103 if ((error = fbread(vp, (offset_t)offset,
1104 lbsize, S_READ, fbp)) != 0) {
1105 return (error);
1107 end = (*fbp)->fb_addr + (*fbp)->fb_count;
1108 beg = (*fbp)->fb_addr;
1109 count = len - sz;
1110 bcopy(beg, buf, count);
1111 beg += count;
1115 * First we verify that the tag id and the FID_LEN are valid.
1116 * Next we verify the crc of the descriptor.
1118 if (ud_verify_tag_and_desc(&(*fid)->fid_tag, UD_FILE_ID_DESC,
1119 tbno, 0, lbsize) != 0) {
1120 /* directory is corrupted */
1121 return (EINVAL);
1123 if (ud_verify_tag_and_desc(&(*fid)->fid_tag, UD_FILE_ID_DESC,
1124 tbno, 1, FID_LEN(*fid)) != 0) {
1125 /* directory is corrupted */
1126 return (EINVAL);
1129 idlen = FID_LEN(*fid);
1131 idlen -= F_LEN;
1132 iulen = SWAP_16((*fid)->fid_iulen);
1133 if (crc_len < (F_LEN - sizeof (struct tag) + idlen)) {
1134 use_id_iu_len:
1135 len = (F_LEN - sizeof (struct tag) + idlen) - crc_len;
1136 sz = end - beg;
1137 if (len <= sz) {
1138 if (copied == 1) {
1139 bcopy(beg, buf, len);
1141 } else {
1142 if (obuf == buf) {
1143 count = crc_len + sizeof (struct tag);
1144 bcopy(*fid, buf, count);
1145 *fid = (struct file_id *)buf;
1146 buf += count;
1147 } else {
1148 bcopy(beg, buf, sz);
1149 *fid = (struct file_id *)buf;
1150 buf += sz;
1152 fbrelse(*fbp, S_OTHER);
1153 *fbp = NULL;
1155 /* Skip to next block */
1156 if (offset & lbmask) {
1157 offset = (offset & ~lbmask) + lbsize;
1159 if ((error = fbread(vp, (offset_t)offset,
1160 lbsize, S_READ, fbp)) != 0) {
1161 return (error);
1163 end = (*fbp)->fb_addr + (*fbp)->fb_count;
1164 beg = (*fbp)->fb_addr;
1165 count = len - sz;
1166 bcopy(beg, buf, count);
1167 beg += count;
1171 *name = ((uint8_t *)*fid) + F_LEN + iulen;
1173 return (0);
1177 int32_t
1178 ud_verify_tag_and_desc(struct tag *tag, uint16_t id, uint32_t blockno,
1179 int32_t verify_desc, int32_t desc_len)
1181 int32_t i;
1182 uint8_t *addr, cksum = 0;
1183 uint16_t crc;
1184 file_entry_t *fe;
1185 struct ext_attr_hdr *eah;
1186 struct file_id *fid;
1187 int32_t fidlen, ea_off;
1189 if (tag->tag_id != SWAP_16(id)) {
1190 return (1);
1192 addr = (uint8_t *)tag;
1193 eah = (struct ext_attr_hdr *)tag;
1194 for (i = 0; i < 4; i++) {
1195 cksum += addr[i];
1197 for (i = 5; i <= 15; i++) {
1198 cksum += addr[i];
1200 if (cksum != tag->tag_cksum) {
1201 cmn_err(CE_NOTE,
1202 "Checksum Does not Verify TAG %x CALC %x blockno 0x%x\n",
1203 tag->tag_cksum, cksum, blockno);
1204 return (1);
1207 * Validate the meta data for UD_FILE_ID_DESC.
1208 * The FID_LEN should not exceed the desc_len.
1209 * This validation is done before the entire descriptor is read.
1210 * A call to this routine is made initially with verify_desc set as 0
1211 * but a non zero value in desc_len.
1213 if (id == UD_FILE_ID_DESC) {
1214 fid = (struct file_id *)tag;
1215 fidlen = FID_LEN(fid);
1216 if (fidlen > desc_len) {
1217 cmn_err(CE_NOTE,
1218 "Invalid FID_LEN(0x%x). Greater than expected(0x%x) blockno 0x%x\n",
1219 fidlen, desc_len, blockno);
1220 return (1);
1223 if (verify_desc == 0)
1224 return (0);
1226 * We are done verifying the tag. We proceed with verifying the
1227 * the descriptor. desc_len indicates the size of the structure
1228 * pointed to by argument tag. It includes the size of struct tag.
1229 * We first check the tag_crc_len since we use this to compute the
1230 * crc of the descriptor.
1231 * Verifying the crc is normally sufficient to ensure the integrity
1232 * of the meta data in the descriptor. However given the paranoia
1233 * about the panic caused by illegal meta data values we do an
1234 * additional check of the meta data for decriptor UD_FILE_ENTRY.
1235 * (The original panic was caused because this routine was not called
1236 * to verify the integrity of the tag and descriptor.)
1238 if (SWAP_16(tag->tag_crc_len) > (desc_len - sizeof (struct tag))) {
1239 cmn_err(CE_NOTE,
1240 "tag_crc_len(0x%x) is greater than expected len(0x%x) blockno 0x%x\n",
1241 SWAP_16(tag->tag_crc_len),
1242 desc_len, blockno);
1243 return (1);
1245 if (tag->tag_crc_len) {
1246 crc = ud_crc(addr + 0x10, SWAP_16(tag->tag_crc_len));
1247 if (crc != SWAP_16(tag->tag_crc)) {
1248 cmn_err(CE_NOTE, "CRC mismatch TAG_ID 0x%x TAG_CRC 0x%x"
1249 " Computed crc 0x%x tag_loc %x blockno 0x%x\n",
1250 id, SWAP_16(tag->tag_crc), crc,
1251 SWAP_32(tag->tag_loc), blockno);
1252 return (1);
1255 switch (id) {
1256 case UD_FILE_ENTRY:
1257 fe = (file_entry_t *)tag;
1258 if ((offsetof(struct file_entry, fe_spec) +
1259 SWAP_32(fe->fe_len_ear) +
1260 SWAP_32(fe->fe_len_adesc)) > desc_len) {
1261 cmn_err(CE_NOTE,
1262 "fe_len_ear(0x%x) fe_len_adesc(0x%x) fields are not OK. blockno 0x%x\n",
1263 SWAP_32(fe->fe_len_ear),
1264 SWAP_32(fe->fe_len_adesc),
1265 blockno);
1266 return (1);
1268 break;
1269 case UD_EXT_ATTR_HDR:
1270 eah = (struct ext_attr_hdr *)tag;
1271 if (SWAP_32(eah->eah_aal) > desc_len) {
1272 cmn_err(CE_NOTE,
1273 "eah_all(0x%x) exceeds desc. len(0x%x) blockno 0x%x\n",
1274 SWAP_32(eah->eah_aal), desc_len, blockno);
1275 return (1);
1277 ea_off = GET_32(&eah->eah_ial);
1278 if (ea_off >= desc_len) {
1279 cmn_err(CE_NOTE,
1280 "ea_off(0x%x) is not less than ea_len(0x%x) blockno 0x%x\n",
1281 ea_off, desc_len, blockno);
1282 return (1);
1284 break;
1285 default:
1286 break;
1288 if (SWAP_32(blockno) != tag->tag_loc) {
1289 cmn_err(CE_NOTE,
1290 "Tag Location mismatch blockno %x tag_blockno %x\n",
1291 blockno, SWAP_32(tag->tag_loc));
1292 return (1);
1294 return (0);
1297 /* **************** udf specific subroutines *********************** */
1299 uint16_t ud_crc_table[256] = {
1300 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
1301 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
1302 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
1303 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
1304 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
1305 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
1306 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
1307 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
1308 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
1309 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
1310 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
1311 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
1312 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
1313 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
1314 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
1315 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
1316 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
1317 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
1318 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
1319 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
1320 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
1321 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1322 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
1323 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
1324 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
1325 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
1326 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
1327 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
1328 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
1329 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
1330 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
1331 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
1334 uint16_t
1335 ud_crc(uint8_t *addr, int32_t len)
1337 uint16_t crc = 0;
1339 while (len-- > 0) {
1340 crc = ud_crc_table[(crc >> 8 ^ *addr++) & 0xff] ^ (crc<<8);
1343 return (crc);
1346 typedef unsigned short unicode_t;
1348 #define POUND 0x0023
1349 #define DOT 0x002E
1350 #define SLASH 0x002F
1351 #define UNDERBAR 0x005F
1354 static uint16_t htoc[16] = {'0', '1', '2', '3',
1355 '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
1359 * An unrecorded block will return all
1360 * 0's on a WORM media. to simulate
1361 * a unrecorded block on a rw media
1362 * we fill it with all zero's
1363 * return 0 : If unrecorded
1364 * return 1 : If recorded.
1366 uint32_t
1367 ud_check_te_unrec(struct udf_vfs *udf_vfsp, caddr_t addr, uint32_t blkno)
1369 int32_t i, lbsize;
1370 struct term_entry *te;
1372 ASSERT(udf_vfsp);
1373 ASSERT(addr);
1375 te = (struct term_entry *)addr;
1376 if (ud_verify_tag_and_desc(&te->te_tag, UD_TERMINAL_ENT,
1377 blkno, 1, udf_vfsp->udf_lbsize) != 0) {
1378 lbsize = udf_vfsp->udf_lbsize;
1379 for (i = 0; i < lbsize; i++) {
1380 if (addr[i] != 0) {
1381 return (1);
1385 return (0);
1390 * The algorithms ud_utf82utf16 and ud_utf162utf8
1391 * donot handle surrogates. This is unicode 1.1 as I
1392 * understand. When writing udf2.0 this code has
1393 * to be changed to process surrogates also
1394 * (Dont ask me what is a surrogate character)
1398 * This will take a utf8 string convert the first character
1399 * to utf16 and return the number of bytes consumed in this
1400 * process. A 0 will be returned if the character is invalid
1402 uint8_t bytes_from_utf8[] = {
1403 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1404 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1405 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1406 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1407 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1408 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1409 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1410 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1411 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1412 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1413 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1414 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1415 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1416 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1417 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1418 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
1420 int32_t
1421 ud_utf82utf16(uint8_t *s_8, uint16_t *c_16, int32_t count)
1423 int32_t extra_bytes;
1424 uint32_t c_32;
1425 ASSERT(s_8);
1426 ASSERT(c_16);
1429 * First convert to a 32-bit
1430 * character
1432 c_32 = 0;
1433 extra_bytes = bytes_from_utf8[*s_8];
1434 if (extra_bytes > count) {
1435 return (0);
1439 * verify if the string is a valid
1440 * utf8 string
1442 if (extra_bytes == 0) {
1444 * Apply one byte rule
1446 if (*s_8 & 0x80) {
1447 return (0);
1449 c_32 = *s_8 & 0x7F;
1450 } else if (extra_bytes == 1) {
1451 if (((*s_8 & 0xE0) != 0xC0) ||
1452 ((*(s_8 + 1) & 0xC0) != 0x80)) {
1453 return (0);
1455 c_32 = *s_8 & 0x1F;
1456 } else if (extra_bytes == 2) {
1457 if (((*s_8 & 0xF0) != 0xE0) ||
1458 ((*(s_8 + 1) & 0xC0) != 0x80) ||
1459 ((*(s_8 + 2) & 0xC0) != 0x80)) {
1460 return (0);
1462 c_32 = *s_8 & 0x0F;
1463 } else if (extra_bytes == 3) {
1464 if (((*s_8 & 0xF8) != 0xF0) ||
1465 ((*(s_8 + 1) & 0xC0) != 0x80) ||
1466 ((*(s_8 + 2) & 0xC0) != 0x80) ||
1467 ((*(s_8 + 3) & 0xC0) != 0x80)) {
1468 return (0);
1470 c_32 = *s_8 & 0x07;
1471 } else if (extra_bytes == 4) {
1472 if (((*s_8 & 0xFC) != 0xF8) ||
1473 ((*(s_8 + 1) & 0xC0) != 0x80) ||
1474 ((*(s_8 + 2) & 0xC0) != 0x80) ||
1475 ((*(s_8 + 3) & 0xC0) != 0x80) ||
1476 ((*(s_8 + 4) & 0xC0) != 0x80)) {
1477 return (0);
1479 c_32 = *s_8 & 0x03;
1480 } else if (extra_bytes == 5) {
1481 if (((*s_8 & 0xFE) != 0xFC) ||
1482 ((*(s_8 + 1) & 0xC0) != 0x80) ||
1483 ((*(s_8 + 2) & 0xC0) != 0x80) ||
1484 ((*(s_8 + 3) & 0xC0) != 0x80) ||
1485 ((*(s_8 + 4) & 0xC0) != 0x80) ||
1486 ((*(s_8 + 5) & 0xC0) != 0x80)) {
1487 return (0);
1489 c_32 = *s_8 & 0x01;
1490 } else {
1491 return (0);
1493 s_8++;
1496 * Convert to 32-bit character
1498 switch (extra_bytes) {
1499 case 5 :
1500 c_32 <<= 6;
1501 c_32 += (*s_8++ & 0x3F);
1502 /* FALLTHROUGH */
1503 case 4 :
1504 c_32 <<= 6;
1505 c_32 += (*s_8++ & 0x3F);
1506 /* FALLTHROUGH */
1507 case 3 :
1508 c_32 <<= 6;
1509 c_32 += (*s_8++ & 0x3F);
1510 /* FALLTHROUGH */
1511 case 2 :
1512 c_32 <<= 6;
1513 c_32 += (*s_8++ & 0x3F);
1514 /* FALLTHROUGH */
1515 case 1 :
1516 c_32 <<= 6;
1517 c_32 += (*s_8++ & 0x3F);
1518 /* FALLTHROUGH */
1519 case 0 :
1520 break;
1524 * now convert the 32-bit
1525 * character into a 16-bit character
1527 *c_16 = c_32;
1528 return (extra_bytes + 1);
1532 * Convert to a form that can be put on the media
1533 * out_len has the size of out_str when we are called.
1534 * This routine will set out_len to actual bytes written to out_str.
1535 * We make sure that we will not attempt to write beyond the out_str_len.
1537 int32_t
1538 ud_compress(int32_t in_len, int32_t *out_len,
1539 uint8_t *in_str, uint8_t *out_str)
1541 int32_t error, in_index, out_index, index, c_tx_sz, out_str_len;
1542 uint16_t w2_char, *w2_str;
1543 uint8_t comp_id;
1545 out_str_len = *out_len;
1546 if (in_len > (out_str_len - 2)) {
1547 return (ENAMETOOLONG);
1550 *out_len = 0;
1551 w2_str = kmem_zalloc(512, KM_SLEEP);
1553 error = in_index = out_index = c_tx_sz = 0;
1554 comp_id = 8;
1555 for (in_index = 0; in_index < in_len; in_index += c_tx_sz) {
1556 if ((c_tx_sz = ud_utf82utf16(&in_str[in_index],
1557 &w2_char, in_len - in_index)) == 0) {
1558 error = EINVAL;
1559 goto end;
1562 * utf-8 characters can be
1563 * of 1 - 6 bytes in length
1565 ASSERT(c_tx_sz > 0);
1566 ASSERT(c_tx_sz < 7);
1567 if ((comp_id == 8) && (w2_char & 0xff00)) {
1568 comp_id = 0x10;
1570 w2_str[out_index++] = w2_char;
1572 if (((comp_id == 0x10) && (out_index > ((out_str_len - 2)/2))) ||
1573 ((comp_id == 0x8) && (out_index > (out_str_len - 2)))) {
1574 error = ENAMETOOLONG;
1575 goto end;
1578 in_index = out_index;
1579 out_index = 0;
1580 out_str[out_index++] = comp_id;
1581 for (index = 0; index < in_index; index++) {
1582 if (comp_id == 0x10) {
1583 out_str[out_index++] = (w2_str[index] & 0xFF00) >> 8;
1585 out_str[out_index++] = w2_str[index] & 0xFF;
1587 ASSERT(out_index <= (out_str_len - 1));
1588 *out_len = out_index;
1589 end:
1590 if (w2_str != NULL) {
1591 kmem_free((caddr_t)w2_str, 512);
1593 return (error);
1597 * Take a utf16 character and convert
1598 * it into a utf8 character.
1599 * A 0 will be returned if the conversion fails
1601 uint8_t first_byte_mark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
1602 int32_t
1603 ud_utf162utf8(uint16_t c_16, uint8_t *s_8)
1605 int32_t nc;
1606 uint32_t c_32;
1607 uint32_t byte_mask = 0xBF;
1608 uint32_t byte_mark = 0x80;
1610 ASSERT(s_8);
1613 * Convert the 16-bit character to
1614 * a 32-bit character
1616 c_32 = c_16;
1619 * By here the 16-bit character is converted
1620 * to a 32-bit wide character
1622 if (c_32 < 0x80) {
1623 nc = 1;
1624 } else if (c_32 < 0x800) {
1625 nc = 2;
1626 } else if (c_32 < 0x10000) {
1627 nc = 3;
1628 } else if (c_32 < 0x200000) {
1629 nc = 4;
1630 } else if (c_32 < 0x4000000) {
1631 nc = 5;
1632 } else if (c_32 < (uint32_t)0x80000000) {
1633 nc = 6;
1634 } else {
1635 nc = 0;
1637 s_8 += nc;
1638 switch (nc) {
1639 case 6 :
1640 *(--s_8) = (c_32 | byte_mark) & byte_mask;
1641 c_32 >>= 6;
1642 /* FALLTHROUGH */
1643 case 5 :
1644 *(--s_8) = (c_32 | byte_mark) & byte_mask;
1645 c_32 >>= 6;
1646 /* FALLTHROUGH */
1647 case 4 :
1648 *(--s_8) = (c_32 | byte_mark) & byte_mask;
1649 c_32 >>= 6;
1650 /* FALLTHROUGH */
1651 case 3 :
1652 *(--s_8) = (c_32 | byte_mark) & byte_mask;
1653 c_32 >>= 6;
1654 /* FALLTHROUGH */
1655 case 2 :
1656 *(--s_8) = (c_32 | byte_mark) & byte_mask;
1657 c_32 >>= 6;
1658 /* FALLTHROUGH */
1659 case 1 :
1660 *(--s_8) = c_32 | first_byte_mark[nc];
1662 return (nc);
1666 * Convert to a form that can be transferred to the user
1667 * Assumption's
1668 * in_length < 256, out_str is at least 255 bytes long
1669 * The converted byte stream length is returned in out_len
1671 #define MAX_ALLOWABLE_STRING 250
1673 int32_t
1674 ud_uncompress(int32_t in_len, int32_t *out_len,
1675 uint8_t *in_str, uint8_t *out_str)
1677 uint8_t comp_id, utf8[6];
1678 uint16_t w2_char, crc;
1679 int32_t error, index, c_tx_sz, len_till_now;
1680 int32_t make_crc, lic, dot_loc, crc_start_loc = 0, k = 0;
1682 if (in_len == 0) {
1683 *out_len = 0;
1684 out_str[0] = '\0';
1685 return (0);
1688 error = len_till_now = make_crc = 0;
1689 dot_loc = lic = -2;
1690 *out_len = 0;
1691 crc = 0;
1692 comp_id = in_str[0];
1695 * File names "." and ".." are invalid under unix.
1696 * Transform them into something
1698 if (comp_id == 8) {
1699 if ((in_str[1] == DOT) &&
1700 ((in_len == 2) || ((in_len == 3) &&
1701 (in_str[2] == DOT)))) {
1702 out_str[k++] = UNDERBAR;
1703 len_till_now = 1;
1704 goto make_append_crc;
1706 } else if (comp_id == 0x10) {
1707 if (((in_str[1] << 8 | in_str[2]) == DOT) &&
1708 ((in_len == 3) || ((in_len == 5) &&
1709 ((in_str[3] << 8 | in_str[4]) == DOT)))) {
1710 out_str[k++] = UNDERBAR;
1711 len_till_now = 1;
1712 goto make_append_crc;
1714 } else {
1715 *out_len = 0;
1716 return (EINVAL);
1719 for (index = 1; index < in_len; ) {
1722 * Uncompress each character
1724 if (comp_id == 0x10) {
1725 w2_char = in_str[index++] << 8;
1726 w2_char |= in_str[index++];
1727 } else {
1728 w2_char = in_str[index++];
1731 if (make_crc != 0) {
1732 crc += w2_char;
1735 if (w2_char == DOT) {
1736 dot_loc = len_till_now;
1740 * Get rid of invalid characters
1742 if ((w2_char == SLASH) ||
1743 (w2_char == 0)) {
1744 make_crc = 1;
1745 if (((comp_id == 8) &&
1746 (lic != (index - 1))) ||
1747 (comp_id == 0x10) &&
1748 (lic != (index - 2))) {
1749 w2_char = UNDERBAR;
1750 lic = index;
1751 } else {
1752 lic = index;
1753 continue;
1758 * Conver a 16bit character to a
1759 * utf8 byte stream
1761 if ((c_tx_sz = ud_utf162utf8(w2_char, utf8)) == 0) {
1762 error = EINVAL;
1763 goto end;
1765 ASSERT(c_tx_sz > 0);
1766 ASSERT(c_tx_sz < 7);
1769 * The output string is larger than
1770 * the maximum allowed string length
1772 if ((crc_start_loc == 0) &&
1773 ((len_till_now + c_tx_sz) > MAX_ALLOWABLE_STRING)) {
1774 crc_start_loc = len_till_now;
1777 if ((len_till_now + c_tx_sz) < MAXNAMELEN) {
1778 (void) strncpy((caddr_t)&out_str[len_till_now],
1779 (caddr_t)utf8, c_tx_sz);
1780 len_till_now += c_tx_sz;
1781 } else {
1782 break;
1787 * If we need to append CRC do it now
1790 if (make_crc) {
1792 if (len_till_now > MAX_ALLOWABLE_STRING) {
1793 len_till_now = crc_start_loc;
1796 if (dot_loc > 0) {
1798 * Make space for crc before the DOT
1799 * move the rest of the file name to the end
1801 for (k = len_till_now - 1; k >= dot_loc; k--) {
1802 out_str[k + 5] = out_str[k];
1804 k = dot_loc;
1805 } else {
1806 k = len_till_now;
1808 make_append_crc:
1809 crc = ud_crc(in_str, in_len);
1810 out_str[k++] = POUND;
1811 out_str[k++] = htoc[(uint16_t)(crc & 0xf000) >> 12];
1812 out_str[k++] = htoc[(uint16_t)(crc & 0xf00) >> 8];
1813 out_str[k++] = htoc[(uint16_t)(crc & 0xf0) >> 4];
1814 out_str[k++] = htoc[crc & 0xf];
1815 len_till_now += 5;
1817 *out_len = len_till_now;
1818 end:
1819 return (error);
1823 struct buf *
1824 ud_bread(dev_t dev, daddr_t blkno, long bsize)
1826 struct buf *bp;
1828 begin:
1829 bp = bread(dev, blkno, bsize);
1831 if (((bp->b_flags & B_ERROR) == 0) &&
1832 (bp->b_bcount != bsize)) {
1834 * Buffer cache returned a
1835 * wrong number of bytes
1836 * flush the old buffer and
1837 * reread it again
1839 if (bp->b_flags & B_DELWRI) {
1840 bwrite(bp);
1841 } else {
1842 bp->b_flags |= (B_AGE | B_STALE);
1843 brelse(bp);
1845 goto begin;
1848 return (bp);
1852 * Decide whether it is okay to remove within a sticky directory.
1853 * Two conditions need to be met: write access to the directory
1854 * is needed. In sticky directories, write access is not sufficient;
1855 * you can remove entries from a directory only if you own the directory,
1856 * if you are privileged, if you own the entry or if they entry is
1857 * a plain file and you have write access to that file.
1858 * Function returns 0 if remove access is granted.
1861 ud_sticky_remove_access(struct ud_inode *dir, struct ud_inode *entry,
1862 struct cred *cr)
1864 uid_t uid;
1866 ASSERT(RW_LOCK_HELD(&entry->i_contents));
1868 if ((dir->i_char & ISVTX) &&
1869 (uid = crgetuid(cr)) != dir->i_uid &&
1870 uid != entry->i_uid &&
1871 (entry->i_type != VREG ||
1872 ud_iaccess(entry, IWRITE, cr, 0) != 0))
1873 return (secpolicy_vnode_remove(cr));
1875 return (0);