xref: /dflybsd-src/sys/vfs/hpfs/hpfs_subr.c (revision b370aff7747b2e03ce9b829fbf2877dffdadfb64)
1 /*-
2  * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sys/fs/hpfs/hpfs_subr.c,v 1.1 1999/12/09 19:09:59 semenu Exp $
27  * $DragonFly: src/sys/vfs/hpfs/hpfs_subr.c,v 1.8 2006/12/23 00:41:29 swildner Exp $
28  */
29 
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/proc.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/vnode.h>
38 #include <sys/mount.h>
39 #include <sys/namei.h>
40 #include <sys/malloc.h>
41 #include <sys/buf.h>
42 
43 #include <sys/buf2.h>
44 
45 #include "hpfs.h"
46 #include "hpfsmount.h"
47 #include "hpfs_subr.h"
48 
49 u_long
50 hpfs_checksum(
51 	u_int8_t *object,
52 	int size)
53 {
54 	int i;
55 	u_long csum=0L;
56 	for (i=0; i < size; i++) {
57 		csum += (u_long) *object++;
58 		csum = (csum << 7) + (csum >> (25));
59 	}
60 	return (csum);
61 }
62 
63 void
64 hpfs_bmdeinit(
65 	struct hpfsmount *hpmp)
66 {
67 	struct buf *bp;
68 	int i;
69 
70 	dprintf(("hpmp_bmdeinit: "));
71 
72 	if (!(hpmp->hpm_mp->mnt_flag & MNT_RDONLY)) {
73 		/*
74 		 * Write down BitMap.
75 		 */
76 		for (i=0; i<hpmp->hpm_dbnum; i++) {
77 			dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i]));
78 
79 			bp = getblk(hpmp->hpm_devvp,
80 				    dbtodoff(hpmp->hpm_bmind[i]),
81 				    BMSIZE, 0, 0);
82 			clrbuf(bp);
83 
84 			bcopy(hpmp->hpm_bitmap + BMSIZE * i, bp->b_data,
85 			      BMSIZE);
86 
87 			bwrite(bp);
88 		}
89 	}
90 
91 	FREE(hpmp->hpm_bitmap,M_HPFSMNT);
92 	FREE(hpmp->hpm_bmind,M_HPFSMNT);
93 
94 	dprintf(("\n"));
95 }
96 
97 /*
98  * Initialize BitMap management, includes calculation of
99  * available blocks number.
100  */
101 int
102 hpfs_bminit(
103 	struct hpfsmount *hpmp)
104 {
105 	struct buf *bp;
106 	int error, i, k;
107 	u_long dbavail;
108 
109 	dprintf(("hpfs_bminit: "));
110 
111 	hpmp->hpm_dbnum = (hpmp->hpm_su.su_btotal + 0x3FFF) / 0x4000;
112 
113 	dprintf(("0x%lx data bands, ", hpmp->hpm_dbnum));
114 
115 	MALLOC(hpmp->hpm_bmind, lsn_t *, hpmp->hpm_dbnum * sizeof(lsn_t),
116 		M_HPFSMNT, M_WAITOK);
117 
118 	MALLOC(hpmp->hpm_bitmap, u_int8_t *, hpmp->hpm_dbnum * BMSIZE,
119 		M_HPFSMNT, M_WAITOK);
120 
121 	error = bread(hpmp->hpm_devvp, dbtodoff(hpmp->hpm_su.su_bitmap.lsn1),
122 		((hpmp->hpm_dbnum + 0x7F) & ~(0x7F)) << 2, &bp);
123 	if (error) {
124 		brelse(bp);
125 		FREE(hpmp->hpm_bitmap, M_HPFSMNT);
126 		FREE(hpmp->hpm_bmind, M_HPFSMNT);
127 		dprintf((" error %d\n", error));
128 		return (error);
129 	}
130 	bcopy(bp->b_data, hpmp->hpm_bmind, hpmp->hpm_dbnum * sizeof(lsn_t));
131 
132 	brelse(bp);
133 
134 	/*
135 	 * Read in all BitMap
136 	 */
137 	for (i=0; i<hpmp->hpm_dbnum; i++) {
138 		dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i]));
139 
140 		error = bread(hpmp->hpm_devvp, dbtodoff(hpmp->hpm_bmind[i]),
141 				BMSIZE, &bp);
142 		if (error) {
143 			brelse(bp);
144 			FREE(hpmp->hpm_bitmap, M_HPFSMNT);
145 			FREE(hpmp->hpm_bmind, M_HPFSMNT);
146 			dprintf((" error %d\n", error));
147 			return (error);
148 		}
149 		bcopy(bp->b_data, hpmp->hpm_bitmap + BMSIZE * i, BMSIZE);
150 
151 		brelse(bp);
152 	}
153 
154 	/*
155 	 * Look througth BitMap	and count free bits
156 	 */
157 	dbavail = 0;
158 	for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++) {
159 		u_int32_t mask;
160 		for (k=0, mask=1; k < 32; k++, mask<<=1)
161 			if(((u_int32_t *)hpmp->hpm_bitmap)[i] & mask)
162 				dbavail ++;
163 
164 	}
165 	hpmp->hpm_bavail = dbavail;
166 
167 	return (0);
168 }
169 
170 int
171 hpfs_cmpfname (
172 	struct hpfsmount *hpmp,
173 	char * uname,
174 	int ulen,
175 	char * dname,
176 	int dlen,
177 	u_int16_t cp)
178 {
179 	int i, res;
180 
181 	for (i = 0; i < ulen && i < dlen; i++) {
182 		res = hpfs_toupper(hpmp, hpfs_u2d(hpmp, uname[i]), cp) -
183 		      hpfs_toupper(hpmp, dname[i], cp);
184 		if (res)
185 			return res;
186 	}
187 	return (ulen - dlen);
188 }
189 
190 int
191 hpfs_cpstrnnicmp (
192 	struct hpfsmount *hpmp,
193 	char * str1,
194 	int str1len,
195 	u_int16_t str1cp,
196 	char * str2,
197 	int str2len,
198 	u_int16_t str2cp)
199 {
200 	int i, res;
201 
202 	for (i = 0; i < str1len && i < str2len; i++) {
203 		res = (int)hpfs_toupper(hpmp, ((u_char *)str1)[i], str1cp) -
204 		      (int)hpfs_toupper(hpmp, ((u_char *)str2)[i], str2cp);
205 		if (res)
206 			return res;
207 	}
208 	return (str1len - str2len);
209 }
210 
211 
212 int
213 hpfs_cpload (
214 	struct hpfsmount *hpmp,
215 	struct cpiblk *cpibp,
216 	struct cpdblk *cpdbp)
217 {
218 	struct buf *bp;
219 	struct cpdsec * cpdsp;
220 	int error, i;
221 
222 	error = bread(hpmp->hpm_devvp, dbtodoff(cpibp->b_cpdsec), DEV_BSIZE, &bp);
223 	if (error) {
224 		brelse(bp);
225 		return (error);
226 	}
227 
228 	cpdsp = (struct cpdsec *)bp->b_data;
229 
230 	for (i=cpdsp->d_cpfirst; i<cpdsp->d_cpcnt; i++) {
231 		if (cpdsp->d_cpdblk[i].b_cpid == cpibp->b_cpid) {
232 			bcopy(cpdsp->d_cpdblk + i, cpdbp,
233 			      sizeof(struct cpdblk));
234 
235 			brelse(bp);
236 
237 			return (0);
238 		}
239 	}
240 
241 	brelse(bp);
242 
243 	return (ENOENT);
244 }
245 
246 
247 /*
248  * Initialize Code Page information management.
249  * Load all copdepages in memory.
250  */
251 int
252 hpfs_cpinit (
253 	struct hpfsmount *hpmp,
254 	struct hpfs_args *argsp)
255 {
256 	struct buf *bp;
257 	int error, i;
258 	lsn_t lsn;
259 	int cpicnt;
260 	struct cpisec * cpisp;
261 	struct cpiblk * cpibp;
262 	struct cpdblk * cpdbp;
263 
264 	dprintf(("hpfs_cpinit: \n"));
265 
266 	if (argsp->flags & HPFSMNT_TABLES) {
267 		bcopy(argsp->d2u, hpmp->hpm_d2u, sizeof(u_char) * 0x80);
268 		bcopy(argsp->u2d, hpmp->hpm_u2d, sizeof(u_char) * 0x80);
269 	} else {
270 		for (i=0x0; i<0x80;i++) {
271 			hpmp->hpm_d2u[i] = i + 0x80;
272 			hpmp->hpm_u2d[i] = i + 0x80;
273 		}
274 	}
275 
276 	cpicnt = hpmp->hpm_sp.sp_cpinum;
277 
278 	MALLOC(hpmp->hpm_cpdblk, struct cpdblk *,
279 		cpicnt * sizeof(struct cpdblk), M_HPFSMNT, M_WAITOK);
280 
281 	cpdbp = hpmp->hpm_cpdblk;
282 	lsn = hpmp->hpm_sp.sp_cpi;
283 
284 	while (cpicnt > 0) {
285 		error = bread(hpmp->hpm_devvp, dbtodoff(lsn), DEV_BSIZE, &bp);
286 		if (error) {
287 			brelse(bp);
288 			return (error);
289 		}
290 
291 		cpisp = (struct cpisec *)bp->b_data;
292 
293 		cpibp = cpisp->s_cpi;
294 		for (i=0; i<cpisp->s_cpicnt; i++, cpicnt --, cpdbp++, cpibp++) {
295 			dprintf(("hpfs_cpinit: Country: %d, CP: %d (%d)\n",
296 				 cpibp->b_country, cpibp->b_cpid,
297 				 cpibp->b_vcpid));
298 
299 			error = hpfs_cpload(hpmp, cpibp, cpdbp);
300 			if (error) {
301 				brelse(bp);
302 				return (error);
303 			}
304 		}
305 		lsn = cpisp->s_next;
306 		brelse(bp);
307 	}
308 
309 	return (0);
310 }
311 
312 int
313 hpfs_cpdeinit (
314 	struct hpfsmount *hpmp)
315 {
316 	dprintf(("hpmp_cpdeinit: "));
317 	FREE(hpmp->hpm_cpdblk,M_HPFSMNT);
318 	return (0);
319 }
320 
321 /*
322  * Lookup for a run of blocks.
323  */
324 int
325 hpfs_bmlookup (
326 	struct hpfsmount *hpmp,
327 	u_long flags,	/* 1 means we want right len blocks in run, not less */
328 	lsn_t lsn,		/* We want near this one */
329 	u_long len,		/* We want such long */
330 	lsn_t *lsnp,	/* We got here */
331 	u_long *lenp)	/* We got this long */
332 {
333 	u_int32_t * bitmap;
334 	u_int32_t mask;
335 	int i,k;
336 	int cband, vcband;
337 	u_int bandsz;
338 	int count;
339 
340 	dprintf(("hpfs_bmlookup: lsn: 0x%x, len 0x%lx | Step1\n", lsn, len));
341 
342 	if (lsn > hpmp->hpm_su.su_btotal) {
343 		kprintf("hpfs_bmlookup: OUT OF VOLUME\n");
344 		return ENOSPC;
345 	}
346 	if (len > hpmp->hpm_bavail) {
347 		kprintf("hpfs_bmlookup: OUT OF SPACE\n");
348 		return ENOSPC;
349 	}
350  	i = lsn >> 5;
351 	k = lsn & 0x1F;
352 	mask = 1 << k;
353 	bitmap = (u_int32_t *)hpmp->hpm_bitmap + i;
354 
355 	if (*bitmap & mask) {
356 		*lsnp = lsn;
357 		*lenp = 0;
358 		for (; k < 32; k++, mask<<=1) {
359 			if (*bitmap & mask)
360 				(*lenp) ++;
361 			else {
362 				if (flags & 1)
363 					goto step2;
364 				else
365 					return (0);
366 			}
367 
368 			if (*lenp == len)
369 				return (0);
370 		}
371 
372 		bitmap++;
373 		i++;
374 		for (; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) {
375 			for (k=0, mask=1; k < 32; k++, mask<<=1) {
376 				if (*bitmap & mask)
377 					(*lenp) ++;
378 				else {
379 					if (flags & 1)
380 						goto step2;
381 					else
382 						return (0);
383 				}
384 
385 				if (*lenp == len)
386 					return (0);
387 			}
388 		}
389 		return (0);
390 	}
391 
392 step2:
393 	/*
394 	 * Lookup all bands begining from cband, lookup for first block
395 	 */
396 	cband = (lsn >> 14);
397 	dprintf(("hpfs_bmlookup: Step2: band 0x%x (0x%lx)\n",
398 		 cband, hpmp->hpm_dbnum));
399 	for (vcband = 0; vcband < hpmp->hpm_dbnum; vcband ++, cband++) {
400 		cband = cband % hpmp->hpm_dbnum;
401 		bandsz = min (hpmp->hpm_su.su_btotal - (cband << 14), 0x4000);
402 		dprintf(("hpfs_bmlookup: band: %d, sz: 0x%x\n", cband, bandsz));
403 
404 		bitmap = (u_int32_t *)hpmp->hpm_bitmap + (cband << 9);
405 		*lsnp = cband << 14;
406 		*lenp = 0;
407 		count = 0;
408 		for (i=0; i < bandsz >> 5; i++, bitmap++) {
409 			for (k=0, mask=1; k < 32; k++, mask<<=1) {
410 				if (*bitmap & mask) {
411 					if (count) {
412 						(*lenp) ++;
413 					} else {
414 						count = 1;
415 						*lsnp = (cband << 14) + (i << 5) + k;
416 						*lenp = 1;
417 					}
418 				} else {
419 					if ((*lenp) && !(flags & 1)) {
420 						return (0);
421 					} else {
422 						count = 0;
423 					}
424 				}
425 
426 				if (*lenp == len)
427 					return (0);
428 			}
429 		}
430 		if (cband == hpmp->hpm_dbnum - 1)  {
431 			if ((*lenp) && !(flags & 1)) {
432 				return (0);
433 			} else {
434 				count = 0;
435 			}
436 		}
437 	}
438 
439 	return (ENOSPC);
440 }
441 
442 /*
443  * Lookup a single free block.	XXX Need locking on BitMap operations
444  * VERY STUPID ROUTINE!!!
445  */
446 int
447 hpfs_bmfblookup (
448 	struct hpfsmount *hpmp,
449 	lsn_t *lp)
450 {
451 	u_int32_t * bitmap;
452 	int i,k;
453 
454 	dprintf(("hpfs_bmfblookup: "));
455 
456 	bitmap = (u_int32_t *)hpmp->hpm_bitmap;
457 	for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) {
458 		k = ffs(*bitmap);
459 		if (k) {
460 			*lp = (i << 5) + k - 1;
461 			dprintf((" found: 0x%x\n",*lp));
462 			return (0);
463 		}
464 	}
465 
466 	return (ENOSPC);
467 }
468 
469 /*
470  * Mark contignous block of blocks.
471  */
472 int
473 hpfs_bmmark (
474 	struct hpfsmount *hpmp,
475 	lsn_t bn,
476 	u_long bl,
477 	int state)
478 {
479 	u_int32_t * bitmap;
480 	int i, didprint = 0;
481 
482 	dprintf(("hpfs_bmmark(0x%x, 0x%lx, %d): \n",bn,bl, state));
483 
484 	if ((bn > hpmp->hpm_su.su_btotal) || (bn+bl > hpmp->hpm_su.su_btotal)) {
485 		kprintf("hpfs_bmmark: MARKING OUT OF VOLUME\n");
486 		return 0;
487 	}
488 	bitmap = (u_int32_t *)hpmp->hpm_bitmap;
489 	bitmap += bn >> 5;
490 
491 	while (bl > 0) {
492 		for (i = bn & 0x1F; (i < 0x20) && (bl > 0) ; i++, bl--) {
493 			if (state) {
494 				if ( *bitmap & (1 << i)) {
495 					if (!didprint) {
496 						kprintf("hpfs_bmmark: ALREADY FREE\n");
497 						didprint = 1;
498 					}
499 				} else
500 					hpmp->hpm_bavail++;
501 
502 				*bitmap |= (1 << i);
503 			} else {
504 				if ((~(*bitmap)) & (1 << i)) {
505 					if (!didprint) {
506 						kprintf("hpfs_bmmark: ALREADY BUSY\n");
507 						didprint = 1;
508 					}
509 				} else
510 					hpmp->hpm_bavail--;
511 
512 				*bitmap &= ~(1 << i);
513 			}
514 		}
515 		bn = 0;
516 		bitmap++;
517 	}
518 
519 	return (0);
520 }
521 
522 
523 int
524 hpfs_validateparent (
525 	struct hpfsnode *hp)
526 {
527 	struct hpfsnode *dhp;
528 	struct vnode *dvp;
529 	struct hpfsmount *hpmp = hp->h_hpmp;
530 	struct buf *bp;
531 	struct dirblk *dp;
532 	struct hpfsdirent *dep;
533 	lsn_t lsn, olsn;
534 	int level, error;
535 
536 	dprintf(("hpfs_validatetimes(0x%x): [parent: 0x%x] ",
537 		hp->h_no, hp->h_fn.fn_parent));
538 
539 	if (hp->h_no == hp->h_fn.fn_parent) {
540 		dhp = hp;
541 	} else {
542 		error = VFS_VGET(hpmp->hpm_mp, NULL, hp->h_fn.fn_parent, &dvp);
543 		if (error)
544 			return (error);
545 		dhp = VTOHP(dvp);
546 	}
547 
548 	lsn = ((alleaf_t *)dhp->h_fn.fn_abd)->al_lsn;
549 
550 	olsn = 0;
551 	level = 1;
552 	bp = NULL;
553 
554 dive:
555 	dprintf(("[dive 0x%x] ", lsn));
556 	if (bp != NULL)
557 		brelse(bp);
558 	error = bread(dhp->h_devvp, dbtodoff(lsn), D_BSIZE, &bp);
559 	if (error)
560 		goto failed;
561 
562 	dp = (struct dirblk *) bp->b_data;
563 	if (dp->d_magic != D_MAGIC) {
564 		kprintf("hpfs_validatetimes: magic doesn't match\n");
565 		error = EINVAL;
566 		goto failed;
567 	}
568 
569 	dep = D_DIRENT(dp);
570 
571 	if (olsn) {
572 		dprintf(("[restore 0x%x] ", olsn));
573 
574 		while(!(dep->de_flag & DE_END) ) {
575 			if((dep->de_flag & DE_DOWN) &&
576 			   (olsn == DE_DOWNLSN(dep)))
577 					 break;
578 			dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
579 		}
580 
581 		if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) {
582 			if (dep->de_flag & DE_END)
583 				goto blockdone;
584 
585 			if (hp->h_no == dep->de_fnode) {
586 				dprintf(("[found] "));
587 				goto readdone;
588 			}
589 
590 			dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
591 		} else {
592 			kprintf("hpfs_validatetimes: ERROR! oLSN not found\n");
593 			error = EINVAL;
594 			goto failed;
595 		}
596 	}
597 
598 	olsn = 0;
599 
600 	while(!(dep->de_flag & DE_END)) {
601 		if(dep->de_flag & DE_DOWN) {
602 			lsn = DE_DOWNLSN(dep);
603 			level++;
604 			goto dive;
605 		}
606 
607 		if (hp->h_no == dep->de_fnode) {
608 			dprintf(("[found] "));
609 			goto readdone;
610 		}
611 
612 		dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
613 	}
614 
615 	if(dep->de_flag & DE_DOWN) {
616 		dprintf(("[enddive] "));
617 		lsn = DE_DOWNLSN(dep);
618 		level++;
619 		goto dive;
620 	}
621 
622 blockdone:
623 	dprintf(("[EOB] "));
624 	olsn = lsn;
625 	lsn = dp->d_parent;
626 	level--;
627 	dprintf(("[level %d] ", level));
628 	if (level > 0)
629 		goto dive;	/* undive really */
630 
631 	goto failed;
632 
633 readdone:
634 	bcopy(dep->de_name,hp->h_name,dep->de_namelen);
635 	hp->h_name[dep->de_namelen] = '\0';
636 	hp->h_namelen = dep->de_namelen;
637 	hp->h_ctime = dep->de_ctime;
638 	hp->h_atime = dep->de_atime;
639 	hp->h_mtime = dep->de_mtime;
640 	hp->h_flag |= H_PARVALID;
641 
642 	dprintf(("[readdone]"));
643 
644 failed:
645 	dprintf(("\n"));
646 	if (bp != NULL)
647 		brelse(bp);
648 	if (hp != dhp)
649 		vput(dvp);
650 
651 	return (error);
652 }
653 
654 struct timespec
655 hpfstimetounix (
656 	u_long hptime)
657 {
658 	struct timespec t;
659 
660 	t.tv_nsec = 0;
661 	t.tv_sec = hptime;
662 
663 	return t;
664 }
665 
666 /*
667  * Write down changes done to parent dir, these are only times for now.
668  * hpfsnode have to be locked.
669  */
670 int
671 hpfs_updateparent (
672 	struct hpfsnode *hp)
673 {
674 	struct hpfsnode *dhp;
675 	struct vnode *dvp;
676 	struct hpfsdirent *dep;
677 	struct buf * bp;
678 	int error;
679 
680 	dprintf(("hpfs_updateparent(0x%x): \n", hp->h_no));
681 
682 	if (!(hp->h_flag & H_PARCHANGE))
683 		return (0);
684 
685 	if (!(hp->h_flag & H_PARVALID)) {
686 		error = hpfs_validateparent (hp);
687 		if (error)
688 			return (error);
689 	}
690 
691 	if (hp->h_no == hp->h_fn.fn_parent) {
692 		dhp = hp;
693 	} else {
694 		error = VFS_VGET(hp->h_hpmp->hpm_mp, NULL,
695 				 hp->h_fn.fn_parent, &dvp);
696 		if (error)
697 			return (error);
698 		dhp = VTOHP(dvp);
699 	}
700 
701 	error = hpfs_genlookupbyname (dhp, hp->h_name, hp->h_namelen,
702 					&bp, &dep);
703 	if (error) {
704 		goto failed;
705 	}
706 
707 	dep->de_atime = hp->h_atime;
708 	dep->de_mtime = hp->h_mtime;
709 	dep->de_size = hp->h_fn.fn_size;
710 
711 	bdwrite (bp);
712 
713 	hp->h_flag &= ~H_PARCHANGE;
714 
715 	error = 0;
716 failed:
717 	if (hp != dhp)
718 		vput(dvp);
719 
720 	return (0);
721 }
722 
723 /*
724  * Write down on disk changes done to fnode. hpfsnode have to be locked.
725  */
726 int
727 hpfs_update (
728 	struct hpfsnode *hp)
729 {
730 	struct buf * bp;
731 
732 	dprintf(("hpfs_update(0x%x): \n", hp->h_no));
733 
734 	if (!(hp->h_flag & H_CHANGE))
735 		return (0);
736 
737 	bp = getblk(hp->h_devvp, dbtodoff(hp->h_no), FNODESIZE, 0, 0);
738 	clrbuf(bp);
739 
740 	bcopy (&hp->h_fn, bp->b_data, sizeof(struct fnode));
741 	bdwrite (bp);
742 
743 	hp->h_flag &= ~H_CHANGE;
744 
745 	if (hp->h_flag & H_PARCHANGE)
746 		return (hpfs_updateparent(hp));
747 
748 	return (0);
749 }
750 
751 /*
752  * Truncate file to specifed size. hpfsnode have to be locked.
753  */
754 int
755 hpfs_truncate (
756 	struct hpfsnode *hp,
757 	u_long size)
758 {
759 	struct hpfsmount *hpmp = hp->h_hpmp;
760 	lsn_t newblen, oldblen;
761 	int error, pf;
762 
763 	dprintf(("hpfs_truncate(0x%x, 0x%x -> 0x%lx): ",
764 		hp->h_no, hp->h_fn.fn_size, size));
765 
766 	newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT;
767 	oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT;
768 
769 	dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen));
770 
771 	error = hpfs_truncatealblk (hpmp, &hp->h_fn.fn_ab, newblen, &pf);
772 	if (error)
773 		return (error);
774 	if (pf) {
775 		hp->h_fn.fn_ab.ab_flag = 0;
776 		hp->h_fn.fn_ab.ab_freecnt = 0x8;
777 		hp->h_fn.fn_ab.ab_busycnt = 0x0;
778 		hp->h_fn.fn_ab.ab_freeoff = sizeof(alblk_t);
779 	}
780 
781 	hp->h_fn.fn_size = size;
782 
783 	hp->h_flag |= (H_CHANGE | H_PARCHANGE);
784 
785 	dprintf(("hpfs_truncate: successful\n"));
786 
787 	return (0);
788 }
789 
790 /*
791  * Enlarge file to specifed size. hpfsnode have to be locked.
792  */
793 int
794 hpfs_extend (
795 	struct hpfsnode *hp,
796 	u_long size)
797 {
798 	struct hpfsmount *hpmp = hp->h_hpmp;
799 	lsn_t newblen, oldblen;
800 	int error;
801 
802 	dprintf(("hpfs_extend(0x%x, 0x%x -> 0x%lx): ",
803 		hp->h_no, hp->h_fn.fn_size, size));
804 
805 	if (hpmp->hpm_bavail < 0x10)
806 		return (ENOSPC);
807 
808 	newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT;
809 	oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT;
810 
811 	dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen));
812 
813 	error = hpfs_addextent(hpmp, hp, newblen - oldblen);
814 	if (error) {
815 		kprintf("hpfs_extend: FAILED TO ADD EXTENT %d\n", error);
816 		return (error);
817 	}
818 
819 	hp->h_fn.fn_size = size;
820 
821 	hp->h_flag |= (H_CHANGE | H_PARCHANGE);
822 
823 	dprintf(("hpfs_extend: successful\n"));
824 
825 	return (0);
826 }
827 
828 /*
829  * Read AlSec structure, and check if magic is valid.
830  * You don't need to brelse buf on error.
831  */
832 int
833 hpfs_breadstruct (
834 	struct hpfsmount *hpmp,
835 	lsn_t lsn,
836 	u_int len,
837 	u_int32_t magic,
838 	struct buf **bpp)
839 {
840 	struct buf *bp;
841 	u_int32_t *mp;
842 	int error;
843 
844 	dprintf(("hpfs_breadstruct: reading at 0x%x\n", lsn));
845 
846 	*bpp = NULL;
847 
848 	error = bread(hpmp->hpm_devvp, dbtodoff(lsn), len, &bp);
849 	if (error) {
850 		brelse(bp);
851 		return (error);
852 	}
853 	mp = (u_int32_t *) bp->b_data;
854 	if (*mp != magic) {
855 		brelse(bp);
856 		kprintf("hpfs_breadstruct: MAGIC DOESN'T MATCH (0x%08x != 0x%08x)\n",
857 			*mp, magic);
858 		return (EINVAL);
859 	}
860 
861 	*bpp = bp;
862 
863 	return (0);
864 }
865 
866