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$ 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 47u_long 48hpfs_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 61void 62hpfs_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, 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 */ 98int 99hpfs_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 hpmp->hpm_bmind = malloc(hpmp->hpm_dbnum * sizeof(lsn_t), 113 M_HPFSMNT, M_WAITOK); 114 115 hpmp->hpm_bitmap = malloc(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 167int 168hpfs_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 187int 188hpfs_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 209int 210hpfs_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 */ 248int 249hpfs_cpinit ( 250 struct mount *mp, 251 struct hpfsmount *hpmp) 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 error = vfs_copyopt(mp->mnt_optnew, "d2u", hpmp->hpm_d2u, 264 sizeof hpmp->hpm_d2u); 265 if (error == ENOENT) 266 for (i=0x0; i<0x80;i++) 267 hpmp->hpm_d2u[i] = i + 0x80; 268 else if (error) 269 return (error); 270 271 error = vfs_copyopt(mp->mnt_optnew, "u2d", hpmp->hpm_u2d, 272 sizeof hpmp->hpm_u2d); 273 if (error == ENOENT) 274 for (i=0x0; i<0x80;i++) 275 hpmp->hpm_u2d[i] = i + 0x80; 276 else if (error) 277 return (error); 278 279 cpicnt = hpmp->hpm_sp.sp_cpinum; 280 281 hpmp->hpm_cpdblk = malloc(cpicnt * sizeof(struct cpdblk), 282 M_HPFSMNT, M_WAITOK); 283 284 cpdbp = hpmp->hpm_cpdblk; 285 lsn = hpmp->hpm_sp.sp_cpi; 286 287 while (cpicnt > 0) { 288 error = bread(hpmp->hpm_devvp, lsn, DEV_BSIZE, NOCRED, &bp); 289 if (error) { 290 brelse(bp); 291 return (error); 292 } 293 294 cpisp = (struct cpisec *)bp->b_data; 295 296 cpibp = cpisp->s_cpi; 297 for (i=0; i<cpisp->s_cpicnt; i++, cpicnt --, cpdbp++, cpibp++) { 298 dprintf(("hpfs_cpinit: Country: %d, CP: %d (%d)\n", 299 cpibp->b_country, cpibp->b_cpid, 300 cpibp->b_vcpid)); 301 302 error = hpfs_cpload(hpmp, cpibp, cpdbp); 303 if (error) { 304 brelse(bp); 305 return (error); 306 } 307 } 308 lsn = cpisp->s_next; 309 brelse(bp); 310 } 311 312 return (0); 313} 314 315int 316hpfs_cpdeinit ( 317 struct hpfsmount *hpmp) 318{ 319 dprintf(("hpmp_cpdeinit: ")); 320 free(hpmp->hpm_cpdblk,M_HPFSMNT); 321 return (0); 322} 323 324/* 325 * Lookup for a run of blocks. 326 */ 327int 328hpfs_bmlookup ( 329 struct hpfsmount *hpmp, 330 u_long flags, /* 1 means we want right len blocks in run, not less */ 331 lsn_t lsn, /* We want near this one */ 332 u_long len, /* We want such long */ 333 lsn_t *lsnp, /* We got here */ 334 u_long *lenp) /* We got this long */ 335{ 336 u_int32_t * bitmap; 337 register u_int32_t mask; 338 int i,k; 339 int cband, vcband; 340 u_int bandsz; 341 int count; 342 343 dprintf(("hpfs_bmlookup: lsn: 0x%x, len 0x%lx | Step1\n", lsn, len)); 344 345 if (lsn > hpmp->hpm_su.su_btotal) { 346 printf("hpfs_bmlookup: OUT OF VOLUME\n"); 347 return ENOSPC; 348 } 349 if (len > hpmp->hpm_bavail) { 350 printf("hpfs_bmlookup: OUT OF SPACE\n"); 351 return ENOSPC; 352 } 353 i = lsn >> 5; 354 k = lsn & 0x1F; 355 mask = 1 << k; 356 bitmap = (u_int32_t *)hpmp->hpm_bitmap + i; 357 358 if (*bitmap & mask) { 359 *lsnp = lsn; 360 *lenp = 0; 361 for (; k < 32; k++, mask<<=1) { 362 if (*bitmap & mask) 363 (*lenp) ++; 364 else { 365 if (flags & 1) 366 goto step2; 367 else 368 return (0); 369 } 370 371 if (*lenp == len) 372 return (0); 373 } 374 375 bitmap++; 376 i++; 377 for (; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) { 378 for (k=0, mask=1; k < 32; k++, mask<<=1) { 379 if (*bitmap & mask) 380 (*lenp) ++; 381 else { 382 if (flags & 1) 383 goto step2; 384 else 385 return (0); 386 } 387 388 if (*lenp == len) 389 return (0); 390 } 391 } 392 return (0); 393 } 394 395step2: 396 /* 397 * Lookup all bands begining from cband, lookup for first block 398 */ 399 cband = (lsn >> 14); 400 dprintf(("hpfs_bmlookup: Step2: band 0x%x (0x%lx)\n", 401 cband, hpmp->hpm_dbnum)); 402 for (vcband = 0; vcband < hpmp->hpm_dbnum; vcband ++, cband++) { 403 cband = cband % hpmp->hpm_dbnum; 404 bandsz = min (hpmp->hpm_su.su_btotal - (cband << 14), 0x4000); 405 dprintf(("hpfs_bmlookup: band: %d, sz: 0x%x\n", cband, bandsz)); 406 407 bitmap = (u_int32_t *)hpmp->hpm_bitmap + (cband << 9); 408 *lsnp = cband << 14; 409 *lenp = 0; 410 count = 0; 411 for (i=0; i < bandsz >> 5; i++, bitmap++) { 412 for (k=0, mask=1; k < 32; k++, mask<<=1) { 413 if (*bitmap & mask) { 414 if (count) { 415 (*lenp) ++; 416 } else { 417 count = 1; 418 *lsnp = (cband << 14) + (i << 5) + k; 419 *lenp = 1; 420 } 421 } else { 422 if ((*lenp) && !(flags & 1)) { 423 return (0); 424 } else { 425 count = 0; 426 } 427 } 428 429 if (*lenp == len) 430 return (0); 431 } 432 } 433 if (cband == hpmp->hpm_dbnum - 1) { 434 if ((*lenp) && !(flags & 1)) { 435 return (0); 436 } else { 437 count = 0; 438 } 439 } 440 } 441 442 return (ENOSPC); 443} 444 445/* 446 * Lookup a single free block. XXX Need locking on BitMap operations 447 * VERY STUPID ROUTINE!!! 448 */ 449int 450hpfs_bmfblookup ( 451 struct hpfsmount *hpmp, 452 lsn_t *lp) 453{ 454 u_int32_t * bitmap; 455 int i,k; 456 457 dprintf(("hpfs_bmfblookup: ")); 458 459 bitmap = (u_int32_t *)hpmp->hpm_bitmap; 460 for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) { 461 k = ffs(*bitmap); 462 if (k) { 463 *lp = (i << 5) + k - 1; 464 dprintf((" found: 0x%x\n",*lp)); 465 return (0); 466 } 467 } 468 469 return (ENOSPC); 470} 471 472/* 473 * Mark contignous block of blocks. 474 */ 475int 476hpfs_bmmark ( 477 struct hpfsmount *hpmp, 478 lsn_t bn, 479 u_long bl, 480 int state) 481{ 482 u_int32_t * bitmap; 483 int i, didprint = 0; 484 485 dprintf(("hpfs_bmmark(0x%x, 0x%lx, %d): \n",bn,bl, state)); 486 487 if ((bn > hpmp->hpm_su.su_btotal) || (bn+bl > hpmp->hpm_su.su_btotal)) { 488 printf("hpfs_bmmark: MARKING OUT OF VOLUME\n"); 489 return 0; 490 } 491 bitmap = (u_int32_t *)hpmp->hpm_bitmap; 492 bitmap += bn >> 5; 493 494 while (bl > 0) { 495 for (i = bn & 0x1F; (i < 0x20) && (bl > 0) ; i++, bl--) { 496 if (state) { 497 if ( *bitmap & (1 << i)) { 498 if (!didprint) { 499 printf("hpfs_bmmark: ALREADY FREE\n"); 500 didprint = 1; 501 } 502 } else 503 hpmp->hpm_bavail++; 504 505 *bitmap |= (1 << i); 506 } else { 507 if ((~(*bitmap)) & (1 << i)) { 508 if (!didprint) { 509 printf("hpfs_bmmark: ALREADY BUSY\n"); 510 didprint = 1; 511 } 512 } else 513 hpmp->hpm_bavail--; 514 515 *bitmap &= ~(1 << i); 516 } 517 } 518 bn = 0; 519 bitmap++; 520 } 521 522 return (0); 523} 524 525 526int 527hpfs_validateparent ( 528 struct hpfsnode *hp) 529{ 530 struct hpfsnode *dhp; 531 struct vnode *dvp; 532 struct hpfsmount *hpmp = hp->h_hpmp; 533 struct buf *bp; 534 struct dirblk *dp; 535 struct hpfsdirent *dep; 536 lsn_t lsn, olsn; 537 int level, error; 538 539 dprintf(("hpfs_validatetimes(0x%x): [parent: 0x%x] ", 540 hp->h_no, hp->h_fn.fn_parent)); 541 542 if (hp->h_no == hp->h_fn.fn_parent) { 543 dhp = hp; 544 } else { 545 error = VFS_VGET(hpmp->hpm_mp, hp->h_fn.fn_parent, 546 LK_EXCLUSIVE, &dvp); 547 if (error) 548 return (error); 549 dhp = VTOHP(dvp); 550 } 551 552 lsn = ((alleaf_t *)dhp->h_fn.fn_abd)->al_lsn; 553 554 olsn = 0; 555 level = 1; 556 bp = NULL; 557 558dive: 559 dprintf(("[dive 0x%x] ", lsn)); 560 if (bp != NULL) 561 brelse(bp); 562 error = bread(dhp->h_devvp, lsn, D_BSIZE, NOCRED, &bp); 563 if (error) 564 goto failed; 565 566 dp = (struct dirblk *) bp->b_data; 567 if (dp->d_magic != D_MAGIC) { 568 printf("hpfs_validatetimes: magic doesn't match\n"); 569 error = EINVAL; 570 goto failed; 571 } 572 573 dep = D_DIRENT(dp); 574 575 if (olsn) { 576 dprintf(("[restore 0x%x] ", olsn)); 577 578 while(!(dep->de_flag & DE_END) ) { 579 if((dep->de_flag & DE_DOWN) && 580 (olsn == DE_DOWNLSN(dep))) 581 break; 582 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); 583 } 584 585 if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) { 586 if (dep->de_flag & DE_END) 587 goto blockdone; 588 589 if (hp->h_no == dep->de_fnode) { 590 dprintf(("[found] ")); 591 goto readdone; 592 } 593 594 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); 595 } else { 596 printf("hpfs_validatetimes: ERROR! oLSN not found\n"); 597 error = EINVAL; 598 goto failed; 599 } 600 } 601 602 olsn = 0; 603 604 while(!(dep->de_flag & DE_END)) { 605 if(dep->de_flag & DE_DOWN) { 606 lsn = DE_DOWNLSN(dep); 607 level++; 608 goto dive; 609 } 610 611 if (hp->h_no == dep->de_fnode) { 612 dprintf(("[found] ")); 613 goto readdone; 614 } 615 616 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen); 617 } 618 619 if(dep->de_flag & DE_DOWN) { 620 dprintf(("[enddive] ")); 621 lsn = DE_DOWNLSN(dep); 622 level++; 623 goto dive; 624 } 625 626blockdone: 627 dprintf(("[EOB] ")); 628 olsn = lsn; 629 lsn = dp->d_parent; 630 level--; 631 dprintf(("[level %d] ", level)); 632 if (level > 0) 633 goto dive; /* undive really */ 634 635 goto failed; 636 637readdone: 638 bcopy(dep->de_name,hp->h_name,dep->de_namelen); 639 hp->h_name[dep->de_namelen] = '\0'; 640 hp->h_namelen = dep->de_namelen; 641 hp->h_ctime = dep->de_ctime; 642 hp->h_atime = dep->de_atime; 643 hp->h_mtime = dep->de_mtime; 644 hp->h_flag |= H_PARVALID; 645 646 dprintf(("[readdone]")); 647 648failed: 649 dprintf(("\n")); 650 if (bp != NULL) 651 brelse(bp); 652 if (hp != dhp) 653 vput(dvp); 654 655 return (error); 656} 657 658struct timespec 659hpfstimetounix ( 660 u_long hptime) 661{ 662 struct timespec t; 663 664 t.tv_nsec = 0; 665 t.tv_sec = hptime; 666 667 return t; 668} 669 670/* 671 * Write down changes done to parent dir, these are only times for now. 672 * hpfsnode have to be locked. 673 */ 674int 675hpfs_updateparent ( 676 struct hpfsnode *hp) 677{ 678 struct hpfsnode *dhp; 679 struct vnode *dvp; 680 struct hpfsdirent *dep; 681 struct buf * bp; 682 int error; 683 684 dprintf(("hpfs_updateparent(0x%x): \n", hp->h_no)); 685 686 if (!(hp->h_flag & H_PARCHANGE)) 687 return (0); 688 689 if (!(hp->h_flag & H_PARVALID)) { 690 error = hpfs_validateparent (hp); 691 if (error) 692 return (error); 693 } 694 695 if (hp->h_no == hp->h_fn.fn_parent) { 696 dhp = hp; 697 } else { 698 error = VFS_VGET(hp->h_hpmp->hpm_mp, hp->h_fn.fn_parent, 699 LK_EXCLUSIVE, &dvp); 700 if (error) 701 return (error); 702 dhp = VTOHP(dvp); 703 } 704 705 error = hpfs_genlookupbyname (dhp, hp->h_name, hp->h_namelen, 706 &bp, &dep); 707 if (error) { 708 goto failed; 709 } 710 711 dep->de_atime = hp->h_atime; 712 dep->de_mtime = hp->h_mtime; 713 dep->de_size = hp->h_fn.fn_size; 714 715 bdwrite (bp); 716 717 hp->h_flag &= ~H_PARCHANGE; 718 719 error = 0; 720failed: 721 if (hp != dhp) 722 vput(dvp); 723 724 return (0); 725} 726 727/* 728 * Write down on disk changes done to fnode. hpfsnode have to be locked. 729 */ 730int 731hpfs_update ( 732 struct hpfsnode *hp) 733{ 734 struct buf * bp; 735 736 dprintf(("hpfs_update(0x%x): \n", hp->h_no)); 737 738 if (!(hp->h_flag & H_CHANGE)) 739 return (0); 740 741 bp = getblk(hp->h_devvp, hp->h_no, FNODESIZE, 0, 0, 0); 742 clrbuf(bp); 743 744 bcopy (&hp->h_fn, bp->b_data, sizeof(struct fnode)); 745 bdwrite (bp); 746 747 hp->h_flag &= ~H_CHANGE; 748 749 if (hp->h_flag & H_PARCHANGE) 750 return (hpfs_updateparent(hp)); 751 752 return (0); 753} 754 755/* 756 * Truncate file to specifed size. hpfsnode have to be locked. 757 */ 758int 759hpfs_truncate ( 760 struct hpfsnode *hp, 761 u_long size) 762{ 763 struct hpfsmount *hpmp = hp->h_hpmp; 764 lsn_t newblen, oldblen; 765 int error, pf; 766 767 dprintf(("hpfs_truncate(0x%x, 0x%x -> 0x%lx): ", 768 hp->h_no, hp->h_fn.fn_size, size)); 769 770 newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT; 771 oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT; 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 */ 797int 798hpfs_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 printf("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 */ 836int 837hpfs_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, lsn, len, NOCRED, &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 printf("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