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