ReactOS  0.4.14-dev-614-gbfd8a84
extent.cpp
Go to the documentation of this file.
1 // 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.
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
29  IN PVCB Vcb,
30  IN PEXTENT_MAP Extent, // Extent array
31  IN int64 Offset, // offset in extent
33  OUT PSIZE_T AvailLength, // available data in this block
34  OUT uint32* Flags,
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
80  IN PVCB Vcb,
81  IN PEXTENT_MAP Extent, // Extent array
82  OUT PSIZE_T AvailLength, // available data in this block
83  OUT uint32* Flags,
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
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
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  */
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 
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
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  */
268  IN PEXTENT_MAP Extent2
269  )
270 {
271  PEXTENT_MAP NewExt;
272  uint32 len, len2;
273 
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  */
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;
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);
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));
330  // read next frag of allocation descriptors if encountered
331  if(len < sizeof(ALLOC_EXT_DESC)) {
333  return NULL;
334  }
336  if(!NextAllocDesc) {
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);
348  return NULL;
349  }
350  NextAllocLoc.Mapping =
351  AllocMap = UDFExtentToMapping(&AllocExt);
352  NextAllocLoc.Length = len;
353  if(!AllocMap) {
354  MyFreePool__(NextAllocDesc);
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);
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);
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);
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
416  Extent[i].extLocation = UDFPartLbaToPhys(Vcb, &locAddr);
417  if(Extent[i].extLocation == LBA_OUT_OF_EXTENT) {
418  UDFPrint(("bad address (2)\n"));
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( 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( 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  */
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;
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);
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));
491  // read next frag of allocation descriptors if encountered
492  if(len < sizeof(ALLOC_EXT_DESC)) {
494  return NULL;
495  }
497  if(!NextAllocDesc) {
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);
508  return NULL;
509  }
510  NextAllocLoc.Mapping =
511  AllocMap = UDFExtentToMapping(&AllocExt);
512  NextAllocLoc.Length = len;
513  if(!AllocMap) {
514  MyFreePool__(NextAllocDesc);
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);
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);
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);
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
565  Extent[i].extLocation = UDFPartLbaToPhys(Vcb,&(AllocDesc[i].extLocation));
566  if(Extent[i].extLocation == LBA_OUT_OF_EXTENT) {
567  UDFPrint(("bad address (2)\n"));
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  */
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;
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);
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));
627  // read next frag of allocation descriptors if encountered
628  if(len < sizeof(ALLOC_EXT_DESC)) {
630  return NULL;
631  }
633  if(!NextAllocDesc) {
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);
644  return NULL;
645  }
646  NextAllocLoc.Mapping =
647  AllocMap = UDFExtentToMapping(&AllocExt);
648  NextAllocLoc.Length = len;
649  if(!AllocMap) {
650  MyFreePool__(NextAllocDesc);
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);
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);
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);
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
701  Extent[i].extLocation = UDFPartLbaToPhys(Vcb,&(AllocDesc[i].extLocation));
702  if(Extent[i].extLocation == LBA_OUT_OF_EXTENT) {
703  UDFPrint(("bad address (2)\n"));
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  */
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 {
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 = (uintptr_t)AllocDescs - (uintptr_t)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
826  IN PVCB Vcb,
827  IN uint32 PartNum,
828  OUT int8** Buff, // data for AllocLoc
829  IN uint32 InitSz,
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);
838  uint32 NewLen;
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 
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  }
863  if(!Alloc) {
864  BrutePoint();
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();
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;
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)) {
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:
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 |
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
1013  IN PVCB Vcb,
1014  IN uint32 PartNum,
1015  OUT int8** Buff, // data for AllocLoc
1016  IN uint32 InitSz,
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 
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  }
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)) {
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;
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)) {
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:
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 |
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
1330  IN PVCB Vcb,
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
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;
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 =
1398  if(!AllocCache) {
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
1418  IN PVCB Vcb,
1419  IN uint32 ParentLocation,
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
1458  IN PVCB Vcb,
1459  IN uint32 ParentLocation,
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;
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
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;
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;
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
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 
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"));
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  }
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);
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) {
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)
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  }
1717 #endif // UDF_FE_ALLOCATION_CHARGE
1718 
1719 } // end UDFAllocateFESpace()
1720 
1721 /*
1722  This routine frees space allocated for FE.
1723  */
1724 void
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
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
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!
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
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
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
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
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));
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
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  SIZE_T aLen, sLen;
1963  SIZE_T 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
2017  if(!NewExtent) {
2018  MyFreePool__(TmpExtInf.Mapping);
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
2031  if(!NewExtent) {
2032  MyFreePool__(TmpExtInf.Mapping);
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
2048  if(!NewExtent) {
2049  MyFreePool__(TmpExtInf.Mapping);
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
2063  if(!NewExtent) {
2064  MyFreePool__(TmpExtInf.Mapping);
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));
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
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 ?
2115  SIZE_T 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  Extent = NULL;
2162  AdPrint(("Alloc->Not (1) NewExtent = Extent = %x\n", NewExtent));
2163  } else
2164  if(l < BOffs) {
2165  // .ExtLength, BOffs & l are already aligned...
2166  if( (((Extent[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh) - (BOffs-l)) > sLen ) {
2167  // xxxxxx -> xxRRxx
2169  if(!NewExtent) {
2171  }
2172  RtlCopyMemory((int8*)NewExtent, (int8*)Extent, i*sizeof(EXTENT_MAP));
2173  RtlCopyMemory((int8*)&(NewExtent[i+3]), (int8*)&(Extent[i+1]), len = UDFGetMappingLength(&(Extent[i+1])) );
2174  NewExtent[i].extLength = (BOffs - l) << BSh;
2175  NewExtent[i].extLength |= flags;
2176  NewExtent[i+1].extLocation = 0;
2177  NewExtent[i+1].extLength = aLen | (target_flags << 30);
2178  NewExtent[i+2].extLength = (Extent[i].extLength & UDF_EXTENT_LENGTH_MASK) -
2179  (NewExtent[i].extLength & UDF_EXTENT_LENGTH_MASK) - aLen ;
2180  NewExtent[i+2].extLocation = Extent[i].extLocation +
2181  (NewExtent[i+2].extLength >> BSh);
2182  NewExtent[i+2].extLength |= flags;
2183  AdPrint(("Alloc->Not (2) new %x\n", NewExtent));
2184  } else {
2185  // xxxxxx -> xxRRRR
2187  if(!NewExtent) {
2189  }
2190  RtlCopyMemory((int8*)NewExtent, (int8*)Extent, i*sizeof(EXTENT_MAP));
2191  RtlCopyMemory((int8*)&(NewExtent[i+2]), (int8*)&(Extent[i+1]), len = UDFGetMappingLength(&(Extent[i+1])) );
2192  NewExtent[i].extLength = ((BOffs - l) << BSh) | flags;
2193  NewExtent[i+1].extLocation = 0;
2194  NewExtent[i+1].extLength = aLen | (target_flags << 30);
2195  AdPrint(("Alloc->Not (3) new %x\n", NewExtent));
2196  }
2197  } else {
2198  // xxxxxx -> RRRRxx
2200  if(!NewExtent) {
2202  }
2203  RtlCopyMemory((int8*)NewExtent, (int8*)Extent, i*sizeof(EXTENT_MAP));
2204  RtlCopyMemory((int8*)&(NewExtent[i+2]), (int8*)&(Extent[i+1]), len = UDFGetMappingLength(&(Extent[i+1])) );
2205  NewExtent[i+1].extLength = (Extent[i].extLength & UDF_EXTENT_LENGTH_MASK) - aLen;
2206  NewExtent[i+1].extLength |= flags;
2207  NewExtent[i].extLocation = 0;
2208  NewExtent[i].extLength = aLen | (target_flags << 30);
2209  AdPrint(("Alloc->Not (4) new %x\n", NewExtent));
2210  }
2211 
2212  if(Deallocate)
2213  UDFMarkSpaceAsXXX(Vcb, (-1), TmpExtInf.Mapping, AS_DISCARDED); // mark as free
2214 
2215  ExtInfo->Modified = TRUE;
2216  ExtInfo->Mapping = NewExtent;
2217 
2218  AdPrint(("Alloc->Not: ExtInfo %x, Extent %x\n", ExtInfo, ExtInfo->Mapping));
2219 
2220  if(Extent) {
2221  AdPrint(("Alloc->Not kill %x\n", Extent));
2223  } else {
2224  AdPrint(("Alloc->Not keep %x\n", Extent));
2225  }
2226 
2227  return STATUS_SUCCESS;
2228 } // end UDFMarkAllocatedAsNotXXX()
2229 //#endif //0
2230 
2231 /*
2232  This routine resizes extent & updates associated mapping
2233  */
2234 OSSTATUS
2236  IN PVCB Vcb,
2237  IN uint32 PartNum,
2238  IN int64 Length, // Required Length
2239  IN BOOLEAN AlwaysInIcb, // must be TRUE for AllocDescs
2240  OUT PEXTENT_INFO ExtInfo
2241  )
2242 {
2243  uint32 i, flags, lba;
2244  SIZE_T lim;
2245  int64 l;
2246  OSSTATUS status;
2247  EXTENT_INFO TmpExtInf;
2248  EXTENT_MAP TmpMapping[2];
2249  uint32 s, pe, BSh, PS;
2250  SIZE_T req_s;
2251  SIZE_T LBS = Vcb->LBlockSize;
2252  BSh = Vcb->BlockSizeBits;
2253  PS = Vcb->WriteBlockSize >> Vcb->BlockSizeBits;
2254  uint32 MaxGrow = (UDF_MAX_EXTENT_LENGTH & ~(LBS-1));
2255  BOOLEAN Sequential = FALSE;
2256 
2257  ASSERT(PartNum < 3);
2258 
2259  ExtPrint(("Resize ExtInfo %x, %I64x -> %I64x\n", ExtInfo, ExtInfo->Length, Length));
2260 
2261  if(ExtInfo->Flags & EXTENT_FLAG_CUT_PREALLOCATED) {
2262  AdPrint((" cut preallocated\n"));
2263  } else
2264  if(ExtInfo->Length == Length) {
2265  return STATUS_SUCCESS;
2266  }
2267  if((ExtInfo->Flags & EXTENT_FLAG_ALLOC_MASK) == EXTENT_FLAG_ALLOC_SEQUENTIAL) {
2268  MaxGrow &= ~(Vcb->WriteBlockSize-1);
2269  Sequential = TRUE;
2270  }
2271 
2272  UDFCheckSpaceAllocation(Vcb, 0, ExtInfo->Mapping, AS_USED); // check if used
2273  if(ExtInfo->Offset) {
2274  if(ExtInfo->Offset + Length <= LBS) {
2275  ExtPrint(("Resize IN-ICB\n"));
2276  ExtInfo->Length = Length;
2277  return STATUS_SUCCESS;
2278  }
2279  if(!AlwaysInIcb) // simulate unused 1st sector in extent
2280  ExtInfo->Offset = LBS; // it'll be truncated later
2281  Length += ExtInfo->Offset; // convert to real offset in extent
2282  }
2283  lba = UDFExtentOffsetToLba(Vcb, ExtInfo->Mapping, Length, NULL, NULL, &flags, &i);
2284  if(ExtInfo->Length < Length) {
2285  // increase extent
2286  if(OS_SUCCESS(UDFGetCachedAllocation(Vcb, ExtInfo->Mapping[0].extLocation,
2287  &TmpExtInf, NULL, UDF_PREALLOC_CLASS_DIR))) {
2288  AdPrint(("Resize found cached(1)\n"));
2289  ExtInfo->Mapping = UDFMergeMappings(ExtInfo->Mapping, TmpExtInf.Mapping);
2290  MyFreePool__(TmpExtInf.Mapping);
2291  }
2292  if((l = UDFGetExtentLength(ExtInfo->Mapping)) >= Length) {
2293  // we have enough space inside extent
2294  ExtInfo->Length = Length;
2295  AdPrint(("Resize do nothing (1)\n"));
2296  } else /*if(lba == LBA_OUT_OF_EXTENT)*/ {
2297 
2298  Length -= ExtInfo->Offset;
2299  if(/*Length && l &&*/ (l % MaxGrow) &&
2300  (Length-1)/MaxGrow != (l-1)/MaxGrow) {
2301  AdPrint(("Crossing MAX_FRAG boundary...\n"));
2302  int64 l2 = ((l-1)/MaxGrow + 1)*MaxGrow;
2303  status = UDFResizeExtent(Vcb, PartNum, l2, AlwaysInIcb, ExtInfo);
2304  if(!OS_SUCCESS(status)) {
2305  UDFPrint(("Sub-call to UDFResizeExtent() failed (%x)\n", status));
2306  return status;
2307  }
2308  l = ExtInfo->Length;
2309  ASSERT(l == l2);
2310  }
2311  while((Length - l) > MaxGrow) {
2312  status = UDFResizeExtent(Vcb, PartNum, l+MaxGrow, AlwaysInIcb, ExtInfo);
2313  if(!OS_SUCCESS(status)) {
2314  UDFPrint(("Sub-call (2) to UDFResizeExtent() failed (%x)\n", status));
2315  return status;
2316  }
2317  l = ExtInfo->Length;
2318  }
2319  Length += ExtInfo->Offset;
2320  // at first, try to resize existing frag
2321 #ifndef UDF_ALLOW_FRAG_AD
2322  i = UDFGetMappingLength(ExtInfo->Mapping);
2323  if(i > (LBS-sizeof(EXTENDED_FILE_ENTRY))) {
2324  // this is very important check since we will not
2325  // be able to _record_ too long AllocDesc because of
2326  // some DEMO limitations in UDFBuildXXXAllocDescs()
2327  AdPrint((" DISK_FULL\n"));
2328  return STATUS_DISK_FULL;
2329  }
2330  i /= sizeof(EXTENT_MAP);
2331 #else //UDF_ALLOW_FRAG_AD
2332  i = UDFGetMappingLength(ExtInfo->Mapping) / sizeof(EXTENT_MAP);
2333 #endif //UDF_ALLOW_FRAG_AD
2334 #ifdef ALLOW_SPARSE
2335  if(!AlwaysInIcb && !(ExtInfo->Offset) &&
2336  (Length - l >= (Vcb->SparseThreshold << BSh))) {
2337  // last frag will be Not-Alloc-Not-Rec...
2338  AdPrint(("Resize sparse (2)\n"));
2339  RtlZeroMemory(&TmpExtInf, sizeof(EXTENT_INFO));
2341  MEM_EXTMAP_TAG);
2342  if(!TmpExtInf.Mapping) return STATUS_INSUFFICIENT_RESOURCES;
2343  TmpExtInf.Mapping[0].extLength = (((uint32)(Length - l) + LBS-1) & ~(LBS-1)) | (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30);
2344  TmpExtInf.Mapping[0].extLocation =// 0;
2345  TmpExtInf.Mapping[1].extLength =
2346  TmpExtInf.Mapping[1].extLocation = 0;
2347  l = Length;
2348  ExtInfo->Mapping = UDFMergeMappings(ExtInfo->Mapping, TmpExtInf.Mapping);
2349  MyFreePool__(TmpExtInf.Mapping);
2350  } else
2351 #endif //ALLOW_SPARSE
2352  // allocate some sectors
2353  if(i>1 && !(ExtInfo->Offset)) {
2354  i-=2;
2355  // check if Not-Alloc-Not-Rec at the end of mapping
2356  if((uint32)Length - (uint32)l + (ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK) > MaxGrow) {
2357  // do nothing, but jump directly to allocator
2358  } else
2359  if((ExtInfo->Mapping[i].extLength >> 30) == EXTENT_NOT_RECORDED_NOT_ALLOCATED) {
2360  AdPrint(("Resize grow sparse (3)\n"));
2361  ExtInfo->Mapping[i].extLength +=
2362  (((uint32)Length-(uint32)l+LBS-1) & ~(LBS-1)) ;
2363  l = Length;
2364  // check if Alloc-Not-Rec at the end of mapping
2365  } else if((ExtInfo->Mapping[i].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) {
2366  AdPrint(("Resize grow Not-Rec (3)\n"));
2367  // current length of last frag
2368  s = ((ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh);
2369  // prefered location of the next frag
2370  lba = ExtInfo->Mapping[i].extLocation + s;
2371  pe=UDFPartEnd(Vcb,PartNum);
2372  // maximum frag length
2373  if(Sequential) {
2374  lim = (((uint32)UDF_MAX_EXTENT_LENGTH) >> BSh) & ~(PS-1);
2375  } else {
2376  lim = (((uint32)UDF_MAX_EXTENT_LENGTH) >> BSh) & ~(LBS-1);
2377  }
2378  // required last extent length
2379  req_s = s + (uint32)( (((Length + LBS - 1) & ~(LBS-1)) -
2380  ((l + LBS - 1) & ~(LBS-1)) ) >> BSh);
2381  if(lim > req_s) {
2382  lim = req_s;
2383  }
2384  UDFAcquireResourceExclusive(&(Vcb->BitMapResource1),TRUE);
2385 /* if((ExtInfo->Flags & EXTENT_FLAG_SEQUENTIAL) &&
2386  ((Length & ~(PS-1)) > (l & ~(PS-1))) &&
2387  TRUE) {
2388  status = UDFResizeExtent(Vcb, PartNum, l+MaxGrow, AlwaysInIcb, ExtInfo);
2389  }*/
2390  // how many sectors we should add
2391  req_s = lim - s;
2392  ASSERT(req_s);
2393  if((lba < pe) && UDFGetFreeBit(Vcb->FSBM_Bitmap, lba)) {
2394  s += UDFGetBitmapLen((uint32*)(Vcb->FSBM_Bitmap), lba, min(pe, lba+req_s-1));
2395  }
2396 /* for(s1=lba; (s<lim) && (s1<pe) && UDFGetFreeBit(Vcb->FSBM_Bitmap, s1); s1++) {
2397  s++;
2398  }*/
2399  if(s==lim) {
2400  // we can just increase the last frag
2401  AdPrint(("Resize grow last Not-Rec (4)\n"));
2402  ExtInfo->Mapping[i].extLength = (lim << BSh) | (EXTENT_NOT_RECORDED_ALLOCATED << 30);
2403  l = Length;
2404  UDFMarkSpaceAsXXXNoProtect(Vcb, 0, &(ExtInfo->Mapping[i]), AS_USED); // mark as used
2405  } else {
2406  // we get here if simple increasing of last frag failed
2407  // it worth truncating last frag and try to allocate
2408  // all required data as a single frag
2409 
2410 /* if(Sequential && s>=PS) {
2411  s &= ~(PS-1);
2412  AdPrint(("Resize grow last Not-Rec (4/2)\n"));
2413  ExtInfo->Mapping[i].extLength = (s << BSh) | (EXTENT_NOT_RECORDED_ALLOCATED << 30);
2414  l += (s << BSh);
2415  UDFMarkSpaceAsXXXNoProtect(Vcb, 0, &(ExtInfo->Mapping[i]), AS_USED); // mark as used
2416  }*/
2417  AdPrint(("Resize reloc last Not-Rec (5)\n"));
2418  TmpExtInf.Mapping = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool , (i+1)*sizeof(EXTENT_MAP),
2419  MEM_EXTMAP_TAG);
2420  if(!TmpExtInf.Mapping) {
2421  UDFPrint(("UDFResizeExtent: !TmpExtInf.Mapping\n"));
2422  UDFReleaseResource(&(Vcb->BitMapResource1));
2424  }
2425  RtlCopyMemory(TmpExtInf.Mapping, ExtInfo->Mapping, i*sizeof(EXTENT_MAP));
2426  TmpExtInf.Mapping[i].extLength =
2427  TmpExtInf.Mapping[i].extLocation = 0;
2428  TmpExtInf.Offset = ExtInfo->Offset;
2429  l -= (ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK);
2430  TmpExtInf.Length = l;
2431  ASSERT(i || !ExtInfo->Offset);
2432  UDFMarkSpaceAsXXXNoProtect(Vcb, 0, &(ExtInfo->Mapping[i]), AS_DISCARDED); // mark as free
2433  MyFreePool__(ExtInfo->Mapping);
2434  (*ExtInfo) = TmpExtInf;
2435  }
2436  UDFCheckSpaceAllocation(Vcb, 0, ExtInfo->Mapping, AS_USED); // check if used
2437  UDFReleaseResource(&(Vcb->BitMapResource1));
2438  // check if Alloc-Rec
2439  } else {
2440  // current length of last frag
2441  s = ((ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK) >> BSh);
2442  // prefered location of the next frag
2443  lba = ExtInfo->Mapping[i].extLocation + s;
2444  pe=UDFPartEnd(Vcb,PartNum);
2445  // maximum frag length
2446  if(Sequential) {
2447  lim = (((uint32)UDF_MAX_EXTENT_LENGTH) >> BSh) & ~(PS-1);
2448  } else {
2449  lim = (((uint32)UDF_MAX_EXTENT_LENGTH) >> BSh) & ~(LBS-1);
2450  }
2451  // required last extent length
2452  req_s = s + (uint32)( (((Length + LBS - 1) & ~(LBS-1)) -
2453  ((l + LBS - 1) & ~(LBS-1)) ) >> BSh);
2454  if(lim > req_s) {
2455  lim = req_s;
2456  }
2457 // s=0;
2458  // how many sectors we should add
2459  req_s = lim - s;
2460  if(req_s) {
2461  uint32 d=0;
2462 
2463  UDFAcquireResourceExclusive(&(Vcb->BitMapResource1),TRUE);
2464  //ASSERT(req_s);
2465  if((lba < pe) && UDFGetFreeBit(Vcb->FSBM_Bitmap, lba)) {
2466  s += (d = UDFGetBitmapLen((uint32*)(Vcb->FSBM_Bitmap), lba, min(pe, lba+req_s-1)));
2467  }
2468  /* for(s1=lba; (s<lim) && (s1<pe) && UDFGetFreeBit(Vcb->FSBM_Bitmap, s1); s1++) {
2469  s++;
2470  }*/
2471 
2472  if(s==lim) {
2473  AdPrint(("Resize grow last Rec (6)\n"));
2474  // we can just increase last frag
2475  TmpMapping[0].extLength = req_s << BSh;
2476  TmpMapping[0].extLocation = lba;
2477  TmpMapping[1].extLength =
2478  TmpMapping[1].extLocation = 0;
2479  UDFMarkSpaceAsXXXNoProtect(Vcb, 0, &TmpMapping[0], AS_USED); // mark as used
2480  l += (s << BSh) - (ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK);
2481  ExtInfo->Mapping[i].extLength = (ExtInfo->Mapping[i].extLength & UDF_EXTENT_FLAG_MASK) | (s << BSh);
2482  } else if(d) {
2483  AdPrint(("Resize part-grow last Rec (6)\n"));
2484  // increase last frag, then alloc rest
2485  TmpMapping[0].extLength = d << BSh;
2486  TmpMapping[0].extLocation = lba;
2487  TmpMapping[1].extLength =
2488  TmpMapping[1].extLocation = 0;
2489  UDFMarkSpaceAsXXXNoProtect(Vcb, 0, &TmpMapping[0], AS_USED); // mark as used
2490  l += (s << BSh) - (ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK);
2491  ExtInfo->Mapping[i].extLength = (ExtInfo->Mapping[i].extLength & UDF_EXTENT_FLAG_MASK) | (s << BSh);
2492  } else {
2493  AdPrint(("Can't grow last Rec (6)\n"));
2494  }
2495  UDFReleaseResource(&(Vcb->BitMapResource1));
2496  } else {
2497  AdPrint(("Max frag length reached (6)\n"));
2498  }
2499  }
2500  }
2501  if(l < Length) {
2502  // we get here if simple increasing of the last frag failed
2503  AdPrint(("Resize add new frag (7)\n"));
2504  if(l < LBS && Length >= LBS &&
2505  (ExtInfo->Flags & EXTENT_FLAG_ALLOC_MASK) == EXTENT_FLAG_ALLOC_SEQUENTIAL) {
2506  AdPrint(("Resize tune for SEQUENTIAL i/o\n"));
2507  }
2509  UDFPartStart(Vcb, PartNum),
2510  UDFPartEnd(Vcb, PartNum),
2511  &TmpExtInf,
2512  ExtInfo->Flags /*& EXTENT_FLAG_ALLOC_MASK*/);
2513  if(!OS_SUCCESS(status)) {
2514  UDFPrint(("UDFResizeExtent: UDFAllocFreeExtent() failed (%x)\n", status));
2515  return status;
2516  }
2517  ExtInfo->Mapping = UDFMergeMappings(ExtInfo->Mapping, TmpExtInf.Mapping);
2518  MyFreePool__(TmpExtInf.Mapping);
2519  }
2520  UDFPackMapping(Vcb, ExtInfo);
2521  }
2522  } else
2523  if(Length) {
2524  // decrease extent
2525  AdPrint(("Resize cut (8)\n"));
2526  lba = UDFExtentOffsetToLba(Vcb, ExtInfo->Mapping, Length-1, NULL, &lim, &flags, &i);
2527  i++;
2530  ASSERT(i);
2531  if(ExtInfo->Mapping[i].extLength) {
2532  UDFCheckSpaceAllocation(Vcb, 0, &(ExtInfo->Mapping[i]), AS_USED); // check if used
2533  if(!ExtInfo->Offset && (ExtInfo->Flags & EXTENT_FLAG_PREALLOCATED)) {
2534 
2535  AdPrint(("Resize try save cutted (8)\n"));
2536  RtlZeroMemory(&TmpExtInf, sizeof(EXTENT_INFO));
2537  s = UDFGetMappingLength(&(ExtInfo->Mapping[i]));
2538 
2540  if(TmpExtInf.Mapping) {
2541  RtlCopyMemory(TmpExtInf.Mapping, &(ExtInfo->Mapping[i]), s);
2542  AdPrint(("Resize save cutted (8)\n"));
2543  if(OS_SUCCESS(UDFStoreCachedAllocation(Vcb, ExtInfo->Mapping[0].extLocation,
2544  &TmpExtInf, 0, UDF_PREALLOC_CLASS_DIR))) {
2545  ExtInfo->Mapping[i].extLength = 0;
2546  ExtInfo->Mapping[i].extLocation = 0;
2547  goto tail_cached;
2548  }
2549  }
2550  }
2551  UDFMarkSpaceAsXXX(Vcb, 0, &(ExtInfo->Mapping[i]), AS_DISCARDED); // mark as free
2552 tail_cached:;
2553  }
2554  if((lim-1 >= LBS) &&
2556  AdPrint(("i=%x, lba=%x, len=%x\n",i,lba,lim));
2557  ASSERT(lim);
2558 // BrutePoint();
2559  EXTENT_MAP ClrMap[2];
2560  ClrMap[0].extLength = lim & ~(LBS-1);
2561  s = (ExtInfo->Mapping[i-1].extLength - ClrMap[0].extLength) & UDF_EXTENT_LENGTH_MASK;
2562  ClrMap[0].extLocation = ExtInfo->Mapping[i-1].extLocation +
2563  (s >> BSh);
2564  ClrMap[1].extLength =
2565  ClrMap[1].extLocation = 0;
2566  ASSERT((ExtInfo->Mapping[i].extLocation < ClrMap[0].extLocation) ||
2567  (ExtInfo->Mapping[i].extLocation >= (ClrMap[0].extLocation + (ClrMap[0].extLength >> BSh))));
2568  UDFCheckSpaceAllocation(Vcb, 0, (PEXTENT_MAP)(&ClrMap), AS_USED); // check if used
2569  UDFMarkSpaceAsXXX(Vcb, 0, (PEXTENT_MAP)(&ClrMap), AS_DISCARDED); // mark as free
2570  ExtInfo->Mapping[i-1].extLength = s | (flags << 30);
2571  }
2572 
2573  s = UDFGetMappingLength(ExtInfo->Mapping);
2574  if(!MyReallocPool__((int8*)(ExtInfo->Mapping), s, (int8**)&(ExtInfo->Mapping), (i+1)*sizeof(EXTENT_MAP))) {
2575  // This must never happen on truncate !!!
2576  AdPrint(("ResizeExtent: MyReallocPool__(8) failed\n"));
2577  }
2578  ExtInfo->Mapping[i].extLength =
2579  ExtInfo->Mapping[i].extLocation = 0;
2580  } else {
2581  AdPrint(("Resize zero (9)\n"));
2582  ASSERT(!ExtInfo->Offset);
2583  UDFMarkSpaceAsXXX(Vcb, 0, ExtInfo->Mapping, AS_DISCARDED); // mark as free
2584  s = UDFGetMappingLength(ExtInfo->Mapping);
2585  if(!MyReallocPool__((int8*)(ExtInfo->Mapping), s, (int8**)&(ExtInfo->Mapping), 2*sizeof(EXTENT_MAP))) {
2586  // This must never happen on truncate !!!
2587  AdPrint(("ResizeExtent: MyReallocPool__(9) failed\n"));
2588  }
2589  ExtInfo->Mapping[0].extLength = LBS | (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30);
2590  ExtInfo->Mapping[0].extLocation =
2591  ExtInfo->Mapping[1].extLength =
2592  ExtInfo->Mapping[1].extLocation = 0;
2593  }
2594  if(ExtInfo->Offset) {
2595  if(!AlwaysInIcb) {
2596  // remove 1st entry pointing to FileEntry
2597  s = UDFGetMappingLength(ExtInfo->Mapping);
2598  RtlMoveMemory(&(ExtInfo->Mapping[0]), &(ExtInfo->Mapping[1]), s - sizeof(EXTENT_MAP));
2599  if(!MyReallocPool__((int8*)(ExtInfo->Mapping), s,
2600  (int8**)&(ExtInfo->Mapping), s - sizeof(EXTENT_MAP) )) {
2601  // This must never happen on truncate !!!
2602  AdPrint(("ResizeExtent: MyReallocPool__(10) failed\n"));
2603  }
2604  Length -= ExtInfo->Offset;
2605  ExtInfo->Offset = 0;
2606  } else {
2607  Length -= ExtInfo->Offset; // back to in-icb
2608  }
2609  }
2610  ExtInfo->Length = Length;
2611  UDFCheckSpaceAllocation(Vcb, 0, ExtInfo->Mapping, AS_USED); // check if used
2612 
2613  for(i=0; (ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK); i++) {
2614  ExtPrint(("Resized Ext: type %x, loc %x, len %x\n",
2615  ExtInfo->Mapping[i].extLength >> 30, ExtInfo->Mapping[i].extLocation, ExtInfo->Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK));
2616  }
2617 
2618  return STATUS_SUCCESS;
2619 } // end UDFResizeExtent()
2620 
2621 /*
2622  This routine (re)builds AllocDescs data for all allocation modes except
2623  in-ICB & resizes associated extent (FileInfo->Dloc->AllocLoc) for
2624  already allocated user data extent (FileInfo->Dloc->DataLoc).
2625  AllocMode in FileEntry pointed by FileInfo must be already initialized.
2626  */
2627 OSSTATUS
2629  IN PVCB Vcb,
2630  IN uint32 PartNum,
2632  OUT int8** AllocData
2633  )
2634 {
2635 // PEXTENT_MAP InMap;
2636 // uint32 i=0;
2637  int8* Allocs;
2638  uint16 AllocMode;
2639  uint32 InitSz;
2640  OSSTATUS status;
2641 
2643  AdPrint(("BuildAllocDesc\n"));
2644  // get space available in the 1st LBlock after FE
2645  InitSz = Vcb->LBlockSize - FileInfo->Dloc->FileEntryLen;
2646  Allocs = (int8*)MyAllocatePool__(NonPagedPool, InitSz);
2647  if(!Allocs) {
2648  *AllocData = NULL;
2649  AdPrint(("BuildAllocDesc: cant alloc %x bytes for Allocs\n", InitSz));
2651  }
2652  RtlZeroMemory(Allocs, InitSz);
2653 // InMap = FileInfo->Dloc->DataLoc.Mapping;
2654  UDFCheckSpaceAllocation(Vcb, 0, InMap, AS_USED); // check if used
2655 
2656  // TODO: move data from mapped locations here
2657 
2658  AllocMode = ((PFILE_ENTRY)(FileInfo->Dloc->FileEntry))->icbTag.flags & ICB_FLAG_ALLOC_MASK;
2659  switch(AllocMode) {
2660  case ICB_FLAG_AD_IN_ICB: {
2661  MyFreePool__(Allocs);
2662  ASSERT(!FileInfo->Dloc->AllocLoc.Mapping);
2663  Allocs = NULL;
2665  break;
2666  }
2667  case ICB_FLAG_AD_SHORT: {
2668  status = UDFBuildShortAllocDescs(Vcb, PartNum, &Allocs, InitSz, FileInfo);
2669  break;
2670  }
2671  case ICB_FLAG_AD_LONG: {
2672  status = UDFBuildLongAllocDescs(Vcb, PartNum, &Allocs, InitSz, FileInfo);
2673  break;
2674  }
2675 /* case ICB_FLAG_AD_EXTENDED: {
2676  status = UDFBuildExtAllocDescs(Vcb, PartNum, &Allocs, InitSz, FileInfo);
2677  break;
2678  }*/
2679  default: {
2680  MyFreePool__(Allocs);
2681  Allocs = NULL;
2683  }
2684  }
2685 
2686  *AllocData = Allocs;
2687  UDFCheckSpaceAllocation(Vcb, 0, FileInfo->Dloc->DataLoc.Mapping, AS_USED); // check if used
2688 
2689  return status;
2690 } // end UDFBuildAllocDescs()
2691 
2692 /*
2693  This routine discards file's allocation
2694  */
2695 void
2697  IN PVCB Vcb,
2698  IN PUDF_FILE_INFO DirInfo,
2700  )
2701 {
2702  if(FileInfo->Dloc->DataLoc.Offset) {
2703  // in-ICB data
2704  if(FileInfo->Dloc->DataLoc.Mapping) {
2705  ASSERT(FileInfo->Dloc->FELoc.Mapping[0].extLocation ==
2706  FileInfo->Dloc->DataLoc.Mapping[0].extLocation);
2707  UDFMarkSpaceAsXXX(Vcb, FileInfo->Dloc, &(FileInfo->Dloc->DataLoc.Mapping[1]), AS_DISCARDED); // free
2708  FileInfo->Dloc->DataLoc.Mapping[1].extLocation =
2709  FileInfo->Dloc->DataLoc.Mapping[1].extLength = 0;
2710  FileInfo->Dloc->DataLoc.Mapping[0].extLocation = 0;
2711  FileInfo->Dloc->DataLoc.Mapping[0].extLength = EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30;
2712  }
2713  if(FileInfo->Dloc->AllocLoc.Mapping) {
2714  ASSERT(FileInfo->Dloc->FELoc.Mapping[0].extLocation ==
2715  FileInfo->Dloc->AllocLoc.Mapping[0].extLocation);
2716  UDFMarkSpaceAsXXX(Vcb, FileInfo->Dloc, &(FileInfo->Dloc->AllocLoc.Mapping[1]), AS_DISCARDED); // free
2717  FileInfo->Dloc->AllocLoc.Mapping[1].extLocation =
2718  FileInfo->Dloc->AllocLoc.Mapping[1].extLength = 0;
2719  FileInfo->Dloc->AllocLoc.Mapping[0].extLocation = 0;
2720  FileInfo->Dloc->AllocLoc.Mapping[0].extLength = EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30;
2721  }
2722  UDFFreeFESpace(Vcb, DirInfo, &(FileInfo->Dloc->FELoc));
2723  } else {
2724  if(FileInfo->Dloc->AllocLoc.Mapping) {
2725  ASSERT(FileInfo->Dloc->FELoc.Mapping[0].extLocation ==
2726  FileInfo->Dloc->AllocLoc.Mapping[0].extLocation);
2727  UDFMarkSpaceAsXXX(Vcb, FileInfo->Dloc, &(FileInfo->Dloc->AllocLoc.Mapping[1]), AS_DISCARDED); // free
2728  FileInfo->Dloc->AllocLoc.Mapping[1].extLocation =
2729  FileInfo->Dloc->AllocLoc.Mapping[1].extLength = 0;
2730  FileInfo->Dloc->AllocLoc.Mapping[0].extLocation = 0;
2731  FileInfo->Dloc->AllocLoc.Mapping[0].extLength = EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30;
2732  }
2733  UDFFreeFESpace(Vcb, DirInfo, &(FileInfo->Dloc->FELoc));
2734  UDFMarkSpaceAsXXX(Vcb, FileInfo->Dloc, FileInfo->Dloc->DataLoc.Mapping, AS_DISCARDED); // free
2735  }
2736  FileInfo->Dloc->DataLoc.Modified =
2737  FileInfo->Dloc->AllocLoc.Modified =
2738  FileInfo->Dloc->FELoc.Modified = FALSE;
2739 } // end UDFFreeFileAllocation()
2740 #endif //UDF_READ_ONLY_BUILD
2741 
2742 /*
2743  This routine packs physically sequential extents into single one
2744  */
2745 void
2746 __fastcall
2748  IN PVCB Vcb,
2749  IN PEXTENT_INFO ExtInfo // Extent array
2750  )
2751 {
2752  PEXTENT_MAP NewMap, OldMap;
2753  uint32 i, j, l;
2754  uint32 LastLba, LastType, OldLen;
2755  uint32 OldSize, NewSize;
2756 #ifdef UDF_DBG
2757  int64 check_size;
2758 #endif //UDF_DBG
2759 
2760  AdPrint(("Pack ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping));
2761  AdPrint((" Length %x\n", ExtInfo->Length));
2762 
2763  OldMap = ExtInfo->Mapping;
2764  LastLba = OldMap[0].extLocation;
2765  OldLen = (OldMap[0].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->BlockSizeBits;
2766  LastType = OldMap[0].extLength >> 30;
2767  OldSize =
2768  NewSize = UDFGetMappingLength(OldMap);
2769 #ifdef UDF_DBG
2770  check_size = UDFGetExtentLength(ExtInfo->Mapping);
2771  ASSERT(!(check_size & (2048-1)));
2772 #endif //UDF_DBG
2773 
2774  l=OldMap[0].extLength & UDF_EXTENT_LENGTH_MASK;
2775  // calculate required length
2776  for(i=1; OldMap[i].extLength; i++) {
2777  if((LastType == (OldMap[i].extLength >> 30))
2778  &&
2779  ((OldMap[i].extLocation == LastLba + OldLen) ||
2780  (!OldMap[i].extLocation && !LastLba && (LastType == EXTENT_NOT_RECORDED_NOT_ALLOCATED)))
2781  &&
2782  (l + (OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK) <= UDF_MAX_EXTENT_LENGTH)) {
2783  // we can pack two blocks in one
2784  l += OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK;
2785  NewSize -= sizeof(EXTENT_MAP);
2786  } else {
2787  l = OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK;
2788  }
2789  LastLba = OldMap[i].extLocation;
2790  LastType = OldMap[i].extLength >> 30;
2791  OldLen = (OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->BlockSizeBits;
2792  }
2793  // no changes ?
2794  if(OldSize <= (NewSize + PACK_MAPPING_THRESHOLD)) {
2795  if(OldSize == NewSize)
2796  return;
2798  return;
2799  }
2800  AdPrint(("Pack ExtInfo %x, Mapping %x, realloc\n", ExtInfo, ExtInfo->Mapping));
2802  MEM_EXTMAP_TAG);
2803  // can't alloc ?
2804  if(!NewMap) return;
2805  // Ok, lets pack it...
2806  j=0;
2807  NewMap[0] = OldMap[0];
2808  LastLba = OldMap[0].extLocation;
2809  OldLen = (OldMap[0].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->BlockSizeBits;
2810  LastType = OldMap[0].extLength >> 30;
2811  for(i=1; OldMap[i].extLength; i++) {
2812 
2813  ExtPrint(("oShExt: type %x, loc %x, len %x\n",
2814  OldMap[i].extLength >> 30, OldMap[i].extLocation, OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK));
2815 
2816  if((LastType == (OldMap[i].extLength >> 30))
2817  &&
2818  ((OldMap[i].extLocation == LastLba + OldLen) ||
2819  (!OldMap[i].extLocation && !LastLba && (LastType == EXTENT_NOT_RECORDED_NOT_ALLOCATED)))
2820  &&
2821  ((NewMap[j].extLength & UDF_EXTENT_LENGTH_MASK) + (OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK) <= UDF_MAX_EXTENT_LENGTH)) {
2822  NewMap[j].extLength += OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK;
2823  } else {
2824  j++;
2825  NewMap[j] = OldMap[i];
2826  }
2827 
2828  ExtPrint(("nShExt: type %x, loc %x, len %x\n",
2829  NewMap[j].extLength >> 30, NewMap[j].extLocation, NewMap[j].extLength & UDF_EXTENT_LENGTH_MASK));
2830 
2831  LastLba = OldMap[i].extLocation;
2832  LastType = OldMap[i].extLength >> 30;
2833  OldLen = (OldMap[i].extLength & UDF_EXTENT_LENGTH_MASK) >> Vcb->BlockSizeBits;
2834  }
2835  // write terminator
2836  j++;
2837  ASSERT(NewSize == (j+1)*sizeof(EXTENT_MAP));
2838  NewMap[j].extLength =
2839  NewMap[j].extLocation = 0;
2840 
2841 #ifdef UDF_DBG
2842  ASSERT(check_size == UDFGetExtentLength(ExtInfo->Mapping));
2843  ASSERT(check_size == UDFGetExtentLength(NewMap));
2844 #endif
2845 
2846  AdPrint(("Pack ExtInfo %x, NewMap %x, OldMap %x\n", ExtInfo, NewMap, OldMap));
2847 
2848  ExtInfo->Mapping = NewMap;
2849  MyFreePool__(OldMap);
2850 
2851  AdPrint(("Pack ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping));
2852  AdPrint((" Length %x\n", ExtInfo->Length));
2853 } // end UDFPackMapping()
2854 
2855 /*
2856  This routine expands mapping to 'frag-per-LBlock' state
2857  */
2858 OSSTATUS
2859 __fastcall
2861  IN PVCB Vcb,
2862  IN PEXTENT_INFO ExtInfo // Extent array
2863  )
2864 {
2865  PEXTENT_MAP NewMapping;
2866  PEXTENT_MAP Mapping = ExtInfo->Mapping;
2867  uint32 LBS = Vcb->LBlockSize;
2868  uint32 len = (uint32)(UDFGetExtentLength(Mapping) >> Vcb->LBlockSizeBits);
2869  uint32 i,j, type, base, d;
2870  LONG l;
2871 
2872  NewMapping = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool , (len+1)*sizeof(EXTENT_MAP),
2873  MEM_EXTMAP_TAG);
2874  if(!NewMapping) return STATUS_INSUFFICIENT_RESOURCES;
2875 
2876  j=0;
2877  d = LBS >> Vcb->BlockSizeBits;
2878  for(i=0; (l = (Mapping[i].extLength & UDF_EXTENT_LENGTH_MASK)); i++) {
2879  base = Mapping[i].extLocation;
2880  type = Mapping[i].extLength & UDF_EXTENT_FLAG_MASK;
2881  for(; l>=(LONG)LBS; j++) {
2882  NewMapping[j].extLength = LBS | type;
2883  NewMapping[j].extLocation = base;
2884  base+=d;
2885  l-=LBS;
2886  }
2887  }
2888  // record terminator
2889  ASSERT(NewMapping);
2890  RtlZeroMemory(&(NewMapping[j]), sizeof(EXTENT_MAP));
2892  ExtInfo->Mapping = NewMapping;
2893 
2894  return STATUS_SUCCESS;
2895 } // end UDFUnPackMapping()
2896 
2897 /*
2898  Relocate a part of extent that starts from relative (inside extent)
2899  block number 'ExtBlock' and has length of 'BC' blocks to continuous
2900  run which starts at block 'Lba'
2901  */
2902 OSSTATUS
2904  IN PVCB Vcb,
2905  IN PEXTENT_INFO ExtInfo,
2906  IN uint32 ExtBlock,
2907  IN uint32 Lba,
2908  IN uint32 BC
2909  )
2910 {
2911  return STATUS_ACCESS_DENIED;
2912 }
2913 
2914 /*
2915  This routine checks if all the data required is in cache.
2916  */
2917 BOOLEAN
2919  IN PVCB Vcb,
2920  IN PEXTENT_INFO ExtInfo, // Extent array
2921  IN int64 Offset, // offset in extent
2922  IN uint32 Length,
2923  IN BOOLEAN ForWrite
2924  )
2925 {
2926  BOOLEAN retstat = FALSE;
2927  PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array
2928  SIZE_T to_read;
2929  uint32 Lba, sect_offs, flags, i;
2930 
2931  WCacheStartDirect__(&(Vcb->FastCache), Vcb, TRUE/*FALSE*//*ForWrite*/);
2932  if(!ExtInfo || !ExtInfo->Mapping) goto EO_IsCached;
2933  if(!Length) {
2934  retstat = TRUE;
2935  goto EO_IsCached;
2936  }
2937 
2938  // prevent reading out of data space
2939  if(Offset > ExtInfo->Length) goto EO_IsCached;
2940  if(Offset+Length > ExtInfo->Length) goto EO_IsCached;
2941  Offset += ExtInfo->Offset; // used for in-ICB data
2942  // read maximal possible part of each frag of extent
2943  Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, &sect_offs, &to_read, &flags, &i);
2944  while(((LONG)Length) > 0) {
2945  // EOF check
2946  if(Lba == LBA_OUT_OF_EXTENT) goto EO_IsCached;
2947  Extent += (i + 1);
2948  // check for reading tail
2949  to_read = min(to_read, Length);
2951  retstat = UDFIsDataCached(Vcb, Lba, (to_read+sect_offs+Vcb->BlockSize-1)>>Vcb->BlockSizeBits);
2952  if(!retstat) goto EO_IsCached;
2953  } else if(ForWrite) {
2954  goto EO_IsCached;
2955  }
2956  Offset += to_read;
2957  Length -= to_read;
2958  Lba = UDFNextExtentToLba(Vcb, Extent, &to_read, &flags, &i);
2959  }
2960  retstat = TRUE;
2961 EO_IsCached:
2962  if(!retstat) {
2963  WCacheEODirect__(&(Vcb->FastCache), Vcb);
2964  }
2965  return retstat;
2966 } // end UDFIsExtentCached()
2967 
2968 /*
2969  This routine reads cached data only.
2970  */
2971 /*OSSTATUS
2972 UDFReadExtentCached(
2973  IN PVCB Vcb,
2974  IN PEXTENT_INFO ExtInfo, // Extent array
2975  IN int64 Offset, // offset in extent
2976  IN uint32 Length,
2977  OUT int8* Buffer,
2978  OUT PSIZE_T ReadBytes
2979  )
2980 {
2981  (*ReadBytes) = 0;
2982  if(!ExtInfo || !ExtInfo->Mapping) return STATUS_INVALID_PARAMETER;
2983 
2984  PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array
2985  uint32 to_read, Lba, sect_offs, flags;
2986  SIZE_T _ReadBytes;
2987  OSSTATUS status;
2988  // prevent reading out of data space
2989  if(Offset > ExtInfo->Length) return STATUS_END_OF_FILE;
2990  if(Offset+Length > ExtInfo->Length) Length = (uint32)(ExtInfo->Length - Offset);
2991  Offset += ExtInfo->Offset; // used for in-ICB data
2992  // read maximal possible part of each frag of extent
2993  while(((LONG)Length) > 0) {
2994  Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, &sect_offs, &to_read, &flags, NULL);
2995  // EOF check
2996  if(Lba == LBA_OUT_OF_EXTENT) return STATUS_END_OF_FILE;
2997  // check for reading tail
2998  to_read = (to_read < Length) ?
2999  to_read : Length;
3000  if(flags == EXTENT_RECORDED_ALLOCATED) {
3001  status = UDFReadDataCached(Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs, to_read, Buffer, &_ReadBytes);
3002  (*ReadBytes) += _ReadBytes;
3003  } else {
3004  RtlZeroMemory(Buffer, to_read);
3005  (*ReadBytes) += to_read;
3006  status = STATUS_SUCCESS;
3007  }
3008  if(!OS_SUCCESS(status)) return status;
3009  // prepare for reading next frag...
3010  Buffer += to_read;
3011  Offset += to_read;
3012  Length -= to_read;
3013  }
3014  return STATUS_SUCCESS;
3015 } // end UDFReadExtentCached()*/
3016 
3017 /*
3018  This routine reads data at any offset from specified extent.
3019  */
3020 OSSTATUS
3022  IN PVCB Vcb,
3023  IN PEXTENT_INFO ExtInfo, // Extent array
3024  IN int64 Offset, // offset in extent
3025  IN SIZE_T Length,
3026  IN BOOLEAN Direct,
3027  OUT int8* Buffer,
3029  )
3030 {
3031  (*ReadBytes) = 0;
3032  if(!ExtInfo || !ExtInfo->Mapping) return STATUS_INVALID_PARAMETER;
3033  ASSERT((uintptr_t)Buffer > 0x1000);
3034 
3035  AdPrint(("Read ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping));
3036 
3037  PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array
3038  SIZE_T to_read, _ReadBytes;
3039  uint32 Lba, sect_offs, flags;
3040  uint32 index;
3041  OSSTATUS status;
3042  // prevent reading out of data space
3043  if(Offset > ExtInfo->Length) return STATUS_END_OF_FILE;
3044  if(Offset+Length > ExtInfo->Length) Length = (uint32)(ExtInfo->Length - Offset);
3045  Offset += ExtInfo->Offset; // used for in-ICB data
3046  // read maximal possible part of each frag of extent
3047  Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, &sect_offs, &to_read, &flags, &index);
3048  _ReadBytes = index;
3049  while(Length) {
3050  // EOF check
3051  if(Lba == LBA_OUT_OF_EXTENT) return STATUS_END_OF_FILE;
3052  Extent += (_ReadBytes + 1);
3053  // check for reading tail
3054  to_read = min(to_read, Length);
3056  status = UDFReadData(Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs, to_read, Direct, Buffer, &_ReadBytes);
3057  (*ReadBytes) += _ReadBytes;
3058  if(!OS_SUCCESS(status)) return status;
3059  } else {
3061  (*ReadBytes) += to_read;
3062  }
3063  // prepare for reading next frag...
3064  Length -= to_read;
3065  if(!Length)
3066  break;
3067  ASSERT(to_read);
3068  Buffer += to_read;
3069 // Offset += to_read;
3071  _ReadBytes = index;
3072  sect_offs = 0;
3073  }
3074  return STATUS_SUCCESS;
3075 } // end UDFReadExtent()
3076 
3077 /*
3078  This routine reads and builds mapping for
3079  specified amount of data at any offset from specified extent.
3080  Size of output buffer is limited by *_SubExtInfoSz
3081  */
3082 OSSTATUS
3084  IN PVCB Vcb,
3085  IN PEXTENT_INFO ExtInfo, // Extent array
3086  IN int64 Offset, // offset in extent to start SubExtent from
3087  OUT PEXTENT_MAP* _SubExtInfo, // SubExtent mapping array
3088  IN OUT uint32* _SubExtInfoSz, // IN: maximum number of fragments to get
3089  // OUT: actually obtained fragments
3090  OUT int64* _NextOffset // offset, caller can start from to continue
3091  )
3092 {
3093  if(!ExtInfo || !ExtInfo->Mapping)
3094  return STATUS_INVALID_PARAMETER;
3095 
3096  PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array
3097  PEXTENT_MAP SubExtInfo;
3098  SIZE_T to_read;
3099  uint32 Lba, sect_offs, flags, Skip_MapEntries;
3100  int32 SubExtInfoSz = *_SubExtInfoSz;
3101  int64 Length;
3102  int64 NextOffset;
3103 // OSSTATUS status = STATUS_BUFFER_OVERFLOW;
3104 
3105  (*_SubExtInfo) = NULL;
3106  (*_SubExtInfoSz) = 0;
3107  NextOffset = Offset;
3108  // prevent reading out of data space
3109  if(Offset >= ExtInfo->Length)
3110  return STATUS_END_OF_FILE;
3111  Length = ExtInfo->Length - Offset;
3112  Offset += ExtInfo->Offset; // used for in-ICB data
3113  // read maximal possible part of each frag of extent
3114  SubExtInfo = (PEXTENT_MAP)MyAllocatePoolTag__(NonPagedPool , SubExtInfoSz*sizeof(EXTENT_MAP),
3115  MEM_EXTMAP_TAG);
3116  (*_SubExtInfo) = SubExtInfo;
3117  if(!SubExtInfo)
3119 
3120  Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, &sect_offs, &to_read, &flags, &Skip_MapEntries);
3121  while(Length && SubExtInfoSz) {
3122  // EOF check
3123  if(Lba == LBA_OUT_OF_EXTENT) {
3124  BrutePoint();
3125  return STATUS_END_OF_FILE;
3126  }
3127  Extent += (Skip_MapEntries + 1);
3128  // check for reading tail
3130  SubExtInfo->extLength = to_read;
3132  SubExtInfo->extLocation = LBA_NOT_ALLOCATED;
3133  } else
3135  ASSERT(!(Lba & 0x80000000));
3136  SubExtInfo->extLocation = Lba | 0x80000000;
3137  } else {
3138  SubExtInfo->extLocation = Lba;
3139  }
3140  (*_SubExtInfoSz)++;
3141  SubExtInfoSz--;
3142  NextOffset += to_read;
3143  // prepare for reading next frag...
3144  Length -= to_read;
3145  if(!Length) {
3146 // status = STATUS_SUCCESS;
3147  break;
3148  }
3149  ASSERT(to_read);
3150  Lba = UDFNextExtentToLba(Vcb, Extent, &to_read, &flags, &Skip_MapEntries);
3151  sect_offs = 0;
3152  }
3153  (*_NextOffset) = NextOffset;
3154  return STATUS_SUCCESS;
3155 } // end UDFReadExtentLocation()
3156 
3157 #ifdef _MSC_VER
3158 #pragma warning(push)
3159 #pragma warning(disable:4035) // re-enable below
3160 #endif
3161 
3162 uint32
3164  IN int8* Buffer,
3165  IN uint32 Length
3166  )
3167 {
3168  uint32 i;
3169  Length /= sizeof(uint32);
3170  for(i=0; i<Length; i++) {
3171  if( ((uint32*)Buffer)[i] )
3172  break;
3173  }
3174  return Length*sizeof(uint32);
3175 }
3176 
3177 #ifdef _MSC_VER
3178 #pragma warning(pop) // re-enable warning #4035
3179 #endif
3180 
3181 #ifndef UDF_READ_ONLY_BUILD
3182 /*
3183  This routine writes data at any offset to specified extent.
3184  */
3185 OSSTATUS
3187  IN PVCB Vcb,
3188  IN PEXTENT_INFO ExtInfo, // Extent array
3189  IN int64 Offset, // offset in extent
3190  IN SIZE_T Length,
3191  IN BOOLEAN Direct, // setting this flag delays flushing of given
3192  // data to indefinite term
3193  IN int8* Buffer,
3194  OUT PSIZE_T WrittenBytes
3195  )
3196 {
3197  if(!ExtInfo || !ExtInfo->Mapping)
3198  return STATUS_INVALID_PARAMETER;
3199 
3200  PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array
3201  uint32 Lba, sect_offs, flags;
3202  OSSTATUS status;
3203  SIZE_T to_write, _WrittenBytes;
3204  BOOLEAN reread_lba;
3205 // BOOLEAN already_prepared = FALSE;
3206 // BOOLEAN prepare = !Buffer;
3207 
3208  AdPrint(("Write ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping));
3209 
3210  Offset += ExtInfo->Offset; // used for in-ICB data
3211  // write maximal possible part of each frag of extent
3212  while(((LONG)Length) > 0) {
3213  UDFCheckSpaceAllocation(Vcb, 0, Extent, AS_USED); // check if used
3214  Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, &sect_offs, &to_write, &flags, NULL);
3215  // EOF check
3216  if(Lba == LBA_OUT_OF_EXTENT) {
3217  return STATUS_END_OF_FILE;
3218  }
3219 /* if((to_write < Length) &&
3220  !Direct && !prepare && !already_prepared) {
3221  // rebuild mapping, allocate space, etc.
3222  // to indicate this, set Buffer to NULL
3223  AdPrint(("UDFWriteExtent: Prepare\n"));
3224  BrutePoint();
3225  _WrittenBytes = 0;
3226  status = UDFWriteExtent(Vcb, ExtInfo, Offset, Length, *//*Direct*//*FALSE, NULL, &_WrittenBytes);
3227  if(!OS_SUCCESS(status)) {
3228  return status;
3229  }
3230  Extent = ExtInfo->Mapping;
3231  Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, &sect_offs, &to_write, &flags, NULL);
3232  already_prepared = TRUE;
3233  }*/
3235  // here we should allocate space for this extent
3236  if(!OS_SUCCESS(status = UDFMarkNotAllocatedAsAllocated(Vcb, Offset, to_write, ExtInfo)))
3237  return status;
3238  Extent = ExtInfo->Mapping;
3239  UDFCheckSpaceAllocation(Vcb, 0, Extent, AS_USED); // check if used
3240  Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, &sect_offs, &to_write, &flags, NULL);
3241  if(Lba == LBA_OUT_OF_EXTENT) {
3242  return STATUS_END_OF_FILE;
3243  }
3244  // we have already re-read Lba
3245  reread_lba = FALSE;
3246  } else {
3247  // we may need to re-read Lba if some changes are
3248  // made while converting from Alloc-Not-Rec
3249  reread_lba = TRUE;
3250  }
3251  // check if writing to not recorded allocated
3252  // in this case we must pad blocks with zeros around
3253  // modified area
3254  //
3255  // ...|xxxxxxxx|xxxxxxxx|xxxxxxxx|...
3256  // . .
3257  // . || .
3258  // . \/ .
3259  // . .
3260  // ...|000ddddd|dddddddd|dd000000|...
3261  // . .
3262  // ^ ^
3263  // sect_offs sect_offs+to_write
3264  // . .
3265  // .<-- to_write -->.
3266  //
3267  to_write = min(to_write, Length);
3269  if(!OS_SUCCESS(status = UDFMarkAllocatedAsRecorded(Vcb, Offset, to_write, ExtInfo)))
3270  return status;
3271  Extent = ExtInfo->Mapping;
3272  UDFCheckSpaceAllocation(Vcb, 0, Extent, AS_USED); // check if used
3273  if(reread_lba) {
3274  Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, &sect_offs, &to_write, &flags, NULL);
3275  to_write = min(to_write, Length);
3276  }
3277  /*
3278  we must fill 1st block with zeros in 1 of 2 cases:
3279  1) start offset is not aligned on LBlock boundary
3280  OR
3281  2) end offset is not aligned on LBlock boundary and lays in
3282  the same LBlock
3283 
3284  we must fill last block with zeros if both
3285  1) end offset is not aligned on LBlock boundary
3286  AND
3287  2) end offset DOESN'T lay in the 1st LBlock
3288  */
3289 
3290 // if(!prepare) {
3291  // pad 1st logical block
3292  if((sect_offs || (sect_offs + to_write < Vcb->LBlockSize) )
3293  &&
3294  !Vcb->CDR_Mode) {
3296  ( ((uint64)Lba) << Vcb->BlockSizeBits),
3297  Vcb->LBlockSize, Direct, Vcb->ZBuffer, &_WrittenBytes);
3298  if(!OS_SUCCESS(status))
3299  return status;
3300  }
3301  // pad last logical block
3302  if((sect_offs + to_write > Vcb->LBlockSize) &&
3303  (sect_offs + to_write) & (Vcb->LBlockSize - 1)) {
3305  (( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs + to_write) & ~((int64)(Vcb->LBlockSize)-1),
3306  Vcb->LBlockSize, Direct, Vcb->ZBuffer, &_WrittenBytes);
3307  }
3308  if(!OS_SUCCESS(status))
3309  return status;
3310 /* } else {
3311  status = STATUS_SUCCESS;
3312  }*/
3313  }
3314  ASSERT(to_write);
3315 // if(!prepare) {
3316  status = UDFWriteData(Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs, to_write, Direct, Buffer, &_WrittenBytes);
3317  *WrittenBytes += _WrittenBytes;
3318  if(!OS_SUCCESS(status)) return status;
3319 /* } else {
3320  status = STATUS_SUCCESS;
3321  *WrittenBytes += to_write;
3322  }*/
3323  // prepare for writing next frag...
3324  Buffer += to_write;
3325  Offset += to_write;
3326  Length -= to_write;
3327  }
3328  AdPrint(("Write: ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping));
3329  return STATUS_SUCCESS;
3330 } // end UDFWriteExtent()
3331 
3332 //#if 0
3333 /*
3334  This routine zeroes/deallocates data at any offset to specified extent.
3335  */
3336 OSSTATUS
3338  IN PVCB Vcb,
3339  IN PEXTENT_INFO ExtInfo, // Extent array
3340  IN int64 Offset, // offset in extent
3341  IN SIZE_T Length,
3342  IN BOOLEAN Deallocate, // deallocate frag or just mark as unrecorded
3343  IN BOOLEAN Direct, // setting this flag delays flushing of given
3344  // data to indefinite term
3345  OUT PSIZE_T WrittenBytes
3346  )
3347 {
3348  if(!ExtInfo || !ExtInfo->Mapping)
3349  return STATUS_INVALID_PARAMETER;
3350 
3351  PEXTENT_MAP Extent = ExtInfo->Mapping; // Extent array
3352  uint32 Lba, sect_offs, flags;
3353  OSSTATUS status;
3354  SIZE_T to_write, _WrittenBytes;
3355  SIZE_T LBS = Vcb->LBlockSize;
3356 
3357  AdPrint(("Zero ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping));
3358 
3359  Offset += ExtInfo->Offset; // used for in-ICB data
3360  // fill/deallocate maximal possible part of each frag of extent
3361  while(((LONG)Length) > 0) {
3362  Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, &sect_offs, &to_write, &flags, NULL);
3363  // EOF check
3364  if(Lba == LBA_OUT_OF_EXTENT) {
3365  return STATUS_END_OF_FILE;
3366  }
3367  // check for writing tail
3368  to_write = min(to_write, Length);
3369 
3371  // here we should do nothing
3372  *WrittenBytes += to_write;
3373  } else
3375  // we should just deallocate this frag
3376  if(Deallocate) {
3377  if(!OS_SUCCESS(status = UDFMarkAllocatedAsNotAllocated(Vcb, Offset, to_write, ExtInfo)))
3378  return status;
3379  }
3380  Extent = ExtInfo->Mapping;
3381  *WrittenBytes += to_write;
3382  } else {
3383  // fill tail of the 1st Block with ZEROs
3384  if(sect_offs) {
3385  status = UDFWriteData(Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits) + sect_offs,
3386  min(to_write, LBS-sect_offs),
3387  Direct, Vcb->ZBuffer, &_WrittenBytes);
3388  *WrittenBytes += _WrittenBytes;
3389  if(!OS_SUCCESS(status))
3390  return status;
3391  Offset += _WrittenBytes;
3392  Length -= _WrittenBytes;
3393  to_write -= _WrittenBytes;
3394  Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, &sect_offs, &to_write, &flags, NULL);
3397  ASSERT(!sect_offs);
3398  }
3399  // deallocate Blocks
3400  if(to_write >= LBS) {
3401  // use 'sect_offs' as length of extent to be deallocated
3402  sect_offs = to_write & ~(LBS - 1);
3403  if(Deallocate) {
3404  status = UDFMarkAllocatedAsNotAllocated(Vcb, Offset, sect_offs, ExtInfo);
3405  } else {
3406  status = UDFMarkRecordedAsAllocated(Vcb, Offset, sect_offs, ExtInfo);
3407  }
3408  if(!OS_SUCCESS(status))
3409  return status;
3410  // reload extent mapping
3411  Extent = ExtInfo->Mapping;
3412  Offset += sect_offs;
3413  Length -= sect_offs;
3414  *WrittenBytes += sect_offs;
3415  to_write -= sect_offs;
3416  Lba = UDFExtentOffsetToLba(Vcb, Extent, Offset, &sect_offs, &to_write, &flags, NULL);
3419  ASSERT(!sect_offs);
3420  }
3421  // fill beginning of the last Block with ZEROs
3422  if(to_write) {
3423  status = UDFWriteData(Vcb, TRUE, ( ((uint64)Lba) << Vcb->BlockSizeBits), to_write, Direct, Vcb->ZBuffer, &_WrittenBytes);
3424  *WrittenBytes += _WrittenBytes;
3425  if(!OS_SUCCESS(status))
3426  return status;
3427  ASSERT(to_write == _WrittenBytes);
3428  }
3429  }
3430  AdPrint(("Zero... ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping));
3431  // prepare for filling next frag...
3432  Offset += to_write;
3433  Length -= to_write;
3434  }
3435  AdPrint(("Zero: ExtInfo %x, Mapping %x\n", ExtInfo, ExtInfo->Mapping));
3436  return STATUS_SUCCESS;
3437 } // end UDFZeroExtent()
3438 //#endif //0
3439 #endif //UDF_READ_ONLY_BUILD
unsigned long long uint64
Definition: platform.h:18
struct _EXTENT_AD * PEXTENT_AD
#define UDFAcquireResourceExclusive(Resource, CanWait)
Definition: env_spec_w32.h:656
int add
Definition: i386-dis.c:3122
struct _UDF_ALLOCATION_CACHE_ITEM * PUDF_ALLOCATION_CACHE_ITEM
uint32 UDFNextExtentToLba(IN PVCB Vcb, IN PEXTENT_MAP Extent, OUT PSIZE_T AvailLength, OUT uint32 *Flags, OUT uint32 *Index)
Definition: extent.cpp:79
void UDFDiscardFESpace(IN PVCB Vcb, IN PEXTENT_MAP Mapping, IN uint32 lim)
Definition: extent.cpp:1329
#define EXTENT_FLAG_VERIFY
Definition: udf_rel.h:81
OSSTATUS UDFAllocateFESpace(IN PVCB Vcb, IN PUDF_FILE_INFO DirInfo, IN uint32 PartNum, IN PEXTENT_INFO FEExtInfo, IN uint32 Len)
Definition: extent.cpp:1563
#define IN
Definition: typedefs.h:38
PEXTENT_AD PEXTENT_MAP
Definition: ecma_167.h:135
#define UDFPrint(Args)
Definition: udffs.h:225
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define EXTENT_RECORDED_ALLOCATED
Definition: ecma_167.h:367
#define ALLOC_DESC_MAX_RECURSE
Definition: udf_rel.h:120
#define TID_ALLOC_EXTENT_DESC
Definition: ecma_167.h:167
void __fastcall UDFPackMapping(IN PVCB Vcb, IN PEXTENT_INFO ExtInfo)
Definition: extent.cpp:2747
static void xor(unsigned char *dst, const unsigned char *a, const unsigned char *b, const int count)
Definition: crypt_des.c:251
#define AdPrint(_x_)
Definition: env_spec_w32.h:292
#define LBA_NOT_ALLOCATED
Definition: udf_rel.h:427
uint32 lengthAllocDescs
Definition: ecma_167.h:766
OSSTATUS UDFReadExtent(IN PVCB Vcb, IN PEXTENT_INFO ExtInfo, IN int64 Offset, IN SIZE_T Length, IN BOOLEAN Direct, OUT int8 *Buffer, OUT PSIZE_T ReadBytes)
Definition: extent.cpp:3021
struct _SHORT_AD SHORT_AD
ecx edi ebx edx edi decl ecx esi eax jecxz decl eax andl eax esi movl edx movl TEMP incl eax andl eax ecx incl ebx eax jnz xchgl ecx incl TEMP esi
Definition: synth_sse3d.h:103
#define __fastcall
Definition: sync.c:41
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
uint32 lengthExtendedAttr
Definition: ecma_167.h:765
struct _EXTENDED_FILE_ENTRY EXTENDED_FILE_ENTRY
#define MEM_LNGAD_TAG
Definition: udf_rel.h:495
EXTENT_AD EXTENT_MAP
Definition: ecma_167.h:134
OSSTATUS UDFBuildShortAllocDescs(IN PVCB Vcb, IN uint32 PartNum, OUT int8 **Buff, IN uint32 InitSz, IN OUT PUDF_FILE_INFO FileInfo)
Definition: extent.cpp:825
unsigned int uint32
Definition: types.h:32
static PVOID Mapping[EMS_PHYSICAL_PAGES]
Definition: emsdrv.c:41
#define UDFReleaseResource(Resource)
Definition: env_spec_w32.h:661
BOOLEAN UDFIsExtentCached(IN PVCB Vcb, IN PEXTENT_INFO ExtInfo, IN int64 Offset, IN uint32 Length, IN BOOLEAN ForWrite)
Definition: extent.cpp:2918
OSSTATUS UDFWriteData(IN PVCB Vcb, IN BOOLEAN Translate, IN int64 Offset, IN SIZE_T Length, IN BOOLEAN Direct, IN int8 *Buffer, OUT PSIZE_T WrittenBytes)
Definition: phys_lib.cpp:4141
ULONG MyReallocPool__(PCHAR addr, ULONG len, PCHAR *pnewaddr, ULONG newlen)
Definition: mem_tools.h:224
OSSTATUS UDFResizeExtent(IN PVCB Vcb, IN uint32 PartNum, IN int64 Length, IN BOOLEAN AlwaysInIcb, OUT PEXTENT_INFO ExtInfo)
Definition: extent.cpp:2235
void UDFSetUpTag(IN PVCB Vcb, IN tag *Tag, IN uint16 DataLen, IN uint32 TagLoc)
Definition: udf_info.cpp:936
#define ICB_FLAG_AD_LONG
Definition: ecma_167.h:494
struct _FILE_ENTRY * PFILE_ENTRY
#define MEM_EXTMAP_TAG
Definition: udf_rel.h:492
OSSTATUS UDFInitAllocationCache(IN PVCB Vcb, IN uint32 AllocClass, OUT PUDF_ALLOCATION_CACHE_ITEM *_AllocCache, OUT uint32 *_lim, IN BOOLEAN Init)
Definition: extent.cpp:1361
uint32 extLocation
Definition: ecma_167.h:129
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define ICB_FLAG_AD_EXTENDED
Definition: ecma_167.h:495
Definition: ecma_167.h:138
Definition: cdstruc.h:504
#define UDFCheckSpaceAllocation(Vcb, FileInfo, Map, asXXX)
Definition: udf_info.h:281
#define UDF_FE_FLAG_IS_SDIR
File is a StreamDir.
Definition: udf_rel.h:327
long_ad LONG_AD
Definition: ecma_167.h:379
OSSTATUS UDFReadData(IN PVCB Vcb, IN BOOLEAN Translate, IN LONGLONG Offset, IN ULONG Length, IN BOOLEAN Direct, OUT PCHAR Buffer, OUT PSIZE_T ReadBytes)
#define UDF_PREALLOC_CLASS_FE
Definition: udf_info.h:355
uint32 UDFExtentOffsetToLba(IN PVCB Vcb, IN PEXTENT_MAP Extent, IN int64 Offset, OUT uint32 *SectorOffset, OUT PSIZE_T AvailLength, OUT uint32 *Flags, OUT uint32 *Index)
Definition: extent.cpp:28
OSSTATUS __fastcall UDFUnPackMapping(IN PVCB Vcb, IN PEXTENT_INFO ExtInfo)
Definition: extent.cpp:2860
long long int64
Definition: platform.h:13
int64 Length
Definition: udf_rel.h:67
static calc_node_t * pop(void)
Definition: rpn_ieee.c:90
#define lba
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_END_OF_FILE
Definition: shellext.h:67
PEXTENT_MAP Mapping
Definition: udf_rel.h:66
OSSTATUS UDFMarkAllocatedAsNotXXX(IN PVCB Vcb, IN int64 Offset, IN uint32 Length, IN PEXTENT_INFO ExtInfo, IN BOOLEAN Deallocate)
Definition: extent.cpp:2094
OSSTATUS UDFReadExtentLocation(IN PVCB Vcb, IN PEXTENT_INFO ExtInfo, IN int64 Offset, OUT PEXTENT_MAP *_SubExtInfo, IN OUT uint32 *_SubExtInfoSz, OUT int64 *_NextOffset)
Definition: extent.cpp:3083
OSSTATUS UDFBuildAllocDescs(IN PVCB Vcb, IN uint32 PartNum, IN OUT PUDF_FILE_INFO FileInfo, OUT int8 **AllocData)
Definition: extent.cpp:2628
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define TID_EXTENDED_FILE_ENTRY
Definition: ecma_167.h:175
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
ULONG_PTR * PSIZE_T
Definition: typedefs.h:78
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
OSSTATUS UDFFlushAllCachedAllocations(IN PVCB Vcb, IN uint32 AllocClass)
Definition: extent.cpp:1508
PEXTENT_MAP UDFLongAllocDescToMapping(IN PVCB Vcb, IN PLONG_AD AllocDesc, IN uint32 AllocDescLength, IN uint32 SubCallCount, OUT PEXTENT_INFO AllocLoc)
Definition: extent.cpp:457
GLuint base
Definition: 3dtext.c:35
long LONG
Definition: pedump.c:60
OSSTATUS UDFZeroExtent(IN PVCB Vcb, IN PEXTENT_INFO ExtInfo, IN int64 Offset, IN SIZE_T Length, IN BOOLEAN Deallocate, IN BOOLEAN Direct, OUT PSIZE_T WrittenBytes)
Definition: extent.cpp:3337
uint32 __fastcall UDFPartLbaToPhys(IN PVCB Vcb, IN lb_addr *Addr)
Definition: alloc.cpp:114
#define OSSTATUS
Definition: env_spec_w32.h:57
struct _ACPI_EFI_BOOT_SERVICES * BS
unsigned int uintptr_t
Definition: crtdefs.h:300
#define SectorOffset(L)
Definition: cdprocs.h:1632
unsigned char BOOLEAN
#define ICB_FLAG_AD_SHORT
Definition: ecma_167.h:493
static const char * ts(int t)
#define EXTENT_NOT_RECORDED_NOT_ALLOCATED
Definition: ecma_167.h:369
smooth NULL
Definition: ftsmooth.c:416
void UDFFreeFESpace(IN PVCB Vcb, IN PUDF_FILE_INFO DirInfo, IN PEXTENT_INFO FEExtInfo)
Definition: extent.cpp:1725
#define UDFMarkSpaceAsXXXNoProtect(Vcb, FileInfo, Map, asXXX)
Definition: udf_info.h:302
PEXTENT_MAP UDFShortAllocDescToMapping(IN PVCB Vcb, IN uint32 PartNum, IN PSHORT_AD AllocDesc, IN uint32 AllocDescLength, IN uint32 SubCallCount, OUT PEXTENT_INFO AllocLoc)
Definition: extent.cpp:294
PEXTENT_MAP __fastcall UDFExtentToMapping_(IN PEXTENT_AD Extent)
Definition: extent.cpp:189
Definition: parser.c:48
#define PACK_MAPPING_THRESHOLD
Definition: udf_rel.h:62
Definition: bufpool.h:45
#define UDFMarkRecordedAsAllocated(Vcb, Off, Len, Ext)
Definition: udf_info.h:516
GLuint index
Definition: glext.h:6031
PEXTENT_MAP UDFExtAllocDescToMapping(IN PVCB Vcb, IN PEXT_AD AllocDesc, IN uint32 AllocDescLength, IN uint32 SubCallCount, OUT PEXTENT_INFO AllocLoc)
Definition: extent.cpp:595
int64 UDFGetExtentLength(IN PEXTENT_MAP Extent)
Definition: extent.cpp:142
struct _SHORT_AD * PSHORT_AD
uint32 __fastcall UDFPartStart(PVCB Vcb, uint32 PartNum)
Definition: alloc.cpp:222
static NTSTATUS ReadBytes(IN PDEVICE_OBJECT LowerDevice, OUT PUCHAR Buffer, IN ULONG BufferSize, OUT PULONG_PTR FilledBytes)
Definition: detect.c:67
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define MyAllocatePool__(type, size)
Definition: mem_tools.h:149
r l[0]
Definition: byte_order.h:167
#define ICB_FLAG_AD_IN_ICB
Definition: ecma_167.h:496
struct _ALLOC_EXT_DESC ALLOC_EXT_DESC
icbtag icbTag
Definition: ecma_167.h:744
Definition: ecma_167.h:742
LONG_AD * PLONG_AD
Definition: ecma_167.h:380
#define UDFGetBadBit(arr, bit)
Definition: udf_info.h:1205
#define d
Definition: ke_i.h:81
UCHAR Flags
Definition: udf_rel.h:69
ecx edi ebx edx edi decl ecx esi eax jecxz decl eax andl eax esi movl eax
Definition: synth_sse3d.h:85
PEXTENT_MAP __fastcall UDFMergeMappings(IN PEXTENT_MAP Extent, IN PEXTENT_MAP Extent2)
Definition: extent.cpp:266
#define EXTENT_FLAG_2K_COMPAT
Definition: udf_rel.h:82
#define UDF_EXT_MAP_MULT
#define Vcb
Definition: cdprocs.h:1425
ULONG to_read
Definition: btrfs.c:4136
uint32 UDFGetZeroLength(IN int8 *Buffer, IN uint32 Length)
Definition: extent.cpp:3163
#define MyFreePool__(addr)
Definition: mem_tools.h:152
#define UDF_VCB_IC_W2K_COMPAT_ALLOC_DESCS
Definition: udf_common.h:501
static const UCHAR Index[8]
Definition: usbohci.c:18
PVOID Alloc(IN DWORD dwFlags, IN SIZE_T dwBytes)
Definition: main.c:63
#define MEM_ALLOC_CACHE_TAG
Definition: udf_rel.h:496
#define BrutePoint()
Definition: env_spec_w32.h:504
uint32 lengthExtendedAttr
Definition: ecma_167.h:533
PEXTENT_MAP UDFReadMappingFromXEntry(IN PVCB Vcb, IN uint32 PartNum, IN tag *XEntry, IN OUT uint32 *Offset, OUT PEXTENT_INFO AllocLoc)
Definition: extent.cpp:735
OSSTATUS UDFMarkAllocatedAsRecorded(IN PVCB Vcb, IN int64 Offset, IN uint32 Length, IN PEXTENT_INFO ExtInfo)
Definition: extent.cpp:1814
#define EXTENT_NOT_RECORDED_ALLOCATED
Definition: ecma_167.h:368
#define Len
Definition: deflate.h:82
struct _ALLOC_EXT_DESC * PALLOC_EXT_DESC
OSSTATUS UDFGetCachedAllocation(IN PVCB Vcb, IN uint32 ParentLocation, OUT PEXTENT_INFO Ext, OUT uint32 *Items, IN uint32 AllocClass)
Definition: extent.cpp:1417
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define UDFExtentToMapping(e)
Definition: udf_info.h:181
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
ecx edi ebx edx edi decl ecx esi eax jecxz decl eax andl ebx
Definition: synth_sse3d.h:83
static struct proto Ext[]
Definition: mkg3states.c:87
GLbitfield flags
Definition: glext.h:7161
OSSTATUS UDFStoreCachedAllocation(IN PVCB Vcb, IN uint32 ParentLocation, IN PEXTENT_INFO Ext, IN uint32 Items, IN uint32 AllocClass)
Definition: extent.cpp:1457
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
Definition: ecma_167.h:513
#define ValidateFileInfo(fi)
Definition: env_spec_w32.h:516
char line[200]
Definition: main.c:97
uint32 Offset
Definition: udf_rel.h:65
uint32 UDFGetMappingLength(IN PEXTENT_MAP Extent)
Definition: extent.cpp:223
#define index(s, c)
Definition: various.h:29
#define OS_SUCCESS(a)
Definition: env_spec_w32.h:56
uint32 lengthAllocDescs
Definition: ecma_167.h:534
#define ExtPrint(_x_)
Definition: env_spec_w32.h:294
OSSTATUS UDFMarkNotAllocatedAsAllocated(IN PVCB Vcb, IN int64 Offset, IN uint32 Length, IN PEXTENT_INFO ExtInfo)
Definition: extent.cpp:1948
#define UDF_MAX_EXTENT_LENGTH
Definition: udf_rel.h:511
GLenum GLsizei len
Definition: glext.h:6722
GLdouble s
Definition: gl.h:2039
OSSTATUS WCacheEODirect__(IN PW_CACHE Cache, IN PVOID Context)
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
#define EXTENT_FLAG_ALLOC_MASK
Definition: udf_rel.h:78
OSSTATUS WCacheStartDirect__(IN PW_CACHE Cache, IN PVOID Context, IN BOOLEAN Exclusive)
GLenum src
Definition: glext.h:6340
ULONG UDFLocateLbaInExtent(IN PVCB Vcb, IN PEXTENT_MAP Extent, IN lba_t lba)
Definition: extent.cpp:116
#define AS_USED
Definition: udf_info.h:327
#define MyAllocatePoolTag__(type, size, tag)
Definition: mem_tools.h:150
#define UDFMarkSpaceAsXXX(Vcb, FileInfo, Map, asXXX)
Definition: udf_info.h:322
uint32 extLength
Definition: ecma_167.h:128
#define UDF_EXTENT_FLAG_MASK
Definition: osta_misc.h:149
struct _EXTENT_AD EXTENT_AD
ULONG_PTR SIZE_T
Definition: typedefs.h:78
icbtag icbTag
Definition: ecma_167.h:515
uint32 __fastcall UDFPartEnd(PVCB Vcb, uint32 PartNum)
Definition: alloc.cpp:242
#define AS_DISCARDED
Definition: udf_info.h:328
unsigned short uint16
Definition: types.h:30
uint16 flags
Definition: ecma_167.h:460
#define MEM_ALLOCDESC_TAG
Definition: udf_rel.h:493
#define EXTENT_FLAG_CUT_PREALLOCATED
Definition: udf_rel.h:80
struct _EXTENDED_FILE_ENTRY * PEXTENDED_FILE_ENTRY
uint32 logicalBlockNum
Definition: ecma_167.h:362
#define min(a, b)
Definition: monoChain.cc:55
#define UDF_PREALLOC_CLASS_DIR
Definition: udf_info.h:356
struct _EXT_AD EXT_AD
OSSTATUS UDFWriteExtent(IN PVCB Vcb, IN PEXTENT_INFO ExtInfo, IN int64 Offset, IN SIZE_T Length, IN BOOLEAN Direct, IN int8 *Buffer, OUT PSIZE_T WrittenBytes)
Definition: extent.cpp:3186
uint16 partitionReferenceNum
Definition: ecma_167.h:363
#define MEM_SHAD_TAG
Definition: udf_rel.h:494
#define EXTENT_NEXT_EXTENT_ALLOCDESC
Definition: ecma_167.h:370
IN ULONG IN ULONG Tag
Definition: evtlib.h:159
void UDFFreeFileAllocation(IN PVCB Vcb, IN PUDF_FILE_INFO DirInfo, IN PUDF_FILE_INFO FileInfo)
Definition: extent.cpp:2696
long int32
Definition: platform.h:12
#define OUT
Definition: typedefs.h:39
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155
void UDFFlushFESpace(IN PVCB Vcb, IN PUDF_DATALOC_INFO Dloc, IN BOOLEAN Discard)
Definition: extent.cpp:1776
OSSTATUS UDFRelocateExtent(IN PVCB Vcb, IN PEXTENT_INFO ExtInfo, IN uint32 ExtBlock, IN uint32 Lba, IN uint32 BC)
Definition: extent.cpp:2903
unsigned int ULONG
Definition: retypes.h:1
#define UDFAllocFreeExtent(v, l, ss, sl, e, af)
Definition: udf_info.h:347
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define UDFGetFreeBit(arr, bit)
Definition: udf_info.h:1199
#define EXTENT_FLAG_PREALLOCATED
Definition: udf_rel.h:79
uint32 lba_t
Definition: platform.h:20
uint32 __fastcall UDFGetPartNumByPhysLba(IN PVCB Vcb, IN uint32 Lba)
Definition: alloc.cpp:201
#define UDFMarkAllocatedAsNotAllocated(Vcb, Off, Len, Ext)
Definition: udf_info.h:503
#define TID_FILE_ENTRY
Definition: ecma_167.h:170
#define EXTENT_FLAG_ALLOC_SEQUENTIAL
Definition: udf_rel.h:77
static void push(calc_node_t *op)
Definition: rpn_ieee.c:113
return STATUS_SUCCESS
Definition: btrfs.c:2938
static SERVICE_STATUS status
Definition: service.c:31
#define UDF_EXTENT_LENGTH_MASK
Definition: osta_misc.h:148
SIZE_T __stdcall UDFGetBitmapLen(uint32 *Bitmap, SIZE_T Offs, SIZE_T Lim)
Definition: alloc.cpp:496
uint32 UDFPhysLbaToPart(IN PVCB Vcb, IN uint32 PartNum, IN uint32 Addr)
Definition: alloc.cpp:46
#define ICB_FLAG_ALLOC_MASK
Definition: ecma_167.h:480
OSSTATUS UDFBuildLongAllocDescs(IN PVCB Vcb, IN uint32 PartNum, OUT int8 **Buff, IN uint32 InitSz, IN OUT PUDF_FILE_INFO FileInfo)
Definition: extent.cpp:1012
char int8
Definition: platform.h:10
#define LBA_OUT_OF_EXTENT
Definition: udf_rel.h:426
struct _FILE_ENTRY FILE_ENTRY
jmp_buf jmp
Definition: mach.c:35
Definition: ps.c:97