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