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: releng/5.0/sys/fs/hpfs/hpfs_subr.c 92462 2002-03-17 01:25:47Z mckusick $
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/bio.h>
41 #include <sys/buf.h>
42
43 #include <fs/hpfs/hpfs.h>
44 #include <fs/hpfs/hpfsmount.h>
45 #include <fs/hpfs/hpfs_subr.h>
46
47 u_long
48 hpfs_checksum(
49 u_int8_t *object,
50 int size)
51 {
52 register 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, hpmp->hpm_bmind[i],
78 BMSIZE, 0, 0);
79 clrbuf(bp);
80
81 bcopy(hpmp->hpm_bitmap + BMSIZE * i, bp->b_data,
82 BMSIZE);
83
84 bwrite(bp);
85 }
86 }
87
88 FREE(hpmp->hpm_bitmap,M_HPFSMNT);
89 FREE(hpmp->hpm_bmind,M_HPFSMNT);
90
91 dprintf(("\n"));
92 }
93
94 /*
95 * Initialize BitMap management, includes calculation of
96 * available blocks number.
97 */
98 int
99 hpfs_bminit(
100 struct hpfsmount *hpmp)
101 {
102 struct buf *bp;
103 int error, i, k;
104 u_long dbavail;
105
106 dprintf(("hpfs_bminit: "));
107
108 hpmp->hpm_dbnum = (hpmp->hpm_su.su_btotal + 0x3FFF) / 0x4000;
109
110 dprintf(("0x%lx data bands, ", hpmp->hpm_dbnum));
111
112 MALLOC(hpmp->hpm_bmind, lsn_t *, hpmp->hpm_dbnum * sizeof(lsn_t),
113 M_HPFSMNT, M_WAITOK);
114
115 MALLOC(hpmp->hpm_bitmap, u_int8_t *, hpmp->hpm_dbnum * BMSIZE,
116 M_HPFSMNT, M_WAITOK);
117
118 error = bread(hpmp->hpm_devvp, hpmp->hpm_su.su_bitmap.lsn1,
119 ((hpmp->hpm_dbnum + 0x7F) & ~(0x7F)) << 2, NOCRED, &bp);
120 if (error) {
121 brelse(bp);
122 FREE(hpmp->hpm_bitmap, M_HPFSMNT);
123 FREE(hpmp->hpm_bmind, M_HPFSMNT);
124 dprintf((" error %d\n", error));
125 return (error);
126 }
127 bcopy(bp->b_data, hpmp->hpm_bmind, hpmp->hpm_dbnum * sizeof(lsn_t));
128
129 brelse(bp);
130
131 /*
132 * Read in all BitMap
133 */
134 for (i=0; i<hpmp->hpm_dbnum; i++) {
135 dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i]));
136
137 error = bread(hpmp->hpm_devvp, hpmp->hpm_bmind[i],
138 BMSIZE, NOCRED, &bp);
139 if (error) {
140 brelse(bp);
141 FREE(hpmp->hpm_bitmap, M_HPFSMNT);
142 FREE(hpmp->hpm_bmind, M_HPFSMNT);
143 dprintf((" error %d\n", error));
144 return (error);
145 }
146 bcopy(bp->b_data, hpmp->hpm_bitmap + BMSIZE * i, BMSIZE);
147
148 brelse(bp);
149 }
150
151 /*
152 * Look througth BitMap and count free bits
153 */
154 dbavail = 0;
155 for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++) {
156 register u_int32_t mask;
157 for (k=0, mask=1; k < 32; k++, mask<<=1)
158 if(((u_int32_t *)hpmp->hpm_bitmap)[i] & mask)
159 dbavail ++;
160
161 }
162 hpmp->hpm_bavail = dbavail;
163
164 return (0);
165 }
166
167 int
168 hpfs_cmpfname (
169 struct hpfsmount *hpmp,
170 char * uname,
171 int ulen,
172 char * dname,
173 int dlen,
174 u_int16_t cp)
175 {
176 register int i, res;
177
178 for (i = 0; i < ulen && i < dlen; i++) {
179 res = hpfs_toupper(hpmp, hpfs_u2d(hpmp, uname[i]), cp) -
180 hpfs_toupper(hpmp, dname[i], cp);
181 if (res)
182 return res;
183 }
184 return (ulen - dlen);
185 }
186
187 int
188 hpfs_cpstrnnicmp (
189 struct hpfsmount *hpmp,
190 char * str1,
191 int str1len,
192 u_int16_t str1cp,
193 char * str2,
194 int str2len,
195 u_int16_t str2cp)
196 {
197 int i, res;
198
199 for (i = 0; i < str1len && i < str2len; i++) {
200 res = (int)hpfs_toupper(hpmp, ((u_char *)str1)[i], str1cp) -
201 (int)hpfs_toupper(hpmp, ((u_char *)str2)[i], str2cp);
202 if (res)
203 return res;
204 }
205 return (str1len - str2len);
206 }
207
208
209 int
210 hpfs_cpload (
211 struct hpfsmount *hpmp,
212 struct cpiblk *cpibp,
213 struct cpdblk *cpdbp)
214 {
215 struct buf *bp;
216 struct cpdsec * cpdsp;
217 int error, i;
218
219 error = bread(hpmp->hpm_devvp, cpibp->b_cpdsec, DEV_BSIZE, NOCRED, &bp);
220 if (error) {
221 brelse(bp);
222 return (error);
223 }
224
225 cpdsp = (struct cpdsec *)bp->b_data;
226
227 for (i=cpdsp->d_cpfirst; i<cpdsp->d_cpcnt; i++) {
228 if (cpdsp->d_cpdblk[i].b_cpid == cpibp->b_cpid) {
229 bcopy(cpdsp->d_cpdblk + i, cpdbp,
230 sizeof(struct cpdblk));
231
232 brelse(bp);
233
234 return (0);
235 }
236 }
237
238 brelse(bp);
239
240 return (ENOENT);
241 }
242
243
244 /*
245 * Initialize Code Page information management.
246 * Load all copdepages in memory.
247 */
248 int
249 hpfs_cpinit (
250 struct hpfsmount *hpmp,
251 struct hpfs_args *argsp)
252 {
253 struct buf *bp;
254 int error, i;
255 lsn_t lsn;
256 int cpicnt;
257 struct cpisec * cpisp;
258 struct cpiblk * cpibp;
259 struct cpdblk * cpdbp;
260
261 dprintf(("hpfs_cpinit: \n"));
262
263 if (argsp->flags & HPFSMNT_TABLES) {
264 bcopy(argsp->d2u, hpmp->hpm_d2u, sizeof(u_char) * 0x80);
265 bcopy(argsp->u2d, hpmp->hpm_u2d, sizeof(u_char) * 0x80);
266 } else {
267 for (i=0x0; i<0x80;i++) {
268 hpmp->hpm_d2u[i] = i + 0x80;
269 hpmp->hpm_u2d[i] = i + 0x80;
270 }
271 }
272
273 cpicnt = hpmp->hpm_sp.sp_cpinum;
274
275 MALLOC(hpmp->hpm_cpdblk, struct cpdblk *,
276 cpicnt * sizeof(struct cpdblk), M_HPFSMNT, M_WAITOK);
277
278 cpdbp = hpmp->hpm_cpdblk;
279 lsn = hpmp->hpm_sp.sp_cpi;
280
281 while (cpicnt > 0) {
282 error = bread(hpmp->hpm_devvp, lsn, DEV_BSIZE, NOCRED, &bp);
283 if (error) {
284 brelse(bp);
285 return (error);
286 }
287
288 cpisp = (struct cpisec *)bp->b_data;
289
290 cpibp = cpisp->s_cpi;
291 for (i=0; i<cpisp->s_cpicnt; i++, cpicnt --, cpdbp++, cpibp++) {
292 dprintf(("hpfs_cpinit: Country: %d, CP: %d (%d)\n",
293 cpibp->b_country, cpibp->b_cpid,
294 cpibp->b_vcpid));
295
296 error = hpfs_cpload(hpmp, cpibp, cpdbp);
297 if (error) {
298 brelse(bp);
299 return (error);
300 }
301 }
302 lsn = cpisp->s_next;
303 brelse(bp);
304 }
305
306 return (0);
307 }
308
309 int
310 hpfs_cpdeinit (
311 struct hpfsmount *hpmp)
312 {
313 dprintf(("hpmp_cpdeinit: "));
314 FREE(hpmp->hpm_cpdblk,M_HPFSMNT);
315 return (0);
316 }
317
318 /*
319 * Lookup for a run of blocks.
320 */
321 int
322 hpfs_bmlookup (
323 struct hpfsmount *hpmp,
324 u_long flags, /* 1 means we want right len blocks in run, not less */
325 lsn_t lsn, /* We want near this one */
326 u_long len, /* We want such long */
327 lsn_t *lsnp, /* We got here */
328 u_long *lenp) /* We got this long */
329 {
330 u_int32_t * bitmap;
331 register u_int32_t mask;
332 int i,k;
333 int cband, vcband;
334 u_int bandsz;
335 int count;
336
337 dprintf(("hpfs_bmlookup: lsn: 0x%x, len 0x%lx | Step1\n", lsn, len));
338
339 if (lsn > hpmp->hpm_su.su_btotal) {
340 printf("hpfs_bmlookup: OUT OF VOLUME\n");
341 return ENOSPC;
342 }
343 if (len > hpmp->hpm_bavail) {
344 printf("hpfs_bmlookup: OUT OF SPACE\n");
345 return ENOSPC;
346 }
347 i = lsn >> 5;
348 k = lsn & 0x1F;
349 mask = 1 << k;
350 bitmap = (u_int32_t *)hpmp->hpm_bitmap + i;
351
352 if (*bitmap & mask) {
353 *lsnp = lsn;
354 *lenp = 0;
355 for (; k < 32; k++, mask<<=1) {
356 if (*bitmap & mask)
357 (*lenp) ++;
358 else {
359 if (flags & 1)
360 goto step2;
361 else
362 return (0);
363 }
364
365 if (*lenp == len)
366 return (0);
367 }
368
369 bitmap++;
370 i++;
371 for (; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) {
372 for (k=0, mask=1; k < 32; k++, mask<<=1) {
373 if (*bitmap & mask)
374 (*lenp) ++;
375 else {
376 if (flags & 1)
377 goto step2;
378 else
379 return (0);
380 }
381
382 if (*lenp == len)
383 return (0);
384 }
385 }
386 return (0);
387 }
388
389 step2:
390 /*
391 * Lookup all bands begining from cband, lookup for first block
392 */
393 cband = (lsn >> 14);
394 dprintf(("hpfs_bmlookup: Step2: band 0x%x (0x%lx)\n",
395 cband, hpmp->hpm_dbnum));
396 for (vcband = 0; vcband < hpmp->hpm_dbnum; vcband ++, cband++) {
397 cband = cband % hpmp->hpm_dbnum;
398 bandsz = min (hpmp->hpm_su.su_btotal - (cband << 14), 0x4000);
399 dprintf(("hpfs_bmlookup: band: %d, sz: 0x%x\n", cband, bandsz));
400
401 bitmap = (u_int32_t *)hpmp->hpm_bitmap + (cband << 9);
402 *lsnp = cband << 14;
403 *lenp = 0;
404 count = 0;
405 for (i=0; i < bandsz >> 5; i++, bitmap++) {
406 for (k=0, mask=1; k < 32; k++, mask<<=1) {
407 if (*bitmap & mask) {
408 if (count) {
409 (*lenp) ++;
410 } else {
411 count = 1;
412 *lsnp = (cband << 14) + (i << 5) + k;
413 *lenp = 1;
414 }
415 } else {
416 if ((*lenp) && !(flags & 1)) {
417 return (0);
418 } else {
419 count = 0;
420 }
421 }
422
423 if (*lenp == len)
424 return (0);
425 }
426 }
427 if (cband == hpmp->hpm_dbnum - 1) {
428 if ((*lenp) && !(flags & 1)) {
429 return (0);
430 } else {
431 count = 0;
432 }
433 }
434 }
435
436 return (ENOSPC);
437 }
438
439 /*
440 * Lookup a single free block. XXX Need locking on BitMap operations
441 * VERY STUPID ROUTINE!!!
442 */
443 int
444 hpfs_bmfblookup (
445 struct hpfsmount *hpmp,
446 lsn_t *lp)
447 {
448 u_int32_t * bitmap;
449 int i,k;
450
451 dprintf(("hpfs_bmfblookup: "));
452
453 bitmap = (u_int32_t *)hpmp->hpm_bitmap;
454 for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) {
455 k = ffs(*bitmap);
456 if (k) {
457 *lp = (i << 5) + k - 1;
458 dprintf((" found: 0x%x\n",*lp));
459 return (0);
460 }
461 }
462
463 return (ENOSPC);
464 }
465
466 /*
467 * Mark contignous block of blocks.
468 */
469 int
470 hpfs_bmmark (
471 struct hpfsmount *hpmp,
472 lsn_t bn,
473 u_long bl,
474 int state)
475 {
476 u_int32_t * bitmap;
477 int i, didprint = 0;
478
479 dprintf(("hpfs_bmmark(0x%x, 0x%lx, %d): \n",bn,bl, state));
480
481 if ((bn > hpmp->hpm_su.su_btotal) || (bn+bl > hpmp->hpm_su.su_btotal)) {
482 printf("hpfs_bmmark: MARKING OUT OF VOLUME\n");
483 return 0;
484 }
485 bitmap = (u_int32_t *)hpmp->hpm_bitmap;
486 bitmap += bn >> 5;
487
488 while (bl > 0) {
489 for (i = bn & 0x1F; (i < 0x20) && (bl > 0) ; i++, bl--) {
490 if (state) {
491 if ( *bitmap & (1 << i)) {
492 if (!didprint) {
493 printf("hpfs_bmmark: ALREADY FREE\n");
494 didprint = 1;
495 }
496 } else
497 hpmp->hpm_bavail++;
498
499 *bitmap |= (1 << i);
500 } else {
501 if ((~(*bitmap)) & (1 << i)) {
502 if (!didprint) {
503 printf("hpfs_bmmark: ALREADY BUSY\n");
504 didprint = 1;
505 }
506 } else
507 hpmp->hpm_bavail--;
508
509 *bitmap &= ~(1 << i);
510 }
511 }
512 bn = 0;
513 bitmap++;
514 }
515
516 return (0);
517 }
518
519
520 int
521 hpfs_validateparent (
522 struct hpfsnode *hp)
523 {
524 struct hpfsnode *dhp;
525 struct vnode *dvp;
526 struct hpfsmount *hpmp = hp->h_hpmp;
527 struct buf *bp;
528 struct dirblk *dp;
529 struct hpfsdirent *dep;
530 lsn_t lsn, olsn;
531 int level, error;
532
533 dprintf(("hpfs_validatetimes(0x%x): [parent: 0x%x] ",
534 hp->h_no, hp->h_fn.fn_parent));
535
536 if (hp->h_no == hp->h_fn.fn_parent) {
537 dhp = hp;
538 } else {
539 error = VFS_VGET(hpmp->hpm_mp, hp->h_fn.fn_parent,
540 LK_EXCLUSIVE, &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, lsn, D_BSIZE, NOCRED, &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 LK_EXCLUSIVE, &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, 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, lsn, len, NOCRED, &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
Cache object: 491721816cda119ca910f9bd28dc4eab
|