xref: /illumos-gate/usr/src/uts/common/fs/udfs/udf_subr.c (revision 06042525)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
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>
64 
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>
76 
77 
78 #include <fs/fs_subr.h>
79 
80 
81 #include <sys/fs/udf_volume.h>
82 #include <sys/fs/udf_inode.h>
83 
84 int32_t ud_trace;
85 
86 /*
87  * HASH chains and mutex
88  */
89 extern union ihead ud_ihead[UD_HASH_SZ];
90 extern kmutex_t ud_icache_lock;
91 
92 
93 extern kmutex_t ud_sync_busy;
94 /*
95  * udf_vfs list manipulation routines
96  */
97 extern kmutex_t udf_vfs_mutex;
98 extern struct udf_vfs *udf_vfs_instances;
99 
100 /*
101  * Used to verify that a given entry on the udf_instances list (see below)
102  * still refers to a mounted file system.
103  *
104  * XXX: This is a crock that substitutes for proper locking to coordinate
105  *      updates to and uses of the entries in udf_instances.
106  */
107 struct check_node {
108 	struct vfs	*vfsp;
109 	struct udf_vfs	*udf_vfs;
110 	dev_t		vfs_dev;
111 };
112 
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);
118 
119 /*
120  * Link udf_vfsp in at the head of the list of udf_vfs_instances.
121  */
122 void
ud_vfs_add(struct udf_vfs * udf_vfsp)123 ud_vfs_add(struct udf_vfs *udf_vfsp)
124 {
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);
129 }
130 
131 /*
132  * Remove udf_vfsp from the list of udf_vfs_instances.
133  *
134  * Does no error checking; udf_vfsp is assumed to actually be on the list.
135  */
136 void
ud_vfs_remove(struct udf_vfs * udf_vfsp)137 ud_vfs_remove(struct udf_vfs *udf_vfsp)
138 {
139 	struct udf_vfs **delpt = &udf_vfs_instances;
140 
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;
147 		}
148 	}
149 	mutex_exit(&udf_vfs_mutex);
150 }
151 
152 /*
153  * Search for the prn in the array
154  * of partitions and translate
155  * to the disk block number
156  */
157 daddr_t
ud_xlate_to_daddr(struct udf_vfs * udf_vfsp,uint16_t prn,uint32_t blkno,int32_t nblks,uint32_t * count)158 ud_xlate_to_daddr(struct udf_vfs *udf_vfsp,
159     uint16_t prn, uint32_t blkno, int32_t nblks, uint32_t *count)
160 {
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;
167 
168 	ud_printf("ud_xlate_to_daddr\n");
169 
170 	/* Is prn valid */
171 	if (prn < udf_vfsp->udf_nmaps) {
172 		map = &(udf_vfsp->udf_maps[prn]);
173 
174 		if (map->udm_flags == UDM_MAP_VPM) {
175 			/*
176 			 * Map is Virtual Parition Map
177 			 * first check for the appropriate
178 			 * table and then return the converted
179 			 * block number
180 			 */
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];
189 				}
190 			}
191 		} else if (map->udm_flags == UDM_MAP_SPM) {
192 			struct stbl *stbl;
193 			struct stbl_entry *te;
194 			int32_t entry_count;
195 
196 			/*
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
202 			 */
203 			begin_req = blkno;
204 			end_req = begin_req + nblks;
205 
206 			stbl = (struct stbl *)map->udm_spaddr[0];
207 			te = (struct stbl_entry *)&stbl->stbl_entry;
208 			entry_count = SWAP_16(stbl->stbl_len);
209 
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;
213 
214 				/*
215 				 * Either unmapped or reserved
216 				 * or defective. need not consider
217 				 */
218 				if (begin_bad >= (uint32_t)0xFFFFFFF0) {
219 					continue;
220 				}
221 				if ((end_req < begin_bad) ||
222 				    (begin_req >= end_bad)) {
223 					continue;
224 				}
225 
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;
236 					}
237 					goto end;
238 				}
239 			}
240 
241 			lblkno = blkno;
242 			*count = end_req - begin_req;
243 		} else {
244 			/*
245 			 * regular partition
246 			 */
247 			lblkno = blkno;
248 			*count = nblks;
249 		}
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) {
253 				/*
254 				 * Check if the block is inside
255 				 * the partition or not
256 				 */
257 				if (lblkno >= ud_parts->udp_length) {
258 					retblkno = 0;
259 				} else {
260 					retblkno = ud_parts->udp_start + lblkno;
261 				}
262 				goto end;
263 			}
264 			ud_parts ++;
265 		}
266 	}
267 
268 end:
269 	return (retblkno);
270 }
271 
272 #ifdef	UNDEF
273 uint32_t
ud_xlate_to_addr(struct udf_vfs * udf_vfsp,uint16_t prn,daddr_t blkno,int32_t lad)274 ud_xlate_to_addr(struct udf_vfs *udf_vfsp,
275     uint16_t prn, daddr_t blkno, int32_t lad)
276 {
277 	int32_t i;
278 	struct ud_part *ud_parts;
279 
280 	ud_printf("ud_xlate_to_addr\n");
281 
282 	if (lad == 0) {
283 		return (blkno);
284 	}
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);
289 		}
290 	}
291 	return (0);
292 }
293 #endif
294 
295 /*
296  * Directories do not have holes
297  */
298 int32_t
ud_ip_off2bno(struct ud_inode * ip,uint32_t offset,uint32_t * bno)299 ud_ip_off2bno(struct ud_inode *ip, uint32_t offset, uint32_t *bno)
300 {
301 	int32_t i, error;
302 	struct icb_ext *iext;
303 
304 	ASSERT(ip->i_type == VDIR);
305 
306 	if (ip->i_desc_type == ICB_FLAG_ONE_AD) {
307 		*bno = ip->i_icb_block;
308 		return (0);
309 	}
310 
311 	if ((error = ud_read_icb_till_off(ip, (u_offset_t)offset)) != 0) {
312 		return (error);
313 	}
314 
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;
323 		}
324 	}
325 	return (0);
326 }
327 
328 static uint32_t cum_sec[] = {
329 	0x0, 0x28de80, 0x4dc880, 0x76a700, 0x9e3400, 0xc71280,
330 	0xee9f80, 0x1177e00, 0x1405c80, 0x167e980, 0x190c800, 0x1b85500
331 };
332 static uint32_t cum_sec_leap[] = {
333 	0x0, 0x28de80, 0x4f1a00, 0x77f880, 0x9f8580, 0xc86400,
334 	0xeff100, 0x118cf80, 0x141ae00, 0x1693b00, 0x1921980, 0x1b9a680
335 };
336 
337 #define	DAYS_PER_YEAR	365
338 
339 #define	SEC_PER_DAY	0x15180
340 #define	SEC_PER_YEAR	0x1e13380
341 
342 
343 /* This holds good till yr 2100 */
344 void
ud_dtime2utime(struct timespec32 * utime,struct tstamp const * dtime)345 ud_dtime2utime(struct timespec32 *utime,
346     struct tstamp const *dtime)
347 {
348 	int16_t year, tzone;
349 	int32_t	sec;
350 	uint32_t *cp;
351 
352 	ud_printf("ud_dtime2utime\n");
353 
354 	year = SWAP_16(dtime->ts_year);
355 	cp = (year % 4) ? cum_sec : cum_sec_leap;
356 
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;
362 
363 	tzone = SWAP_16(dtime->ts_tzone);
364 	if ((tzone & TMODE) == 0x1000) {
365 		/* Local time */
366 		if ((tzone & TINVALID) != TINVALID) {
367 			if (tzone & TSIGN) {
368 				/*
369 				 * Sign extend the tzone
370 				 */
371 				sec = tzone | 0xFFFFF000;
372 			} else {
373 				sec = tzone & TOFFSET;
374 			}
375 			sec *= 60;
376 			utime->tv_sec -= sec;
377 		}
378 	}
379 
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;
393 		}
394 	}
395 }
396 
397 void
ud_utime2dtime(struct timespec32 const * utime,struct tstamp * dtime)398 ud_utime2dtime(struct timespec32 const *utime,
399     struct tstamp *dtime)
400 {
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;
406 
407 	ud_printf("ud_utime2dtime\n");
408 
409 	if (sec < 0) {
410 		before = 1;
411 		sec = sec * -1;
412 		if (usec) {
413 			sec = sec + 1;
414 			usec = 1000 * 1000 - usec;
415 		}
416 	}
417 
418 	dtime->ts_csec = usec / 10000;
419 	usec %= 10000;
420 	dtime->ts_husec = usec / 100;
421 	dtime->ts_usec = usec % 100;
422 
423 	nyrs = sec / SEC_PER_YEAR;
424 	if (before == 0) {
425 		lyrs = (nyrs + 1) / 4;
426 	} else {
427 		lyrs = (nyrs + 2) / 4;
428 	}
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;
435 		}
436 	}
437 	sec -= nyrs * SEC_PER_YEAR + lyrs * SEC_PER_DAY;
438 
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;
447 			}
448 		}
449 	} else {
450 		nyrs += 1970;
451 	}
452 	cp = (nyrs % 4) ? cum_sec : cum_sec_leap;
453 	dummy = sec / (SEC_PER_DAY * 29);
454 	if (dummy > 11) {
455 		dummy = 11;
456 	}
457 	if (sec < cp[dummy]) {
458 		dummy--;
459 	}
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;
472 
473 	/* GMT offset is 0 */
474 	dtime->ts_tzone = SWAP_16(0x1000);
475 }
476 
477 
478 int32_t
ud_syncip(struct ud_inode * ip,int32_t flags,int32_t waitfor)479 ud_syncip(struct ud_inode *ip, int32_t flags, int32_t waitfor)
480 {
481 	int32_t error;
482 	struct vnode *vp = ITOV(ip);
483 
484 	ud_printf("ud_syncip\n");
485 
486 	if (ip->i_udf == NULL) {
487 		return (0);
488 	}
489 
490 	if (!vn_has_cached_data(vp) || (vp->v_type == VCHR)) {
491 		error = 0;
492 	} else {
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);
497 	}
498 
499 	if (ip->i_flag & (IUPD |IACC | ICHG | IMOD)) {
500 		ud_iupdat(ip, waitfor);
501 	}
502 
503 	return (error);
504 }
505 
506 
507 /* ARGSUSED */
508 int32_t
ud_fbwrite(struct fbuf * fbp,struct ud_inode * ip)509 ud_fbwrite(struct fbuf *fbp, struct ud_inode *ip)
510 {
511 	ud_printf("ud_fbwrite\n");
512 
513 	ASSERT(fbp != NULL);
514 
515 	return (fbwrite(fbp));
516 }
517 
518 
519 void
ud_sbwrite(struct udf_vfs * udf_vfsp)520 ud_sbwrite(struct udf_vfs *udf_vfsp)
521 {
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;
527 
528 	ud_printf("ud_sbwrite\n");
529 	ASSERT(udf_vfsp);
530 	ASSERT(MUTEX_HELD(&udf_vfsp->udf_lock));
531 
532 	/*
533 	 * updatable information in the superblock
534 	 * integrity type, udf_maxuniq, udf_nfiles, udf_ndirs
535 	 * udp_nfree in lvid
536 	 */
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);
542 	}
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++;
550 	}
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);
554 
555 	ud_update_regid(&iu->lvidiu_regid);
556 
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));
562 
563 	/*
564 	 * Don't release the buffer after writing to the disk
565 	 */
566 	bwrite2(udf_vfsp->udf_iseq);
567 }
568 
569 
570 int32_t
ud_sync_indir(struct ud_inode * ip)571 ud_sync_indir(struct ud_inode *ip)
572 {
573 	int32_t elen;
574 
575 	ud_printf("ud_sync_indir\n");
576 
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);
585 	}
586 
587 	if (ip->i_astrat == STRAT_TYPE4) {
588 		int32_t ndentry;
589 
590 		ndentry = ip->i_max_emb / elen;
591 		if (ip->i_ext_used < ndentry) {
592 			return (0);
593 		}
594 		ASSERT(ip->i_con);
595 	} else {
596 		cmn_err(CE_WARN, "unsupported strategy type\n");
597 		return (EINVAL);
598 	}
599 
600 	return (0);
601 }
602 
603 void
ud_update(int32_t flag)604 ud_update(int32_t flag)
605 {
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;
612 
613 	ud_printf("ud_update\n");
614 
615 	mutex_enter(&ud_sync_busy);
616 	/*
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.
621 	 */
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;
628 		}
629 		udfsp->udf_wnext = update_list;
630 		update_list = udfsp;
631 		check_cnt++;
632 	}
633 	mutex_exit(&udf_vfs_mutex);
634 
635 	if (update_list == NULL) {
636 		mutex_exit(&ud_sync_busy);
637 		return;
638 	}
639 
640 	check_size = sizeof (struct check_node) * check_cnt;
641 	check_list = ptr = kmem_alloc(check_size, KM_NOSLEEP);
642 
643 	/*
644 	 * Write back modified superblocks.
645 	 * Consistency check that the superblock of
646 	 * each file system is still in the buffer cache.
647 	 *
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.
654 	 */
655 	check_cnt = 0;
656 	for (udfsp = update_list; udfsp != NULL; udfsp = udfsnext) {
657 		/*
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.)
663 		 */
664 		udfsnext = udfsp->udf_wnext;
665 		vfsp = udfsp->udf_vfs;
666 
667 		if (!vfsp->vfs_data) {
668 			vfs_unlock(vfsp);
669 			continue;
670 		}
671 		mutex_enter(&udfsp->udf_lock);
672 
673 		/*
674 		 * Build up the STABLE check list, so we can unlock the vfs
675 		 * until we do the actual checking.
676 		 */
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++;
684 			}
685 		}
686 
687 		/*
688 		 * superblock is not modified
689 		 */
690 		if (udfsp->udf_mod == 0) {
691 			mutex_exit(&udfsp->udf_lock);
692 			vfs_unlock(vfsp);
693 			continue;
694 		}
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;
700 		}
701 		udfsp->udf_mod = 0;
702 		mutex_exit(&udfsp->udf_lock);
703 
704 		ud_update_superblock(vfsp);
705 		vfs_unlock(vfsp);
706 	}
707 
708 	ud_flushi(flag);
709 	/*
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.
713 	 */
714 	bflush((dev_t)NODEV);
715 
716 	if (check_list == NULL) {
717 		mutex_exit(&ud_sync_busy);
718 		return;
719 	}
720 
721 	/*
722 	 * For each udf filesystem in the STABLE check_list, update
723 	 * the clean flag if warranted.
724 	 */
725 	start_time = gethrestime_sec();
726 	for (ptr = check_list; check_cnt > 0; check_cnt--, ptr++) {
727 		/*
728 		 * ud_still_mounted() returns with vfsp and the vfs_reflock
729 		 * held if ptr refers to a vfs that is still mounted.
730 		 */
731 		if ((vfsp = ud_still_mounted(ptr)) == NULL) {
732 			continue;
733 		}
734 		ud_checkclean(vfsp, ptr->udf_vfs, ptr->vfs_dev, start_time);
735 		vfs_unlock(vfsp);
736 	}
737 	mutex_exit(&ud_sync_busy);
738 	kmem_free(check_list, check_size);
739 }
740 
741 
742 /*
743  * Returns vfsp and hold the lock if the vfs is still being mounted.
744  * Otherwise, returns 0.
745  *
746  * For our purposes, "still mounted" means that the file system still appears
747  * on the list of UFS file system instances.
748  */
749 vfs_t *
ud_still_mounted(struct check_node * checkp)750 ud_still_mounted(struct check_node *checkp)
751 {
752 	struct vfs *vfsp;
753 	struct udf_vfs *udf_vfsp;
754 
755 	ud_printf("ud_still_mounted\n");
756 
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;
762 		}
763 		/*
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?)
770 		 */
771 		vfsp = udf_vfsp->udf_vfs;
772 		if (vfsp != checkp->vfsp) {
773 			continue;
774 		}
775 		if (vfsp->vfs_dev != checkp->vfs_dev) {
776 			continue;
777 		}
778 		if (vfs_lock(vfsp) != 0) {
779 			continue;
780 		}
781 		mutex_exit(&udf_vfs_mutex);
782 		return (vfsp);
783 	}
784 	mutex_exit(&udf_vfs_mutex);
785 	return (NULL);
786 }
787 
788 /* ARGSUSED */
789 void
ud_checkclean(struct vfs * vfsp,struct udf_vfs * udf_vfsp,dev_t dev,time_t timev)790 ud_checkclean(struct vfs *vfsp,
791     struct udf_vfs *udf_vfsp, dev_t dev, time_t timev)
792 {
793 	ud_printf("ud_checkclean\n");
794 	udf_vfsp = (struct udf_vfs *)vfsp->vfs_data;
795 	/*
796 	 * ignore if buffers or inodes are busy
797 	 */
798 	if ((bcheck(dev, udf_vfsp->udf_iseq)) ||
799 	    (ud_icheck(udf_vfsp))) {
800 		return;
801 	}
802 	mutex_enter(&udf_vfsp->udf_lock);
803 	ud_sbwrite(udf_vfsp);
804 	mutex_exit(&udf_vfsp->udf_lock);
805 }
806 
807 int32_t
ud_icheck(struct udf_vfs * udf_vfsp)808 ud_icheck(struct udf_vfs *udf_vfsp)
809 {
810 	int32_t index, error = 0;
811 	union ihead *ih;
812 	struct ud_inode *ip;
813 
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;
825 			}
826 		}
827 	}
828 end:
829 	mutex_exit(&ud_icache_lock);
830 	return (error);
831 }
832 
833 void
ud_flushi(int32_t flag)834 ud_flushi(int32_t flag)
835 {
836 	struct ud_inode *ip, *lip;
837 	struct vnode *vp;
838 	int cheap = flag & SYNC_ATTR;
839 	int32_t index;
840 	union  ihead *ih;
841 
842 	/*
843 	 * Write back each (modified) inode,
844 	 * but don't sync back pages if vnode is
845 	 * part of the virtual swap device.
846 	 */
847 	mutex_enter(&ud_icache_lock);
848 	for (index = 0; index < UD_HASH_SZ; index++) {
849 		ih = &ud_ihead[index];
850 		lip = NULL;
851 
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;
856 
857 			vp = ITOV(ip);
858 			/*
859 			 * Skip locked & inactive inodes.
860 			 * Skip vnodes w/ no cached data and no inode changes.
861 			 * Skip read-only vnodes
862 			 */
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;
868 			}
869 
870 			if (!rw_tryenter(&ip->i_contents, RW_WRITER)) {
871 				continue;
872 			}
873 
874 			VN_HOLD(vp);
875 
876 			if (lip != NULL) {
877 				ITIMES(lip);
878 				VN_RELE(ITOV(lip));
879 			}
880 			lip = ip;
881 
882 			/*
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.
887 			 */
888 			if (cheap || IS_SWAPVP(vp)) {
889 				ud_iupdat(ip, 0);
890 			} else {
891 				(void) ud_syncip(ip, B_ASYNC, I_SYNC);
892 			}
893 			rw_exit(&ip->i_contents);
894 		}
895 		if (lip != NULL) {
896 			ITIMES(lip);
897 			VN_RELE(ITOV(lip));
898 		}
899 	}
900 	mutex_exit(&ud_icache_lock);
901 }
902 
903 
904 void
ud_update_regid(struct regid * reg)905 ud_update_regid(struct regid *reg)
906 {
907 	ud_printf("ud_update_regid\n");
908 
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;
913 }
914 
915 /* ARGSUSED4 */
916 void
ud_make_tag(struct udf_vfs * udf_vfsp,struct tag * tag,uint16_t tag_id,uint32_t blkno,uint16_t crc_len)917 ud_make_tag(struct udf_vfs *udf_vfsp,
918     struct tag *tag, uint16_t tag_id, uint32_t blkno, uint16_t crc_len)
919 {
920 	int32_t i;
921 	uint16_t crc;
922 	uint8_t *addr, cksum = 0;
923 
924 	ud_printf("ud_make_tag\n");
925 
926 	ASSERT(crc_len > 0x10);
927 	addr = (uint8_t *)tag;
928 	crc_len -= sizeof (struct tag);
929 	crc = ud_crc(addr + 0x10, crc_len);
930 
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);
937 
938 	tag->tag_crc_len = SWAP_16(crc_len);
939 	tag->tag_loc = SWAP_32(blkno);
940 
941 	addr = (uint8_t *)tag;
942 	for (i = 0; i <= 15; i++) {
943 		cksum += addr[i];
944 	}
945 	tag->tag_cksum = cksum;
946 }
947 
948 int32_t
ud_make_dev_spec_ear(struct dev_spec_ear * ds,major_t major,minor_t minor)949 ud_make_dev_spec_ear(struct dev_spec_ear *ds,
950     major_t major, minor_t minor)
951 {
952 	int32_t attr_len;
953 
954 	ud_printf("ud_make_dev_spec_ear\n");
955 
956 	bzero(ds, sizeof (struct dev_spec_ear));
957 
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);
965 
966 	return (attr_len);
967 }
968 
969 
970 int32_t
ud_get_next_fid(struct ud_inode * ip,struct fbuf ** fbp,uint32_t offset,struct file_id ** fid,uint8_t ** name,uint8_t * buf)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)
973 {
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;
983 
984 	ud_printf("ud_get_next_fid\n");
985 
986 	obuf = buf;
987 	udf_vfsp = ip->i_udf;
988 	lbsize = udf_vfsp->udf_lbsize;
989 	lbmask = udf_vfsp->udf_lbmask;
990 
991 	if ((error = ud_ip_off2bno(ip, offset, &tbno)) != 0) {
992 		return (error);
993 	}
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);
999 		}
1000 	}
1001 
1002 	end = (*fbp)->fb_addr + (*fbp)->fb_count;
1003 	beg = (*fbp)->fb_addr + (offset & lbmask);
1004 
1005 
1006 	if ((offset % lbsize) ||
1007 	    (offset == 0)) {
1008 		sz = end - beg;
1009 	} else {
1010 		sz = 0;
1011 	}
1012 
1013 
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;
1022 
1023 		/* Skip to next block */
1024 		if (offset & lbmask) {
1025 			offset = (offset & ~lbmask) + lbsize;
1026 		}
1027 		if ((error = fbread(vp, (offset_t)offset,
1028 		    lbsize, S_READ, fbp)) != 0) {
1029 			return (error);
1030 		}
1031 		end = (*fbp)->fb_addr + (*fbp)->fb_count;
1032 		beg = (*fbp)->fb_addr;
1033 
1034 		bcopy(beg, buf + sz, F_LEN - sz);
1035 		beg = beg + F_LEN - sz;
1036 		*fid = (struct file_id *)buf;
1037 
1038 		buf += F_LEN;
1039 	}
1040 
1041 
1042 	/*
1043 	 * Check if this a valid file_identifier
1044 	 */
1045 	if (ud_verify_tag_and_desc(&(*fid)->fid_tag, UD_FILE_ID_DESC,
1046 	    tbno, 0, lbsize) != 0) {
1047 		/*
1048 		 * Either end of directory or corrupted
1049 		 */
1050 		return (EINVAL);
1051 	}
1052 
1053 	crc_len = SWAP_16((*fid)->fid_tag.tag_crc_len);
1054 	if (crc_len > udf_vfsp->udf_lbsize) {
1055 		/*
1056 		 * Entries cannot be larger than
1057 		 * blocksize
1058 		 */
1059 		return (EINVAL);
1060 	}
1061 
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;
1066 	}
1067 
1068 	/*
1069 	 * By now beg points to the start fo the file name
1070 	 */
1071 
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;
1078 		}
1079 		beg += len;
1080 	} else {
1081 		copied = 1;
1082 		/*
1083 		 * We are releasing the
1084 		 * old buffer so copy fid to buf
1085 		 */
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;
1095 		}
1096 		fbrelse(*fbp, S_OTHER);
1097 		*fbp = NULL;
1098 
1099 		/* Skip to next block */
1100 		if (offset & lbmask) {
1101 			offset = (offset & ~lbmask) + lbsize;
1102 		}
1103 		if ((error = fbread(vp, (offset_t)offset,
1104 		    lbsize, S_READ, fbp)) != 0) {
1105 			return (error);
1106 		}
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;
1112 	}
1113 
1114 	/*
1115 	 * First we verify that the tag id and the FID_LEN are valid.
1116 	 * Next we verify the crc of the descriptor.
1117 	 */
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);
1122 	}
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);
1127 	}
1128 
1129 	idlen = FID_LEN(*fid);
1130 
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);
1140 			}
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;
1151 			}
1152 			fbrelse(*fbp, S_OTHER);
1153 			*fbp = NULL;
1154 
1155 			/* Skip to next block */
1156 			if (offset & lbmask) {
1157 				offset = (offset & ~lbmask) + lbsize;
1158 			}
1159 			if ((error = fbread(vp, (offset_t)offset,
1160 			    lbsize, S_READ, fbp)) != 0) {
1161 				return (error);
1162 			}
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;
1168 		}
1169 	}
1170 
1171 	*name = ((uint8_t *)*fid) + F_LEN + iulen;
1172 
1173 	return (0);
1174 }
1175 
1176 
1177 int32_t
ud_verify_tag_and_desc(struct tag * tag,uint16_t id,uint32_t blockno,int32_t verify_desc,int32_t desc_len)1178 ud_verify_tag_and_desc(struct tag *tag, uint16_t id, uint32_t blockno,
1179     int32_t verify_desc, int32_t desc_len)
1180 {
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;
1188 
1189 	if (tag->tag_id != SWAP_16(id)) {
1190 		return (1);
1191 	}
1192 	addr = (uint8_t *)tag;
1193 	eah = (struct ext_attr_hdr *)tag;
1194 	for (i = 0; i < 4; i++) {
1195 		cksum += addr[i];
1196 	}
1197 	for (i = 5; i <= 15; i++) {
1198 		cksum += addr[i];
1199 	}
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);
1205 	}
1206 	/*
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.
1212 	 */
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);
1221 		}
1222 	}
1223 	if (verify_desc == 0)
1224 		return (0);
1225 	/*
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.)
1237 	 */
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);
1244 	}
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);
1253 		}
1254 	}
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);
1267 			}
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);
1276 			}
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);
1283 			}
1284 			break;
1285 		default:
1286 			break;
1287 	}
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);
1293 	}
1294 	return (0);
1295 }
1296 
1297 /* **************** udf specific subroutines *********************** */
1298 
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
1332 };
1333 
1334 uint16_t
ud_crc(uint8_t * addr,int32_t len)1335 ud_crc(uint8_t *addr, int32_t len)
1336 {
1337 	uint16_t crc = 0;
1338 
1339 	while (len-- > 0) {
1340 		crc = ud_crc_table[(crc >> 8 ^ *addr++) & 0xff] ^ (crc<<8);
1341 	}
1342 
1343 	return (crc);
1344 }
1345 
1346 typedef unsigned short unicode_t;
1347 
1348 #define	POUND		0x0023
1349 #define	DOT		0x002E
1350 #define	SLASH		0x002F
1351 #define	UNDERBAR	0x005F
1352 
1353 
1354 static uint16_t htoc[16] = {'0', '1', '2', '3',
1355 	'4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
1356 
1357 
1358 /*
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.
1365  */
1366 uint32_t
ud_check_te_unrec(struct udf_vfs * udf_vfsp,caddr_t addr,uint32_t blkno)1367 ud_check_te_unrec(struct udf_vfs *udf_vfsp, caddr_t addr, uint32_t blkno)
1368 {
1369 	int32_t i, lbsize;
1370 	struct term_entry *te;
1371 
1372 	ASSERT(udf_vfsp);
1373 	ASSERT(addr);
1374 
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);
1382 			}
1383 		}
1384 	}
1385 	return (0);
1386 }
1387 
1388 
1389 /*
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)
1395  */
1396 
1397 /*
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
1401  */
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
1419 };
1420 int32_t
ud_utf82utf16(uint8_t * s_8,uint16_t * c_16,int32_t count)1421 ud_utf82utf16(uint8_t *s_8, uint16_t *c_16, int32_t count)
1422 {
1423 	int32_t extra_bytes;
1424 	uint32_t c_32;
1425 	ASSERT(s_8);
1426 	ASSERT(c_16);
1427 
1428 	/*
1429 	 * First convert to a 32-bit
1430 	 * character
1431 	 */
1432 	c_32 = 0;
1433 	extra_bytes = bytes_from_utf8[*s_8];
1434 	if (extra_bytes > count) {
1435 		return (0);
1436 	}
1437 
1438 	/*
1439 	 * verify if the string is a valid
1440 	 * utf8 string
1441 	 */
1442 	if (extra_bytes == 0) {
1443 		/*
1444 		 * Apply one byte rule
1445 		 */
1446 		if (*s_8 & 0x80) {
1447 			return (0);
1448 		}
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);
1454 		}
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);
1461 		}
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);
1469 		}
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);
1478 		}
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);
1488 		}
1489 		c_32 = *s_8 & 0x01;
1490 	} else {
1491 		return (0);
1492 	}
1493 	s_8++;
1494 
1495 	/*
1496 	 * Convert to 32-bit character
1497 	 */
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;
1521 	}
1522 
1523 	/*
1524 	 * now convert the 32-bit
1525 	 * character into a 16-bit character
1526 	 */
1527 	*c_16 = c_32;
1528 	return (extra_bytes + 1);
1529 }
1530 
1531 /*
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.
1536  */
1537 int32_t
ud_compress(int32_t in_len,int32_t * out_len,uint8_t * in_str,uint8_t * out_str)1538 ud_compress(int32_t in_len, int32_t *out_len,
1539     uint8_t *in_str, uint8_t *out_str)
1540 {
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;
1544 
1545 	out_str_len = *out_len;
1546 	if (in_len > (out_str_len - 2)) {
1547 		return (ENAMETOOLONG);
1548 	}
1549 
1550 	*out_len = 0;
1551 	w2_str = (uint16_t *)kmem_zalloc(512, KM_SLEEP);
1552 
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;
1560 		}
1561 		/*
1562 		 * utf-8 characters can be
1563 		 * of 1 - 6 bytes in length
1564 		 */
1565 		ASSERT(c_tx_sz > 0);
1566 		ASSERT(c_tx_sz < 7);
1567 		if ((comp_id == 8) && (w2_char & 0xff00)) {
1568 			comp_id = 0x10;
1569 		}
1570 		w2_str[out_index++] = w2_char;
1571 	}
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;
1576 	}
1577 
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;
1584 		}
1585 		out_str[out_index++] = w2_str[index] & 0xFF;
1586 	}
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);
1592 	}
1593 	return (error);
1594 }
1595 
1596 /*
1597  * Take a utf16 character and convert
1598  * it into a utf8 character.
1599  * A 0 will be returned if the conversion fails
1600  */
1601 uint8_t first_byte_mark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
1602 int32_t
ud_utf162utf8(uint16_t c_16,uint8_t * s_8)1603 ud_utf162utf8(uint16_t c_16, uint8_t *s_8)
1604 {
1605 	int32_t nc;
1606 	uint32_t c_32;
1607 	uint32_t byte_mask = 0xBF;
1608 	uint32_t byte_mark = 0x80;
1609 
1610 	ASSERT(s_8);
1611 
1612 	/*
1613 	 * Convert the 16-bit character to
1614 	 * a 32-bit character
1615 	 */
1616 	c_32 = c_16;
1617 
1618 	/*
1619 	 * By here the 16-bit character is converted
1620 	 * to a 32-bit wide character
1621 	 */
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;
1636 	}
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];
1661 	}
1662 	return (nc);
1663 }
1664 
1665 /*
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
1670  */
1671 #define	MAX_ALLOWABLE_STRING 250
1672 
1673 int32_t
ud_uncompress(int32_t in_len,int32_t * out_len,uint8_t * in_str,uint8_t * out_str)1674 ud_uncompress(int32_t in_len, int32_t *out_len,
1675     uint8_t *in_str, uint8_t *out_str)
1676 {
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;
1681 
1682 	if (in_len == 0) {
1683 		*out_len = 0;
1684 		out_str[0] = '\0';
1685 		return (0);
1686 	}
1687 
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];
1693 
1694 	/*
1695 	 * File names "." and ".." are invalid under unix.
1696 	 * Transform them into something
1697 	 */
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;
1705 		}
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;
1713 		}
1714 	} else {
1715 		*out_len = 0;
1716 		return (EINVAL);
1717 	}
1718 
1719 	for (index = 1; index < in_len; ) {
1720 
1721 		/*
1722 		 * Uncompress each character
1723 		 */
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++];
1729 		}
1730 
1731 		if (make_crc != 0) {
1732 			crc += w2_char;
1733 		}
1734 
1735 		if (w2_char == DOT) {
1736 			dot_loc = len_till_now;
1737 		}
1738 
1739 		/*
1740 		 * Get rid of invalid characters
1741 		 */
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;
1754 			}
1755 		}
1756 
1757 		/*
1758 		 * Conver a 16bit character to a
1759 		 * utf8 byte stream
1760 		 */
1761 		if ((c_tx_sz = ud_utf162utf8(w2_char, utf8)) == 0) {
1762 			error = EINVAL;
1763 			goto end;
1764 		}
1765 		ASSERT(c_tx_sz > 0);
1766 		ASSERT(c_tx_sz < 7);
1767 
1768 		/*
1769 		 * The output string is larger than
1770 		 * the maximum allowed string length
1771 		 */
1772 		if ((crc_start_loc == 0) &&
1773 		    ((len_till_now + c_tx_sz) > MAX_ALLOWABLE_STRING)) {
1774 			crc_start_loc = len_till_now;
1775 		}
1776 
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;
1783 		}
1784 	}
1785 
1786 	/*
1787 	 * If we need to append CRC do it now
1788 	 */
1789 
1790 	if (make_crc) {
1791 
1792 		if (len_till_now > MAX_ALLOWABLE_STRING) {
1793 			len_till_now = crc_start_loc;
1794 		}
1795 
1796 		if (dot_loc > 0) {
1797 			/*
1798 			 * Make space for crc before the DOT
1799 			 * move the rest of the file name to the end
1800 			 */
1801 			for (k = len_till_now - 1; k >= dot_loc; k--) {
1802 				out_str[k + 5] = out_str[k];
1803 			}
1804 			k = dot_loc;
1805 		} else {
1806 			k = len_till_now;
1807 		}
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;
1816 	}
1817 	*out_len = len_till_now;
1818 end:
1819 	return (error);
1820 }
1821 
1822 
1823 struct buf *
ud_bread(dev_t dev,daddr_t blkno,long bsize)1824 ud_bread(dev_t dev, daddr_t blkno, long bsize)
1825 {
1826 	struct buf *bp;
1827 
1828 begin:
1829 	bp = bread(dev, blkno, bsize);
1830 
1831 	if (((bp->b_flags & B_ERROR) == 0) &&
1832 	    (bp->b_bcount != bsize)) {
1833 		/*
1834 		 * Buffer cache returned a
1835 		 * wrong number of bytes
1836 		 * flush the old buffer and
1837 		 * reread it again
1838 		 */
1839 		if (bp->b_flags & B_DELWRI) {
1840 			bwrite(bp);
1841 		} else {
1842 			bp->b_flags |= (B_AGE | B_STALE);
1843 			brelse(bp);
1844 		}
1845 		goto begin;
1846 	}
1847 
1848 	return (bp);
1849 }
1850 
1851 /*
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.
1859  */
1860 int
ud_sticky_remove_access(struct ud_inode * dir,struct ud_inode * entry,struct cred * cr)1861 ud_sticky_remove_access(struct ud_inode *dir, struct ud_inode *entry,
1862     struct cred *cr)
1863 {
1864 	uid_t uid;
1865 
1866 	ASSERT(RW_LOCK_HELD(&entry->i_contents));
1867 
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));
1874 
1875 	return (0);
1876 }
1877