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/malloc.h> 39 #include <sys/buf.h> 40 41 #include <sys/buf2.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 kfree(hpmp->hpm_bitmap, M_HPFSMNT); 90 kfree(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 hpmp->hpm_bmind = kmalloc(hpmp->hpm_dbnum * sizeof(lsn_t), M_HPFSMNT, 114 M_WAITOK); 115 116 hpmp->hpm_bitmap = kmalloc(hpmp->hpm_dbnum * BMSIZE, M_HPFSMNT, 117 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 kfree(hpmp->hpm_bitmap, M_HPFSMNT); 124 kfree(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 kfree(hpmp->hpm_bitmap, M_HPFSMNT); 143 kfree(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 hpmp->hpm_cpdblk = kmalloc(cpicnt * sizeof(struct cpdblk), M_HPFSMNT, 277 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 kfree(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 kprintf("hpfs_bmlookup: OUT OF VOLUME\n"); 342 return ENOSPC; 343 } 344 if (len > hpmp->hpm_bavail) { 345 kprintf("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 kprintf("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 kprintf("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 kprintf("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, NULL, 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 kprintf("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 kprintf("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, NULL, 693 hp->h_fn.fn_parent, &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; 759 #ifdef HPFS_DEBUG 760 lsn_t oldblen; 761 #endif 762 int error, pf; 763 764 dprintf(("hpfs_truncate(0x%x, 0x%x -> 0x%lx): ", 765 hp->h_no, hp->h_fn.fn_size, size)); 766 767 newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT; 768 #ifdef HPFS_DEBUG 769 oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT; 770 #endif 771 772 dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen)); 773 774 error = hpfs_truncatealblk (hpmp, &hp->h_fn.fn_ab, newblen, &pf); 775 if (error) 776 return (error); 777 if (pf) { 778 hp->h_fn.fn_ab.ab_flag = 0; 779 hp->h_fn.fn_ab.ab_freecnt = 0x8; 780 hp->h_fn.fn_ab.ab_busycnt = 0x0; 781 hp->h_fn.fn_ab.ab_freeoff = sizeof(alblk_t); 782 } 783 784 hp->h_fn.fn_size = size; 785 786 hp->h_flag |= (H_CHANGE | H_PARCHANGE); 787 788 dprintf(("hpfs_truncate: successful\n")); 789 790 return (0); 791 } 792 793 /* 794 * Enlarge file to specifed size. hpfsnode have to be locked. 795 */ 796 int 797 hpfs_extend ( 798 struct hpfsnode *hp, 799 u_long size) 800 { 801 struct hpfsmount *hpmp = hp->h_hpmp; 802 lsn_t newblen, oldblen; 803 int error; 804 805 dprintf(("hpfs_extend(0x%x, 0x%x -> 0x%lx): ", 806 hp->h_no, hp->h_fn.fn_size, size)); 807 808 if (hpmp->hpm_bavail < 0x10) 809 return (ENOSPC); 810 811 newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT; 812 oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT; 813 814 dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen)); 815 816 error = hpfs_addextent(hpmp, hp, newblen - oldblen); 817 if (error) { 818 kprintf("hpfs_extend: FAILED TO ADD EXTENT %d\n", error); 819 return (error); 820 } 821 822 hp->h_fn.fn_size = size; 823 824 hp->h_flag |= (H_CHANGE | H_PARCHANGE); 825 826 dprintf(("hpfs_extend: successful\n")); 827 828 return (0); 829 } 830 831 /* 832 * Read AlSec structure, and check if magic is valid. 833 * You don't need to brelse buf on error. 834 */ 835 int 836 hpfs_breadstruct ( 837 struct hpfsmount *hpmp, 838 lsn_t lsn, 839 u_int len, 840 u_int32_t magic, 841 struct buf **bpp) 842 { 843 struct buf *bp; 844 u_int32_t *mp; 845 int error; 846 847 dprintf(("hpfs_breadstruct: reading at 0x%x\n", lsn)); 848 849 *bpp = NULL; 850 851 error = bread(hpmp->hpm_devvp, dbtodoff(lsn), len, &bp); 852 if (error) { 853 brelse(bp); 854 return (error); 855 } 856 mp = (u_int32_t *) bp->b_data; 857 if (*mp != magic) { 858 brelse(bp); 859 kprintf("hpfs_breadstruct: MAGIC DOESN'T MATCH (0x%08x != 0x%08x)\n", 860 *mp, magic); 861 return (EINVAL); 862 } 863 864 *bpp = bp; 865 866 return (0); 867 } 868 869