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