1 //////////////////////////////////////////////////////////////////// 2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine 3 // All rights reserved 4 // This file was released under the GPLv2 on June 2015. 5 //////////////////////////////////////////////////////////////////// 6 /* 7 Module name: 8 9 extent.cpp 10 11 Abstract: 12 13 This file contains filesystem-specific routines 14 responsible for extent & mapping management 15 16 */ 17 18 #include "udf.h" 19 20 #define UDF_BUG_CHECK_ID UDF_FILE_UDF_INFO_EXTENT 21 22 /* 23 This routine converts offset in extent to Lba & returns offset in the 1st 24 sector & bytes before end of block. 25 Here we assume no references to AllocDescs 26 */ 27 uint32 28 UDFExtentOffsetToLba( 29 IN PVCB Vcb, 30 IN PEXTENT_MAP Extent, // Extent array 31 IN int64 Offset, // offset in extent 32 OUT uint32* SectorOffset, 33 OUT uint32* AvailLength, // available data in this block 34 OUT uint32* Flags, 35 OUT uint32* Index 36 ) 37 { 38 uint32 j=0, l, d, BSh = Vcb->BlockSizeBits; 39 uint32 Offs; 40 uint32 i=0, BOffset; // block nums 41 42 BOffset = (uint32)(Offset >> BSh); 43 // scan extent table for suitable range (frag) 44 ExtPrint(("ExtLen %x\n", Extent->extLength)); 45 while(i+(d = (l = (Extent->extLength & UDF_EXTENT_LENGTH_MASK)) >> BSh) <= BOffset) { 46 47 if(!l) { 48 if(Index) (*Index) = j-1; 49 if(Flags) { 50 Extent--; 51 (*Flags) = (Extent->extLength >> 30); 52 } 53 return LBA_OUT_OF_EXTENT; 54 } 55 if(!d) 56 break; 57 i += d; //frag offset 58 j++; // frag index 59 Extent++; 60 } 61 BOffset -= i; 62 Offs = (*((uint32*)&Offset)) - (i << BSh); // offset in frag 63 64 if(SectorOffset) 65 (*SectorOffset) = Offs & (Vcb->BlockSize-1);// offset in 1st Lba 66 if(AvailLength) 67 (*AvailLength) = l - Offs;// bytes to EO frag 68 if(Flags) 69 (*Flags) = (Extent->extLength >> 30); 70 if(Index) 71 (*Index) = j; 72 73 ASSERT(((Extent->extLength >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED) || Extent->extLocation); 74 75 return Extent->extLocation + BOffset;// 1st Lba 76 } // end UDFExtentOffsetToLba() 77 78 uint32 79 UDFNextExtentToLba( 80 IN PVCB Vcb, 81 IN PEXTENT_MAP Extent, // Extent array 82 OUT uint32* AvailLength, // available data in this block 83 OUT uint32* Flags, 84 OUT uint32* Index 85 ) 86 { 87 // uint32 Lba; 88 89 uint32 l; 90 // uint32 d; 91 92 // scan extent table for suitable range (frag) 93 // d = (l = (Extent->extLength & UDF_EXTENT_LENGTH_MASK)); 94 l = (Extent->extLength & UDF_EXTENT_LENGTH_MASK); 95 96 if(!l) { 97 (*Index) = -1; 98 Extent--; 99 (*Flags) = (Extent->extLength >> 30); 100 return LBA_OUT_OF_EXTENT; 101 } 102 103 (*Index) = 0; 104 (*AvailLength) = l;// bytes to EO frag 105 (*Flags) = (Extent->extLength >> 30); 106 107 ASSERT(((*Flags) == EXTENT_NOT_RECORDED_NOT_ALLOCATED) || Extent->extLocation); 108 109 return Extent->extLocation;// 1st Lba 110 } // end UDFNextExtentToLba() 111 112 /* 113 This routine locates frag containing specified Lba in extent 114 */ 115 ULONG 116 UDFLocateLbaInExtent( 117 IN PVCB Vcb, 118 IN PEXTENT_MAP Extent, // Extent array 119 IN lba_t lba 120 ) 121 { 122 uint32 l, BSh = Vcb->BlockSizeBits; 123 uint32 i=0; 124 125 while((l = ((Extent->extLength & UDF_EXTENT_LENGTH_MASK) >> BSh))) { 126 127 if(Extent->extLocation >= lba && 128 Extent->extLocation+l < lba) { 129 return i; 130 } 131 i++; //frag offset 132 Extent++; 133 } 134 return LBA_OUT_OF_EXTENT;// index of item in extent, containing out Lba 135 } // end UDFLocateLbaInExtent() 136 137 /* 138 This routine calculates total length of specified extent. 139 Here we assume no references to AllocDescs 140 */ 141 int64 142 UDFGetExtentLength( 143 IN PEXTENT_MAP Extent // Extent array 144 ) 145 { 146 if(!Extent) return 0; 147 int64 i=0; 148 149 #if defined(_X86_) && defined(_MSC_VER) && !defined(__clang__) 150 151 __asm push ebx 152 __asm push ecx 153 __asm push esi 154 155 __asm lea ebx,i 156 __asm mov esi,Extent 157 __asm xor ecx,ecx 158 While_1: 159 __asm mov eax,[esi+ecx*8] // Extent[j].extLength 160 __asm and eax,UDF_EXTENT_LENGTH_MASK 161 __asm jz EO_While 162 __asm add [ebx],eax 163 __asm adc [ebx+4],0 164 __asm inc ecx 165 __asm jmp While_1 166 EO_While:; 167 __asm pop esi 168 __asm pop ecx 169 __asm pop ebx 170 171 #else // NO X86 optimization , use generic C/C++ 172 173 while(Extent->extLength) { 174 i += (Extent->extLength & UDF_EXTENT_LENGTH_MASK); 175 Extent++; 176 } 177 178 #endif // _X86_ 179 180 return i; 181 } // UDFGetExtentLength() 182 183 /* 184 This routine appends Zero-terminator to single Extent-entry. 185 Such operation makes it compatible with other internal routines 186 */ 187 PEXTENT_MAP 188 __fastcall 189 UDFExtentToMapping_( 190 IN PEXTENT_AD Extent 191 #ifdef UDF_TRACK_EXTENT_TO_MAPPING 192 ,IN ULONG src, 193 IN ULONG line 194 #endif //UDF_TRACK_EXTENT_TO_MAPPING 195 ) 196 { 197 PEXTENT_MAP Map; 198 199 #ifdef UDF_TRACK_EXTENT_TO_MAPPING 200 #define UDF_EXT_MAP_MULT 4 201 #else //UDF_TRACK_EXTENT_TO_MAPPING 202 #define UDF_EXT_MAP_MULT 2 203 #endif //UDF_TRACK_EXTENT_TO_MAPPING 204 205 Map = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool , UDF_EXT_MAP_MULT * 206 sizeof(EXTENT_MAP), MEM_EXTMAP_TAG); 207 if(!Map) return NULL; 208 RtlZeroMemory((int8*)(Map+1), sizeof(EXTENT_MAP)); 209 Map[0].extLength = Extent->extLength; 210 Map[0].extLocation = Extent->extLocation; 211 #ifdef UDF_TRACK_EXTENT_TO_MAPPING 212 Map[2].extLength = src; 213 Map[2].extLocation = line; 214 #endif //UDF_TRACK_EXTENT_TO_MAPPING 215 return Map; 216 } // end UDFExtentToMapping() 217 218 /* 219 This routine calculates file mapping length (in bytes) including 220 ZERO-terminator 221 */ 222 uint32 223 UDFGetMappingLength( 224 IN PEXTENT_MAP Extent 225 ) 226 { 227 if(!Extent) return 0; 228 uint32 i=0; 229 230 #if defined(_X86_) && defined(_MSC_VER) && !defined(__clang__) 231 __asm push ebx 232 233 __asm mov ebx,Extent 234 __asm xor eax,eax 235 While_1: 236 __asm mov ecx,[ebx+eax*8] 237 __asm jecxz EO_While 238 __asm inc eax 239 __asm jmp While_1 240 EO_While: 241 __asm inc eax 242 __asm shl eax,3 243 __asm mov i,eax 244 245 __asm pop ebx 246 247 #else // NO X86 optimization , use generic C/C++ 248 249 while(Extent->extLength) { 250 i++; 251 Extent++; 252 } 253 i++; 254 i*=sizeof(EXTENT_MAP); 255 256 #endif // _X86_ 257 258 return i; // i*sizeof(EXTENT_MAP) 259 } // end UDFGetMappingLength() 260 261 /* 262 This routine merges 2 sequencial file mappings 263 */ 264 PEXTENT_MAP 265 __fastcall 266 UDFMergeMappings( 267 IN PEXTENT_MAP Extent, 268 IN PEXTENT_MAP Extent2 269 ) 270 { 271 PEXTENT_MAP NewExt; 272 uint32 len, len2; 273 274 len = UDFGetMappingLength(Extent); 275 len2 = UDFGetMappingLength(Extent2); 276 ASSERT(len2 && len); 277 if(!len2) { 278 return Extent; 279 } 280 if(MyReallocPool__((int8*)Extent, len, (int8**)(&NewExt), len+len2-sizeof(EXTENT_MAP))) { 281 RtlCopyMemory(((int8*)NewExt)+len-sizeof(EXTENT_MAP), (int8*)Extent2, len2); 282 } else { 283 ExtPrint(("UDFMergeMappings failed\n")); 284 BrutePoint(); 285 } 286 return NewExt; 287 } // end UDFMergeMappings() 288 289 /* 290 This routine builds file mapping according to ShortAllocDesc (SHORT_AD) 291 array 292 */ 293 PEXTENT_MAP 294 UDFShortAllocDescToMapping( 295 IN PVCB Vcb, 296 IN uint32 PartNum, 297 IN PSHORT_AD AllocDesc, 298 IN uint32 AllocDescLength, 299 IN uint32 SubCallCount, 300 OUT PEXTENT_INFO AllocLoc 301 ) 302 { 303 uint32 i, lim, l, len, type; 304 // uint32 BSh; 305 PEXTENT_MAP Extent, Extent2, AllocMap; 306 EXTENT_AD AllocExt; 307 PALLOC_EXT_DESC NextAllocDesc; 308 lb_addr locAddr; 309 uint32 ReadBytes; 310 EXTENT_INFO NextAllocLoc; 311 BOOLEAN w2k_compat = FALSE; 312 313 ExtPrint(("UDFShortAllocDescToMapping: len=%x\n", AllocDescLength)); 314 315 if(SubCallCount > ALLOC_DESC_MAX_RECURSE) return NULL; 316 317 locAddr.partitionReferenceNum = (uint16)PartNum; 318 // BSh = Vcb->BlockSizeBits; 319 l = ((lim = (AllocDescLength/sizeof(SHORT_AD))) + 1 ) * sizeof(EXTENT_AD); 320 Extent = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool, l, MEM_EXTMAP_TAG); 321 if(!Extent) return NULL; 322 323 NextAllocLoc.Offset = 0; 324 325 for(i=0;i<lim;i++) { 326 type = AllocDesc[i].extLength >> 30; 327 len = AllocDesc[i].extLength & UDF_EXTENT_LENGTH_MASK; 328 ExtPrint(("ShExt: type %x, loc %x, len %x\n", type, AllocDesc[i].extPosition, len)); 329 if(type == EXTENT_NEXT_EXTENT_ALLOCDESC) { 330 // read next frag of allocation descriptors if encountered 331 if(len < sizeof(ALLOC_EXT_DESC)) { 332 MyFreePool__(Extent); 333 return NULL; 334 } 335 NextAllocDesc = (PALLOC_EXT_DESC)MyAllocatePoolTag__(NonPagedPool, len, MEM_ALLOCDESC_TAG); 336 if(!NextAllocDesc) { 337 MyFreePool__(Extent); 338 return NULL; 339 } 340 // record information about this frag 341 locAddr.logicalBlockNum = AllocDesc[i].extPosition; 342 AllocExt.extLength = len; 343 AllocExt.extLocation = UDFPartLbaToPhys(Vcb, &locAddr); 344 if(AllocExt.extLocation == LBA_OUT_OF_EXTENT) { 345 UDFPrint(("bad address\n")); 346 MyFreePool__(NextAllocDesc); 347 MyFreePool__(Extent); 348 return NULL; 349 } 350 NextAllocLoc.Mapping = 351 AllocMap = UDFExtentToMapping(&AllocExt); 352 NextAllocLoc.Length = len; 353 if(!AllocMap) { 354 MyFreePool__(NextAllocDesc); 355 MyFreePool__(Extent); 356 return NULL; 357 } 358 AllocLoc->Mapping = UDFMergeMappings(AllocLoc->Mapping, AllocMap); 359 if(!AllocLoc->Mapping || 360 // read this frag 361 !OS_SUCCESS(UDFReadExtent(Vcb, &NextAllocLoc, 362 0, len, FALSE, (int8*)NextAllocDesc, &ReadBytes))) 363 { 364 MyFreePool__(AllocMap); 365 MyFreePool__(NextAllocDesc); 366 MyFreePool__(Extent); 367 return NULL; 368 } 369 MyFreePool__(AllocMap); 370 // check integrity 371 if((NextAllocDesc->descTag.tagIdent != TID_ALLOC_EXTENT_DESC) || 372 (NextAllocDesc->lengthAllocDescs > (len - sizeof(ALLOC_EXT_DESC))) ) { 373 UDFPrint(("Integrity check failed\n")); 374 UDFPrint(("NextAllocDesc->descTag.tagIdent = %x\n", NextAllocDesc->descTag.tagIdent)); 375 UDFPrint(("NextAllocDesc->lengthAllocDescs = %x\n", NextAllocDesc->lengthAllocDescs)); 376 UDFPrint(("len = %x\n", len)); 377 MyFreePool__(NextAllocDesc); 378 MyFreePool__(Extent); 379 return NULL; 380 } 381 // perform recursive call to obtain mapping 382 NextAllocLoc.Flags = 0; 383 Extent2 = UDFShortAllocDescToMapping(Vcb, PartNum, (PSHORT_AD)(NextAllocDesc+1), 384 NextAllocDesc->lengthAllocDescs, SubCallCount+1, AllocLoc); 385 if(!Extent2) { 386 MyFreePool__(NextAllocDesc); 387 MyFreePool__(Extent); 388 return NULL; 389 } 390 UDFCheckSpaceAllocation(Vcb, 0, Extent2, AS_USED); // check if used 391 // and merge this 2 mappings into 1 392 Extent[i].extLength = 0; 393 Extent[i].extLocation = 0; 394 Extent = UDFMergeMappings(Extent, Extent2); 395 396 if(NextAllocLoc.Flags & EXTENT_FLAG_2K_COMPAT) { 397 ExtPrint(("w2k-compat\n")); 398 AllocLoc->Flags |= EXTENT_FLAG_2K_COMPAT; 399 } 400 401 MyFreePool__(Extent2); 402 return Extent; 403 } 404 // 405 #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT 406 ASSERT(!(len & (Vcb->LBlockSize-1) )); 407 #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT 408 if(len & (Vcb->LBlockSize-1)) { 409 w2k_compat = TRUE; 410 } 411 Extent[i].extLength = (len+Vcb->LBlockSize-1) & ~(Vcb->LBlockSize-1); 412 locAddr.logicalBlockNum = AllocDesc[i].extPosition; 413 // Note: for compatibility Adaptec DirectCD we check 'len' here 414 // That strange implementation records bogus extLocation in terminal entries 415 if(type != EXTENT_NOT_RECORDED_NOT_ALLOCATED && len) { 416 Extent[i].extLocation = UDFPartLbaToPhys(Vcb, &locAddr); 417 if(Extent[i].extLocation == LBA_OUT_OF_EXTENT) { 418 UDFPrint(("bad address (2)\n")); 419 MyFreePool__(Extent); 420 return NULL; 421 } 422 } else { 423 Extent[i].extLocation = 0; 424 } 425 if(!len) { 426 // some UDF implementations set strange AllocDesc sequence length, 427 // but terminates it with zeros in proper place, so handle 428 // this case 429 ASSERT(i>=(lim-1)); 430 ASSERT(!Extent[i].extLength); 431 Extent[i].extLocation = 0; 432 if(/*!SubCallCount &&*/ w2k_compat) { 433 ExtPrint(("w2k-compat\n")); 434 AllocLoc->Flags |= EXTENT_FLAG_2K_COMPAT; 435 } 436 return Extent; 437 } 438 Extent[i].extLength |= (type << 30); 439 } 440 // set terminator 441 Extent[i].extLength = 0; 442 Extent[i].extLocation = 0; 443 444 if(/*!SubCallCount &&*/ w2k_compat) { 445 ExtPrint(("w2k-compat\n")); 446 AllocLoc->Flags |= EXTENT_FLAG_2K_COMPAT; 447 } 448 449 return Extent; 450 } // end UDFShortAllocDescToMapping() 451 452 /* 453 This routine builds file mapping according to LongAllocDesc (LONG_AD) 454 array 455 */ 456 PEXTENT_MAP 457 UDFLongAllocDescToMapping( 458 IN PVCB Vcb, 459 IN PLONG_AD AllocDesc, 460 IN uint32 AllocDescLength, 461 IN uint32 SubCallCount, 462 OUT PEXTENT_INFO AllocLoc // .Mapping must be intialized (non-Zero) 463 ) 464 { 465 uint32 i, lim, l, len, type; 466 // uint32 BSh; 467 PEXTENT_MAP Extent, Extent2, AllocMap; 468 EXTENT_AD AllocExt; 469 PALLOC_EXT_DESC NextAllocDesc; 470 uint32 ReadBytes; 471 EXTENT_INFO NextAllocLoc; 472 473 ExtPrint(("UDFLongAllocDescToMapping: len=%x\n", AllocDescLength)); 474 475 if(SubCallCount > ALLOC_DESC_MAX_RECURSE) return NULL; 476 477 // BSh = Vcb->BlockSizeBits; 478 l = ((lim = (AllocDescLength/sizeof(LONG_AD))) + 1 ) * sizeof(EXTENT_AD); 479 Extent = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool, l, MEM_EXTMAP_TAG); 480 if(!Extent) return NULL; 481 482 NextAllocLoc.Offset = 0; 483 484 for(i=0;i<lim;i++) { 485 type = AllocDesc[i].extLength >> 30; 486 len = AllocDesc[i].extLength & UDF_EXTENT_LENGTH_MASK; 487 ExtPrint(("LnExt: type %x, loc %x (%x:%x), len %x\n", type, UDFPartLbaToPhys(Vcb,&(AllocDesc[i].extLocation)), 488 AllocDesc[i].extLocation.partitionReferenceNum, AllocDesc[i].extLocation.logicalBlockNum, 489 len)); 490 if(type == EXTENT_NEXT_EXTENT_ALLOCDESC) { 491 // read next frag of allocation descriptors if encountered 492 if(len < sizeof(ALLOC_EXT_DESC)) { 493 MyFreePool__(Extent); 494 return NULL; 495 } 496 NextAllocDesc = (PALLOC_EXT_DESC)MyAllocatePoolTag__(NonPagedPool, len, MEM_ALLOCDESC_TAG); 497 if(!NextAllocDesc) { 498 MyFreePool__(Extent); 499 return NULL; 500 } 501 // record information about this frag 502 AllocExt.extLength = len; 503 AllocExt.extLocation = UDFPartLbaToPhys(Vcb,&(AllocDesc[i].extLocation)); 504 if(AllocExt.extLocation == LBA_OUT_OF_EXTENT) { 505 UDFPrint(("bad address\n")); 506 MyFreePool__(NextAllocDesc); 507 MyFreePool__(Extent); 508 return NULL; 509 } 510 NextAllocLoc.Mapping = 511 AllocMap = UDFExtentToMapping(&AllocExt); 512 NextAllocLoc.Length = len; 513 if(!AllocMap) { 514 MyFreePool__(NextAllocDesc); 515 MyFreePool__(Extent); 516 return NULL; 517 } 518 AllocLoc->Mapping = UDFMergeMappings(AllocLoc->Mapping, AllocMap); 519 if(!AllocLoc->Mapping || 520 // read this frag 521 !OS_SUCCESS(UDFReadExtent(Vcb, &NextAllocLoc, 522 0, len, FALSE, (int8*)NextAllocDesc, &ReadBytes))) 523 { 524 MyFreePool__(AllocMap); 525 MyFreePool__(NextAllocDesc); 526 MyFreePool__(Extent); 527 return NULL; 528 } 529 MyFreePool__(AllocMap); 530 // check integrity 531 if((NextAllocDesc->descTag.tagIdent != TID_ALLOC_EXTENT_DESC) || 532 (NextAllocDesc->lengthAllocDescs > (len - sizeof(ALLOC_EXT_DESC))) ) { 533 UDFPrint(("Integrity check failed\n")); 534 UDFPrint(("NextAllocDesc->descTag.tagIdent = %x\n", NextAllocDesc->descTag.tagIdent)); 535 UDFPrint(("NextAllocDesc->lengthAllocDescs = %x\n", NextAllocDesc->lengthAllocDescs)); 536 UDFPrint(("len = %x\n", len)); 537 MyFreePool__(NextAllocDesc); 538 MyFreePool__(Extent); 539 return NULL; 540 } 541 // perform recursive call to obtain mapping 542 Extent2 = UDFLongAllocDescToMapping(Vcb, (PLONG_AD)(NextAllocDesc+1), 543 NextAllocDesc->lengthAllocDescs, SubCallCount+1, AllocLoc); 544 if(!Extent2) { 545 MyFreePool__(NextAllocDesc); 546 MyFreePool__(Extent); 547 return NULL; 548 } 549 // and merge this 2 mappings into 1 550 Extent[i].extLength = 0; 551 Extent[i].extLocation = 0; 552 Extent = UDFMergeMappings(Extent, Extent2); 553 MyFreePool__(Extent2); 554 return Extent; 555 } 556 // 557 Extent[i].extLength = len; 558 #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT 559 ASSERT(!(len & (Vcb->LBlockSize-1) )); 560 #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT 561 Extent[i].extLength = (len+Vcb->LBlockSize-1) & ~(Vcb->LBlockSize-1); 562 // Note: for compatibility Adaptec DirectCD we check 'len' here 563 // That strange implementation records bogus extLocation in terminal entries 564 if(type != EXTENT_NOT_RECORDED_NOT_ALLOCATED && len) { 565 Extent[i].extLocation = UDFPartLbaToPhys(Vcb,&(AllocDesc[i].extLocation)); 566 if(Extent[i].extLocation == LBA_OUT_OF_EXTENT) { 567 UDFPrint(("bad address (2)\n")); 568 MyFreePool__(Extent); 569 return NULL; 570 } 571 } else { 572 Extent[i].extLocation = 0; 573 } 574 if(!len) { 575 // some UDF implementations set strange AllocDesc sequence length, 576 // but terminates it with zeros in proper place, so handle 577 // this case 578 Extent[i].extLocation = 0; 579 return Extent; 580 } 581 Extent[i].extLength |= (type << 30); 582 } 583 // set terminator 584 Extent[i].extLength = 0; 585 Extent[i].extLocation = 0; 586 587 return Extent; 588 } // end UDFLongAllocDescToMapping() 589 590 /* 591 This routine builds file mapping according to ExtendedAllocDesc (EXT_AD) 592 array 593 */ 594 PEXTENT_MAP 595 UDFExtAllocDescToMapping( 596 IN PVCB Vcb, 597 IN PEXT_AD AllocDesc, 598 IN uint32 AllocDescLength, 599 IN uint32 SubCallCount, 600 OUT PEXTENT_INFO AllocLoc // .Mapping must be intialized (non-Zero) 601 ) 602 { 603 uint32 i, lim, l, len, type; 604 // uint32 BSh; 605 PEXTENT_MAP Extent, Extent2, AllocMap; 606 EXTENT_AD AllocExt; 607 PALLOC_EXT_DESC NextAllocDesc; 608 uint32 ReadBytes; 609 EXTENT_INFO NextAllocLoc; 610 611 ExtPrint(("UDFExtAllocDescToMapping: len=%x\n", AllocDescLength)); 612 613 if(SubCallCount > ALLOC_DESC_MAX_RECURSE) return NULL; 614 615 // BSh = Vcb->BlockSizeBits; 616 l = ((lim = (AllocDescLength/sizeof(EXT_AD))) + 1 ) * sizeof(EXTENT_AD); 617 Extent = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool, l, MEM_EXTMAP_TAG); 618 if(!Extent) return NULL; 619 620 NextAllocLoc.Offset = 0; 621 622 for(i=0;i<lim;i++) { 623 type = AllocDesc[i].extLength >> 30; 624 len = AllocDesc[i].extLength & UDF_EXTENT_LENGTH_MASK; 625 ExtPrint(("ExExt: type %x, loc %x, len %x\n", type, UDFPartLbaToPhys(Vcb,&(AllocDesc[i].extLocation)), len)); 626 if(type == EXTENT_NEXT_EXTENT_ALLOCDESC) { 627 // read next frag of allocation descriptors if encountered 628 if(len < sizeof(ALLOC_EXT_DESC)) { 629 MyFreePool__(Extent); 630 return NULL; 631 } 632 NextAllocDesc = (PALLOC_EXT_DESC)MyAllocatePoolTag__(NonPagedPool, len, MEM_ALLOCDESC_TAG); 633 if(!NextAllocDesc) { 634 MyFreePool__(Extent); 635 return NULL; 636 } 637 // record information about this frag 638 AllocExt.extLength = len; 639 AllocExt.extLocation = UDFPartLbaToPhys(Vcb,&(AllocDesc[i].extLocation)); 640 if(AllocExt.extLocation == LBA_OUT_OF_EXTENT) { 641 UDFPrint(("bad address\n")); 642 MyFreePool__(NextAllocDesc); 643 MyFreePool__(Extent); 644 return NULL; 645 } 646 NextAllocLoc.Mapping = 647 AllocMap = UDFExtentToMapping(&AllocExt); 648 NextAllocLoc.Length = len; 649 if(!AllocMap) { 650 MyFreePool__(NextAllocDesc); 651 MyFreePool__(Extent); 652 return NULL; 653 } 654 AllocLoc->Mapping = UDFMergeMappings(AllocLoc->Mapping, AllocMap); 655 if(!AllocLoc->Mapping || 656 // read this frag 657 !OS_SUCCESS(UDFReadExtent(Vcb, &NextAllocLoc, 658 0, len, FALSE, (int8*)NextAllocDesc, &ReadBytes))) 659 { 660 MyFreePool__(AllocMap); 661 MyFreePool__(NextAllocDesc); 662 MyFreePool__(Extent); 663 return NULL; 664 } 665 MyFreePool__(AllocMap); 666 // check integrity 667 if((NextAllocDesc->descTag.tagIdent != TID_ALLOC_EXTENT_DESC) || 668 (NextAllocDesc->lengthAllocDescs > (len - sizeof(ALLOC_EXT_DESC))) ) { 669 UDFPrint(("Integrity check failed\n")); 670 MyFreePool__(NextAllocDesc); 671 MyFreePool__(Extent); 672 return NULL; 673 } 674 // perform recursive call to obtain mapping 675 Extent2 = UDFExtAllocDescToMapping(Vcb, (PEXT_AD)(NextAllocDesc+1), 676 NextAllocDesc->lengthAllocDescs, SubCallCount+1, AllocLoc); 677 if(!Extent2) { 678 MyFreePool__(NextAllocDesc); 679 MyFreePool__(Extent); 680 return NULL; 681 } 682 // and merge this 2 mappings into 1 683 Extent[i].extLength = 0; 684 Extent[i].extLocation = 0; 685 Extent = UDFMergeMappings(Extent, Extent2); 686 MyFreePool__(Extent2); 687 return Extent; 688 } 689 /* if((AllocDesc[i].extLength & UDF_EXTENT_LENGTH_MASK) > // Uncomment!!! 690 (AllocDesc[i].recordedLength & UDF_EXTENT_LENGTH_MASK)) { 691 Extent[i].extLength = AllocDesc[i].recordedLength; 692 Extent[i].extLocation = UDFPartLbaToPhys(Vcb,&(AllocDesc[i].extLocation)); 693 }*/ 694 Extent[i].extLength = len; 695 #ifdef UDF_CHECK_EXTENT_SIZE_ALIGNMENT 696 ASSERT(!(len & (Vcb->LBlockSize-1) )); 697 #endif //UDF_CHECK_EXTENT_SIZE_ALIGNMENT 698 // Note: for compatibility Adaptec DirectCD we check 'len' here 699 // That strange implementation records bogus extLocation in terminal entries 700 if(type != EXTENT_NOT_RECORDED_NOT_ALLOCATED && len) { 701 Extent[i].extLocation = UDFPartLbaToPhys(Vcb,&(AllocDesc[i].extLocation)); 702 if(Extent[i].extLocation == LBA_OUT_OF_EXTENT) { 703 UDFPrint(("bad address (2)\n")); 704 MyFreePool__(Extent); 705 return NULL; 706 } 707 } else { 708 Extent[i].extLocation = 0; 709 } 710 if(!len) { 711 // some UDF implementations set strange AllocDesc sequence length, 712 // but terminates it with zeros in proper place, so handle 713 // this case 714 Extent[i].extLocation = 0; 715 return Extent; 716 } 717 Extent[i].extLength |= (type << 30); 718 } 719 // set terminator 720 Extent[i].extLength = 0; 721 Extent[i].extLocation = 0; 722 723 return Extent; 724 } // end UDFExtAllocDescToMapping() 725 726 727 /* 728 This routine builds FileMapping according to given FileEntry 729 Return: pointer to EXTENT_MAP array 730 or offset inside FileEntry (negative) 731 when ICB_FLAG_AD_IN_ICB encountered 732 of NULL if an error occured 733 */ 734 PEXTENT_MAP 735 UDFReadMappingFromXEntry( 736 IN PVCB Vcb, 737 IN uint32 PartNum, 738 IN tag* XEntry, 739 IN OUT uint32* Offset, 740 OUT PEXTENT_INFO AllocLoc // .Mapping must be intialized (non-Zero) 741 ) 742 { 743 PEXTENT_AD Extent; 744 uint16 AllocMode; 745 int8* AllocDescs; 746 uint32 len; 747 // EntityID* eID; // for compatibility with Adaptec DirectCD 748 749 Extent = NULL; 750 (*Offset) = 0; 751 752 753 if(XEntry->tagIdent == TID_FILE_ENTRY) { 754 // UDFPrint(("Standard FileEntry\n")); 755 PFILE_ENTRY FileEntry = (PFILE_ENTRY)XEntry; 756 ExtPrint(("Standard FileEntry\n")); 757 758 AllocDescs = (int8*)(((int8*)(FileEntry+1))+(FileEntry->lengthExtendedAttr)); 759 len = FileEntry->lengthAllocDescs; 760 AllocLoc->Offset = sizeof(FILE_ENTRY) + FileEntry->lengthExtendedAttr; 761 // eID = &(FileEntry->impIdent); 762 763 AllocMode = FileEntry->icbTag.flags & ICB_FLAG_ALLOC_MASK; 764 765 } else if(XEntry->tagIdent == TID_EXTENDED_FILE_ENTRY) { 766 // UDFPrint(("Extended FileEntry\n")); 767 ExtPrint(("Extended FileEntry\n")); 768 PEXTENDED_FILE_ENTRY ExFileEntry = (PEXTENDED_FILE_ENTRY)XEntry; 769 770 AllocDescs = (((int8*)(ExFileEntry+1))+(ExFileEntry->lengthExtendedAttr)); 771 len = ExFileEntry->lengthAllocDescs; 772 AllocLoc->Offset = sizeof(EXTENDED_FILE_ENTRY) + ExFileEntry->lengthExtendedAttr; 773 // eID = &(FileEntry->impIdent); 774 775 AllocMode = ExFileEntry->icbTag.flags & ICB_FLAG_ALLOC_MASK; 776 777 } else { 778 return NULL; 779 } 780 781 // for compatibility with Adaptec DirectCD 782 // if(!(Vcb->UDF_VCB_IC_ADAPTEC_NONALLOC_COMPAT)) 783 784 AllocLoc->Length=len; 785 AllocLoc->Flags |= EXTENT_FLAG_VERIFY; // for metadata 786 787 switch (AllocMode) { 788 case ICB_FLAG_AD_SHORT: { 789 Extent = UDFShortAllocDescToMapping(Vcb, PartNum, (PSHORT_AD)AllocDescs, len, 0, AllocLoc); 790 break; 791 } 792 case ICB_FLAG_AD_LONG: { 793 Extent = UDFLongAllocDescToMapping(Vcb, (PLONG_AD)AllocDescs, len, 0, AllocLoc); 794 break; 795 } 796 case ICB_FLAG_AD_EXTENDED: { 797 Extent = UDFExtAllocDescToMapping(Vcb, (PEXT_AD)AllocDescs, len, 0, AllocLoc); 798 break; 799 } 800 default : { // case ICB_FLAG_AD_IN_ICB 801 Extent = NULL; 802 *Offset = (uint32)AllocDescs - (uint32)XEntry; 803 AllocLoc->Offset=0; 804 AllocLoc->Length=0; 805 if(AllocLoc->Mapping) MyFreePool__(AllocLoc->Mapping); 806 AllocLoc->Mapping=NULL; 807 break; 808 } 809 } 810 811 ExtPrint(("UDFReadMappingFromXEntry: mode %x, loc %x, len %x\n", AllocMode, 812 AllocLoc->Mapping ? AllocLoc->Mapping[0].extLocation : -1, len)); 813 814 UDFCheckSpaceAllocation(Vcb, 0, Extent, AS_USED); // check if used 815 816 return Extent; 817 }// end UDFReadMappingFromXEntry() 818 819 #ifndef UDF_READ_ONLY_BUILD 820 /* 821 This routine builds data for AllocDesc sequence for specified 822 extent 823 */ 824 OSSTATUS 825 UDFBuildShortAllocDescs( 826 IN PVCB Vcb, 827 IN uint32 PartNum, 828 OUT int8** Buff, // data for AllocLoc 829 IN uint32 InitSz, 830 IN OUT PUDF_FILE_INFO FileInfo 831 ) 832 { 833 uint32 i, j; 834 uint32 len=0; 835 PEXTENT_MAP Extent = FileInfo->Dloc->DataLoc.Mapping; 836 PEXTENT_INFO AllocExtent = &(FileInfo->Dloc->AllocLoc); 837 PSHORT_AD Alloc; 838 uint32 NewLen; 839 OSSTATUS status; 840 uint32 ph_len=0; // in general, this should be uint64, 841 // but we need its lower part only 842 #ifdef UDF_ALLOW_FRAG_AD 843 uint32 ts, ac, len2; 844 uint32 LBS = Vcb->LBlockSize; 845 uint32 LBSh = Vcb->BlockSizeBits; 846 uint32 TagLen = 0; 847 tag* Tag = NULL; 848 PSHORT_AD saved_Alloc; 849 uint32 TagLoc, prevTagLoc; 850 uint32 BufOffs; 851 uint32 ExtOffs; 852 uint32 saved_NewLen; 853 #endif //UDF_ALLOW_FRAG_AD 854 855 ValidateFileInfo(FileInfo); 856 ExtPrint(("UDFBuildShortAllocDescs: FE %x\n", FileInfo->Dloc->FELoc.Mapping[0].extLocation)); 857 // calculate length 858 for(len=0; (i=(Extent[len].extLength & UDF_EXTENT_LENGTH_MASK)); len++, ph_len+=i) { 859 ExtPrint(("bShExt: type %x, loc %x, len %x\n", 860 Extent[len].extLength >> 30, Extent[len].extLocation, Extent[len].extLength & UDF_EXTENT_LENGTH_MASK)); 861 } 862 Alloc = (PSHORT_AD)MyAllocatePoolTag__(NonPagedPool, (len+1)*sizeof(SHORT_AD), MEM_SHAD_TAG); 863 if(!Alloc) { 864 BrutePoint(); 865 return STATUS_INSUFFICIENT_RESOURCES; 866 } 867 // fill contiguous AllocDesc buffer (decribing UserData) 868 for(i=0;i<len;i++) { 869 Alloc[i].extLength = Extent[i].extLength; 870 Alloc[i].extPosition = UDFPhysLbaToPart(Vcb, PartNum, Extent[i].extLocation); 871 } 872 if((Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) && i) { 873 Alloc[i-1].extLength -= (ph_len - (ULONG)(FileInfo->Dloc->DataLoc.Length)) & 874 (Vcb->LBlockSize-1); 875 ExtPrint(("bShExt: cut tail -> %x\n", 876 Alloc[i-1].extLength & UDF_EXTENT_LENGTH_MASK)); 877 } 878 Alloc[i].extLength = 879 Alloc[i].extPosition = 0; 880 j = len*sizeof(SHORT_AD); // required space 881 len = (InitSz & ~(sizeof(SHORT_AD)-1)); // space available in 1st block 882 ASSERT(len == InitSz); 883 884 // Ok. Let's init AllocLoc 885 if(!(FileInfo->Dloc->AllocLoc.Mapping)) { 886 FileInfo->Dloc->AllocLoc.Mapping = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool, 2 * sizeof(EXTENT_MAP), MEM_EXTMAP_TAG); 887 if(!(FileInfo->Dloc->AllocLoc.Mapping)) { 888 BrutePoint(); 889 MyFreePool__(Alloc); 890 return STATUS_INSUFFICIENT_RESOURCES; 891 } 892 // allocation descriptors are located in the same sector as FileEntry 893 // (at least their 1st part), just after it 894 FileInfo->Dloc->AllocLoc.Mapping[0] = FileInfo->Dloc->FELoc.Mapping[0]; 895 FileInfo->Dloc->AllocLoc.Offset = FileInfo->Dloc->FileEntryLen; 896 FileInfo->Dloc->AllocLoc.Length = 0; 897 // set terminator 898 FileInfo->Dloc->AllocLoc.Mapping[1].extLength = 899 FileInfo->Dloc->AllocLoc.Mapping[1].extLocation = 0; 900 } 901 902 if(j <= len) { 903 // we needn't allocating additional blocks to store AllocDescs 904 AdPrint(("in-ICB AllocDescs, j=%x\n",j)); 905 RtlCopyMemory(*Buff, (int8*)Alloc, j); 906 NewLen = j; 907 MyFreePool__(Alloc); 908 } else { 909 #ifndef UDF_ALLOW_FRAG_AD 910 AdPrint((" DISK_FULL\n")); 911 return STATUS_DISK_FULL; 912 #else //UDF_ALLOW_FRAG_AD 913 AdPrint(("multi-block AllocDescs, j=%x\n",j)); 914 BufOffs = 0; 915 TagLoc = prevTagLoc = 0; 916 // calculate the space available for SHORT_ADs in each block 917 ac = (LBS - (sizeof(ALLOC_EXT_DESC) + sizeof(SHORT_AD))) & ~(sizeof(SHORT_AD)-1); 918 len2 = len; 919 // tail size 920 ts = InitSz - len2; 921 len -= sizeof(SHORT_AD); 922 // calculate actual AllocSequence length (in bytes) 923 NewLen = ( ((j - len + ac - 1) / ac) << LBSh) + InitSz + sizeof(SHORT_AD); 924 MyFreePool__(*Buff); 925 (*Buff) = (int8*)MyAllocatePoolTag__(NonPagedPool, NewLen, MEM_SHAD_TAG); 926 if(!(*Buff)) { 927 status = STATUS_INSUFFICIENT_RESOURCES; 928 UDFPrint(("UDFResizeExtent() failed (%x)\n",status)); 929 BrutePoint(); 930 goto sh_alloc_err; 931 } 932 if(UDFGetExtentLength(AllocExtent->Mapping) < NewLen) { 933 status = UDFResizeExtent(Vcb, PartNum, NewLen, TRUE, AllocExtent); 934 if(!OS_SUCCESS(status)) { 935 UDFPrint(("UDFResizeExtent(2) failed (%x)\n",status)); 936 BrutePoint(); 937 sh_alloc_err: 938 MyFreePool__(Alloc); 939 return status; 940 } 941 } 942 ExtOffs = AllocExtent->Offset; 943 RtlZeroMemory(*Buff, NewLen); 944 saved_NewLen = NewLen; 945 NewLen = 0; // recorded length 946 saved_Alloc = Alloc; 947 // fill buffer sector by sector (adding links at the end of each one) 948 while(TRUE) { 949 950 // j - remained AllocDescs length (in bytes) 951 // len - bytes available for AllocDescs in current block 952 // ac - bytes available for AllocDescs in each block 953 954 // leave space for terminator or pointer to next part of sequence 955 if(j == len2) { 956 // if we have only 1 SHORT_AD that we can fit in last sector 957 // we shall do it instead of recording link & allocating new block 958 len = 959 TagLen = len2; 960 } 961 ASSERT(saved_NewLen >= (BufOffs + len)); 962 RtlCopyMemory( (*Buff)+BufOffs, (int8*)Alloc, len); 963 Alloc = (PSHORT_AD)((int8*)Alloc + len); 964 j -= len; 965 BufOffs += len; 966 if(Tag) { 967 // Set up Tag for AllocDesc 968 Tag->tagIdent = TID_ALLOC_EXTENT_DESC; 969 UDFSetUpTag(Vcb, Tag, (uint16)TagLen, TagLoc); 970 prevTagLoc = TagLoc; 971 } 972 if(!j) { 973 // terminate loop 974 NewLen = BufOffs; 975 break; 976 } 977 len = ac; 978 if(j <= (len + sizeof(SHORT_AD))) 979 len = j - sizeof(SHORT_AD); 980 len2 = len + sizeof(SHORT_AD); 981 // we have more than 1 SHORT_AD that we can't fit in current block 982 // so we shall set up pointer to the next block 983 ((PSHORT_AD)((*Buff)+BufOffs))->extLength = /*LBS*/ len2 | 984 (((uint32)EXTENT_NEXT_EXTENT_ALLOCDESC) << 30) ; 985 ((PSHORT_AD)((*Buff)+BufOffs))->extPosition = TagLoc = 986 UDFPhysLbaToPart(Vcb, PartNum, 987 UDFExtentOffsetToLba(Vcb, AllocExtent->Mapping, 988 ExtOffs+BufOffs+sizeof(SHORT_AD)+ts, 989 NULL, NULL, NULL, NULL) ); 990 // reflect additional (link) block & LBlock tail (if any) 991 BufOffs += ts+sizeof(SHORT_AD); 992 // init AllocDesc 993 ( (PALLOC_EXT_DESC) ((*Buff)+BufOffs))->lengthAllocDescs = len2; 994 ( (PALLOC_EXT_DESC) ((*Buff)+BufOffs))->previousAllocExtLocation = prevTagLoc; 995 Tag = (tag*)((*Buff)+BufOffs); 996 TagLen = len2; 997 ts = LBS-len2-sizeof(ALLOC_EXT_DESC); 998 BufOffs += sizeof(ALLOC_EXT_DESC); 999 } 1000 MyFreePool__(saved_Alloc); 1001 #endif //UDF_ALLOW_FRAG_AD 1002 } 1003 status = UDFResizeExtent(Vcb, PartNum, NewLen, TRUE, AllocExtent); 1004 return status; 1005 } // end UDFBuildShortAllocDescs() 1006 1007 /* 1008 This routine builds data for AllocDesc sequence for specified 1009 extent 1010 */ 1011 OSSTATUS 1012 UDFBuildLongAllocDescs( 1013 IN PVCB Vcb, 1014 IN uint32 PartNum, 1015 OUT int8** Buff, // data for AllocLoc 1016 IN uint32 InitSz, 1017 IN OUT PUDF_FILE_INFO FileInfo 1018 ) 1019 { 1020 uint32 i, j; 1021 uint32 len=0; 1022 PEXTENT_MAP Extent = FileInfo->Dloc->DataLoc.Mapping; 1023 PEXTENT_INFO AllocExtent = &(FileInfo->Dloc->AllocLoc); 1024 PLONG_AD Alloc; 1025 uint32 NewLen; 1026 OSSTATUS status; 1027 uint32 ph_len=0; // in general, this should be uint64, 1028 // but we need its lower part only 1029 #ifdef UDF_ALLOW_FRAG_AD 1030 uint32 ac, len2, ts; 1031 uint32 TagLoc, prevTagLoc; 1032 uint32 LBS = Vcb->LBlockSize; 1033 uint32 LBSh = Vcb->BlockSizeBits; 1034 uint32 BufOffs; 1035 uint32 ExtOffs = AllocExtent->Offset; 1036 PLONG_AD saved_Alloc; 1037 uint32 TagLen = 0; 1038 tag* Tag = NULL; 1039 #endif //UDF_ALLOW_FRAG_AD 1040 1041 ValidateFileInfo(FileInfo); 1042 ExtPrint(("UDFBuildLongAllocDescs: FE %x\n", FileInfo->Dloc->FELoc.Mapping[0].extLocation)); 1043 // calculate length 1044 //for(len=0; i=(Extent[len].extLength & UDF_EXTENT_LENGTH_MASK); len++, ph_len+=i); 1045 for(len=0; (i=(Extent[len].extLength & UDF_EXTENT_LENGTH_MASK)); len++, ph_len+=i) { 1046 ExtPrint(("bLnExt: type %x, loc %x, len %x\n", 1047 Extent[len].extLength >> 30, Extent[len].extLocation, Extent[len].extLength & UDF_EXTENT_LENGTH_MASK)); 1048 } 1049 Alloc = (PLONG_AD)MyAllocatePoolTag__(NonPagedPool, (len+1)*sizeof(LONG_AD), MEM_LNGAD_TAG); 1050 if(!Alloc) return STATUS_INSUFFICIENT_RESOURCES; 1051 // fill contiguous AllocDesc buffer (decribing UserData) 1052 for(i=0;i<len;i++) { 1053 Alloc[i].extLength = Extent[i].extLength; 1054 Alloc[i].extLocation.logicalBlockNum = UDFPhysLbaToPart(Vcb, PartNum, Extent[i].extLocation); 1055 Alloc[i].extLocation.partitionReferenceNum = (uint16)PartNum; 1056 RtlZeroMemory(&(Alloc[i].impUse), sizeof(Alloc[i].impUse)); 1057 } 1058 if((Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS) && i) { 1059 Alloc[i-1].extLength -= (ph_len - (ULONG)(FileInfo->Dloc->DataLoc.Length)) & 1060 (Vcb->LBlockSize-1); 1061 ExtPrint(("bLnExt: cut tail -> %x\n", 1062 Alloc[i-1].extLength & UDF_EXTENT_LENGTH_MASK)); 1063 } 1064 RtlZeroMemory(&(Alloc[i]), sizeof(LONG_AD)); 1065 j = len*sizeof(LONG_AD); // required space 1066 len = (InitSz & ~(sizeof(LONG_AD)-1)); // space available in 1st block 1067 ASSERT(len == InitSz); 1068 1069 // Ok. Let's init AllocLoc 1070 if(!(FileInfo->Dloc->AllocLoc.Mapping)) { 1071 FileInfo->Dloc->AllocLoc.Mapping = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool, 2 * sizeof(EXTENT_MAP), MEM_EXTMAP_TAG); 1072 if(!(FileInfo->Dloc->AllocLoc.Mapping)) { 1073 MyFreePool__(Alloc); 1074 return STATUS_INSUFFICIENT_RESOURCES; 1075 } 1076 // allocation descriptors are located in the same sector as FileEntry 1077 // (at least their 1st part), just after it 1078 FileInfo->Dloc->AllocLoc.Mapping[0] = FileInfo->Dloc->FELoc.Mapping[0]; 1079 FileInfo->Dloc->AllocLoc.Offset = FileInfo->Dloc->FileEntryLen; 1080 FileInfo->Dloc->AllocLoc.Length = 0; 1081 // set terminator 1082 FileInfo->Dloc->AllocLoc.Mapping[1].extLength = 1083 FileInfo->Dloc->AllocLoc.Mapping[1].extLocation = 0; 1084 } 1085 1086 if(j <= len) { 1087 // we needn't allocating additional blocks to store AllocDescs 1088 RtlCopyMemory(*Buff, (int8*)Alloc, j); 1089 NewLen = j; 1090 MyFreePool__(Alloc); 1091 } else { 1092 #ifndef UDF_ALLOW_FRAG_AD 1093 AdPrint((" DISK_FULL\n")); 1094 return STATUS_DISK_FULL; 1095 #else //UDF_ALLOW_FRAG_AD 1096 BufOffs = 0; 1097 TagLoc = prevTagLoc = 0; 1098 // calculate the space available for LONG_ADs in each block 1099 ac = (LBS - (sizeof(ALLOC_EXT_DESC) + sizeof(LONG_AD))) & ~(sizeof(LONG_AD)-1); 1100 len2 = len; 1101 // tail size 1102 ts = InitSz - len2; 1103 len -= sizeof(LONG_AD); 1104 // calculate actual AllocSequence length (in LBlocks) 1105 NewLen = ( ((j - len + ac - 1) / ac) << LBSh) + InitSz + sizeof(LONG_AD); 1106 MyFreePool__(*Buff); 1107 (*Buff) = (int8*)MyAllocatePoolTag__(NonPagedPool, NewLen, MEM_LNGAD_TAG); 1108 if(!(*Buff)) { 1109 status = STATUS_INSUFFICIENT_RESOURCES; 1110 goto lad_alloc_err; 1111 } 1112 if(UDFGetExtentLength(AllocExtent->Mapping) < NewLen) { 1113 status = UDFResizeExtent(Vcb, PartNum, NewLen, TRUE, AllocExtent); 1114 if(!OS_SUCCESS(status)) { 1115 lad_alloc_err: 1116 MyFreePool__(Alloc); 1117 return status; 1118 } 1119 } 1120 ExtOffs = AllocExtent->Offset; 1121 RtlZeroMemory(*Buff, NewLen); 1122 NewLen = 0; // recorded length 1123 saved_Alloc = Alloc; 1124 len2 = len+sizeof(LONG_AD); 1125 // fill buffer sector by sector (adding links at the end of each one) 1126 while(TRUE) { 1127 1128 // j - remained AllocDescs length (in bytes) 1129 // len - bytes available for in AllocDescs each block 1130 1131 // leave space for terminator or pointer to next part of sequence 1132 if(j == len2) { 1133 // if we have only 1 LONG_AD that we can fit in last sector 1134 // we shall do it instead of recording link & allocating new block 1135 len = 1136 TagLen = len2; 1137 } 1138 RtlCopyMemory( (*Buff)+BufOffs, (int8*)Alloc, len); 1139 Alloc = (PLONG_AD)((int8*)Alloc + len); 1140 j -= len; 1141 BufOffs += len; 1142 if(Tag) { 1143 // Set up Tag for AllocDesc 1144 Tag->tagIdent = TID_ALLOC_EXTENT_DESC; 1145 UDFSetUpTag(Vcb, Tag, (uint16)TagLen, TagLoc); 1146 prevTagLoc = TagLoc; 1147 } 1148 if(!j) { 1149 // terminate loop 1150 NewLen = BufOffs; 1151 break; 1152 } 1153 len = ac; 1154 if(j <= (len + sizeof(LONG_AD))) 1155 len = j - sizeof(LONG_AD); 1156 len2 = len+sizeof(LONG_AD); 1157 // we have more than 1 LONG_AD that we can't fit in current block 1158 // so we shall set up pointer to the next block 1159 ((PLONG_AD)((*Buff)+BufOffs))->extLength = /*LBS*/ len2 | 1160 (((uint32)EXTENT_NEXT_EXTENT_ALLOCDESC) << 30) ; 1161 ((PLONG_AD)((*Buff)+BufOffs))->extLocation.logicalBlockNum = TagLoc = 1162 UDFPhysLbaToPart(Vcb, PartNum, 1163 UDFExtentOffsetToLba(Vcb, AllocExtent->Mapping, 1164 ExtOffs+BufOffs+sizeof(LONG_AD)+ts, 1165 NULL, NULL, NULL, NULL) ); 1166 ((PLONG_AD)((*Buff)+BufOffs))->extLocation.partitionReferenceNum = (uint16)PartNum; 1167 // reflect additional (link) block & LBlock tail (if any) 1168 BufOffs += ts+sizeof(LONG_AD); 1169 // init AllocDesc 1170 ( (PALLOC_EXT_DESC) ((*Buff)+BufOffs))->lengthAllocDescs = len2; 1171 ( (PALLOC_EXT_DESC) ((*Buff)+BufOffs))->previousAllocExtLocation = prevTagLoc; 1172 Tag = (tag*)((*Buff)+BufOffs); 1173 TagLen = len2; 1174 ts = LBS-len2-sizeof(ALLOC_EXT_DESC); 1175 BufOffs += sizeof(ALLOC_EXT_DESC); 1176 } 1177 MyFreePool__(saved_Alloc); 1178 #endif //UDF_ALLOW_FRAG_AD 1179 } 1180 status = UDFResizeExtent(Vcb, PartNum, NewLen, TRUE, AllocExtent); 1181 return status; 1182 } // end UDFBuildLongAllocDescs() 1183 1184 /* 1185 This routine builds data for AllocDesc sequence for specified 1186 extent 1187 */ 1188 /*OSSTATUS 1189 UDFBuildExtAllocDescs( 1190 IN PVCB Vcb, 1191 IN uint32 PartNum, 1192 OUT int8** Buff, // data for AllocLoc 1193 IN uint32 InitSz, 1194 IN OUT PUDF_FILE_INFO FileInfo 1195 ) 1196 { 1197 uint32 i, j; 1198 uint32 len=0, ac, len2; 1199 uint32 TagLoc, prevTagLoc; 1200 uint32 LBS = Vcb->LBlockSize; 1201 uint32 LBSh = Vcb->BlockSizeBits; 1202 PEXTENT_MAP Extent = FileInfo->Dloc->DataLoc.Mapping; 1203 PEXTENT_INFO AllocExtent = &(FileInfo->Dloc->AllocLoc); 1204 PEXT_AD Alloc, saved_Alloc; 1205 uint32 BufOffs; 1206 uint32 ExtOffs = AllocExtent->Offset; 1207 uint32 NewLen; 1208 OSSTATUS status; 1209 uint32 TagLen = 0; 1210 tag* Tag = NULL; 1211 1212 ValidateFileInfo(FileInfo); 1213 // calculate length 1214 for(len=0; Extent[len].extLength; len++); 1215 Alloc = (PEXT_AD)MyAllocatePool__(NonPagedPool, (len+1)*sizeof(EXT_AD)); 1216 if(!Alloc) return STATUS_INSUFFICIENT_RESOURCES; 1217 // fill contiguous AllocDesc buffer (decribing UserData) 1218 for(i=0;i<len;i++) { 1219 Alloc[i].extLength = 1220 Alloc[i].recordedLength = 1221 Alloc[i].informationLength = Extent[i].extLength; 1222 Alloc[i].extLocation.logicalBlockNum = UDFPhysLbaToPart(Vcb, PartNum, Extent[i].extLocation); 1223 Alloc[i].extLocation.partitionReferenceNum = (uint16)PartNum; 1224 } 1225 RtlZeroMemory(&(Alloc[i]), sizeof(EXT_AD)); 1226 j = len*sizeof(EXT_AD); // required space 1227 len = InitSz; // space available in 1st block 1228 1229 // Ok. Let's init AllocLoc 1230 if(!(FileInfo->Dloc->AllocLoc.Mapping)) { 1231 FileInfo->Dloc->AllocLoc.Mapping = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, 2 * sizeof(EXTENT_MAP)); 1232 if(!(FileInfo->Dloc->AllocLoc.Mapping)) { 1233 MyFreePool__(Alloc); 1234 return STATUS_INSUFFICIENT_RESOURCES; 1235 } 1236 // allocation descriptors are located in the same sector as FileEntry 1237 // (at least their 1st part), just after it 1238 FileInfo->Dloc->AllocLoc.Mapping[0] = FileInfo->Dloc->FELoc.Mapping[0]; 1239 FileInfo->Dloc->AllocLoc.Offset = FileInfo->Dloc->FileEntryLen; 1240 FileInfo->Dloc->AllocLoc.Length = 0; 1241 // set terminator 1242 FileInfo->Dloc->AllocLoc.Mapping[1].extLength = 1243 FileInfo->Dloc->AllocLoc.Mapping[1].extLocation = 0; 1244 } 1245 1246 if(j <= len) { 1247 // we needn't allocating additional blocks to store AllocDescs 1248 RtlCopyMemory(*Buff, (int8*)Alloc, j); 1249 NewLen = j; 1250 MyFreePool__(Alloc); 1251 } else { 1252 BufOffs = 0; 1253 TagLoc = prevTagLoc = 0; 1254 // calculate the space available for EXT_ADs in each block 1255 ac = (LBS - (sizeof(ALLOC_EXT_DESC) + sizeof(EXT_AD))) & ~(sizeof(EXT_AD)-1); 1256 // calculate actual AllocSequence length (in LBlocks) 1257 len -= sizeof(EXT_AD); 1258 NewLen = ( ((j - len + ac - 1) / ac) << LBSh) + len + sizeof(EXT_AD); 1259 MyFreePool__(*Buff); 1260 (*Buff) = (int8*)MyAllocatePool__(NonPagedPool, NewLen); 1261 if(UDFGetExtentLength(AllocExtent->Mapping) < NewLen) { 1262 status = UDFResizeExtent(Vcb, PartNum, NewLen, TRUE, AllocExtent); 1263 if(!OS_SUCCESS(status)) { 1264 MyFreePool__(Alloc); 1265 return status; 1266 } 1267 } 1268 RtlZeroMemory(*Buff, NewLen); 1269 NewLen = 0; // recorded length 1270 saved_Alloc = Alloc; 1271 len2 = len + sizeof(EXT_AD); 1272 // fill buffer sector by sector (adding links at the end of each one) 1273 while(TRUE) { 1274 1275 // j - remained AllocDescs length (in bytes) 1276 // len - bytes available for in AllocDescs each block 1277 1278 // leave space for terminator or pointer to next part of sequence 1279 if(j == len2) { 1280 // if we have only 1 EXT_AD that we can fit in last sector 1281 // we shall do it instead of recording link & allocating new block 1282 len = 1283 TagLen = len2; 1284 } 1285 RtlCopyMemory( (*Buff)+BufOffs, (int8*)Alloc, len); 1286 Alloc = (PEXT_AD)((int8*)Alloc + len); 1287 j -= len; 1288 BufOffs += len; 1289 if(Tag) { 1290 // Set up Tag for AllocDesc 1291 Tag->tagIdent = TID_ALLOC_EXTENT_DESC; 1292 UDFSetUpTag(Vcb, Tag, (uint16)TagLen, TagLoc); 1293 prevTagLoc = TagLoc; 1294 } 1295 if(!j) { 1296 // terminate loop 1297 NewLen = BufOffs; 1298 break; 1299 } 1300 len = ac; 1301 if(j <= (len + sizeof(EXT_AD))) 1302 len = j - sizeof(EXT_AD); 1303 len2 = len + sizeof(EXT_AD); 1304 // we have more than 1 EXT_AD that we can't fit in current block 1305 // so we shall set up pointer to the next block 1306 ((PEXT_AD)((*Buff)+BufOffs))->extLength = 1307 ((PEXT_AD)((*Buff)+BufOffs))->recordedLength = LBS; 1308 ((PEXT_AD)((*Buff)+BufOffs))->informationLength = len2 | 1309 (((uint32)EXTENT_NEXT_EXTENT_ALLOCDESC) << 30) ; 1310 ((PEXT_AD)((*Buff)+BufOffs))->extLocation.logicalBlockNum = TagLoc = 1311 UDFPhysLbaToPart(Vcb, PartNum, 1312 UDFExtentOffsetToLba(Vcb, AllocExtent->Mapping, ExtOffs + BufOffs + 2*sizeof(EXT_AD)-1, NULL, NULL, NULL, NULL) ); 1313 ((PEXT_AD)((*Buff)+BufOffs))->extLocation.partitionReferenceNum = (uint16)PartNum; 1314 BufOffs = (BufOffs + 2*sizeof(EXT_AD) - 1) & ~(sizeof(EXT_AD)-1) ; 1315 // init AllocDesc 1316 ( (PALLOC_EXT_DESC) ((*Buff)+BufOffs))->lengthAllocDescs = len2; 1317 ( (PALLOC_EXT_DESC) ((*Buff)+BufOffs))->previousAllocExtLocation = prevTagLoc; 1318 Tag = (tag*)((*Buff)+BufOffs); 1319 TagLen = len2; 1320 BufOffs += sizeof(ALLOC_EXT_DESC); 1321 } 1322 MyFreePool__(saved_Alloc); 1323 } 1324 status = UDFResizeExtent(Vcb, PartNum, NewLen, TRUE, AllocExtent); 1325 return status; 1326 } // end UDFBuildExtAllocDescs()*/ 1327 1328 void 1329 UDFDiscardFESpace( 1330 IN PVCB Vcb, 1331 IN PEXTENT_MAP Mapping, 1332 IN uint32 lim 1333 ) 1334 { 1335 #ifdef UDF_FE_ALLOCATION_CHARGE // UDF_FE_ALLOCATION_CHARGE 1336 PEXTENT_MAP Mapping2; 1337 uint32 i; 1338 1339 UDFPrint((" DiscardFESpace\n")); 1340 Mapping2 = Mapping; 1341 for(i=0;i<lim;i++, Mapping++) { 1342 // we should not discard allocated FEs 1343 if( (Mapping->extLength >> 30) == EXTENT_RECORDED_ALLOCATED) { 1344 UDFPrint((" used @ %x\n", Mapping->extLocation)); 1345 Mapping->extLength = Vcb->LBlockSize | (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30); 1346 Mapping->extLocation = 0; 1347 } else { 1348 UDFPrint((" free @ %x\n", Mapping->extLocation)); 1349 } 1350 } 1351 UDFMarkSpaceAsXXX(Vcb, 0, Mapping2, AS_DISCARDED); 1352 1353 MyFreePool__(Mapping2); 1354 #else // UDF_FE_ALLOCATION_CHARGE 1355 ASSERT(!Dloc->DirIndex->FECharge.Mapping); 1356 return; 1357 #endif // UDF_FE_ALLOCATION_CHARGE 1358 } // end UDFDiscardFESpace() 1359 1360 OSSTATUS 1361 UDFInitAllocationCache( 1362 IN PVCB Vcb, 1363 IN uint32 AllocClass, 1364 OUT PUDF_ALLOCATION_CACHE_ITEM* _AllocCache, 1365 OUT uint32* _lim, 1366 IN BOOLEAN Init 1367 ) 1368 { 1369 PUDF_ALLOCATION_CACHE_ITEM AllocCache; 1370 PUDF_ALLOCATION_CACHE_ITEM* pAllocCache; 1371 uint32 i, lim; 1372 uint32* plim; 1373 1374 switch(AllocClass) { 1375 case UDF_PREALLOC_CLASS_FE: 1376 UDFPrint(("AllocationCache FE:\n")); 1377 pAllocCache = &(Vcb->FEChargeCache); 1378 plim = &(Vcb->FEChargeCacheMaxSize); 1379 lim = 32; 1380 break; 1381 case UDF_PREALLOC_CLASS_DIR: 1382 UDFPrint(("AllocationCache DIR:\n")); 1383 pAllocCache = &(Vcb->PreallocCache); 1384 plim = &(Vcb->PreallocCacheMaxSize); 1385 lim = 32; 1386 break; 1387 default: 1388 return STATUS_INVALID_PARAMETER; 1389 } 1390 if(!(*plim)) { 1391 if(!Init) { 1392 return STATUS_UNSUCCESSFUL; 1393 } 1394 (*pAllocCache) = AllocCache = 1395 (PUDF_ALLOCATION_CACHE_ITEM) 1396 MyAllocatePoolTag__(NonPagedPool , sizeof(UDF_ALLOCATION_CACHE_ITEM)*lim, 1397 MEM_ALLOC_CACHE_TAG); 1398 if(!AllocCache) { 1399 return STATUS_INSUFFICIENT_RESOURCES; 1400 } 1401 RtlZeroMemory(AllocCache, sizeof(UDF_ALLOCATION_CACHE_ITEM)*lim); 1402 for(i=0; i<lim; i++) { 1403 AllocCache[i].ParentLocation = LBA_NOT_ALLOCATED; 1404 } 1405 (*plim) = lim; 1406 } else { 1407 lim = (*plim); 1408 AllocCache = (*pAllocCache); 1409 } 1410 (*_lim) = lim; 1411 (*_AllocCache) = AllocCache; 1412 1413 return STATUS_SUCCESS; 1414 } // end UDFInitAllocationCache() 1415 1416 OSSTATUS 1417 UDFGetCachedAllocation( 1418 IN PVCB Vcb, 1419 IN uint32 ParentLocation, 1420 OUT PEXTENT_INFO Ext, 1421 OUT uint32* Items, // optional 1422 IN uint32 AllocClass 1423 ) 1424 { 1425 PUDF_ALLOCATION_CACHE_ITEM AllocCache; 1426 uint32 i, lim; 1427 OSSTATUS status; 1428 1429 UDFAcquireResourceExclusive(&(Vcb->PreallocResource),TRUE); 1430 1431 status = UDFInitAllocationCache(Vcb, AllocClass, &AllocCache, &lim, FALSE); 1432 if(!OS_SUCCESS(status)) { 1433 UDFReleaseResource(&(Vcb->PreallocResource)); 1434 return status; 1435 } 1436 UDFPrint(("Get AllocationCache for %x\n", ParentLocation)); 1437 1438 for(i=0; i<lim; i++) { 1439 if(AllocCache[i].ParentLocation == ParentLocation) { 1440 (*Ext) = AllocCache[i].Ext; 1441 AdPrint((" map %x (%x)\n", Ext->Mapping, i)); 1442 if(Items) { 1443 (*Items) = AllocCache[i].Items; 1444 } 1445 RtlZeroMemory(&(AllocCache[i]), sizeof(AllocCache[i])); 1446 AllocCache[i].ParentLocation = LBA_NOT_ALLOCATED; 1447 UDFReleaseResource(&(Vcb->PreallocResource)); 1448 return STATUS_SUCCESS; 1449 } 1450 } 1451 AdPrint((" no map\n")); 1452 UDFReleaseResource(&(Vcb->PreallocResource)); 1453 return STATUS_UNSUCCESSFUL; 1454 } // end UDFGetCachedAllocation() 1455 1456 OSSTATUS 1457 UDFStoreCachedAllocation( 1458 IN PVCB Vcb, 1459 IN uint32 ParentLocation, 1460 IN PEXTENT_INFO Ext, 1461 IN uint32 Items, 1462 IN uint32 AllocClass 1463 ) 1464 { 1465 PUDF_ALLOCATION_CACHE_ITEM AllocCache; 1466 uint32 i, lim; 1467 OSSTATUS status; 1468 1469 UDFAcquireResourceExclusive(&(Vcb->PreallocResource),TRUE); 1470 1471 status = UDFInitAllocationCache(Vcb, AllocClass, &AllocCache, &lim, TRUE); 1472 if(!OS_SUCCESS(status)) { 1473 UDFReleaseResource(&(Vcb->PreallocResource)); 1474 return status; 1475 } 1476 UDFPrint(("Store AllocationCache for %x, map %x\n", ParentLocation, Ext->Mapping)); 1477 1478 for(i=0; i<lim; i++) { 1479 if(AllocCache[i].ParentLocation == LBA_NOT_ALLOCATED) { 1480 AdPrint((" stored in %x\n", i)); 1481 AllocCache[i].Ext = (*Ext); 1482 AllocCache[i].Items = Items; 1483 AllocCache[i].ParentLocation = ParentLocation; 1484 UDFReleaseResource(&(Vcb->PreallocResource)); 1485 return STATUS_SUCCESS; 1486 } 1487 } 1488 // 1489 AdPrint((" drop map %x (%x)\n", AllocCache[lim-1].Ext.Mapping, lim-1)); 1490 switch(AllocClass) { 1491 case UDF_PREALLOC_CLASS_FE: 1492 UDFDiscardFESpace(Vcb, AllocCache[lim-1].Ext.Mapping, AllocCache[lim-1].Items); 1493 break; 1494 case UDF_PREALLOC_CLASS_DIR: 1495 UDFMarkSpaceAsXXX(Vcb, 0, AllocCache[lim-1].Ext.Mapping, AS_DISCARDED); 1496 break; 1497 } 1498 RtlMoveMemory(&(AllocCache[1]), &(AllocCache[0]), sizeof(UDF_ALLOCATION_CACHE_ITEM)*(lim-1)); 1499 AllocCache[0].Ext = (*Ext); 1500 AllocCache[0].Items = Items; 1501 AllocCache[0].ParentLocation = ParentLocation; 1502 AdPrint((" stored in 0\n")); 1503 UDFReleaseResource(&(Vcb->PreallocResource)); 1504 return STATUS_SUCCESS; 1505 } // end UDFStoreCachedAllocation() 1506 1507 OSSTATUS 1508 UDFFlushAllCachedAllocations( 1509 IN PVCB Vcb, 1510 IN uint32 AllocClass 1511 ) 1512 { 1513 PUDF_ALLOCATION_CACHE_ITEM AllocCache; 1514 uint32 i, lim; 1515 OSSTATUS status; 1516 1517 UDFPrint(("Flush AllocationCache\n")); 1518 UDFAcquireResourceExclusive(&(Vcb->PreallocResource),TRUE); 1519 1520 status = UDFInitAllocationCache(Vcb, AllocClass, &AllocCache, &lim, FALSE); 1521 if(!OS_SUCCESS(status)) { 1522 UDFReleaseResource(&(Vcb->PreallocResource)); 1523 return status; 1524 } 1525 1526 for(i=0; i<lim; i++) { 1527 if(AllocCache[i].ParentLocation != LBA_NOT_ALLOCATED) { 1528 switch(AllocClass) { 1529 case UDF_PREALLOC_CLASS_FE: 1530 UDFDiscardFESpace(Vcb, AllocCache[i].Ext.Mapping, AllocCache[i].Items); 1531 break; 1532 case UDF_PREALLOC_CLASS_DIR: 1533 UDFMarkSpaceAsXXX(Vcb, 0, AllocCache[i].Ext.Mapping, AS_DISCARDED); 1534 break; 1535 } 1536 } 1537 } 1538 MyFreePool__(AllocCache); 1539 switch(AllocClass) { 1540 case UDF_PREALLOC_CLASS_FE: 1541 Vcb->FEChargeCache = NULL; 1542 Vcb->FEChargeCacheMaxSize = 0; 1543 break; 1544 case UDF_PREALLOC_CLASS_DIR: 1545 Vcb->PreallocCache = NULL; 1546 Vcb->PreallocCacheMaxSize = 0; 1547 break; 1548 } 1549 UDFReleaseResource(&(Vcb->PreallocResource)); 1550 // 1551 return STATUS_SUCCESS; 1552 } // end UDFFlushAllCachedAllocations() 1553 1554 /* 1555 This routine allocates space for FE of the file being created 1556 If FE-Charge is enabled it reserves an extent & allocates 1557 space in it. It works much faster then usual way both while 1558 allocating & accessing on disk 1559 If FE-Charge is disabled FE may be allocated at any suitable 1560 location 1561 */ 1562 OSSTATUS 1563 UDFAllocateFESpace( 1564 IN PVCB Vcb, 1565 IN PUDF_FILE_INFO DirInfo, 1566 IN uint32 PartNum, 1567 IN PEXTENT_INFO FEExtInfo, 1568 IN uint32 Len 1569 ) 1570 { 1571 #ifdef UDF_FE_ALLOCATION_CHARGE // UDF_FE_ALLOCATION_CHARGE 1572 OSSTATUS status; 1573 PEXTENT_INFO Ext; 1574 EXTENT_AD Extent; 1575 BOOLEAN retry = FALSE; 1576 uint32 i, lim; 1577 1578 /* 1579 1. #Dir1#->*File* -> Dir1's FECharge 1580 2. #Dir1#->*Dir* -> Dir1's FECharge 1581 3. #Dir1#->*SDir* -> Dir1's FECharge 1582 4. Dir1->#SDir#->*Stream* -> Dir1's FEChargeSDir 1583 5. Dir1->#File#->*SDir* -> Dir1's FEChargeSDir 1584 6. Dir1->#Dir#->*SDir* -> (see p.2) 1585 7. Dir1->File->#SDir#->*Stream* -> Dir1's FEChargeSDir 1586 8. Dir1->Dir->#SDir#->*Stream* -> (see p.4) 1587 1588 ## ~ DirInfo 1589 ** ~ Object to be created 1590 1591 */ 1592 1593 // ASSERT(!FEExtInfo->Mapping); 1594 // check if DirInfo we are called with is a Directory 1595 // (it can be a file with SDir) 1596 if(!DirInfo || !DirInfo->Dloc->DirIndex || 1597 ((lim = ((DirInfo->Dloc->FE_Flags & UDF_FE_FLAG_IS_SDIR) ? Vcb->FEChargeSDir : Vcb->FECharge)) <= 1)) 1598 #endif // UDF_FE_ALLOCATION_CHARGE 1599 return UDFAllocFreeExtent(Vcb, Len, 1600 UDFPartStart(Vcb, PartNum), UDFPartEnd(Vcb, PartNum), FEExtInfo, EXTENT_FLAG_VERIFY); 1601 #ifdef UDF_FE_ALLOCATION_CHARGE // UDF_FE_ALLOCATION_CHARGE 1602 1603 Ext = &(DirInfo->Dloc->DirIndex->FECharge); 1604 1605 while(TRUE) { 1606 1607 if(!Ext->Mapping) { 1608 ULONG p_start; 1609 ULONG p_end; 1610 ULONG fe_loc; 1611 ULONG l1, l2; 1612 1613 p_start = UDFPartStart(Vcb, PartNum); 1614 p_end = UDFPartEnd(Vcb, PartNum); 1615 fe_loc = DirInfo->Dloc->FELoc.Mapping[0].extLocation; 1616 1617 status = UDFGetCachedAllocation(Vcb, fe_loc, Ext, NULL, UDF_PREALLOC_CLASS_FE); 1618 if(OS_SUCCESS(status)) { 1619 // do nothing, even do not unpack 1620 } else 1621 if(Vcb->LowFreeSpace) { 1622 status = UDFAllocFreeExtent(Vcb, Len << Vcb->LBlockSizeBits,p_start, p_end, FEExtInfo, EXTENT_FLAG_VERIFY); 1623 if(OS_SUCCESS(status)) { 1624 UDFPrint(("FE @ %x (1)\n", FEExtInfo->Mapping[0].extLocation )); 1625 } 1626 return status; 1627 } else { 1628 if(fe_loc > p_start + 512*16) { 1629 l1 = fe_loc - 512*16; 1630 } else { 1631 l1 = p_start; 1632 } 1633 if(fe_loc + 512*16 < p_end) { 1634 l2 = fe_loc + 512*16; 1635 } else { 1636 l2 = p_end; 1637 } 1638 status = UDFAllocFreeExtent(Vcb, lim << Vcb->LBlockSizeBits, l1, l2, Ext, EXTENT_FLAG_VERIFY); 1639 if(!OS_SUCCESS(status)) { 1640 status = UDFAllocFreeExtent(Vcb, lim << Vcb->LBlockSizeBits, (p_start+fe_loc)/2, (fe_loc+p_end)/2, Ext, EXTENT_FLAG_VERIFY); 1641 } 1642 if(!OS_SUCCESS(status)) { 1643 status = UDFAllocFreeExtent(Vcb, lim << Vcb->LBlockSizeBits, p_start, p_end, Ext, EXTENT_FLAG_VERIFY); 1644 } 1645 if(!OS_SUCCESS(status)) { 1646 status = UDFAllocFreeExtent(Vcb, lim << Vcb->LBlockSizeBits, p_start+1024, p_end-1024, Ext, EXTENT_FLAG_VERIFY); 1647 } 1648 if(!OS_SUCCESS(status = UDFAllocFreeExtent(Vcb, lim << Vcb->LBlockSizeBits, p_start, p_end, Ext, EXTENT_FLAG_VERIFY) )) { 1649 // can't pre-allocate space for multiple FEs. Try single FE 1650 UDFPrint(("allocate single FE entry\n")); 1651 status = UDFAllocFreeExtent(Vcb, Len, 1652 p_start, p_end, FEExtInfo, EXTENT_FLAG_VERIFY); 1653 if(OS_SUCCESS(status)) { 1654 UDFPrint(("FE @ %x (2)\n", FEExtInfo->Mapping[0].extLocation )); 1655 } 1656 return status; 1657 } 1658 status = UDFUnPackMapping(Vcb, Ext); 1659 if(!OS_SUCCESS(status)) { 1660 MyFreePool__(Ext->Mapping); 1661 Ext->Mapping = NULL; 1662 return status; 1663 } 1664 } 1665 } 1666 1667 for(i=0;i<lim;i++) { 1668 if( (Ext->Mapping[i].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED ) { 1669 Ext->Mapping[i].extLength &= UDF_EXTENT_LENGTH_MASK; // EXTENT_RECORDED_ALLOCATED 1670 1671 Extent.extLength = Vcb->LBlockSize | (EXTENT_NOT_RECORDED_ALLOCATED << 30); 1672 Extent.extLocation = Ext->Mapping[i].extLocation; 1673 1674 if(Vcb->BSBM_Bitmap) { 1675 uint32 lba = Ext->Mapping[i].extLocation; 1676 if(UDFGetBadBit((uint32*)(Vcb->BSBM_Bitmap), lba)) { 1677 UDFPrint(("Remove BB @ %x from FE charge\n", lba)); 1678 Ext->Mapping[i].extLength |= (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30); 1679 Ext->Mapping[i].extLocation = 0; 1680 continue; 1681 } 1682 } 1683 1684 FEExtInfo->Mapping = UDFExtentToMapping(&Extent); 1685 if(!FEExtInfo->Mapping) { 1686 ASSERT(!(Ext->Mapping[i].extLength >> 30)); 1687 Ext->Mapping[i].extLength |= (EXTENT_NOT_RECORDED_ALLOCATED << 30); 1688 return STATUS_INSUFFICIENT_RESOURCES; 1689 } 1690 UDFPrint(("FE @ %x (3)\n", FEExtInfo->Mapping[0].extLocation )); 1691 FEExtInfo->Length = Len; 1692 FEExtInfo->Offset = 0; 1693 FEExtInfo->Modified = TRUE; 1694 return STATUS_SUCCESS; 1695 } 1696 } 1697 1698 if(Vcb->LowFreeSpace) { 1699 status = UDFAllocFreeExtent(Vcb, Len, 1700 UDFPartStart(Vcb, PartNum), UDFPartEnd(Vcb, PartNum), FEExtInfo, EXTENT_FLAG_VERIFY); 1701 if(OS_SUCCESS(status)) { 1702 UDFPrint(("FE @ %x (4)\n", FEExtInfo->Mapping[0].extLocation )); 1703 } 1704 return status; 1705 } 1706 if(retry) 1707 return STATUS_INSUFFICIENT_RESOURCES; 1708 1709 // we can get here if there are no free slots in 1710 // preallocated FE charge. So, we should release 1711 // memory and try to allocate space for new FE charge. 1712 MyFreePool__(Ext->Mapping); 1713 Ext->Mapping = NULL; 1714 retry = TRUE; 1715 } 1716 return STATUS_INSUFFICIENT_RESOURCES; 1717 #endif // UDF_FE_ALLOCATION_CHARGE 1718 1719 } // end UDFAllocateFESpace() 1720 1721 /* 1722 This routine frees space allocated for FE. 1723 */ 1724 void 1725 UDFFreeFESpace( 1726 IN PVCB Vcb, 1727 IN PUDF_FILE_INFO DirInfo, 1728 IN PEXTENT_INFO FEExtInfo 1729 ) 1730 { 1731 #ifdef UDF_FE_ALLOCATION_CHARGE // UDF_FE_ALLOCATION_CHARGE 1732 PEXTENT_INFO Ext; 1733 uint32 i, lim, j=-1; 1734 uint32 Lba; 1735 1736 // check if the DirInfo we are called with is a Directory 1737 // (it can be a file with SDir) 1738 if(DirInfo && DirInfo->Dloc->DirIndex && 1739 (Ext = &(DirInfo->Dloc->DirIndex->FECharge))->Mapping) { 1740 if(!FEExtInfo->Mapping) 1741 return; 1742 Lba = FEExtInfo->Mapping[0].extLocation; 1743 1744 lim = (DirInfo->Dloc->FE_Flags & UDF_FE_FLAG_IS_SDIR) ? Vcb->FEChargeSDir : Vcb->FECharge; 1745 for(i=0;i<lim;i++) { 1746 if(Ext->Mapping[i].extLocation == Lba) { 1747 ASSERT(!(Ext->Mapping[i].extLength >> 30)); 1748 Ext->Mapping[i].extLength |= (EXTENT_NOT_RECORDED_ALLOCATED << 30); 1749 goto clean_caller; 1750 } 1751 if(!Ext->Mapping[i].extLocation) { 1752 j = i; 1753 } 1754 } 1755 if(j != (ULONG)-1) { 1756 i = j; 1757 Ext->Mapping[i].extLocation = Lba; 1758 Ext->Mapping[i].extLength = Vcb->LBlockSize | (EXTENT_NOT_RECORDED_ALLOCATED << 30); 1759 goto clean_caller; 1760 } 1761 } 1762 #endif // UDF_FE_ALLOCATION_CHARGE 1763 UDFMarkSpaceAsXXX(Vcb, 0, FEExtInfo->Mapping, AS_DISCARDED); // free 1764 clean_caller: 1765 FEExtInfo->Mapping[0].extLocation = 0; 1766 FEExtInfo->Mapping[0].extLength = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30); 1767 return; 1768 } // end UDFFreeFESpace() 1769 #endif //UDF_READ_ONLY_BUILD 1770 1771 /* 1772 This routine flushes FE-Charge buffer, marks unused blocks as free 1773 in bitmap & releases memory allocated for FE-Charge management 1774 */ 1775 void 1776 UDFFlushFESpace( 1777 IN PVCB Vcb, 1778 IN PUDF_DATALOC_INFO Dloc, 1779 IN BOOLEAN Discard 1780 ) 1781 { 1782 #ifdef UDF_FE_ALLOCATION_CHARGE // UDF_FE_ALLOCATION_CHARGE 1783 PEXTENT_MAP Mapping; 1784 uint32 lim; 1785 1786 if(!(Mapping = Dloc->DirIndex->FECharge.Mapping)) 1787 return; 1788 1789 lim = (Dloc->FE_Flags & UDF_FE_FLAG_IS_SDIR) ? Vcb->FEChargeSDir : Vcb->FECharge; 1790 1791 if(!Discard) { 1792 // cache it! 1793 if(OS_SUCCESS(UDFStoreCachedAllocation(Vcb, 1794 Dloc->FELoc.Mapping[0].extLocation, 1795 &Dloc->DirIndex->FECharge, lim, UDF_PREALLOC_CLASS_FE))) { 1796 Dloc->DirIndex->FECharge.Mapping = NULL; 1797 return; 1798 } 1799 } 1800 Dloc->DirIndex->FECharge.Mapping = NULL; 1801 UDFDiscardFESpace(Vcb, Mapping, lim); 1802 #else // UDF_FE_ALLOCATION_CHARGE 1803 ASSERT(!Dloc->DirIndex->FECharge.Mapping); 1804 return; 1805 #endif // UDF_FE_ALLOCATION_CHARGE 1806 } // end UDFFlushFESpace() 1807 1808 #ifndef UDF_READ_ONLY_BUILD 1809 /* 1810 This routine rebuilds mapping on write attempts to Alloc-Not-Rec area. 1811 Here we assume that required area lays in a single frag. 1812 */ 1813 OSSTATUS 1814 UDFMarkAllocatedAsRecorded( 1815 IN PVCB Vcb, 1816 IN int64 Offset, 1817 IN uint32 Length, 1818 IN PEXTENT_INFO ExtInfo // Extent array 1819 ) 1820 { 1821 uint32 i, len, lba, sLen; 1822 PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array 1823 PEXTENT_MAP NewExtent; 1824 uint32 BS = Vcb->BlockSize; 1825 uint32 LBS = Vcb->LBlockSize; 1826 uint32 BSh = Vcb->BlockSizeBits; 1827 BOOLEAN TryPack = TRUE; 1828 #ifdef UDF_DBG 1829 int64 check_size; 1830 #endif //UDF_DBG 1831 // I don't know what else comment can be added here. 1832 // Just belive that it works 1833 lba = UDFExtentOffsetToLba(Vcb, ExtInfo->Mapping, (Offset & ~((int64)LBS-1)), NULL, NULL, NULL, &i); 1834 if(i == (ULONG)-1) return STATUS_INVALID_PARAMETER; 1835 #ifdef UDF_DBG 1836 check_size = UDFGetExtentLength(ExtInfo->Mapping); 1837 ASSERT(!(check_size & (LBS-1))); 1838 #endif //UDF_DBG 1839 AdPrint(("Alloc->Rec ExtInfo %x, Extent %x\n", ExtInfo, Extent)); 1840 if((Extent[i].extLength >> 30) == EXTENT_RECORDED_ALLOCATED) return STATUS_SUCCESS; 1841 if((Extent[i].extLength >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED) return STATUS_INVALID_PARAMETER; 1842 ASSERT((((uint32)Offset) & (LBS-1)) + Length <= (Extent[i].extLength & UDF_EXTENT_LENGTH_MASK)); 1843 sLen = (( (((uint32)Offset) & (LBS-1)) + Length+LBS-1) & ~(LBS-1)) >> BSh; 1844 if((Extent[i].extLocation == lba) && (((Extent[i].extLength & UDF_EXTENT_LENGTH_MASK ) >> BSh) == sLen)) { 1845 // xxxxxx -> RRRRRR 1846 Extent[i].extLength &= UDF_EXTENT_LENGTH_MASK; 1847 // Extent[i].extLength |= (EXTENT_RECORDED_ALLOCATED << 30); // = 0; 1848 ExtInfo->Modified = TRUE; 1849 if(i && 1850 ((Extent[i-1].extLength >> 30) == EXTENT_RECORDED_ALLOCATED) && 1851 (lba == (Extent[i-1].extLocation + ((len = Extent[i-1].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh))) && 1852 ((len + (Extent[i].extLength & UDF_EXTENT_LENGTH_MASK)) <= UDF_MAX_EXTENT_LENGTH) && 1853 (i == ((UDFGetMappingLength(Extent) / sizeof(EXTENT_MAP)) - 2)) && 1854 TRUE) { 1855 // make optimization for sequentially written files 1856 Extent[i-1].extLength += Extent[i].extLength; 1857 Extent[i].extLocation = 0; 1858 Extent[i].extLength = 0; 1859 } else { 1860 UDFPackMapping(Vcb, ExtInfo); 1861 } 1862 AdPrint(("Alloc->Rec (1) new %x\n", ExtInfo->Mapping)); 1863 #ifdef UDF_DBG 1864 ASSERT(check_size == UDFGetExtentLength(ExtInfo->Mapping)); 1865 #endif 1866 AdPrint(("Alloc->Rec: ExtInfo %x, Extent %x\n", ExtInfo, ExtInfo->Mapping)); 1867 return STATUS_SUCCESS; 1868 } 1869 if(Extent[i].extLocation < lba) { 1870 if( (((Extent[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh) - (lba - Extent[i].extLocation)) 1871 > sLen ) { 1872 // xxxxxx -> xxRRxx 1873 NewExtent = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool , UDFGetMappingLength(Extent) + sizeof(EXTENT_MAP)*2, 1874 MEM_EXTMAP_TAG); 1875 if(!NewExtent) return STATUS_INSUFFICIENT_RESOURCES; 1876 Extent[i].extLength &= UDF_EXTENT_LENGTH_MASK; 1877 RtlCopyMemory((int8*)NewExtent, (int8*)Extent, i*sizeof(EXTENT_MAP)); 1878 RtlCopyMemory((int8*)&(NewExtent[i+3]), (int8*)&(Extent[i+1]), len = UDFGetMappingLength(&(Extent[i+1])) ); 1879 NewExtent[i].extLocation = Extent[i].extLocation; 1880 NewExtent[i].extLength = (lba - Extent[i].extLocation) << BSh; 1881 NewExtent[i+1].extLength = (Length+BS-1) & ~(BS-1); 1882 NewExtent[i+1].extLocation = lba; 1883 NewExtent[i+2].extLength = Extent[i].extLength - NewExtent[i].extLength - NewExtent[i+1].extLength; 1884 NewExtent[i+2].extLocation = lba + ((Length+BS-1) >> BSh); 1885 ASSERT(!(NewExtent[i].extLength >> 30)); 1886 ASSERT(!(NewExtent[i+2].extLength >> 30)); 1887 NewExtent[i].extLength |= (EXTENT_NOT_RECORDED_ALLOCATED << 30); 1888 NewExtent[i+2].extLength |= (EXTENT_NOT_RECORDED_ALLOCATED << 30); 1889 TryPack = FALSE; 1890 AdPrint(("Alloc->Rec (2) new %x\n", NewExtent)); 1891 } else { 1892 // xxxxxx -> xxRRRR 1893 NewExtent = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool , UDFGetMappingLength(Extent) + sizeof(EXTENT_MAP), 1894 MEM_EXTMAP_TAG); 1895 if(!NewExtent) return STATUS_INSUFFICIENT_RESOURCES; 1896 Extent[i].extLength &= UDF_EXTENT_LENGTH_MASK; 1897 RtlCopyMemory((int8*)NewExtent, (int8*)Extent, i*sizeof(EXTENT_MAP)); 1898 RtlCopyMemory((int8*)&(NewExtent[i+2]), (int8*)&(Extent[i+1]), len = UDFGetMappingLength(&(Extent[i+1])) ); 1899 NewExtent[i].extLocation = Extent[i].extLocation; 1900 NewExtent[i].extLength = (lba - Extent[i].extLocation) << BSh; 1901 NewExtent[i+1].extLength = Extent[i].extLength - NewExtent[i].extLength; 1902 NewExtent[i+1].extLocation = lba; 1903 ASSERT(!(NewExtent[i].extLength >> 30)); 1904 NewExtent[i].extLength |= (EXTENT_NOT_RECORDED_ALLOCATED << 30); 1905 AdPrint(("Alloc->Rec (3) new %x\n", NewExtent)); 1906 } 1907 } else { 1908 // xxxxxx -> RRRRxx 1909 NewExtent = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool , UDFGetMappingLength(Extent) + sizeof(EXTENT_MAP), 1910 MEM_EXTMAP_TAG); 1911 if(!NewExtent) return STATUS_INSUFFICIENT_RESOURCES; 1912 Extent[i].extLength &= UDF_EXTENT_LENGTH_MASK; 1913 RtlCopyMemory((int8*)NewExtent, (int8*)Extent, i*sizeof(EXTENT_MAP)); 1914 RtlCopyMemory((int8*)&(NewExtent[i+2]), (int8*)&(Extent[i+1]), len = UDFGetMappingLength(&(Extent[i+1])) ); 1915 NewExtent[i].extLocation = Extent[i].extLocation; 1916 NewExtent[i].extLength = (Length+BS-1) & ~(BS-1); 1917 NewExtent[i+1].extLength = Extent[i].extLength - NewExtent[i].extLength; 1918 NewExtent[i+1].extLocation = Extent[i].extLocation + (NewExtent[i].extLength >> BSh); 1919 ASSERT(!(NewExtent[i+1].extLength >> 30)); 1920 NewExtent[i+1].extLength |= (EXTENT_NOT_RECORDED_ALLOCATED << 30); 1921 AdPrint(("Alloc->Rec (4) new %x\n", NewExtent)); 1922 } 1923 1924 //ASSERT(check_size == UDFGetExtentLength(Extent)); 1925 //ASSERT(!(check_size & (LBS-1))); 1926 1927 AdPrint(("Free Extent %x (new %x)\n", Extent, NewExtent)); 1928 MyFreePool__(Extent); 1929 ExtInfo->Modified = TRUE; 1930 ExtInfo->Mapping = NewExtent; 1931 if(TryPack) 1932 UDFPackMapping(Vcb, ExtInfo); 1933 #ifdef UDF_DBG 1934 ASSERT(check_size == UDFGetExtentLength(ExtInfo->Mapping)); 1935 ASSERT(!(check_size & (LBS-1))); 1936 #endif 1937 1938 AdPrint(("Alloc->Rec: ExtInfo %x, Extent %x\n", ExtInfo, ExtInfo->Mapping)); 1939 1940 return STATUS_SUCCESS; 1941 } // end UDFMarkAllocatedAsRecorded() 1942 1943 /* 1944 This routine rebuilds mapping on write attempts to Not-Alloc-Not-Rec area. 1945 Here we assume that required area lays in a single frag. 1946 */ 1947 OSSTATUS 1948 UDFMarkNotAllocatedAsAllocated( 1949 IN PVCB Vcb, 1950 IN int64 Offset, 1951 IN uint32 Length, 1952 IN PEXTENT_INFO ExtInfo // Extent array 1953 ) 1954 { 1955 uint32 i, len, /*lba,*/ d, l, BOffs, j; 1956 PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array 1957 PEXTENT_MAP NewExtent; 1958 // uint32 BS = Vcb->BlockSize; 1959 uint32 BSh = Vcb->BlockSizeBits; 1960 OSSTATUS status; 1961 EXTENT_INFO TmpExtInf; 1962 uint32 aLen, sLen; 1963 uint32 LBS = Vcb->LBlockSize; 1964 // I don't know what else comment can be added here. 1965 // Just belive that it works 1966 /*lba = */ 1967 #ifndef ALLOW_SPARSE 1968 BrutePoint(); 1969 #endif 1970 AdPrint(("Not->Alloc ExtInfo %x, Extent %x\n", ExtInfo, Extent)); 1971 UDFExtentOffsetToLba(Vcb, ExtInfo->Mapping, Offset, NULL, NULL, NULL, &i); 1972 if(i == (ULONG)-1) return STATUS_INVALID_PARAMETER; 1973 if((Extent[i].extLength >> 30) != EXTENT_NOT_RECORDED_NOT_ALLOCATED) return STATUS_SUCCESS; 1974 1975 uint32 PartNum = UDFGetPartNumByPhysLba(Vcb, Extent[0].extLocation); 1976 BOffs = (uint32)(Offset >> BSh); 1977 // length of existing Not-Alloc-Not-Rec frag 1978 sLen = (( (((uint32)Offset) & (LBS-1)) + Length+LBS-1) & ~(LBS-1)) >> BSh; 1979 // required allocation length increment (in bytes) 1980 aLen = (uint32)( ((Offset+Length+LBS-1) & ~(LBS-1)) - (Offset & ~(LBS-1))); 1981 1982 // try to extend previous frag or allocate space _after_ it to 1983 // avoid backward seeks, if previous frag is not Not-Rec-Not-Alloc 1984 if(i && ((Extent[i-1].extLength >> 30) != EXTENT_NOT_RECORDED_NOT_ALLOCATED) ) { 1985 status = UDFAllocFreeExtent(Vcb, aLen, 1986 Extent[i-1].extLocation + ((Extent[i-1].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh), 1987 min(UDFPartEnd(Vcb, PartNum), Extent[i-1].extLocation + ((Extent[i-1].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh) + sLen ), 1988 &TmpExtInf, ExtInfo->Flags /*& EXTENT_FLAG_ALLOC_MASK*/); 1989 if(status == STATUS_DISK_FULL) 1990 // if there are not enough free blocks after that frag... 1991 goto try_alloc_anywhere; 1992 } else { 1993 try_alloc_anywhere: 1994 // ... try to alloc required disk space anywhere 1995 status = UDFAllocFreeExtent(Vcb, aLen, 1996 UDFPartStart(Vcb, PartNum), 1997 UDFPartEnd(Vcb, PartNum), 1998 &TmpExtInf, ExtInfo->Flags /*& EXTENT_FLAG_ALLOC_MASK*/); 1999 } 2000 // check for successfull allocation 2001 if(!OS_SUCCESS(status)) { 2002 AdPrint(("Not->Alloc no free\n")); 2003 return status; 2004 } 2005 // get number of frags in allocated block 2006 d = (UDFGetMappingLength(TmpExtInf.Mapping) / sizeof(EXTENT_MAP)) - 1; 2007 // calculate number of existing blocks before the frag to be changed 2008 l=0; 2009 for(j=0; j<i; j++) { 2010 l += (uint32)((Extent[j].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh); 2011 } 2012 // and now just update mapping... 2013 if( (l == BOffs) && (((Extent[j].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh) == sLen) ) { 2014 // xxxxxx -> RRRRRR 2015 // (d-1) - since we have to raplace last frag of Extent with 1 or more frags of TmpExtInf.Mapping 2016 NewExtent = (PEXTENT_AD)MyAllocatePool__(NonPagedPool, UDFGetMappingLength(Extent) + (d-1)*sizeof(EXTENT_MAP) ); 2017 if(!NewExtent) { 2018 MyFreePool__(TmpExtInf.Mapping); 2019 return STATUS_INSUFFICIENT_RESOURCES; 2020 } 2021 RtlCopyMemory((int8*)NewExtent, (int8*)Extent, i*sizeof(EXTENT_MAP)); 2022 RtlCopyMemory((int8*)&(NewExtent[i]), (int8*)(TmpExtInf.Mapping), d*sizeof(EXTENT_MAP) ); 2023 RtlCopyMemory((int8*)&(NewExtent[i+d]), (int8*)&(Extent[i+1]), len = UDFGetMappingLength(&(Extent[i+1])) ); 2024 AdPrint(("Not->Alloc (1) new %x\n", NewExtent)); 2025 } else 2026 if(l < BOffs) { 2027 // .ExtLength, BOffs & l are already aligned... 2028 if( (((Extent[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh) - (BOffs-l)) > sLen ) { 2029 // xxxxxx -> xxRRxx 2030 NewExtent = (PEXTENT_AD)MyAllocatePool__(NonPagedPool, UDFGetMappingLength(Extent) + (d+1)*sizeof(EXTENT_MAP) ); 2031 if(!NewExtent) { 2032 MyFreePool__(TmpExtInf.Mapping); 2033 return STATUS_INSUFFICIENT_RESOURCES; 2034 } 2035 RtlCopyMemory((int8*)NewExtent, (int8*)Extent, i*sizeof(EXTENT_MAP)); 2036 RtlCopyMemory((int8*)&(NewExtent[i+1]), (int8*)(TmpExtInf.Mapping), d*sizeof(EXTENT_MAP) ); 2037 RtlCopyMemory((int8*)&(NewExtent[i+d+2]), (int8*)&(Extent[i+1]), len = UDFGetMappingLength(&(Extent[i+1])) ); 2038 NewExtent[i].extLocation = 0; 2039 NewExtent[i].extLength = (BOffs - l) << BSh; 2040 NewExtent[i+d+1].extLength = Extent[i].extLength - NewExtent[i].extLength - aLen; 2041 NewExtent[i+d+1].extLocation = 0; 2042 NewExtent[i].extLength |= (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30); 2043 NewExtent[i+d+1].extLength |= (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30); 2044 AdPrint(("Not->Alloc (2) new %x\n", NewExtent)); 2045 } else { 2046 // xxxxxx -> xxRRRR 2047 NewExtent = (PEXTENT_AD)MyAllocatePool__(NonPagedPool, UDFGetMappingLength(Extent) + d*sizeof(EXTENT_MAP) ); 2048 if(!NewExtent) { 2049 MyFreePool__(TmpExtInf.Mapping); 2050 return STATUS_INSUFFICIENT_RESOURCES; 2051 } 2052 RtlCopyMemory((int8*)NewExtent, (int8*)Extent, i*sizeof(EXTENT_MAP)); 2053 RtlCopyMemory((int8*)&(NewExtent[i+1]), (int8*)(TmpExtInf.Mapping), d*sizeof(EXTENT_MAP) ); 2054 RtlCopyMemory((int8*)&(NewExtent[i+d+1]), (int8*)&(Extent[i+1]), len = UDFGetMappingLength(&(Extent[i+1])) ); 2055 NewExtent[i].extLocation = 0; 2056 NewExtent[i].extLength = (BOffs - l) << BSh; 2057 NewExtent[i].extLength |= (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30); 2058 AdPrint(("Not->Alloc (3) new %x\n", NewExtent)); 2059 } 2060 } else { 2061 // xxxxxx -> RRRRxx 2062 NewExtent = (PEXTENT_AD)MyAllocatePool__(NonPagedPool, UDFGetMappingLength(Extent) + d*sizeof(EXTENT_MAP) ); 2063 if(!NewExtent) { 2064 MyFreePool__(TmpExtInf.Mapping); 2065 return STATUS_INSUFFICIENT_RESOURCES; 2066 } 2067 RtlCopyMemory((int8*)NewExtent, (int8*)Extent, i*sizeof(EXTENT_MAP)); 2068 RtlCopyMemory((int8*)&(NewExtent[i]), (int8*)(TmpExtInf.Mapping), d*sizeof(EXTENT_MAP) ); 2069 RtlCopyMemory((int8*)&(NewExtent[i+d+1]), (int8*)&(Extent[i+1]), len = UDFGetMappingLength(&(Extent[i+1])) ); 2070 NewExtent[i+d].extLength = (Extent[i].extLength & UDF_EXTENT_LENGTH_MASK) - aLen; 2071 NewExtent[i+d].extLocation = 0; 2072 NewExtent[i+d].extLength |= (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30); 2073 AdPrint(("Not->Alloc (4) new %x\n", NewExtent)); 2074 } 2075 2076 AdPrint(("Free Extent %x, TmpExtInf.Mapping, (new %x)\n", Extent, TmpExtInf.Mapping, NewExtent)); 2077 MyFreePool__(Extent); 2078 MyFreePool__(TmpExtInf.Mapping); 2079 ExtInfo->Modified = TRUE; 2080 ExtInfo->Mapping = NewExtent; 2081 2082 AdPrint(("Not->Alloc: ExtInfo %x, Extent %x\n", ExtInfo, ExtInfo->Mapping)); 2083 2084 return STATUS_SUCCESS; 2085 } // end UDFMarkNotAllocatedAsAllocated() 2086 2087 //#if 0 2088 /* 2089 This routine rebuilds mapping on write zero attempts to 2090 Alloc-Not-Rec area. 2091 Here we assume that required area lays in a single frag. 2092 */ 2093 OSSTATUS 2094 UDFMarkAllocatedAsNotXXX( 2095 IN PVCB Vcb, 2096 IN int64 Offset, 2097 IN uint32 Length, 2098 IN PEXTENT_INFO ExtInfo, // Extent array 2099 IN BOOLEAN Deallocate 2100 ) 2101 { 2102 uint32 i, len, /*lba, d,*/ l, BOffs, j; 2103 PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array 2104 PEXTENT_MAP NewExtent; 2105 // EXTENT_MAP TmpExtent; 2106 // uint32 BS = Vcb->BlockSize; 2107 uint32 BSh = Vcb->BlockSizeBits; 2108 // OSSTATUS status; 2109 EXTENT_INFO TmpExtInf; 2110 uint32 aLen, sLen; 2111 uint32 flags; 2112 uint32 target_flags = Deallocate ? 2113 EXTENT_NOT_RECORDED_NOT_ALLOCATED : 2114 EXTENT_NOT_RECORDED_ALLOCATED; 2115 uint32 LBS = Vcb->LBlockSize; 2116 EXTENT_MAP DeadMapping[2]; 2117 // I don't know what else comment can be added here. 2118 // Just belive that it works 2119 /*lba = */ 2120 #ifndef ALLOW_SPARSE 2121 if(Deallocate) { 2122 BrutePoint(); 2123 } 2124 #endif 2125 2126 AdPrint(("Alloc->Not ExtInfo %x, Extent %x\n", ExtInfo, Extent)); 2127 2128 DeadMapping[0].extLocation = 2129 UDFExtentOffsetToLba(Vcb, ExtInfo->Mapping, Offset, NULL, NULL, NULL, &i); 2130 if(i == (ULONG)-1) { 2131 BrutePoint(); 2132 return STATUS_INVALID_PARAMETER; 2133 } 2134 DeadMapping[0].extLength = Extent[i].extLength; 2135 DeadMapping[1].extLocation = 2136 DeadMapping[1].extLength = 0; 2137 TmpExtInf.Mapping = (PEXTENT_MAP)&DeadMapping; 2138 TmpExtInf.Offset = 0; 2139 TmpExtInf.Length = Extent[i].extLength & UDF_EXTENT_LENGTH_MASK; 2140 2141 flags = Extent[i].extLength >> 30; 2142 if(flags == target_flags) return STATUS_SUCCESS; 2143 2144 // uint32 PartNum = UDFGetPartNumByPhysLba(Vcb, Extent[0].extLocation); 2145 BOffs = (uint32)(Offset >> BSh); 2146 // length of existing Alloc-(Not-)Rec frag (in sectors) 2147 sLen = (( (((uint32)Offset) & (LBS-1)) + Length+LBS-1) & ~(LBS-1)) >> BSh; 2148 // required deallocation length increment (in bytes) 2149 aLen = (uint32)( ((Offset+Length+LBS-1) & ~(LBS-1)) - (Offset & ~(LBS-1)) ); 2150 2151 l=0; 2152 for(j=0; j<i; j++) { 2153 l += (uint32)((Extent[j].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh); 2154 } 2155 flags <<= 30; 2156 if( (l == BOffs) && (((Extent[j].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh) == sLen) ) { 2157 // xxxxxx -> RRRRRR 2158 Extent[i].extLocation = 0; 2159 Extent[i].extLength = (Extent[i].extLength & UDF_EXTENT_LENGTH_MASK) | flags; 2160 NewExtent = Extent; 2161 AdPrint(("Alloc->Not (1) NewExtent = Extent = %x\n", NewExtent)); 2162 } else 2163 if(l < BOffs) { 2164 // .ExtLength, BOffs & l are already aligned... 2165 if( (((Extent[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh) - (BOffs-l)) > sLen ) { 2166 // xxxxxx -> xxRRxx 2167 NewExtent = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, UDFGetMappingLength(Extent) + 2*sizeof(EXTENT_MAP) ); 2168 if(!NewExtent) { 2169 return STATUS_INSUFFICIENT_RESOURCES; 2170 } 2171 RtlCopyMemory((int8*)NewExtent, (int8*)Extent, i*sizeof(EXTENT_MAP)); 2172 RtlCopyMemory((int8*)&(NewExtent[i+3]), (int8*)&(Extent[i+1]), len = UDFGetMappingLength(&(Extent[i+1])) ); 2173 NewExtent[i].extLength = (BOffs - l) << BSh; 2174 NewExtent[i].extLength |= flags; 2175 NewExtent[i+1].extLocation = 0; 2176 NewExtent[i+1].extLength = aLen | (target_flags << 30); 2177 NewExtent[i+2].extLength = (Extent[i].extLength & UDF_EXTENT_LENGTH_MASK) - 2178 (NewExtent[i].extLength & UDF_EXTENT_LENGTH_MASK) - aLen ; 2179 NewExtent[i+2].extLocation = Extent[i].extLocation + 2180 (NewExtent[i+2].extLength >> BSh); 2181 NewExtent[i+2].extLength |= flags; 2182 AdPrint(("Alloc->Not (2) new %x\n", NewExtent)); 2183 } else { 2184 // xxxxxx -> xxRRRR 2185 NewExtent = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, UDFGetMappingLength(Extent) + sizeof(EXTENT_MAP) ); 2186 if(!NewExtent) { 2187 return STATUS_INSUFFICIENT_RESOURCES; 2188 } 2189 RtlCopyMemory((int8*)NewExtent, (int8*)Extent, i*sizeof(EXTENT_MAP)); 2190 RtlCopyMemory((int8*)&(NewExtent[i+2]), (int8*)&(Extent[i+1]), len = UDFGetMappingLength(&(Extent[i+1])) ); 2191 NewExtent[i].extLength = ((BOffs - l) << BSh) | flags; 2192 NewExtent[i+1].extLocation = 0; 2193 NewExtent[i+1].extLength = aLen | (target_flags << 30); 2194 AdPrint(("Alloc->Not (3) new %x\n", NewExtent)); 2195 } 2196 } else { 2197 // xxxxxx -> RRRRxx 2198 NewExtent = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, UDFGetMappingLength(Extent) + sizeof(EXTENT_MAP) ); 2199 if(!NewExtent) { 2200 return STATUS_INSUFFICIENT_RESOURCES; 2201 } 2202 RtlCopyMemory((int8*)NewExtent, (int8*)Extent, i*sizeof(EXTENT_MAP)); 2203 RtlCopyMemory((int8*)&(NewExtent[i+2]), (int8*)&(Extent[i+1]), len = UDFGetMappingLength(&(Extent[i+1])) ); 2204 NewExtent[i+1].extLength = (Extent[i].extLength & UDF_EXTENT_LENGTH_MASK) - aLen; 2205 NewExtent[i+1].extLength |= flags; 2206 NewExtent[i].extLocation = 0; 2207 NewExtent[i].extLength = aLen | (target_flags << 30); 2208 AdPrint(("Alloc->Not (4) new %x\n", NewExtent)); 2209 } 2210 2211 if(Deallocate) 2212 UDFMarkSpaceAsXXX(Vcb, (-1), TmpExtInf.Mapping, AS_DISCARDED); // mark as free 2213 2214 if(Extent) { 2215 AdPrint(("Alloc->Not kill %x\n", Extent)); 2216 MyFreePool__(Extent); 2217 } else { 2218 AdPrint(("Alloc->Not keep %x\n", Extent)); 2219 } 2220 ExtInfo->Modified = TRUE; 2221 ExtInfo->Mapping = NewExtent; 2222 AdPrint(("Alloc->Not: ExtInfo %x, Extent %x\n", ExtInfo, ExtInfo->Mapping)); 2223 2224 return STATUS_SUCCESS; 2225 } // end UDFMarkAllocatedAsNotXXX() 2226 //#endif //0 2227 2228 /* 2229 This routine resizes extent & updates associated mapping 2230 */ 2231 OSSTATUS 2232 UDFResizeExtent( 2233 IN PVCB Vcb, 2234 IN uint32 PartNum, 2235 IN int64 Length, // Required Length 2236 IN BOOLEAN AlwaysInIcb, // must be TRUE for AllocDescs 2237 OUT PEXTENT_INFO ExtInfo 2238 ) 2239 { 2240 uint32 i, flags, lba, lim; 2241 int64 l; 2242 OSSTATUS status; 2243 EXTENT_INFO TmpExtInf; 2244 EXTENT_MAP TmpMapping[2]; 2245 uint32 s, req_s, pe, BSh, LBS, PS; 2246 LBS = Vcb->LBlockSize; 2247 BSh = Vcb->BlockSizeBits; 2248 PS = Vcb->WriteBlockSize >> Vcb->BlockSizeBits; 2249 uint32 MaxGrow = (UDF_MAX_EXTENT_LENGTH & ~(LBS-1)); 2250 BOOLEAN Sequential = FALSE; 2251 2252 ASSERT(PartNum < 3); 2253 2254 ExtPrint(("Resize ExtInfo %x, %I64x -> %I64x\n", ExtInfo, ExtInfo->Length, Length)); 2255 2256 if(ExtInfo->Flags & EXTENT_FLAG_CUT_PREALLOCATED) { 2257 AdPrint((" cut preallocated\n")); 2258 } else 2259 if(ExtInfo->Length == Length) { 2260 return STATUS_SUCCESS; 2261 } 2262 if((ExtInfo->Flags & EXTENT_FLAG_ALLOC_MASK) == EXTENT_FLAG_ALLOC_SEQUENTIAL) { 2263 MaxGrow &= ~(Vcb->WriteBlockSize-1); 2264 Sequential = TRUE; 2265 } 2266 2267 UDFCheckSpaceAllocation(Vcb, 0, ExtInfo->Mapping, AS_USED); // check if used 2268 if(ExtInfo->Offset) { 2269 if(ExtInfo->Offset + Length <= LBS) { 2270 ExtPrint(("Resize IN-ICB\n")); 2271 ExtInfo->Length = Length; 2272 return STATUS_SUCCESS; 2273 } 2274 if(!AlwaysInIcb) // simulate unused 1st sector in extent 2275 ExtInfo->Offset = LBS; // it'll be truncated later 2276 Length += ExtInfo->Offset; // convert to real offset in extent 2277 } 2278 lba = UDFExtentOffsetToLba(Vcb, ExtInfo->Mapping, Length, NULL, NULL, &flags, &i); 2279 if(ExtInfo->Length < Length) { 2280 // increase extent 2281 if(OS_SUCCESS(UDFGetCachedAllocation(Vcb, ExtInfo->Mapping[0].extLocation, 2282 &TmpExtInf, NULL, UDF_PREALLOC_CLASS_DIR))) { 2283 AdPrint(("Resize found cached(1)\n")); 2284 ExtInfo->Mapping = UDFMergeMappings(ExtInfo->Mapping, TmpExtInf.Mapping); 2285 MyFreePool__(TmpExtInf.Mapping); 2286 } 2287 if((l = UDFGetExtentLength(ExtInfo->Mapping)) >= Length) { 2288 // we have enough space inside extent 2289 ExtInfo->Length = Length; 2290 AdPrint(("Resize do nothing (1)\n")); 2291 } else /*if(lba == LBA_OUT_OF_EXTENT)*/ { 2292 2293 Length -= ExtInfo->Offset; 2294 if(/*Length && l &&*/ (l % MaxGrow) && 2295 (Length-1)/MaxGrow != (l-1)/MaxGrow) { 2296 AdPrint(("Crossing MAX_FRAG boundary...\n")); 2297 int64 l2 = ((l-1)/MaxGrow + 1)*MaxGrow; 2298 status = UDFResizeExtent(Vcb, PartNum, l2, AlwaysInIcb, ExtInfo); 2299 if(!OS_SUCCESS(status)) { 2300 UDFPrint(("Sub-call to UDFResizeExtent() failed (%x)\n", status)); 2301 return status; 2302 } 2303 l = ExtInfo->Length; 2304 ASSERT(l == l2); 2305 } 2306 while((Length - l) > MaxGrow) { 2307 status = UDFResizeExtent(Vcb, PartNum, l+MaxGrow, AlwaysInIcb, ExtInfo); 2308 if(!OS_SUCCESS(status)) { 2309 UDFPrint(("Sub-call (2) to UDFResizeExtent() failed (%x)\n", status)); 2310 return status; 2311 } 2312 l = ExtInfo->Length; 2313 } 2314 Length += ExtInfo->Offset; 2315 // at first, try to resize existing frag 2316 #ifndef UDF_ALLOW_FRAG_AD 2317 i = UDFGetMappingLength(ExtInfo->Mapping); 2318 if(i > (LBS-sizeof(EXTENDED_FILE_ENTRY))) { 2319 // this is very important check since we will not 2320 // be able to _record_ too long AllocDesc because of 2321 // some DEMO limitations in UDFBuildXXXAllocDescs() 2322 AdPrint((" DISK_FULL\n")); 2323 return STATUS_DISK_FULL; 2324 } 2325 i /= sizeof(EXTENT_MAP); 2326 #else //UDF_ALLOW_FRAG_AD 2327 i = UDFGetMappingLength(ExtInfo->Mapping) / sizeof(EXTENT_MAP); 2328 #endif //UDF_ALLOW_FRAG_AD 2329 #ifdef ALLOW_SPARSE 2330 if(!AlwaysInIcb && !(ExtInfo->Offset) && 2331 (Length - l >= (Vcb->SparseThreshold << BSh))) { 2332 // last frag will be Not-Alloc-Not-Rec... 2333 AdPrint(("Resize sparse (2)\n")); 2334 RtlZeroMemory(&TmpExtInf, sizeof(EXTENT_INFO)); 2335 TmpExtInf.Mapping = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool , sizeof(EXTENT_MAP)*2, 2336 MEM_EXTMAP_TAG); 2337 if(!TmpExtInf.Mapping) return STATUS_INSUFFICIENT_RESOURCES; 2338 TmpExtInf.Mapping[0].extLength = (((uint32)(Length - l) + LBS-1) & ~(LBS-1)) | (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30); 2339 TmpExtInf.Mapping[0].extLocation =// 0; 2340 TmpExtInf.Mapping[1].extLength = 2341 TmpExtInf.Mapping[1].extLocation = 0; 2342 l = Length; 2343 ExtInfo->Mapping = UDFMergeMappings(ExtInfo->Mapping, TmpExtInf.Mapping); 2344 MyFreePool__(TmpExtInf.Mapping); 2345 } else 2346 #endif //ALLOW_SPARSE 2347 // allocate some sectors 2348 if(i>1 && !(ExtInfo->Offset)) { 2349 i-=2; 2350 // check if Not-Alloc-Not-Rec at the end of mapping 2351 if((uint32)Length - (uint32)l + (ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK) > MaxGrow) { 2352 // do nothing, but jump directly to allocator 2353 } else 2354 if((ExtInfo->Mapping[i].extLength >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED) { 2355 AdPrint(("Resize grow sparse (3)\n")); 2356 ExtInfo->Mapping[i].extLength += 2357 (((uint32)Length-(uint32)l+LBS-1) & ~(LBS-1)) ; 2358 l = Length; 2359 // check if Alloc-Not-Rec at the end of mapping 2360 } else if((ExtInfo->Mapping[i].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) { 2361 AdPrint(("Resize grow Not-Rec (3)\n")); 2362 // current length of last frag 2363 s = ((ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh); 2364 // prefered location of the next frag 2365 lba = ExtInfo->Mapping[i].extLocation + s; 2366 pe=UDFPartEnd(Vcb,PartNum); 2367 // maximum frag length 2368 if(Sequential) { 2369 lim = (((uint32)UDF_MAX_EXTENT_LENGTH) >> BSh) & ~(PS-1); 2370 } else { 2371 lim = (((uint32)UDF_MAX_EXTENT_LENGTH) >> BSh) & ~(LBS-1); 2372 } 2373 // required last extent length 2374 req_s = s + (uint32)( (((Length + LBS - 1) & ~(LBS-1)) - 2375 ((l + LBS - 1) & ~(LBS-1)) ) >> BSh); 2376 if(lim > req_s) { 2377 lim = req_s; 2378 } 2379 UDFAcquireResourceExclusive(&(Vcb->BitMapResource1),TRUE); 2380 /* if((ExtInfo->Flags & EXTENT_FLAG_SEQUENTIAL) && 2381 ((Length & ~(PS-1)) > (l & ~(PS-1))) && 2382 TRUE) { 2383 status = UDFResizeExtent(Vcb, PartNum, l+MaxGrow, AlwaysInIcb, ExtInfo); 2384 }*/ 2385 // how many sectors we should add 2386 req_s = lim - s; 2387 ASSERT(req_s); 2388 if((lba < pe) && UDFGetFreeBit(Vcb->FSBM_Bitmap, lba)) { 2389 s += UDFGetBitmapLen((uint32*)(Vcb->FSBM_Bitmap), lba, min(pe, lba+req_s-1)); 2390 } 2391 /* for(s1=lba; (s<lim) && (s1<pe) && UDFGetFreeBit(Vcb->FSBM_Bitmap, s1); s1++) { 2392 s++; 2393 }*/ 2394 if(s==lim) { 2395 // we can just increase the last frag 2396 AdPrint(("Resize grow last Not-Rec (4)\n")); 2397 ExtInfo->Mapping[i].extLength = (lim << BSh) | (EXTENT_NOT_RECORDED_ALLOCATED << 30); 2398 l = Length; 2399 UDFMarkSpaceAsXXXNoProtect(Vcb, 0, &(ExtInfo->Mapping[i]), AS_USED); // mark as used 2400 } else { 2401 // we get here if simple increasing of last frag failed 2402 // it worth truncating last frag and try to allocate 2403 // all required data as a single frag 2404 2405 /* if(Sequential && s>=PS) { 2406 s &= ~(PS-1); 2407 AdPrint(("Resize grow last Not-Rec (4/2)\n")); 2408 ExtInfo->Mapping[i].extLength = (s << BSh) | (EXTENT_NOT_RECORDED_ALLOCATED << 30); 2409 l += (s << BSh); 2410 UDFMarkSpaceAsXXXNoProtect(Vcb, 0, &(ExtInfo->Mapping[i]), AS_USED); // mark as used 2411 }*/ 2412 AdPrint(("Resize reloc last Not-Rec (5)\n")); 2413 TmpExtInf.Mapping = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool , (i+1)*sizeof(EXTENT_MAP), 2414 MEM_EXTMAP_TAG); 2415 if(!TmpExtInf.Mapping) { 2416 UDFPrint(("UDFResizeExtent: !TmpExtInf.Mapping\n")); 2417 UDFReleaseResource(&(Vcb->BitMapResource1)); 2418 return STATUS_INSUFFICIENT_RESOURCES; 2419 } 2420 RtlCopyMemory(TmpExtInf.Mapping, ExtInfo->Mapping, i*sizeof(EXTENT_MAP)); 2421 TmpExtInf.Mapping[i].extLength = 2422 TmpExtInf.Mapping[i].extLocation = 0; 2423 TmpExtInf.Offset = ExtInfo->Offset; 2424 l -= (ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK); 2425 TmpExtInf.Length = l; 2426 ASSERT(i || !ExtInfo->Offset); 2427 UDFMarkSpaceAsXXXNoProtect(Vcb, 0, &(ExtInfo->Mapping[i]), AS_DISCARDED); // mark as free 2428 MyFreePool__(ExtInfo->Mapping); 2429 (*ExtInfo) = TmpExtInf; 2430 } 2431 UDFCheckSpaceAllocation(Vcb, 0, ExtInfo->Mapping, AS_USED); // check if used 2432 UDFReleaseResource(&(Vcb->BitMapResource1)); 2433 // check if Alloc-Rec 2434 } else { 2435 // current length of last frag 2436 s = ((ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh); 2437 // prefered location of the next frag 2438 lba = ExtInfo->Mapping[i].extLocation + s; 2439 pe=UDFPartEnd(Vcb,PartNum); 2440 // maximum frag length 2441 if(Sequential) { 2442 lim = (((uint32)UDF_MAX_EXTENT_LENGTH) >> BSh) & ~(PS-1); 2443 } else { 2444 lim = (((uint32)UDF_MAX_EXTENT_LENGTH) >> BSh) & ~(LBS-1); 2445 } 2446 // required last extent length 2447 req_s = s + (uint32)( (((Length + LBS - 1) & ~(LBS-1)) - 2448 ((l + LBS - 1) & ~(LBS-1)) ) >> BSh); 2449 if(lim > req_s) { 2450 lim = req_s; 2451 } 2452 // s=0; 2453 // how many sectors we should add 2454 req_s = lim - s; 2455 if(req_s) { 2456 uint32 d=0; 2457 2458 UDFAcquireResourceExclusive(&(Vcb->BitMapResource1),TRUE); 2459 //ASSERT(req_s); 2460 if((lba < pe) && UDFGetFreeBit(Vcb->FSBM_Bitmap, lba)) { 2461 s += (d = UDFGetBitmapLen((uint32*)(Vcb->FSBM_Bitmap), lba, min(pe, lba+req_s-1))); 2462 } 2463 /* for(s1=lba; (s<lim) && (s1<pe) && UDFGetFreeBit(Vcb->FSBM_Bitmap, s1); s1++) { 2464 s++; 2465 }*/ 2466 2467 if(s==lim) { 2468 AdPrint(("Resize grow last Rec (6)\n")); 2469 // we can just increase last frag 2470 TmpMapping[0].extLength = req_s << BSh; 2471 TmpMapping[0].extLocation = lba; 2472 TmpMapping[1].extLength = 2473 TmpMapping[1].extLocation = 0; 2474 UDFMarkSpaceAsXXXNoProtect(Vcb, 0, &TmpMapping[0], AS_USED); // mark as used 2475 l += (s << BSh) - (ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK); 2476 ExtInfo->Mapping[i].extLength = (ExtInfo->Mapping[i].extLength & UDF_EXTENT_FLAG_MASK) | (s << BSh); 2477 } else if(d) { 2478 AdPrint(("Resize part-grow last Rec (6)\n")); 2479 // increase last frag, then alloc rest 2480 TmpMapping[0].extLength = d << BSh; 2481 TmpMapping[0].extLocation = lba; 2482 TmpMapping[1].extLength = 2483 TmpMapping[1].extLocation = 0; 2484 UDFMarkSpaceAsXXXNoProtect(Vcb, 0, &TmpMapping[0], AS_USED); // mark as used 2485 l += (s << BSh) - (ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK); 2486 ExtInfo->Mapping[i].extLength = (ExtInfo->Mapping[i].extLength & UDF_EXTENT_FLAG_MASK) | (s << BSh); 2487 } else { 2488 AdPrint(("Can't grow last Rec (6)\n")); 2489 } 2490 UDFReleaseResource(&(Vcb->BitMapResource1)); 2491 } else { 2492 AdPrint(("Max frag length reached (6)\n")); 2493 } 2494 } 2495 } 2496 if(l < Length) { 2497 // we get here if simple increasing of the last frag failed 2498 AdPrint(("Resize add new frag (7)\n")); 2499 if(l < LBS && Length >= LBS && 2500 (ExtInfo->Flags & EXTENT_FLAG_ALLOC_MASK) == EXTENT_FLAG_ALLOC_SEQUENTIAL) { 2501 AdPrint(("Resize tune for SEQUENTIAL i/o\n")); 2502 } 2503 status = UDFAllocFreeExtent(Vcb, Length - l, 2504 UDFPartStart(Vcb, PartNum), 2505 UDFPartEnd(Vcb, PartNum), 2506 &TmpExtInf, 2507 ExtInfo->Flags /*& EXTENT_FLAG_ALLOC_MASK*/); 2508 if(!OS_SUCCESS(status)) { 2509 UDFPrint(("UDFResizeExtent: UDFAllocFreeExtent() failed (%x)\n", status)); 2510 return status; 2511 } 2512 ExtInfo->Mapping = UDFMergeMappings(ExtInfo->Mapping, TmpExtInf.Mapping); 2513 MyFreePool__(TmpExtInf.Mapping); 2514 } 2515 UDFPackMapping(Vcb, ExtInfo); 2516 } 2517 } else 2518 if(Length) { 2519 // decrease extent 2520 AdPrint(("Resize cut (8)\n")); 2521 lba = UDFExtentOffsetToLba(Vcb, ExtInfo->Mapping, Length-1, NULL, &lim, &flags, &i); 2522 i++; 2523 ASSERT(lba != LBA_OUT_OF_EXTENT); 2524 ASSERT(lba != LBA_NOT_ALLOCATED); 2525 ASSERT(i); 2526 if(ExtInfo->Mapping[i].extLength) { 2527 UDFCheckSpaceAllocation(Vcb, 0, &(ExtInfo->Mapping[i]), AS_USED); // check if used 2528 if(!ExtInfo->Offset && (ExtInfo->Flags & EXTENT_FLAG_PREALLOCATED)) { 2529 2530 AdPrint(("Resize try save cutted (8)\n")); 2531 RtlZeroMemory(&TmpExtInf, sizeof(EXTENT_INFO)); 2532 s = UDFGetMappingLength(&(ExtInfo->Mapping[i])); 2533 2534 TmpExtInf.Mapping = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool , s, MEM_EXTMAP_TAG); 2535 if(TmpExtInf.Mapping) { 2536 RtlCopyMemory(TmpExtInf.Mapping, &(ExtInfo->Mapping[i]), s); 2537 AdPrint(("Resize save cutted (8)\n")); 2538 if(OS_SUCCESS(UDFStoreCachedAllocation(Vcb, ExtInfo->Mapping[0].extLocation, 2539 &TmpExtInf, 0, UDF_PREALLOC_CLASS_DIR))) { 2540 ExtInfo->Mapping[i].extLength = 0; 2541 ExtInfo->Mapping[i].extLocation = 0; 2542 goto tail_cached; 2543 } 2544 } 2545 } 2546 UDFMarkSpaceAsXXX(Vcb, 0, &(ExtInfo->Mapping[i]), AS_DISCARDED); // mark as free 2547 tail_cached:; 2548 } 2549 if((lim-1 >= LBS) && 2550 (flags != EXTENT_NOT_RECORDED_NOT_ALLOCATED)) { 2551 AdPrint(("i=%x, lba=%x, len=%x\n",i,lba,lim)); 2552 ASSERT(lim); 2553 // BrutePoint(); 2554 EXTENT_MAP ClrMap[2]; 2555 ClrMap[0].extLength = lim & ~(LBS-1); 2556 s = (ExtInfo->Mapping[i-1].extLength - ClrMap[0].extLength) & UDF_EXTENT_LENGTH_MASK; 2557 ClrMap[0].extLocation = ExtInfo->Mapping[i-1].extLocation + 2558 (s >> BSh); 2559 ClrMap[1].extLength = 2560 ClrMap[1].extLocation = 0; 2561 ASSERT((ExtInfo->Mapping[i].extLocation < ClrMap[0].extLocation) || 2562 (ExtInfo->Mapping[i].extLocation >= (ClrMap[0].extLocation + (ClrMap[0].extLength >> BSh)))); 2563 UDFCheckSpaceAllocation(Vcb, 0, (PEXTENT_MAP)(&ClrMap), AS_USED); // check if used 2564 UDFMarkSpaceAsXXX(Vcb, 0, (PEXTENT_MAP)(&ClrMap), AS_DISCARDED); // mark as free 2565 ExtInfo->Mapping[i-1].extLength = s | (flags << 30); 2566 } 2567 2568 s = UDFGetMappingLength(ExtInfo->Mapping); 2569 if(!MyReallocPool__((int8*)(ExtInfo->Mapping), s, (int8**)&(ExtInfo->Mapping), (i+1)*sizeof(EXTENT_MAP))) { 2570 // This must never happen on truncate !!! 2571 AdPrint(("ResizeExtent: MyReallocPool__(8) failed\n")); 2572 } 2573 ExtInfo->Mapping[i].extLength = 2574 ExtInfo->Mapping[i].extLocation = 0; 2575 } else { 2576 AdPrint(("Resize zero (9)\n")); 2577 ASSERT(!ExtInfo->Offset); 2578 UDFMarkSpaceAsXXX(Vcb, 0, ExtInfo->Mapping, AS_DISCARDED); // mark as free 2579 s = UDFGetMappingLength(ExtInfo->Mapping); 2580 if(!MyReallocPool__((int8*)(ExtInfo->Mapping), s, (int8**)&(ExtInfo->Mapping), 2*sizeof(EXTENT_MAP))) { 2581 // This must never happen on truncate !!! 2582 AdPrint(("ResizeExtent: MyReallocPool__(9) failed\n")); 2583 } 2584 ExtInfo->Mapping[0].extLength = LBS | (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30); 2585 ExtInfo->Mapping[0].extLocation = 2586 ExtInfo->Mapping[1].extLength = 2587 ExtInfo->Mapping[1].extLocation = 0; 2588 } 2589 if(ExtInfo->Offset) { 2590 if(!AlwaysInIcb) { 2591 // remove 1st entry pointing to FileEntry 2592 s = UDFGetMappingLength(ExtInfo->Mapping); 2593 RtlMoveMemory(&(ExtInfo->Mapping[0]), &(ExtInfo->Mapping[1]), s - sizeof(EXTENT_MAP)); 2594 if(!MyReallocPool__((int8*)(ExtInfo->Mapping), s, 2595 (int8**)&(ExtInfo->Mapping), s - sizeof(EXTENT_MAP) )) { 2596 // This must never happen on truncate !!! 2597 AdPrint(("ResizeExtent: MyReallocPool__(10) failed\n")); 2598 } 2599 Length -= ExtInfo->Offset; 2600 ExtInfo->Offset = 0; 2601 } else { 2602 Length -= ExtInfo->Offset; // back to in-icb 2603 } 2604 } 2605 ExtInfo->Length = Length; 2606 UDFCheckSpaceAllocation(Vcb, 0, ExtInfo->Mapping, AS_USED); // check if used 2607 2608 for(i=0; (ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK); i++) { 2609 ExtPrint(("Resized Ext: type %x, loc %x, len %x\n", 2610 ExtInfo->Mapping[i].extLength >> 30, ExtInfo->Mapping[i].extLocation, ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK)); 2611 } 2612 2613 return STATUS_SUCCESS; 2614 } // end UDFResizeExtent() 2615 2616 /* 2617 This routine (re)builds AllocDescs data for all allocation modes except 2618 in-ICB & resizes associated extent (FileInfo->Dloc->AllocLoc) for 2619 already allocated user data extent (FileInfo->Dloc->DataLoc). 2620 AllocMode in FileEntry pointed by FileInfo must be already initialized. 2621 */ 2622 OSSTATUS 2623 UDFBuildAllocDescs( 2624 IN PVCB Vcb, 2625 IN uint32 PartNum, 2626 IN OUT PUDF_FILE_INFO FileInfo, 2627 OUT int8** AllocData 2628 ) 2629 { 2630 // PEXTENT_MAP InMap; 2631 // uint32 i=0; 2632 int8* Allocs; 2633 uint16 AllocMode; 2634 uint32 InitSz; 2635 OSSTATUS status; 2636 2637 ValidateFileInfo(FileInfo); 2638 AdPrint(("BuildAllocDesc\n")); 2639 // get space available in the 1st LBlock after FE 2640 InitSz = Vcb->LBlockSize - FileInfo->Dloc->FileEntryLen; 2641 Allocs = (int8*)MyAllocatePool__(NonPagedPool, InitSz); 2642 if(!Allocs) { 2643 *AllocData = NULL; 2644 AdPrint(("BuildAllocDesc: cant alloc %x bytes for Allocs\n", InitSz)); 2645 return STATUS_INSUFFICIENT_RESOURCES; 2646 } 2647 RtlZeroMemory(Allocs, InitSz); 2648 // InMap = FileInfo->Dloc->DataLoc.Mapping; 2649 UDFCheckSpaceAllocation(Vcb, 0, InMap, AS_USED); // check if used 2650 2651 // TODO: move data from mapped locations here 2652 2653 AllocMode = ((PFILE_ENTRY)(FileInfo->Dloc->FileEntry))->icbTag.flags & ICB_FLAG_ALLOC_MASK; 2654 switch(AllocMode) { 2655 case ICB_FLAG_AD_IN_ICB: { 2656 MyFreePool__(Allocs); 2657 ASSERT(!FileInfo->Dloc->AllocLoc.Mapping); 2658 Allocs = NULL; 2659 status = STATUS_SUCCESS; 2660 break; 2661 } 2662 case ICB_FLAG_AD_SHORT: { 2663 status = UDFBuildShortAllocDescs(Vcb, PartNum, &Allocs, InitSz, FileInfo); 2664 break; 2665 } 2666 case ICB_FLAG_AD_LONG: { 2667 status = UDFBuildLongAllocDescs(Vcb, PartNum, &Allocs, InitSz, FileInfo); 2668 break; 2669 } 2670 /* case ICB_FLAG_AD_EXTENDED: { 2671 status = UDFBuildExtAllocDescs(Vcb, PartNum, &Allocs, InitSz, FileInfo); 2672 break; 2673 }*/ 2674 default: { 2675 MyFreePool__(Allocs); 2676 Allocs = NULL; 2677 status = STATUS_INVALID_PARAMETER; 2678 } 2679 } 2680 2681 *AllocData = Allocs; 2682 UDFCheckSpaceAllocation(Vcb, 0, FileInfo->Dloc->DataLoc.Mapping, AS_USED); // check if used 2683 2684 return status; 2685 } // end UDFBuildAllocDescs() 2686 2687 /* 2688 This routine discards file's allocation 2689 */ 2690 void 2691 UDFFreeFileAllocation( 2692 IN PVCB Vcb, 2693 IN PUDF_FILE_INFO DirInfo, 2694 IN PUDF_FILE_INFO FileInfo 2695 ) 2696 { 2697 if(FileInfo->Dloc->DataLoc.Offset) { 2698 // in-ICB data 2699 if(FileInfo->Dloc->DataLoc.Mapping) { 2700 ASSERT(FileInfo->Dloc->FELoc.Mapping[0].extLocation == 2701 FileInfo->Dloc->DataLoc.Mapping[0].extLocation); 2702 UDFMarkSpaceAsXXX(Vcb, FileInfo->Dloc, &(FileInfo->Dloc->DataLoc.Mapping[1]), AS_DISCARDED); // free 2703 FileInfo->Dloc->DataLoc.Mapping[1].extLocation = 2704 FileInfo->Dloc->DataLoc.Mapping[1].extLength = 0; 2705 FileInfo->Dloc->DataLoc.Mapping[0].extLocation = 0; 2706 FileInfo->Dloc->DataLoc.Mapping[0].extLength = EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30; 2707 } 2708 if(FileInfo->Dloc->AllocLoc.Mapping) { 2709 ASSERT(FileInfo->Dloc->FELoc.Mapping[0].extLocation == 2710 FileInfo->Dloc->AllocLoc.Mapping[0].extLocation); 2711 UDFMarkSpaceAsXXX(Vcb, FileInfo->Dloc, &(FileInfo->Dloc->AllocLoc.Mapping[1]), AS_DISCARDED); // free 2712 FileInfo->Dloc->AllocLoc.Mapping[1].extLocation = 2713 FileInfo->Dloc->AllocLoc.Mapping[1].extLength = 0; 2714 FileInfo->Dloc->AllocLoc.Mapping[0].extLocation = 0; 2715 FileInfo->Dloc->AllocLoc.Mapping[0].extLength = EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30; 2716 } 2717 UDFFreeFESpace(Vcb, DirInfo, &(FileInfo->Dloc->FELoc)); 2718 } else { 2719 if(FileInfo->Dloc->AllocLoc.Mapping) { 2720 ASSERT(FileInfo->Dloc->FELoc.Mapping[0].extLocation == 2721 FileInfo->Dloc->AllocLoc.Mapping[0].extLocation); 2722 UDFMarkSpaceAsXXX(Vcb, FileInfo->Dloc, &(FileInfo->Dloc->AllocLoc.Mapping[1]), AS_DISCARDED); // free 2723 FileInfo->Dloc->AllocLoc.Mapping[1].extLocation = 2724 FileInfo->Dloc->AllocLoc.Mapping[1].extLength = 0; 2725 FileInfo->Dloc->AllocLoc.Mapping[0].extLocation = 0; 2726 FileInfo->Dloc->AllocLoc.Mapping[0].extLength = EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30; 2727 } 2728 UDFFreeFESpace(Vcb, DirInfo, &(FileInfo->Dloc->FELoc)); 2729 UDFMarkSpaceAsXXX(Vcb, FileInfo->Dloc, FileInfo->Dloc->DataLoc.Mapping, AS_DISCARDED); // free 2730 } 2731 FileInfo->Dloc->DataLoc.Modified = 2732 FileInfo->Dloc->AllocLoc.Modified = 2733 FileInfo->Dloc->FELoc.Modified = FALSE; 2734 } // end UDFFreeFileAllocation() 2735 #endif //UDF_READ_ONLY_BUILD 2736 2737 /* 2738 This routine packs physically sequential extents into single one 2739 */ 2740 void 2741 __fastcall 2742 UDFPackMapping( 2743 IN PVCB Vcb, 2744 IN PEXTENT_INFO ExtInfo // Extent array 2745 ) 2746 { 2747 PEXTENT_MAP NewMap, OldMap; 2748 uint32 i, j, l; 2749 uint32 LastLba, LastType, OldLen; 2750 uint32 OldSize, NewSize; 2751 #ifdef UDF_DBG 2752 int64 check_size; 2753 #endif //UDF_DBG 2754 2755 AdPrint(("Pack ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping)); 2756 AdPrint((" Length %x\n", ExtInfo->Length)); 2757 2758 OldMap = ExtInfo->Mapping; 2759 LastLba = OldMap[0].extLocation; 2760 OldLen = (OldMap[0].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->BlockSizeBits; 2761 LastType = OldMap[0].extLength >> 30; 2762 OldSize = 2763 NewSize = UDFGetMappingLength(OldMap); 2764 #ifdef UDF_DBG 2765 check_size = UDFGetExtentLength(ExtInfo->Mapping); 2766 ASSERT(!(check_size & (2048-1))); 2767 #endif //UDF_DBG 2768 2769 l=OldMap[0].extLength & UDF_EXTENT_LENGTH_MASK; 2770 // calculate required length 2771 for(i=1; OldMap[i].extLength; i++) { 2772 if((LastType == (OldMap[i].extLength >> 30)) 2773 && 2774 ((OldMap[i].extLocation == LastLba + OldLen) || 2775 (!OldMap[i].extLocation && !LastLba && (LastType == EXTENT_NOT_RECORDED_NOT_ALLOCATED))) 2776 && 2777 (l + (OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK) <= UDF_MAX_EXTENT_LENGTH)) { 2778 // we can pack two blocks in one 2779 l += OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK; 2780 NewSize -= sizeof(EXTENT_MAP); 2781 } else { 2782 l = OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK; 2783 } 2784 LastLba = OldMap[i].extLocation; 2785 LastType = OldMap[i].extLength >> 30; 2786 OldLen = (OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->BlockSizeBits; 2787 } 2788 // no changes ? 2789 if(OldSize <= (NewSize + PACK_MAPPING_THRESHOLD)) { 2790 if(OldSize == NewSize) 2791 return; 2792 if(NewSize >= PACK_MAPPING_THRESHOLD) 2793 return; 2794 } 2795 AdPrint(("Pack ExtInfo %x, Mapping %x, realloc\n", ExtInfo, ExtInfo->Mapping)); 2796 NewMap = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool , NewSize, 2797 MEM_EXTMAP_TAG); 2798 // can't alloc ? 2799 if(!NewMap) return; 2800 // Ok, lets pack it... 2801 j=0; 2802 NewMap[0] = OldMap[0]; 2803 LastLba = OldMap[0].extLocation; 2804 OldLen = (OldMap[0].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->BlockSizeBits; 2805 LastType = OldMap[0].extLength >> 30; 2806 for(i=1; OldMap[i].extLength; i++) { 2807 2808 ExtPrint(("oShExt: type %x, loc %x, len %x\n", 2809 OldMap[i].extLength >> 30, OldMap[i].extLocation, OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK)); 2810 2811 if((LastType == (OldMap[i].extLength >> 30)) 2812 && 2813 ((OldMap[i].extLocation == LastLba + OldLen) || 2814 (!OldMap[i].extLocation && !LastLba && (LastType == EXTENT_NOT_RECORDED_NOT_ALLOCATED))) 2815 && 2816 ((NewMap[j].extLength & UDF_EXTENT_LENGTH_MASK) + (OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK) <= UDF_MAX_EXTENT_LENGTH)) { 2817 NewMap[j].extLength += OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK; 2818 } else { 2819 j++; 2820 NewMap[j] = OldMap[i]; 2821 } 2822 2823 ExtPrint(("nShExt: type %x, loc %x, len %x\n", 2824 NewMap[j].extLength >> 30, NewMap[j].extLocation, NewMap[j].extLength & UDF_EXTENT_LENGTH_MASK)); 2825 2826 LastLba = OldMap[i].extLocation; 2827 LastType = OldMap[i].extLength >> 30; 2828 OldLen = (OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->BlockSizeBits; 2829 } 2830 // write terminator 2831 j++; 2832 ASSERT(NewSize == (j+1)*sizeof(EXTENT_MAP)); 2833 NewMap[j].extLength = 2834 NewMap[j].extLocation = 0; 2835 2836 #ifdef UDF_DBG 2837 ASSERT(check_size == UDFGetExtentLength(ExtInfo->Mapping)); 2838 ASSERT(check_size == UDFGetExtentLength(NewMap)); 2839 #endif 2840 2841 AdPrint(("Pack ExtInfo %x, NewMap %x, OldMap %x\n", ExtInfo, NewMap, OldMap)); 2842 2843 ExtInfo->Mapping = NewMap; 2844 MyFreePool__(OldMap); 2845 2846 AdPrint(("Pack ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping)); 2847 AdPrint((" Length %x\n", ExtInfo->Length)); 2848 } // end UDFPackMapping() 2849 2850 /* 2851 This routine expands mapping to 'frag-per-LBlock' state 2852 */ 2853 OSSTATUS 2854 __fastcall 2855 UDFUnPackMapping( 2856 IN PVCB Vcb, 2857 IN PEXTENT_INFO ExtInfo // Extent array 2858 ) 2859 { 2860 PEXTENT_MAP NewMapping; 2861 PEXTENT_MAP Mapping = ExtInfo->Mapping; 2862 uint32 LBS = Vcb->LBlockSize; 2863 uint32 len = (uint32)(UDFGetExtentLength(Mapping) >> Vcb->LBlockSizeBits); 2864 uint32 i,j, type, base, d; 2865 LONG l; 2866 2867 NewMapping = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool , (len+1)*sizeof(EXTENT_MAP), 2868 MEM_EXTMAP_TAG); 2869 if(!NewMapping) return STATUS_INSUFFICIENT_RESOURCES; 2870 2871 j=0; 2872 d = LBS >> Vcb->BlockSizeBits; 2873 for(i=0; (l = (Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK)); i++) { 2874 base = Mapping[i].extLocation; 2875 type = Mapping[i].extLength & UDF_EXTENT_FLAG_MASK; 2876 for(; l>=(LONG)LBS; j++) { 2877 NewMapping[j].extLength = LBS | type; 2878 NewMapping[j].extLocation = base; 2879 base+=d; 2880 l-=LBS; 2881 } 2882 } 2883 // record terminator 2884 ASSERT(NewMapping); 2885 RtlZeroMemory(&(NewMapping[j]), sizeof(EXTENT_MAP)); 2886 MyFreePool__(Mapping); 2887 ExtInfo->Mapping = NewMapping; 2888 2889 return STATUS_SUCCESS; 2890 } // end UDFUnPackMapping() 2891 2892 /* 2893 Relocate a part of extent that starts from relative (inside extent) 2894 block number 'ExtBlock' and has length of 'BC' blocks to continuous 2895 run which starts at block 'Lba' 2896 */ 2897 OSSTATUS 2898 UDFRelocateExtent( 2899 IN PVCB Vcb, 2900 IN PEXTENT_INFO ExtInfo, 2901 IN uint32 ExtBlock, 2902 IN uint32 Lba, 2903 IN uint32 BC 2904 ) 2905 { 2906 return STATUS_ACCESS_DENIED; 2907 } 2908 2909 /* 2910 This routine checks if all the data required is in cache. 2911 */ 2912 BOOLEAN 2913 UDFIsExtentCached( 2914 IN PVCB Vcb, 2915 IN PEXTENT_INFO ExtInfo, // Extent array 2916 IN int64 Offset, // offset in extent 2917 IN uint32 Length, 2918 IN BOOLEAN ForWrite 2919 ) 2920 { 2921 BOOLEAN retstat = FALSE; 2922 PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array 2923 uint32 to_read, Lba, sect_offs, flags, i; 2924 2925 WCacheStartDirect__(&(Vcb->FastCache), Vcb, TRUE/*FALSE*//*ForWrite*/); 2926 if(!ExtInfo || !ExtInfo->Mapping) goto EO_IsCached; 2927 if(!Length) { 2928 retstat = TRUE; 2929 goto EO_IsCached; 2930 } 2931 2932 // prevent reading out of data space 2933 if(Offset > ExtInfo->Length) goto EO_IsCached; 2934 if(Offset+Length > ExtInfo->Length) goto EO_IsCached; 2935 Offset += ExtInfo->Offset; // used for in-ICB data 2936 // read maximal possible part of each frag of extent 2937 Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_read, &flags, &i); 2938 while(((LONG)Length) > 0) { 2939 // EOF check 2940 if(Lba == LBA_OUT_OF_EXTENT) goto EO_IsCached; 2941 Extent += (i + 1); 2942 // check for reading tail 2943 to_read = min(to_read, Length); 2944 if(flags == EXTENT_RECORDED_ALLOCATED) { 2945 retstat = UDFIsDataCached(Vcb, Lba, (to_read+sect_offs+Vcb->BlockSize-1)>>Vcb->BlockSizeBits); 2946 if(!retstat) goto EO_IsCached; 2947 } else if(ForWrite) { 2948 goto EO_IsCached; 2949 } 2950 Offset += to_read; 2951 Length -= to_read; 2952 Lba = UDFNextExtentToLba(Vcb, Extent, &to_read, &flags, &i); 2953 } 2954 retstat = TRUE; 2955 EO_IsCached: 2956 if(!retstat) { 2957 WCacheEODirect__(&(Vcb->FastCache), Vcb); 2958 } 2959 return retstat; 2960 } // end UDFIsExtentCached() 2961 2962 /* 2963 This routine reads cached data only. 2964 */ 2965 /*OSSTATUS 2966 UDFReadExtentCached( 2967 IN PVCB Vcb, 2968 IN PEXTENT_INFO ExtInfo, // Extent array 2969 IN int64 Offset, // offset in extent 2970 IN uint32 Length, 2971 OUT int8* Buffer, 2972 OUT uint32* ReadBytes 2973 ) 2974 { 2975 (*ReadBytes) = 0; 2976 if(!ExtInfo || !ExtInfo->Mapping) return STATUS_INVALID_PARAMETER; 2977 2978 PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array 2979 uint32 to_read, Lba, sect_offs, flags, _ReadBytes; 2980 OSSTATUS status; 2981 // prevent reading out of data space 2982 if(Offset > ExtInfo->Length) return STATUS_END_OF_FILE; 2983 if(Offset+Length > ExtInfo->Length) Length = (uint32)(ExtInfo->Length - Offset); 2984 Offset += ExtInfo->Offset; // used for in-ICB data 2985 // read maximal possible part of each frag of extent 2986 while(((LONG)Length) > 0) { 2987 Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_read, &flags, NULL); 2988 // EOF check 2989 if(Lba == LBA_OUT_OF_EXTENT) return STATUS_END_OF_FILE; 2990 // check for reading tail 2991 to_read = (to_read < Length) ? 2992 to_read : Length; 2993 if(flags == EXTENT_RECORDED_ALLOCATED) { 2994 status = UDFReadDataCached(Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs, to_read, Buffer, &_ReadBytes); 2995 (*ReadBytes) += _ReadBytes; 2996 } else { 2997 RtlZeroMemory(Buffer, to_read); 2998 (*ReadBytes) += to_read; 2999 status = STATUS_SUCCESS; 3000 } 3001 if(!OS_SUCCESS(status)) return status; 3002 // prepare for reading next frag... 3003 Buffer += to_read; 3004 Offset += to_read; 3005 Length -= to_read; 3006 } 3007 return STATUS_SUCCESS; 3008 } // end UDFReadExtentCached()*/ 3009 3010 /* 3011 This routine reads data at any offset from specified extent. 3012 */ 3013 OSSTATUS 3014 UDFReadExtent( 3015 IN PVCB Vcb, 3016 IN PEXTENT_INFO ExtInfo, // Extent array 3017 IN int64 Offset, // offset in extent 3018 IN uint32 Length, 3019 IN BOOLEAN Direct, 3020 OUT int8* Buffer, 3021 OUT uint32* ReadBytes 3022 ) 3023 { 3024 (*ReadBytes) = 0; 3025 if(!ExtInfo || !ExtInfo->Mapping) return STATUS_INVALID_PARAMETER; 3026 ASSERT((uint32)Buffer > 0x1000); 3027 3028 AdPrint(("Read ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping)); 3029 3030 PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array 3031 uint32 to_read, Lba, sect_offs, flags, _ReadBytes; 3032 OSSTATUS status; 3033 // prevent reading out of data space 3034 if(Offset > ExtInfo->Length) return STATUS_END_OF_FILE; 3035 if(Offset+Length > ExtInfo->Length) Length = (uint32)(ExtInfo->Length - Offset); 3036 Offset += ExtInfo->Offset; // used for in-ICB data 3037 // read maximal possible part of each frag of extent 3038 Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_read, &flags, &_ReadBytes); 3039 while(Length) { 3040 // EOF check 3041 if(Lba == LBA_OUT_OF_EXTENT) return STATUS_END_OF_FILE; 3042 Extent += (_ReadBytes + 1); 3043 // check for reading tail 3044 to_read = min(to_read, Length); 3045 if(flags == EXTENT_RECORDED_ALLOCATED) { 3046 status = UDFReadData(Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs, to_read, Direct, Buffer, &_ReadBytes); 3047 (*ReadBytes) += _ReadBytes; 3048 if(!OS_SUCCESS(status)) return status; 3049 } else { 3050 RtlZeroMemory(Buffer, to_read); 3051 (*ReadBytes) += to_read; 3052 } 3053 // prepare for reading next frag... 3054 Length -= to_read; 3055 if(!Length) 3056 break; 3057 ASSERT(to_read); 3058 Buffer += to_read; 3059 // Offset += to_read; 3060 Lba = UDFNextExtentToLba(Vcb, Extent, &to_read, &flags, &_ReadBytes); 3061 sect_offs = 0; 3062 } 3063 return STATUS_SUCCESS; 3064 } // end UDFReadExtent() 3065 3066 /* 3067 This routine reads and builds mapping for 3068 specified amount of data at any offset from specified extent. 3069 Size of output buffer is limited by *_SubExtInfoSz 3070 */ 3071 OSSTATUS 3072 UDFReadExtentLocation( 3073 IN PVCB Vcb, 3074 IN PEXTENT_INFO ExtInfo, // Extent array 3075 IN int64 Offset, // offset in extent to start SubExtent from 3076 OUT PEXTENT_MAP* _SubExtInfo, // SubExtent mapping array 3077 IN OUT uint32* _SubExtInfoSz, // IN: maximum number of fragments to get 3078 // OUT: actually obtained fragments 3079 OUT int64* _NextOffset // offset, caller can start from to continue 3080 ) 3081 { 3082 if(!ExtInfo || !ExtInfo->Mapping) 3083 return STATUS_INVALID_PARAMETER; 3084 3085 PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array 3086 PEXTENT_MAP SubExtInfo; 3087 uint32 to_read, Lba, sect_offs, flags, Skip_MapEntries; 3088 int32 SubExtInfoSz = *_SubExtInfoSz; 3089 int64 Length; 3090 int64 NextOffset; 3091 // OSSTATUS status = STATUS_BUFFER_OVERFLOW; 3092 3093 (*_SubExtInfo) = NULL; 3094 (*_SubExtInfoSz) = 0; 3095 NextOffset = Offset; 3096 // prevent reading out of data space 3097 if(Offset >= ExtInfo->Length) 3098 return STATUS_END_OF_FILE; 3099 Length = ExtInfo->Length - Offset; 3100 Offset += ExtInfo->Offset; // used for in-ICB data 3101 // read maximal possible part of each frag of extent 3102 SubExtInfo = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool , SubExtInfoSz*sizeof(EXTENT_MAP), 3103 MEM_EXTMAP_TAG); 3104 (*_SubExtInfo) = SubExtInfo; 3105 if(!SubExtInfo) 3106 return STATUS_INSUFFICIENT_RESOURCES; 3107 3108 Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_read, &flags, &Skip_MapEntries); 3109 while(Length && SubExtInfoSz) { 3110 // EOF check 3111 if(Lba == LBA_OUT_OF_EXTENT) { 3112 BrutePoint(); 3113 return STATUS_END_OF_FILE; 3114 } 3115 Extent += (Skip_MapEntries + 1); 3116 // check for reading tail 3117 to_read = (int32)min((int64)to_read, Length); 3118 SubExtInfo->extLength = to_read; 3119 if(flags == EXTENT_NOT_RECORDED_NOT_ALLOCATED) { 3120 SubExtInfo->extLocation = LBA_NOT_ALLOCATED; 3121 } else 3122 if(flags == EXTENT_NOT_RECORDED_ALLOCATED) { 3123 ASSERT(!(Lba & 0x80000000)); 3124 SubExtInfo->extLocation = Lba | 0x80000000; 3125 } else { 3126 SubExtInfo->extLocation = Lba; 3127 } 3128 (*_SubExtInfoSz)++; 3129 SubExtInfoSz--; 3130 NextOffset += to_read; 3131 // prepare for reading next frag... 3132 Length -= to_read; 3133 if(!Length) { 3134 // status = STATUS_SUCCESS; 3135 break; 3136 } 3137 ASSERT(to_read); 3138 Lba = UDFNextExtentToLba(Vcb, Extent, &to_read, &flags, &Skip_MapEntries); 3139 sect_offs = 0; 3140 } 3141 (*_NextOffset) = NextOffset; 3142 return STATUS_SUCCESS; 3143 } // end UDFReadExtentLocation() 3144 3145 #ifdef _MSC_VER 3146 #pragma warning(push) 3147 #pragma warning(disable:4035) // re-enable below 3148 #endif 3149 3150 uint32 3151 UDFGetZeroLength( 3152 IN int8* Buffer, 3153 IN uint32 Length 3154 ) 3155 { 3156 uint32 i; 3157 Length /= sizeof(uint32); 3158 for(i=0; i<Length; i++) { 3159 if( ((uint32*)Buffer)[i] ) 3160 break; 3161 } 3162 return Length*sizeof(uint32); 3163 } 3164 3165 #ifdef _MSC_VER 3166 #pragma warning(pop) // re-enable warning #4035 3167 #endif 3168 3169 #ifndef UDF_READ_ONLY_BUILD 3170 /* 3171 This routine writes data at any offset to specified extent. 3172 */ 3173 OSSTATUS 3174 UDFWriteExtent( 3175 IN PVCB Vcb, 3176 IN PEXTENT_INFO ExtInfo, // Extent array 3177 IN int64 Offset, // offset in extent 3178 IN uint32 Length, 3179 IN BOOLEAN Direct, // setting this flag delays flushing of given 3180 // data to indefinite term 3181 IN int8* Buffer, 3182 OUT uint32* WrittenBytes 3183 ) 3184 { 3185 if(!ExtInfo || !ExtInfo->Mapping) 3186 return STATUS_INVALID_PARAMETER; 3187 3188 PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array 3189 uint32 to_write, Lba, sect_offs, flags; 3190 OSSTATUS status; 3191 uint32 _WrittenBytes; 3192 BOOLEAN reread_lba; 3193 // BOOLEAN already_prepared = FALSE; 3194 // BOOLEAN prepare = !Buffer; 3195 3196 AdPrint(("Write ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping)); 3197 3198 Offset += ExtInfo->Offset; // used for in-ICB data 3199 // write maximal possible part of each frag of extent 3200 while(((LONG)Length) > 0) { 3201 UDFCheckSpaceAllocation(Vcb, 0, Extent, AS_USED); // check if used 3202 Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_write, &flags, NULL); 3203 // EOF check 3204 if(Lba == LBA_OUT_OF_EXTENT) { 3205 return STATUS_END_OF_FILE; 3206 } 3207 /* if((to_write < Length) && 3208 !Direct && !prepare && !already_prepared) { 3209 // rebuild mapping, allocate space, etc. 3210 // to indicate this, set Buffer to NULL 3211 AdPrint(("UDFWriteExtent: Prepare\n")); 3212 BrutePoint(); 3213 _WrittenBytes = 0; 3214 status = UDFWriteExtent(Vcb, ExtInfo, Offset, Length, *//*Direct*//*FALSE, NULL, &_WrittenBytes); 3215 if(!OS_SUCCESS(status)) { 3216 return status; 3217 } 3218 Extent = ExtInfo->Mapping; 3219 Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_write, &flags, NULL); 3220 already_prepared = TRUE; 3221 }*/ 3222 if(flags == EXTENT_NOT_RECORDED_NOT_ALLOCATED) { 3223 // here we should allocate space for this extent 3224 if(!OS_SUCCESS(status = UDFMarkNotAllocatedAsAllocated(Vcb, Offset, to_write, ExtInfo))) 3225 return status; 3226 Extent = ExtInfo->Mapping; 3227 UDFCheckSpaceAllocation(Vcb, 0, Extent, AS_USED); // check if used 3228 Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_write, &flags, NULL); 3229 if(Lba == LBA_OUT_OF_EXTENT) { 3230 return STATUS_END_OF_FILE; 3231 } 3232 // we have already re-read Lba 3233 reread_lba = FALSE; 3234 } else { 3235 // we may need to re-read Lba if some changes are 3236 // made while converting from Alloc-Not-Rec 3237 reread_lba = TRUE; 3238 } 3239 // check if writing to not recorded allocated 3240 // in this case we must pad blocks with zeros around 3241 // modified area 3242 // 3243 // ...|xxxxxxxx|xxxxxxxx|xxxxxxxx|... 3244 // . . 3245 // . || . 3246 // . \/ . 3247 // . . 3248 // ...|000ddddd|dddddddd|dd000000|... 3249 // . . 3250 // ^ ^ 3251 // sect_offs sect_offs+to_write 3252 // . . 3253 // .<-- to_write -->. 3254 // 3255 to_write = min(to_write, Length); 3256 if(flags == EXTENT_NOT_RECORDED_ALLOCATED) { 3257 if(!OS_SUCCESS(status = UDFMarkAllocatedAsRecorded(Vcb, Offset, to_write, ExtInfo))) 3258 return status; 3259 Extent = ExtInfo->Mapping; 3260 UDFCheckSpaceAllocation(Vcb, 0, Extent, AS_USED); // check if used 3261 if(reread_lba) { 3262 Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_write, &flags, NULL); 3263 to_write = min(to_write, Length); 3264 } 3265 /* 3266 we must fill 1st block with zeros in 1 of 2 cases: 3267 1) start offset is not aligned on LBlock boundary 3268 OR 3269 2) end offset is not aligned on LBlock boundary and lays in 3270 the same LBlock 3271 3272 we must fill last block with zeros if both 3273 1) end offset is not aligned on LBlock boundary 3274 AND 3275 2) end offset DOESN'T lay in the 1st LBlock 3276 */ 3277 3278 // if(!prepare) { 3279 // pad 1st logical block 3280 if((sect_offs || (sect_offs + to_write < Vcb->LBlockSize) ) 3281 && 3282 !Vcb->CDR_Mode) { 3283 status = UDFWriteData(Vcb, TRUE, 3284 ( ((uint64)Lba) << Vcb->BlockSizeBits), 3285 Vcb->LBlockSize, Direct, Vcb->ZBuffer, &_WrittenBytes); 3286 if(!OS_SUCCESS(status)) 3287 return status; 3288 } 3289 // pad last logical block 3290 if((sect_offs + to_write > Vcb->LBlockSize) && 3291 (sect_offs + to_write) & (Vcb->LBlockSize - 1)) { 3292 status = UDFWriteData(Vcb, TRUE, 3293 (( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs + to_write) & ~((int64)(Vcb->LBlockSize)-1), 3294 Vcb->LBlockSize, Direct, Vcb->ZBuffer, &_WrittenBytes); 3295 } 3296 if(!OS_SUCCESS(status)) 3297 return status; 3298 /* } else { 3299 status = STATUS_SUCCESS; 3300 }*/ 3301 } 3302 ASSERT(to_write); 3303 // if(!prepare) { 3304 status = UDFWriteData(Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs, to_write, Direct, Buffer, &_WrittenBytes); 3305 *WrittenBytes += _WrittenBytes; 3306 if(!OS_SUCCESS(status)) return status; 3307 /* } else { 3308 status = STATUS_SUCCESS; 3309 *WrittenBytes += to_write; 3310 }*/ 3311 // prepare for writing next frag... 3312 Buffer += to_write; 3313 Offset += to_write; 3314 Length -= to_write; 3315 } 3316 AdPrint(("Write: ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping)); 3317 return STATUS_SUCCESS; 3318 } // end UDFWriteExtent() 3319 3320 //#if 0 3321 /* 3322 This routine zeroes/deallocates data at any offset to specified extent. 3323 */ 3324 OSSTATUS 3325 UDFZeroExtent( 3326 IN PVCB Vcb, 3327 IN PEXTENT_INFO ExtInfo, // Extent array 3328 IN int64 Offset, // offset in extent 3329 IN uint32 Length, 3330 IN BOOLEAN Deallocate, // deallocate frag or just mark as unrecorded 3331 IN BOOLEAN Direct, // setting this flag delays flushing of given 3332 // data to indefinite term 3333 OUT uint32* WrittenBytes 3334 ) 3335 { 3336 if(!ExtInfo || !ExtInfo->Mapping) 3337 return STATUS_INVALID_PARAMETER; 3338 3339 PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array 3340 uint32 to_write, Lba, sect_offs, flags; 3341 OSSTATUS status; 3342 uint32 _WrittenBytes; 3343 uint32 LBS = Vcb->LBlockSize; 3344 3345 AdPrint(("Zero ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping)); 3346 3347 Offset += ExtInfo->Offset; // used for in-ICB data 3348 // fill/deallocate maximal possible part of each frag of extent 3349 while(((LONG)Length) > 0) { 3350 Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_write, &flags, NULL); 3351 // EOF check 3352 if(Lba == LBA_OUT_OF_EXTENT) { 3353 return STATUS_END_OF_FILE; 3354 } 3355 // check for writing tail 3356 to_write = min(to_write, Length); 3357 3358 if(flags == EXTENT_NOT_RECORDED_NOT_ALLOCATED) { 3359 // here we should do nothing 3360 *WrittenBytes += to_write; 3361 } else 3362 if(flags == EXTENT_NOT_RECORDED_ALLOCATED) { 3363 // we should just deallocate this frag 3364 if(Deallocate) { 3365 if(!OS_SUCCESS(status = UDFMarkAllocatedAsNotAllocated(Vcb, Offset, to_write, ExtInfo))) 3366 return status; 3367 } 3368 Extent = ExtInfo->Mapping; 3369 *WrittenBytes += to_write; 3370 } else { 3371 // fill tail of the 1st Block with ZEROs 3372 if(sect_offs) { 3373 status = UDFWriteData(Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs, 3374 min(to_write, LBS-sect_offs), 3375 Direct, Vcb->ZBuffer, &_WrittenBytes); 3376 *WrittenBytes += _WrittenBytes; 3377 if(!OS_SUCCESS(status)) 3378 return status; 3379 Offset += _WrittenBytes; 3380 Length -= _WrittenBytes; 3381 to_write -= _WrittenBytes; 3382 Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_write, &flags, NULL); 3383 ASSERT(flags != EXTENT_NOT_RECORDED_NOT_ALLOCATED); 3384 ASSERT(flags != EXTENT_NOT_RECORDED_ALLOCATED); 3385 ASSERT(!sect_offs); 3386 } 3387 // deallocate Blocks 3388 if(to_write >= LBS) { 3389 // use 'sect_offs' as length of extent to be deallocated 3390 sect_offs = to_write & ~(LBS - 1); 3391 if(Deallocate) { 3392 status = UDFMarkAllocatedAsNotAllocated(Vcb, Offset, sect_offs, ExtInfo); 3393 } else { 3394 status = UDFMarkRecordedAsAllocated(Vcb, Offset, sect_offs, ExtInfo); 3395 } 3396 if(!OS_SUCCESS(status)) 3397 return status; 3398 // reload extent mapping 3399 Extent = ExtInfo->Mapping; 3400 Offset += sect_offs; 3401 Length -= sect_offs; 3402 *WrittenBytes += sect_offs; 3403 to_write -= sect_offs; 3404 Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, §_offs, &to_write, &flags, NULL); 3405 ASSERT(flags != EXTENT_NOT_RECORDED_NOT_ALLOCATED); 3406 ASSERT(flags != EXTENT_NOT_RECORDED_ALLOCATED); 3407 ASSERT(!sect_offs); 3408 } 3409 // fill beginning of the last Block with ZEROs 3410 if(to_write) { 3411 status = UDFWriteData(Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits), to_write, Direct, Vcb->ZBuffer, &_WrittenBytes); 3412 *WrittenBytes += _WrittenBytes; 3413 if(!OS_SUCCESS(status)) 3414 return status; 3415 ASSERT(to_write == _WrittenBytes); 3416 } 3417 } 3418 AdPrint(("Zero... ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping)); 3419 // prepare for filling next frag... 3420 Offset += to_write; 3421 Length -= to_write; 3422 } 3423 AdPrint(("Zero: ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping)); 3424 return STATUS_SUCCESS; 3425 } // end UDFZeroExtent() 3426 //#endif //0 3427 #endif //UDF_READ_ONLY_BUILD 3428