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