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.6 2003/08/15 07:26:15 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, 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, &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, &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 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 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, &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, &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 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, &dvp); 540 if (error) 541 return (error); 542 dhp = VTOHP(dvp); 543 } 544 545 lsn = ((alleaf_t *)dhp->h_fn.fn_abd)->al_lsn; 546 547 olsn = 0; 548 level = 1; 549 bp = NULL; 550 551 dive: 552 dprintf(("[dive 0x%x] ", lsn)); 553 if (bp != NULL) 554 brelse(bp); 555 error = bread(dhp->h_devvp, lsn, D_BSIZE, &bp); 556 if (error) 557 goto failed; 558 559 dp = (struct dirblk *) bp->b_data; 560 if (dp->d_magic != D_MAGIC) { 561 printf("hpfs_validatetimes: magic doesn't match\n"); 562 error = EINVAL; 563 goto failed; 564 } 565 566 dep = D_DIRENT(dp); 567 568 if (olsn) { 569 dprintf(("[restore 0x%x] ", olsn)); 570 571 while(!(dep->de_flag & DE_END) ) { 572 if((dep->de_flag & DE_DOWN) && 573 (olsn == DE_DOWNLSN(dep))) 574 break; 575 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); 576 } 577 578 if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) { 579 if (dep->de_flag & DE_END) 580 goto blockdone; 581 582 if (hp->h_no == dep->de_fnode) { 583 dprintf(("[found] ")); 584 goto readdone; 585 } 586 587 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); 588 } else { 589 printf("hpfs_validatetimes: ERROR! oLSN not found\n"); 590 error = EINVAL; 591 goto failed; 592 } 593 } 594 595 olsn = 0; 596 597 while(!(dep->de_flag & DE_END)) { 598 if(dep->de_flag & DE_DOWN) { 599 lsn = DE_DOWNLSN(dep); 600 level++; 601 goto dive; 602 } 603 604 if (hp->h_no == dep->de_fnode) { 605 dprintf(("[found] ")); 606 goto readdone; 607 } 608 609 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); 610 } 611 612 if(dep->de_flag & DE_DOWN) { 613 dprintf(("[enddive] ")); 614 lsn = DE_DOWNLSN(dep); 615 level++; 616 goto dive; 617 } 618 619 blockdone: 620 dprintf(("[EOB] ")); 621 olsn = lsn; 622 lsn = dp->d_parent; 623 level--; 624 dprintf(("[level %d] ", level)); 625 if (level > 0) 626 goto dive; /* undive really */ 627 628 goto failed; 629 630 readdone: 631 bcopy(dep->de_name,hp->h_name,dep->de_namelen); 632 hp->h_name[dep->de_namelen] = '\0'; 633 hp->h_namelen = dep->de_namelen; 634 hp->h_ctime = dep->de_ctime; 635 hp->h_atime = dep->de_atime; 636 hp->h_mtime = dep->de_mtime; 637 hp->h_flag |= H_PARVALID; 638 639 dprintf(("[readdone]")); 640 641 failed: 642 dprintf(("\n")); 643 if (bp != NULL) 644 brelse(bp); 645 if (hp != dhp) 646 vput(dvp); 647 648 return (error); 649 } 650 651 struct timespec 652 hpfstimetounix ( 653 u_long hptime) 654 { 655 struct timespec t; 656 657 t.tv_nsec = 0; 658 t.tv_sec = hptime; 659 660 return t; 661 } 662 663 /* 664 * Write down changes done to parent dir, these are only times for now. 665 * hpfsnode have to be locked. 666 */ 667 int 668 hpfs_updateparent ( 669 struct hpfsnode *hp) 670 { 671 struct hpfsnode *dhp; 672 struct vnode *dvp; 673 struct hpfsdirent *dep; 674 struct buf * bp; 675 int error; 676 677 dprintf(("hpfs_updateparent(0x%x): \n", hp->h_no)); 678 679 if (!(hp->h_flag & H_PARCHANGE)) 680 return (0); 681 682 if (!(hp->h_flag & H_PARVALID)) { 683 error = hpfs_validateparent (hp); 684 if (error) 685 return (error); 686 } 687 688 if (hp->h_no == hp->h_fn.fn_parent) { 689 dhp = hp; 690 } else { 691 error = VFS_VGET(hp->h_hpmp->hpm_mp, hp->h_fn.fn_parent, 692 &dvp); 693 if (error) 694 return (error); 695 dhp = VTOHP(dvp); 696 } 697 698 error = hpfs_genlookupbyname (dhp, hp->h_name, hp->h_namelen, 699 &bp, &dep); 700 if (error) { 701 goto failed; 702 } 703 704 dep->de_atime = hp->h_atime; 705 dep->de_mtime = hp->h_mtime; 706 dep->de_size = hp->h_fn.fn_size; 707 708 bdwrite (bp); 709 710 hp->h_flag &= ~H_PARCHANGE; 711 712 error = 0; 713 failed: 714 if (hp != dhp) 715 vput(dvp); 716 717 return (0); 718 } 719 720 /* 721 * Write down on disk changes done to fnode. hpfsnode have to be locked. 722 */ 723 int 724 hpfs_update ( 725 struct hpfsnode *hp) 726 { 727 struct buf * bp; 728 729 dprintf(("hpfs_update(0x%x): \n", hp->h_no)); 730 731 if (!(hp->h_flag & H_CHANGE)) 732 return (0); 733 734 bp = getblk(hp->h_devvp, hp->h_no, FNODESIZE, 0, 0); 735 clrbuf(bp); 736 737 bcopy (&hp->h_fn, bp->b_data, sizeof(struct fnode)); 738 bdwrite (bp); 739 740 hp->h_flag &= ~H_CHANGE; 741 742 if (hp->h_flag & H_PARCHANGE) 743 return (hpfs_updateparent(hp)); 744 745 return (0); 746 } 747 748 /* 749 * Truncate file to specifed size. hpfsnode have to be locked. 750 */ 751 int 752 hpfs_truncate ( 753 struct hpfsnode *hp, 754 u_long size) 755 { 756 struct hpfsmount *hpmp = hp->h_hpmp; 757 lsn_t newblen, oldblen; 758 int error, pf; 759 760 dprintf(("hpfs_truncate(0x%x, 0x%x -> 0x%lx): ", 761 hp->h_no, hp->h_fn.fn_size, size)); 762 763 newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT; 764 oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT; 765 766 dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen)); 767 768 error = hpfs_truncatealblk (hpmp, &hp->h_fn.fn_ab, newblen, &pf); 769 if (error) 770 return (error); 771 if (pf) { 772 hp->h_fn.fn_ab.ab_flag = 0; 773 hp->h_fn.fn_ab.ab_freecnt = 0x8; 774 hp->h_fn.fn_ab.ab_busycnt = 0x0; 775 hp->h_fn.fn_ab.ab_freeoff = sizeof(alblk_t); 776 } 777 778 hp->h_fn.fn_size = size; 779 780 hp->h_flag |= (H_CHANGE | H_PARCHANGE); 781 782 dprintf(("hpfs_truncate: successful\n")); 783 784 return (0); 785 } 786 787 /* 788 * Enlarge file to specifed size. hpfsnode have to be locked. 789 */ 790 int 791 hpfs_extend ( 792 struct hpfsnode *hp, 793 u_long size) 794 { 795 struct hpfsmount *hpmp = hp->h_hpmp; 796 lsn_t newblen, oldblen; 797 int error; 798 799 dprintf(("hpfs_extend(0x%x, 0x%x -> 0x%lx): ", 800 hp->h_no, hp->h_fn.fn_size, size)); 801 802 if (hpmp->hpm_bavail < 0x10) 803 return (ENOSPC); 804 805 newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT; 806 oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT; 807 808 dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen)); 809 810 error = hpfs_addextent(hpmp, hp, newblen - oldblen); 811 if (error) { 812 printf("hpfs_extend: FAILED TO ADD EXTENT %d\n", error); 813 return (error); 814 } 815 816 hp->h_fn.fn_size = size; 817 818 hp->h_flag |= (H_CHANGE | H_PARCHANGE); 819 820 dprintf(("hpfs_extend: successful\n")); 821 822 return (0); 823 } 824 825 /* 826 * Read AlSec structure, and check if magic is valid. 827 * You don't need to brelse buf on error. 828 */ 829 int 830 hpfs_breadstruct ( 831 struct hpfsmount *hpmp, 832 lsn_t lsn, 833 u_int len, 834 u_int32_t magic, 835 struct buf **bpp) 836 { 837 struct buf *bp; 838 u_int32_t *mp; 839 int error; 840 841 dprintf(("hpfs_breadstruct: reading at 0x%x\n", lsn)); 842 843 *bpp = NULL; 844 845 error = bread(hpmp->hpm_devvp, lsn, len, &bp); 846 if (error) { 847 brelse(bp); 848 return (error); 849 } 850 mp = (u_int32_t *) bp->b_data; 851 if (*mp != magic) { 852 brelse(bp); 853 printf("hpfs_breadstruct: MAGIC DOESN'T MATCH (0x%08x != 0x%08x)\n", 854 *mp, magic); 855 return (EINVAL); 856 } 857 858 *bpp = bp; 859 860 return (0); 861 } 862 863