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