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]
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>
29 #include <sys/systm.h>
30 #include <sys/sysmacros.h>
31 #include <sys/resource.h>
32 #include <sys/signal.h>
38 #include <sys/vnode.h>
43 #include <sys/fcntl.h>
44 #include <sys/flock.h>
49 #include <sys/errno.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>
70 #include <vm/seg_map.h>
71 #include <vm/seg_kmem.h>
72 #include <vm/seg_vn.h>
78 #include <fs/fs_subr.h>
81 #include <sys/fs/udf_volume.h>
82 #include <sys/fs/udf_inode.h>
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.
109 struct udf_vfs
*udf_vfs
;
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.
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.
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
;
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
158 ud_xlate_to_daddr(struct udf_vfs
*udf_vfsp
,
159 uint16_t prn
, uint32_t blkno
, int32_t nblks
, uint32_t *count
)
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");
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
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
]);
188 blkno
-= map
->udm_count
[i
];
191 } else if (map
->udm_flags
== UDM_MAP_SPM
) {
193 struct stbl_entry
*te
;
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
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) {
221 if ((end_req
< begin_bad
) ||
222 (begin_req
>= end_bad
)) {
226 if (begin_req
< begin_bad
) {
227 ASSERT(end_req
>= begin_bad
);
230 retblkno
= SWAP_32(te
->sent_ml
) +
231 begin_req
- begin_bad
;
232 if (end_req
< end_bad
) {
233 *count
= end_req
- begin_req
;
235 *count
= end_bad
- begin_req
;
242 *count
= end_req
- begin_req
;
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
) {
260 retblkno
= ud_parts
->udp_start
+ lblkno
;
274 ud_xlate_to_addr(struct udf_vfs
*udf_vfsp
,
275 uint16_t prn
, daddr_t blkno
, int32_t lad
)
278 struct ud_part
*ud_parts
;
280 ud_printf("ud_xlate_to_addr\n");
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
);
296 * Directories do not have holes
299 ud_ip_off2bno(struct ud_inode
*ip
, uint32_t offset
, uint32_t *bno
)
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
;
311 if ((error
= ud_read_icb_till_off(ip
, (u_offset_t
)offset
)) != 0) {
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
);
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 */
345 ud_dtime2utime(struct timespec32
*utime
,
346 struct tstamp
const *dtime
)
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 +
363 tzone
= SWAP_16(dtime
->ts_tzone
);
364 if ((tzone
& TMODE
) == 0x1000) {
366 if ((tzone
& TINVALID
) != TINVALID
) {
369 * Sign extend the tzone
371 sec
= tzone
| 0xFFFFF000;
373 sec
= tzone
& TOFFSET
;
376 utime
->tv_sec
-= sec
;
380 utime
->tv_nsec
= ((((dtime
->ts_csec
* 100) +
381 dtime
->ts_husec
) * 100) +
382 dtime
->ts_usec
) * 1000;
384 utime
->tv_sec
+= (year
- 1970) * SEC_PER_YEAR
;
385 utime
->tv_sec
+= ((year
- 1969) / 4) * SEC_PER_DAY
;
387 utime
->tv_sec
= ((1970 - year
) * SEC_PER_YEAR
+
388 ((1972 - year
) / 4) * SEC_PER_DAY
-
390 if (utime
->tv_nsec
) {
392 utime
->tv_nsec
= 1000 * 1000 * 1000 - utime
->tv_nsec
;
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
;
407 ud_printf("ud_utime2dtime\n");
414 usec
= 1000 * 1000 - usec
;
418 dtime
->ts_csec
= usec
/ 10000;
420 dtime
->ts_husec
= usec
/ 100;
421 dtime
->ts_usec
= usec
% 100;
423 nyrs
= sec
/ SEC_PER_YEAR
;
425 lyrs
= (nyrs
+ 1) / 4;
427 lyrs
= (nyrs
+ 2) / 4;
429 if (nyrs
!= ((sec
- (lyrs
* SEC_PER_DAY
)) / SEC_PER_YEAR
)) {
432 lyrs
= (nyrs
+ 1) / 4;
434 lyrs
= (nyrs
+ 2) / 4;
437 sec
-= nyrs
* SEC_PER_YEAR
+ lyrs
* SEC_PER_DAY
;
443 if ((nyrs
% 4) == 0) {
444 sec
= SEC_PER_YEAR
+ SEC_PER_DAY
- sec
;
446 sec
= SEC_PER_YEAR
- sec
;
452 cp
= (nyrs
% 4) ? cum_sec
: cum_sec_leap
;
453 dummy
= sec
/ (SEC_PER_DAY
* 29);
457 if (sec
< cp
[dummy
]) {
460 dtime
->ts_year
= SWAP_16(nyrs
);
461 dtime
->ts_month
= dummy
;
462 sec
-= cp
[dtime
->ts_month
];
464 dtime
->ts_day
= sec
/ SEC_PER_DAY
;
465 sec
-= dtime
->ts_day
* SEC_PER_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);
479 ud_syncip(struct ud_inode
*ip
, int32_t flags
, int32_t waitfor
)
482 struct vnode
*vp
= ITOV(ip
);
484 ud_printf("ud_syncip\n");
486 if (ip
->i_udf
== NULL
) {
490 if (!vn_has_cached_data(vp
) || (vp
->v_type
== VCHR
)) {
493 rw_exit(&ip
->i_contents
);
494 error
= VOP_PUTPAGE(vp
, (offset_t
)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
);
509 ud_fbwrite(struct fbuf
*fbp
, struct ud_inode
*ip
)
511 ud_printf("ud_fbwrite\n");
515 return (fbwrite(fbp
));
520 ud_sbwrite(struct udf_vfs
*udf_vfsp
)
522 struct log_vol_int_desc
*lvid
;
523 struct ud_part
*ud_part
;
528 ud_printf("ud_sbwrite\n");
530 ASSERT(MUTEX_HELD(&udf_vfsp
->udf_lock
));
533 * updatable information in the superblock
534 * integrity type, udf_maxuniq, udf_nfiles, udf_ndirs
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
);
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
);
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
);
571 ud_sync_indir(struct ud_inode
*ip
)
575 ud_printf("ud_sync_indir\n");
577 if (ip
->i_desc_type
== ICB_FLAG_ONE_AD
) {
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
);
587 if (ip
->i_astrat
== STRAT_TYPE4
) {
590 ndentry
= ip
->i_max_emb
/ elen
;
591 if (ip
->i_ext_used
< ndentry
) {
596 cmn_err(CE_WARN
, "unsupported strategy type\n");
604 ud_update(int32_t flag
)
607 struct udf_vfs
*udfsp
, *udfsnext
, *update_list
= NULL
;
608 int32_t check_cnt
= 0;
610 struct check_node
*check_list
, *ptr
;
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) {
629 udfsp
->udf_wnext
= update_list
;
633 mutex_exit(&udf_vfs_mutex
);
635 if (update_list
== NULL
) {
636 mutex_exit(&ud_sync_busy
);
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
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
) {
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) {
680 ptr
->udf_vfs
= udfsp
;
681 ptr
->vfs_dev
= vfsp
->vfs_dev
;
688 * superblock is not modified
690 if (udfsp
->udf_mod
== 0) {
691 mutex_exit(&udfsp
->udf_lock
);
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");
702 mutex_exit(&udfsp
->udf_lock
);
704 ud_update_superblock(vfsp
);
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
);
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
) {
734 ud_checkclean(vfsp
, ptr
->udf_vfs
, ptr
->vfs_dev
, start_time
);
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.
750 ud_still_mounted(struct check_node
*checkp
)
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
) {
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
771 vfsp
= udf_vfsp
->udf_vfs
;
772 if (vfsp
!= checkp
->vfsp
) {
775 if (vfsp
->vfs_dev
!= checkp
->vfs_dev
) {
778 if (vfs_lock(vfsp
) != 0) {
781 mutex_exit(&udf_vfs_mutex
);
784 mutex_exit(&udf_vfs_mutex
);
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
))) {
802 mutex_enter(&udf_vfsp
->udf_lock
);
803 ud_sbwrite(udf_vfsp
);
804 mutex_exit(&udf_vfsp
->udf_lock
);
808 ud_icheck(struct udf_vfs
*udf_vfsp
)
810 int32_t index
, error
= 0;
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
)))) {
829 mutex_exit(&ud_icache_lock
);
834 ud_flushi(int32_t flag
)
836 struct ud_inode
*ip
, *lip
;
838 int cheap
= flag
& SYNC_ATTR
;
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
];
852 for (ip
= ih
->ih_chain
[0], lip
= NULL
;
853 ip
&& ip
!= (struct ud_inode
*)ih
;
855 int flag
= ip
->i_flag
;
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
)) {
870 if (!rw_tryenter(&ip
->i_contents
, RW_WRITER
)) {
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
)) {
891 (void) ud_syncip(ip
, B_ASYNC
, I_SYNC
);
893 rw_exit(&ip
->i_contents
);
900 mutex_exit(&ud_icache_lock
);
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
;
917 ud_make_tag(struct udf_vfs
*udf_vfsp
,
918 struct tag
*tag
, uint16_t tag_id
, uint32_t blkno
, uint16_t crc_len
)
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);
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
++) {
945 tag
->tag_cksum
= cksum
;
949 ud_make_dev_spec_ear(struct dev_spec_ear
*ds
,
950 major_t major
, minor_t minor
)
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);
961 ds
->ds_attr_len
= SWAP_32(attr_len
);
963 ds
->ds_major_id
= SWAP_32(major
);
964 ds
->ds_minor_id
= SWAP_32(minor
);
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
);
976 int32_t error
, lbsize
, lbmask
, sz
, iulen
, idlen
, copied
= 0;
977 struct udf_vfs
*udf_vfsp
;
984 ud_printf("ud_get_next_fid\n");
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) {
994 /* First time read */
996 if ((error
= fbread(vp
, (offset_t
)(offset
& ~lbmask
),
997 lbsize
, S_READ
, fbp
)) != 0) {
1002 end
= (*fbp
)->fb_addr
+ (*fbp
)->fb_count
;
1003 beg
= (*fbp
)->fb_addr
+ (offset
& lbmask
);
1006 if ((offset
% lbsize
) ||
1015 *fid
= (struct file_id
*)beg
;
1019 bcopy(beg
, buf
, sz
);
1020 fbrelse(*fbp
, S_OTHER
);
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) {
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
;
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
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
1062 if (crc_len
< (F_LEN
- sizeof (struct tag
))) {
1063 iulen
= SWAP_16((*fid
)->fid_iulen
);
1064 idlen
= FID_LEN(*fid
) - F_LEN
;
1069 * By now beg points to the start fo the file name
1073 len
= crc_len
+ sizeof (struct tag
) - (F_LEN
);
1076 bcopy(beg
, buf
, len
);
1083 * We are releasing the
1084 * old buffer so copy fid to buf
1088 bcopy(*fid
, buf
, count
);
1089 *fid
= (struct file_id
*)buf
;
1092 bcopy(beg
, buf
, sz
);
1093 *fid
= (struct file_id
*)buf
;
1096 fbrelse(*fbp
, S_OTHER
);
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) {
1107 end
= (*fbp
)->fb_addr
+ (*fbp
)->fb_count
;
1108 beg
= (*fbp
)->fb_addr
;
1110 bcopy(beg
, buf
, 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 */
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 */
1129 idlen
= FID_LEN(*fid
);
1132 iulen
= SWAP_16((*fid
)->fid_iulen
);
1133 if (crc_len
< (F_LEN
- sizeof (struct tag
) + idlen
)) {
1135 len
= (F_LEN
- sizeof (struct tag
) + idlen
) - crc_len
;
1139 bcopy(beg
, buf
, len
);
1143 count
= crc_len
+ sizeof (struct tag
);
1144 bcopy(*fid
, buf
, count
);
1145 *fid
= (struct file_id
*)buf
;
1148 bcopy(beg
, buf
, sz
);
1149 *fid
= (struct file_id
*)buf
;
1152 fbrelse(*fbp
, S_OTHER
);
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) {
1163 end
= (*fbp
)->fb_addr
+ (*fbp
)->fb_count
;
1164 beg
= (*fbp
)->fb_addr
;
1166 bcopy(beg
, buf
, count
);
1171 *name
= ((uint8_t *)*fid
) + F_LEN
+ iulen
;
1178 ud_verify_tag_and_desc(struct tag
*tag
, uint16_t id
, uint32_t blockno
,
1179 int32_t verify_desc
, int32_t desc_len
)
1182 uint8_t *addr
, cksum
= 0;
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
)) {
1192 addr
= (uint8_t *)tag
;
1193 eah
= (struct ext_attr_hdr
*)tag
;
1194 for (i
= 0; i
< 4; i
++) {
1197 for (i
= 5; i
<= 15; i
++) {
1200 if (cksum
!= tag
->tag_cksum
) {
1202 "Checksum Does not Verify TAG %x CALC %x blockno 0x%x\n",
1203 tag
->tag_cksum
, cksum
, blockno
);
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
) {
1218 "Invalid FID_LEN(0x%x). Greater than expected(0x%x) blockno 0x%x\n",
1219 fidlen
, desc_len
, blockno
);
1223 if (verify_desc
== 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
))) {
1240 "tag_crc_len(0x%x) is greater than expected len(0x%x) blockno 0x%x\n",
1241 SWAP_16(tag
->tag_crc_len
),
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
);
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
) {
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
),
1269 case UD_EXT_ATTR_HDR
:
1270 eah
= (struct ext_attr_hdr
*)tag
;
1271 if (SWAP_32(eah
->eah_aal
) > desc_len
) {
1273 "eah_all(0x%x) exceeds desc. len(0x%x) blockno 0x%x\n",
1274 SWAP_32(eah
->eah_aal
), desc_len
, blockno
);
1277 ea_off
= GET_32(&eah
->eah_ial
);
1278 if (ea_off
>= desc_len
) {
1280 "ea_off(0x%x) is not less than ea_len(0x%x) blockno 0x%x\n",
1281 ea_off
, desc_len
, blockno
);
1288 if (SWAP_32(blockno
) != tag
->tag_loc
) {
1290 "Tag Location mismatch blockno %x tag_blockno %x\n",
1291 blockno
, SWAP_32(tag
->tag_loc
));
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
1335 ud_crc(uint8_t *addr
, int32_t len
)
1340 crc
= ud_crc_table
[(crc
>> 8 ^ *addr
++) & 0xff] ^ (crc
<<8);
1346 typedef unsigned short unicode_t
;
1348 #define POUND 0x0023
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.
1367 ud_check_te_unrec(struct udf_vfs
*udf_vfsp
, caddr_t addr
, uint32_t blkno
)
1370 struct term_entry
*te
;
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
++) {
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
1421 ud_utf82utf16(uint8_t *s_8
, uint16_t *c_16
, int32_t count
)
1423 int32_t extra_bytes
;
1429 * First convert to a 32-bit
1433 extra_bytes
= bytes_from_utf8
[*s_8
];
1434 if (extra_bytes
> count
) {
1439 * verify if the string is a valid
1442 if (extra_bytes
== 0) {
1444 * Apply one byte rule
1450 } else if (extra_bytes
== 1) {
1451 if (((*s_8
& 0xE0) != 0xC0) ||
1452 ((*(s_8
+ 1) & 0xC0) != 0x80)) {
1456 } else if (extra_bytes
== 2) {
1457 if (((*s_8
& 0xF0) != 0xE0) ||
1458 ((*(s_8
+ 1) & 0xC0) != 0x80) ||
1459 ((*(s_8
+ 2) & 0xC0) != 0x80)) {
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)) {
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)) {
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)) {
1496 * Convert to 32-bit character
1498 switch (extra_bytes
) {
1501 c_32
+= (*s_8
++ & 0x3F);
1505 c_32
+= (*s_8
++ & 0x3F);
1509 c_32
+= (*s_8
++ & 0x3F);
1513 c_32
+= (*s_8
++ & 0x3F);
1517 c_32
+= (*s_8
++ & 0x3F);
1524 * now convert the 32-bit
1525 * character into a 16-bit character
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.
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
;
1545 out_str_len
= *out_len
;
1546 if (in_len
> (out_str_len
- 2)) {
1547 return (ENAMETOOLONG
);
1551 w2_str
= (uint16_t *)kmem_zalloc(512, KM_SLEEP
);
1553 error
= in_index
= out_index
= c_tx_sz
= 0;
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) {
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)) {
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
;
1578 in_index
= out_index
;
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
;
1590 if (w2_str
!= NULL
) {
1591 kmem_free((caddr_t
)w2_str
, 512);
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};
1603 ud_utf162utf8(uint16_t c_16
, uint8_t *s_8
)
1607 uint32_t byte_mask
= 0xBF;
1608 uint32_t byte_mark
= 0x80;
1613 * Convert the 16-bit character to
1614 * a 32-bit character
1619 * By here the 16-bit character is converted
1620 * to a 32-bit wide character
1624 } else if (c_32
< 0x800) {
1626 } else if (c_32
< 0x10000) {
1628 } else if (c_32
< 0x200000) {
1630 } else if (c_32
< 0x4000000) {
1632 } else if (c_32
< (uint32_t)0x80000000) {
1640 *(--s_8
) = (c_32
| byte_mark
) & byte_mask
;
1644 *(--s_8
) = (c_32
| byte_mark
) & byte_mask
;
1648 *(--s_8
) = (c_32
| byte_mark
) & byte_mask
;
1652 *(--s_8
) = (c_32
| byte_mark
) & byte_mask
;
1656 *(--s_8
) = (c_32
| byte_mark
) & byte_mask
;
1660 *(--s_8
) = c_32
| first_byte_mark
[nc
];
1666 * Convert to a form that can be transferred to the user
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
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;
1688 error
= len_till_now
= make_crc
= 0;
1692 comp_id
= in_str
[0];
1695 * File names "." and ".." are invalid under unix.
1696 * Transform them into something
1699 if ((in_str
[1] == DOT
) &&
1700 ((in_len
== 2) || ((in_len
== 3) &&
1701 (in_str
[2] == DOT
)))) {
1702 out_str
[k
++] = UNDERBAR
;
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
;
1712 goto make_append_crc
;
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
++];
1728 w2_char
= in_str
[index
++];
1731 if (make_crc
!= 0) {
1735 if (w2_char
== DOT
) {
1736 dot_loc
= len_till_now
;
1740 * Get rid of invalid characters
1742 if ((w2_char
== SLASH
) ||
1745 if (((comp_id
== 8) &&
1746 (lic
!= (index
- 1))) ||
1747 (comp_id
== 0x10) &&
1748 (lic
!= (index
- 2))) {
1758 * Conver a 16bit character to a
1761 if ((c_tx_sz
= ud_utf162utf8(w2_char
, utf8
)) == 0) {
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
;
1787 * If we need to append CRC do it now
1792 if (len_till_now
> MAX_ALLOWABLE_STRING
) {
1793 len_till_now
= crc_start_loc
;
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
];
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];
1817 *out_len
= len_till_now
;
1824 ud_bread(dev_t dev
, daddr_t blkno
, long bsize
)
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
1839 if (bp
->b_flags
& B_DELWRI
) {
1842 bp
->b_flags
|= (B_AGE
| B_STALE
);
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
,
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
));