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