1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
13 This file contains filesystem-specific routines
14 for Directory tree & related structures support
21 #include "..\namesup.h"
23 #ifdef UDF_BUG_CHECK_ID
24 #undef UDF_BUG_CHECK_ID
25 #endif //UDF_BUG_CHECK_ID
26 #endif //UDF_CHECK_UTIL
28 #define UDF_BUG_CHECK_ID UDF_FILE_UDF_INFO_DIR
30 #define MEM_USDIRHASH_TAG "USDirHash"
32 #define UDF_DUMP_DIRTREE
33 #ifdef UDF_DUMP_DIRTREE
34 #define DirPrint(x) KdPrint(x)
36 #define DirPrint(x) {;}
40 This routine initializes DirIndex array
48 PDIR_INDEX_HDR hDirNdx
;
49 PDIR_INDEX_ITEM
* FrameList
;
53 #ifdef UDF_LIMIT_DIR_SIZE
54 if(i
>UDF_DIR_INDEX_FRAME
)
56 #endif //UDF_LIMIT_DIR_SIZE
58 j
= i
>> UDF_DIR_INDEX_FRAME_SH
;
59 i
&= (UDF_DIR_INDEX_FRAME
-1);
61 hDirNdx
= (PDIR_INDEX_HDR
)MyAllocatePoolTag__(UDF_DIR_INDEX_MT
, sizeof(DIR_INDEX_HDR
)+(j
+(i
!=0))*sizeof(PDIR_INDEX_ITEM
), MEM_DIR_HDR_TAG
);
62 if(!hDirNdx
) return NULL
;
63 RtlZeroMemory(hDirNdx
, sizeof(DIR_INDEX_HDR
));
65 FrameList
= (PDIR_INDEX_ITEM
*)(hDirNdx
+1);
66 for(k
=0; k
<j
; k
++, FrameList
++) {
67 (*FrameList
) = (PDIR_INDEX_ITEM
)MyAllocatePoolTag__(UDF_DIR_INDEX_MT
, UDF_DIR_INDEX_FRAME
*sizeof(DIR_INDEX_ITEM
), MEM_DIR_NDX_TAG
);
70 // item pointet by FrameList is NULL, it could not be allocated
74 MyFreePool__(*FrameList
);
76 MyFreePool__(hDirNdx
);
79 RtlZeroMemory((*FrameList
), UDF_DIR_INDEX_FRAME
*sizeof(DIR_INDEX_ITEM
));
82 (*FrameList
) = (PDIR_INDEX_ITEM
)MyAllocatePoolTag__(UDF_DIR_INDEX_MT
, AlignDirIndex(i
)*sizeof(DIR_INDEX_ITEM
), MEM_DIR_NDX_TAG
);
85 RtlZeroMemory((*FrameList
), i
*sizeof(DIR_INDEX_ITEM
));
88 hDirNdx
->FrameCount
= j
+(i
!=0);
89 hDirNdx
->LastFrameCount
= i
? i
: UDF_DIR_INDEX_FRAME
;
92 } // UDFDirIndexAlloc()
95 This routine releases DirIndex array
99 PDIR_INDEX_HDR hDirNdx
103 PDIR_INDEX_ITEM
* FrameList
;
105 FrameList
= (PDIR_INDEX_ITEM
*)(hDirNdx
+1);
107 for(k
=0; k
<hDirNdx
->FrameCount
; k
++, FrameList
++) {
108 if(*FrameList
) MyFreePool__(*FrameList
);
110 MyFreePool__(hDirNdx
);
111 } // UDFDirIndexFree();
114 This routine grows DirIndex array
118 IN PDIR_INDEX_HDR
* _hDirNdx
,
119 IN uint_di d
// increment
123 PDIR_INDEX_HDR hDirNdx
= *_hDirNdx
;
124 PDIR_INDEX_ITEM
* FrameList
;
126 if(d
> UDF_DIR_INDEX_FRAME
)
127 return STATUS_INVALID_PARAMETER
;
129 j
= hDirNdx
->LastFrameCount
+d
;
131 if(j
> UDF_DIR_INDEX_FRAME
) {
132 #ifndef UDF_LIMIT_DIR_SIZE // release
134 k
= hDirNdx
->FrameCount
;
135 if(!MyReallocPool__((int8
*)hDirNdx
, sizeof(DIR_INDEX_HDR
) + k
*sizeof(PDIR_INDEX_ITEM
),
136 (int8
**)(&hDirNdx
), sizeof(DIR_INDEX_HDR
) + (k
+1)*sizeof(PDIR_INDEX_ITEM
) ) )
137 return STATUS_INSUFFICIENT_RESOURCES
;
138 FrameList
= (PDIR_INDEX_ITEM
*)(hDirNdx
+1);
140 if(!MyReallocPool__((int8
*)(FrameList
[k
-1]), AlignDirIndex(hDirNdx
->LastFrameCount
)*sizeof(DIR_INDEX_ITEM
),
141 (int8
**)(&(FrameList
[k
-1])), UDF_DIR_INDEX_FRAME
*sizeof(DIR_INDEX_ITEM
) ) )
142 return STATUS_INSUFFICIENT_RESOURCES
;
143 RtlZeroMemory(&(FrameList
[k
-1][hDirNdx
->LastFrameCount
]),
144 (UDF_DIR_INDEX_FRAME
-hDirNdx
->LastFrameCount
)*sizeof(DIR_INDEX_ITEM
));
145 hDirNdx
->LastFrameCount
= UDF_DIR_INDEX_FRAME
;
146 // Allocate new frame
147 FrameList
[k
] = (PDIR_INDEX_ITEM
)MyAllocatePoolTag__(UDF_DIR_INDEX_MT
, AlignDirIndex(j
-UDF_DIR_INDEX_FRAME
)*sizeof(DIR_INDEX_ITEM
), MEM_DIR_NDX_TAG
);
149 return STATUS_INSUFFICIENT_RESOURCES
;
150 hDirNdx
->FrameCount
++;
151 RtlZeroMemory(FrameList
[k
], (j
-UDF_DIR_INDEX_FRAME
)*sizeof(DIR_INDEX_ITEM
));
152 hDirNdx
->LastFrameCount
= j
-UDF_DIR_INDEX_FRAME
;
153 (*_hDirNdx
) = hDirNdx
;
154 #else // UDF_LIMIT_DIR_SIZE
155 return STATUS_INSUFFICIENT_RESOURCES
;
156 #endif // UDF_LIMIT_DIR_SIZE
158 k
= hDirNdx
->FrameCount
;
159 FrameList
= (PDIR_INDEX_ITEM
*)(hDirNdx
+1);
160 if(!MyReallocPool__((int8
*)(FrameList
[k
-1]), AlignDirIndex(hDirNdx
->LastFrameCount
)*sizeof(DIR_INDEX_ITEM
),
161 (int8
**)(&(FrameList
[k
-1])), AlignDirIndex(j
)*sizeof(DIR_INDEX_ITEM
) ) )
162 return STATUS_INSUFFICIENT_RESOURCES
;
163 RtlZeroMemory(&(FrameList
[k
-1][hDirNdx
->LastFrameCount
]),
164 (j
-hDirNdx
->LastFrameCount
)*sizeof(DIR_INDEX_ITEM
));
165 hDirNdx
->LastFrameCount
= j
;
167 return STATUS_SUCCESS
;
168 } // end UDFDirIndexGrow()
171 Thisd routine truncates DirIndex array
175 IN PDIR_INDEX_HDR
* _hDirNdx
,
176 IN uint_di d
// decrement
181 if(d
> UDF_DIR_INDEX_FRAME
) {
184 k
= (d
> UDF_DIR_INDEX_FRAME
) ? UDF_DIR_INDEX_FRAME
: d
;
185 if(!OS_SUCCESS(status
= UDFDirIndexTrunc(_hDirNdx
, k
))) {
190 return STATUS_SUCCESS
;
193 PDIR_INDEX_HDR hDirNdx
= *_hDirNdx
;
194 PDIR_INDEX_ITEM
* FrameList
;
196 j
= UDF_DIR_INDEX_FRAME
+hDirNdx
->LastFrameCount
-d
;
197 FrameList
= (PDIR_INDEX_ITEM
*)(hDirNdx
+1);
198 k
= hDirNdx
->FrameCount
-1;
200 if(j
<= UDF_DIR_INDEX_FRAME
) {
203 // someone tries to trunc. residual entries...
204 return STATUS_INVALID_PARAMETER
;
206 MyFreePool__(FrameList
[k
]);
208 hDirNdx
->LastFrameCount
= UDF_DIR_INDEX_FRAME
;
209 hDirNdx
->FrameCount
--;
210 // Truncate new last frame
211 if(!MyReallocPool__((int8
*)(FrameList
[k
-1]), UDF_DIR_INDEX_FRAME
*sizeof(DIR_INDEX_ITEM
),
212 (int8
**)(&(FrameList
[k
-1])), AlignDirIndex(j
)*sizeof(DIR_INDEX_ITEM
) ) )
213 return STATUS_INSUFFICIENT_RESOURCES
;
214 hDirNdx
->LastFrameCount
= j
;
216 if(!MyReallocPool__((int8
*)hDirNdx
, sizeof(DIR_INDEX_HDR
) + (k
+1)*sizeof(PDIR_INDEX_ITEM
),
217 (int8
**)(&hDirNdx
), sizeof(DIR_INDEX_HDR
) + k
*sizeof(PDIR_INDEX_ITEM
) ) )
218 return STATUS_INSUFFICIENT_RESOURCES
;
220 (*_hDirNdx
) = hDirNdx
;
224 j
-= UDF_DIR_INDEX_FRAME
;
226 // someone tries to trunc. residual entries...
227 return STATUS_INVALID_PARAMETER
;
230 if(!MyReallocPool__((int8
*)(FrameList
[k
]), AlignDirIndex(hDirNdx
->LastFrameCount
)*sizeof(DIR_INDEX_ITEM
),
231 (int8
**)(&(FrameList
[k
])), AlignDirIndex(j
)*sizeof(DIR_INDEX_ITEM
) ) )
232 return STATUS_INSUFFICIENT_RESOURCES
;
233 hDirNdx
->LastFrameCount
= j
;
235 return STATUS_SUCCESS
;
236 } // end UDFDirIndexTrunc()
238 #if defined _X86_ && !defined UDF_LIMIT_DIR_SIZE
239 #pragma warning(disable:4035) // re-enable below
241 This routine returns pointer to DirIndex item with index i.
247 IN PDIR_INDEX_HDR hDirNdx
, // ECX
264 shr ecx
,UDF_DIR_INDEX_FRAME_SH
; ecx
= j
265 mov edx
,[ebx
]hDirNdx
.FrameCount
; edx
= k
269 and eax
,(1 shl UDF_DIR_INDEX_FRAME_SH
)-1 ; eax
= i
274 cmp eax
,[ebx
].LastFrameCount
277 add ebx
,size DIR_INDEX_HDR
; ((PDIR_INDEX_ITEM
*)(hDirNdx
+1))...
278 mov ebx
,[ebx
+ecx
*4] ; ...[j
]...
279 mov edx
,size DIR_INDEX_ITEM
296 ((j
= (i
>> UDF_DIR_INDEX_FRAME_SH
)) < (k
= hDirNdx
->FrameCount
) ) &&
297 ((i
= (i
& (UDF_DIR_INDEX_FRAME
-1))) < ((j
< (k
-1)) ? UDF_DIR_INDEX_FRAME
: hDirNdx
->LastFrameCount
)) )
298 return &( (((PDIR_INDEX_ITEM
*)(hDirNdx
+1))[j
])[i
] );
302 #pragma warning(default:4035)
306 This routine returns pointer to DirIndex'es frame & index inside it
307 according to start Index parameter. It also initializes scan parameters
311 IN PDIR_INDEX_HDR hDirNdx
,
313 OUT uint32
* FrameLen
,
318 if(Frame
>= hDirNdx
->FrameCount
)
321 #ifdef UDF_LIMIT_DIR_SIZE
324 (*FrameLen
) = hDirNdx
->LastFrameCount
;
325 #else //UDF_LIMIT_DIR_SIZE
326 (*Index
) = Frame
*UDF_DIR_INDEX_FRAME
+Rel
;
328 (*FrameLen
) = (Frame
< (hDirNdx
->FrameCount
-1)) ? UDF_DIR_INDEX_FRAME
:
329 hDirNdx
->LastFrameCount
;
330 #endif //UDF_LIMIT_DIR_SIZE
332 return ((PDIR_INDEX_ITEM
*)(hDirNdx
+1))[Frame
]+Rel
;
333 } // end UDFDirIndexGetFrame()
336 This routine initializes indexes for optimized DirIndex scan
337 according to start Index parameter
342 IN PUDF_FILE_INFO DirInfo
, //
343 OUT PUDF_DIR_SCAN_CONTEXT Context
,
347 Context
->DirInfo
= DirInfo
;
348 Context
->hDirNdx
= DirInfo
->Dloc
->DirIndex
;
349 if( (Context
->frame
= (Index
>> UDF_DIR_INDEX_FRAME_SH
)) >=
350 Context
->hDirNdx
->FrameCount
) {
353 if( (Context
->j
= Index
& (UDF_DIR_INDEX_FRAME
-1)) >=
354 ((Context
->frame
< (Context
->hDirNdx
->FrameCount
-1))
356 UDF_DIR_INDEX_FRAME
: Context
->hDirNdx
->LastFrameCount
) ) {
359 Context
->DirNdx
= UDFDirIndexGetFrame(Context
->hDirNdx
,
369 } // end UDFDirIndexInitScan()
373 PUDF_DIR_SCAN_CONTEXT Context
,
374 PUDF_FILE_INFO
* _FileInfo
377 PUDF_FILE_INFO FileInfo
;
378 PUDF_FILE_INFO ParFileInfo
;
384 if(Context
->j
>= Context
->d
) {
387 Context
->DirNdx
= UDFDirIndexGetFrame(Context
->hDirNdx
,
393 if(!Context
->DirNdx
) {
400 if(FileInfo
= Context
->DirNdx
->FileInfo
) {
401 if(FileInfo
->ParentFile
!= Context
->DirInfo
) {
402 ParFileInfo
= UDFLocateParallelFI(Context
->DirInfo
,
406 if(ParFileInfo
->ParentFile
!= Context
->DirInfo
) {
410 FileInfo
= ParFileInfo
;
413 (*_FileInfo
) = FileInfo
;
416 return (Context
->DirNdx
);
417 } // end UDFDirIndexScan()
420 This routine calculates hashes for directory search
425 IN PUNICODE_STRING Name
,
426 OUT PHASH_ENTRY hashes
,
430 UNICODE_STRING UName
;
431 WCHAR ShortNameBuffer
[13];
434 if(!Name
->Buffer
) return 0;
436 if(Mask
& HASH_POSIX
)
437 hashes
->hPosix
= crc32((uint8
*)(Name
->Buffer
), Name
->Length
);
439 if(Mask
& HASH_ULFN
) {
440 /* if(OS_SUCCESS(MyInitUnicodeString(&UName, L"")) &&
441 OS_SUCCESS(MyAppendUnicodeStringToStringTag(&UName, Name, MEM_USDIRHASH_TAG))) {*/
442 if(OS_SUCCESS(MyCloneUnicodeString(&UName
, Name
))) {
443 RtlUpcaseUnicodeString(&UName
, &UName
, FALSE
);
444 /* if(!RtlCompareUnicodeString(Name, &UName, FALSE)) {
445 RetFlags |= UDF_FI_FLAG_LFN;
447 hashes
->hLfn
= crc32((uint8
*)(UName
.Buffer
), UName
.Length
);
451 MyFreePool__(UName
.Buffer
);
454 if(Mask
& HASH_DOS
) {
455 UName
.Buffer
= (PWCHAR
)(&ShortNameBuffer
);
456 UName
.MaximumLength
= 13*sizeof(WCHAR
);
457 UDFDOSName(Vcb
, &UName
, Name
, (Mask
& HASH_KEEP_NAME
) ? TRUE
: FALSE
);
458 if(!RtlCompareUnicodeString(Name
, &UName
, TRUE
)) {
459 RetFlags
|= UDF_FI_FLAG_DOS
;
461 hashes
->hDos
= crc32((uint8
*)(UName
.Buffer
), UName
.Length
);
464 } // UDFBuildHashEntry()
466 #ifdef UDF_CHECK_UTIL
470 IN uint32 prevOffset
,
474 PFILE_IDENT_DESC FileId
;
475 while(prevOffset
+sizeof(FILE_IDENT_DESC
) < Length
) {
477 FileId
= (PFILE_IDENT_DESC
)(buff
+prevOffset
);
478 if(FileId
->descTag
.tagIdent
!= TID_FILE_IDENT_DESC
)
480 if(FileId
->descTag
.descVersion
!= 2 && FileId
->descTag
.descVersion
!= 3)
482 if(FileId
->fileVersionNum
!= 1)
484 if(FileId
->fileCharacteristics
& (~0x1f))
486 if(prevOffset
+ ((FileId
->lengthFileIdent
+ FileId
->lengthOfImpUse
+ sizeof(FILE_IDENT_DESC
) + 3) & (~((uint32
)3))) <= Length
) {
487 KdPrint(("UDFFindNextFI OK: %x\n", prevOffset
));
492 } // end UDFFindNextFI()
493 #else //UDF_CHECK_UTIL
494 #define UDFFindNextFI(a,b,c) 0
495 #endif //UDF_CHECK_UTIL
498 This routine scans directory extent & builds index table for FileIdents
503 IN OUT PUDF_FILE_INFO FileInfo
506 PDIR_INDEX_HDR hDirNdx
;
507 PDIR_INDEX_ITEM DirNdx
;
508 PFILE_IDENT_DESC FileId
;
510 uint32 prevOffset
= 0;
514 PEXTENT_INFO ExtInfo
; // Extent array for directory
519 if(!FileInfo
) return STATUS_INVALID_PARAMETER
;
520 ValidateFileInfo(FileInfo
);
522 ExtInfo
= &(FileInfo
->Dloc
->DataLoc
);
523 FileInfo
->Dloc
->DirIndex
= NULL
;
524 KdPrint(("UDF: scaning directory\n"));
525 // allocate buffer for the whole directory
526 ASSERT((uint32
)(ExtInfo
->Length
));
528 return STATUS_FILE_CORRUPT_ERROR
;
529 buff
= (int8
*)DbgAllocatePool(PagedPool
, (uint32
)(ExtInfo
->Length
));
531 return STATUS_INSUFFICIENT_RESOURCES
;
533 ExtInfo
->Flags
|= EXTENT_FLAG_ALLOC_SEQUENTIAL
;
536 status
= UDFReadExtent(Vcb
, ExtInfo
, 0, (uint32
)(ExtInfo
->Length
), FALSE
, buff
, &ReadBytes
);
537 if(!OS_SUCCESS(status
)) {
541 // scan Dir to get entry counter
542 FileId
= (PFILE_IDENT_DESC
)buff
;
543 DirPrint((" ExtInfo->Length %x\n", ExtInfo
->Length
));
545 while(Offset
<ExtInfo
->Length
) {
546 DirPrint((" Offset %x\n", Offset
));
547 if(!FileId
->descTag
.tagIdent
) {
548 DirPrint((" term item\n"));
551 if(FileId
->descTag
.tagIdent
!= TID_FILE_IDENT_DESC
) {
552 DirPrint((" Inv. tag %x\n", FileId
->descTag
.tagIdent
));
553 Offset
= UDFFindNextFI(buff
, prevOffset
, (ULONG
)(ExtInfo
->Length
));
555 DirPrint((" can't find next\n"));
558 DirPrint((" found next offs %x\n", Offset
));
559 FileId
= (PFILE_IDENT_DESC
)((buff
)+Offset
);
562 if(((ULONG
)Offset
& (Vcb
->LBlockSize
-1)) > (Vcb
->LBlockSize
-sizeof(FILE_IDENT_DESC
))) {
563 DirPrint((" badly aligned\n", Offset
));
565 DirPrint((" queue repack request\n"));
566 FileInfo
->Dloc
->DirIndex
->DelCount
= Vcb
->PackDirThreshold
+1;
570 Offset
+= (FileId
->lengthFileIdent
+ FileId
->lengthOfImpUse
+ sizeof(FILE_IDENT_DESC
) + 3) & (~((uint32
)3));
571 FileId
= (PFILE_IDENT_DESC
)((buff
)+Offset
);
573 if(Offset
+sizeof(FILE_IDENT_DESC
) > ExtInfo
->Length
) {
574 if(Offset
!= ExtInfo
->Length
) {
575 KdPrint((" Trash at the end of Dir\n"));
581 DirPrint((" final Offset %x\n", Offset
));
582 if(Offset
> ExtInfo
->Length
) {
584 KdPrint((" Unexpected end of Dir\n"));
586 return STATUS_FILE_CORRUPT_ERROR
;
588 // allocate buffer for directory index & zero it
589 DirPrint((" Count %x\n", Count
));
590 hDirNdx
= UDFDirIndexAlloc(Count
+1);
593 return STATUS_INSUFFICIENT_RESOURCES
;
597 hDirNdx
->DIFlags
|= (ExtInfo
->Offset
? UDF_DI_FLAG_INIT_IN_ICB
: 0);
598 // add entry pointing to the directory itself
599 DirNdx
= UDFDirIndex(hDirNdx
,0);
600 ASSERT(FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
);
601 DirNdx
->FileEntryLoc
.partitionReferenceNum
= PartNum
=
602 (uint16
)UDFGetPartNumByPhysLba(Vcb
, FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
);
603 ASSERT(PartNum
!= -1);
604 DirNdx
->FileEntryLoc
.logicalBlockNum
=
605 UDFPhysLbaToPart(Vcb
, PartNum
, FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
);
606 if(DirNdx
->FileEntryLoc
.logicalBlockNum
== -1) {
607 DirPrint((" err: FileEntryLoc=-1\n"));
609 return STATUS_FILE_CORRUPT_ERROR
;
611 DirNdx
->FileCharacteristics
= (FileInfo
->FileIdent
) ?
612 FileInfo
->FileIdent
->fileCharacteristics
:
614 // DirNdx->Offset = 0;
615 // DirNdx->Length = 0;
616 DirNdx
->FName
.Buffer
= L
".";
617 DirNdx
->FName
.Length
=
618 (DirNdx
->FName
.MaximumLength
= sizeof(L
".")) - sizeof(WCHAR
);
619 DirNdx
->FileInfo
= FileInfo
;
620 DirNdx
->FI_Flags
|= UDF_FI_FLAG_KEEP_NAME
;
621 DirNdx
->FI_Flags
|= UDFBuildHashEntry(Vcb
, &(DirNdx
->FName
), &(DirNdx
->hashes
),
622 HASH_ALL
| HASH_KEEP_NAME
);
624 FileId
= (PFILE_IDENT_DESC
)buff
;
625 status
= STATUS_SUCCESS
;
627 while((Offset
<ExtInfo
->Length
) && FileId
->descTag
.tagIdent
) {
628 // add new entry to index list
629 if(FileId
->descTag
.tagIdent
!= TID_FILE_IDENT_DESC
) {
630 KdPrint((" Invalid tagIdent %x (expected %x) offst %x\n", FileId
->descTag
.tagIdent
, TID_FILE_IDENT_DESC
, Offset
));
631 DirPrint((" FileId: filen %x, iulen %x, charact %x\n",
632 FileId
->lengthFileIdent
, FileId
->lengthOfImpUse
, FileId
->fileCharacteristics
));
633 DirPrint((" loc: @%x\n", UDFExtentOffsetToLba(Vcb
, ExtInfo
->Mapping
, Offset
, NULL
, NULL
, NULL
, NULL
)));
634 KdDump(FileId
, sizeof(FileId
->descTag
));
635 Offset
= UDFFindNextFI(buff
, prevOffset
, (ULONG
)(ExtInfo
->Length
));
638 UDFDirIndexFree(hDirNdx
);
639 return STATUS_FILE_CORRUPT_ERROR
;
641 DirPrint((" found next offs %x\n", Offset
));
642 FileId
= (PFILE_IDENT_DESC
)((buff
)+Offset
);
645 DirNdx
= UDFDirIndex(hDirNdx
,Count
);
646 // allocate buffer & fill it with decompressed unicode filename
647 if(FileId
->fileCharacteristics
& FILE_DELETED
) {
648 DirPrint((" FILE_DELETED\n"));
651 DirPrint((" FileId: offs %x, filen %x, iulen %x\n", Offset
, FileId
->lengthFileIdent
, FileId
->lengthOfImpUse
));
652 DirNdx
->Length
= (FileId
->lengthFileIdent
+ FileId
->lengthOfImpUse
+ sizeof(FILE_IDENT_DESC
) + 3) & (~((uint32
)3));
653 DirPrint((" DirNdx: Length %x, Charact %x\n", DirNdx
->Length
, FileId
->fileCharacteristics
));
654 if(FileId
->fileCharacteristics
& FILE_PARENT
) {
655 DirPrint((" parent\n"));
656 // init 'parent' entry
657 // '..' points to Parent Object (if any),
658 // otherwise it points to the Dir itself
659 DirNdx
->FName
.Buffer
= L
"..";
660 DirNdx
->FName
.Length
=
661 (DirNdx
->FName
.MaximumLength
= sizeof(L
"..")) - sizeof(WCHAR
);
662 DirNdx
->FileInfo
= (FileInfo
->ParentFile
) ?
663 FileInfo
->ParentFile
: FileInfo
;
664 DirNdx
->FI_Flags
|= UDF_FI_FLAG_KEEP_NAME
;
665 DirNdx
->FI_Flags
|= UDFBuildHashEntry(Vcb
, &(DirNdx
->FName
), &(DirNdx
->hashes
), HASH_ALL
| HASH_KEEP_NAME
);
667 // init plain file/dir entry
668 ASSERT( (Offset
+sizeof(FILE_IDENT_DESC
)+FileId
->lengthOfImpUse
+FileId
->lengthFileIdent
) <=
670 UDFDecompressUnicode(&(DirNdx
->FName
),
671 ((uint8
*)(FileId
+1)) + (FileId
->lengthOfImpUse
),
672 FileId
->lengthFileIdent
,
674 UDFNormalizeFileName(&(DirNdx
->FName
), valueCRC
);
675 DirNdx
->FI_Flags
|= UDFBuildHashEntry(Vcb
, &(DirNdx
->FName
), &(DirNdx
->hashes
), HASH_ALL
);
677 if((FileId
->fileCharacteristics
& FILE_METADATA
)
679 !DirNdx
->FName
.Buffer
681 ((DirNdx
->FName
.Length
>= sizeof(UDF_RESERVED_NAME_HDR
)-sizeof(WCHAR
)) &&
682 (RtlCompareMemory(DirNdx
->FName
.Buffer
, UDF_RESERVED_NAME_HDR
, sizeof(UDF_RESERVED_NAME_HDR
)-sizeof(WCHAR
)) == sizeof(UDF_RESERVED_NAME_HDR
)-sizeof(WCHAR
)) )) {
683 DirPrint((" metadata\n"));
684 DirNdx
->FI_Flags
|= UDF_FI_FLAG_FI_INTERNAL
;
687 KdPrint(("%ws\n", DirNdx
->FName
.Buffer
));
689 DirPrint(("%ws\n", DirNdx
->FName
.Buffer
));
690 // remember FileEntry location...
691 DirNdx
->FileEntryLoc
= FileId
->icb
.extLocation
;
692 // ... and some file characteristics
693 DirNdx
->FileCharacteristics
= FileId
->fileCharacteristics
;
694 DirNdx
->Offset
= Offset
;
695 #ifdef UDF_CHECK_DISK_ALLOCATION
696 if(!(FileId
->fileCharacteristics
& FILE_DELETED
) &&
697 (UDFPartLbaToPhys(Vcb
, &(DirNdx
->FileEntryLoc
)) != LBA_OUT_OF_EXTENT
) &&
698 UDFGetFreeBit(((uint32
*)(Vcb
->FSBM_Bitmap
)), UDFPartLbaToPhys(Vcb
, &(DirNdx
->FileEntryLoc
)) )) {
700 AdPrint(("Ref to Discarded block %x\n",UDFPartLbaToPhys(Vcb
, &(DirNdx
->FileEntryLoc
)) ));
702 FileId
->fileCharacteristics
|= FILE_DELETED
;
704 if(UDFPartLbaToPhys(Vcb
, &(DirNdx
->FileEntryLoc
)) == LBA_OUT_OF_EXTENT
) {
705 AdPrint(("Ref to Invalid block %x\n", UDFPartLbaToPhys(Vcb
, &(DirNdx
->FileEntryLoc
)) ));
707 FileId
->fileCharacteristics
|= FILE_DELETED
;
709 #endif // UDF_CHECK_DISK_ALLOCATION
711 Offset
+= DirNdx
->Length
;
712 FileId
= (PFILE_IDENT_DESC
)(((int8
*)FileId
)+DirNdx
->Length
);
714 if(Offset
+sizeof(FILE_IDENT_DESC
) > ExtInfo
->Length
) {
715 if(Offset
!= ExtInfo
->Length
) {
716 KdPrint((" Trash at the end of Dir (2)\n"));
722 // we needn't writing terminator 'cause the buffer is already zero-filled
725 UDFDirIndexFree(hDirNdx
);
726 KdPrint((" Directory too short\n"));
727 return STATUS_FILE_CORRUPT_ERROR
;
730 FileInfo
->Dloc
->DirIndex
= hDirNdx
;
732 } // end UDFIndexDirectory()
734 #ifndef UDF_READ_ONLY_BUILD
736 This routine removes all DELETED entries from Dir & resizes it.
737 It must be called before closing, no files sould be opened.
742 IN OUT PUDF_FILE_INFO FileInfo
// source (opened)
749 uint32 DataLocOffset
;
750 uint32 Offset
, curOffset
;
755 PUDF_FILE_INFO curFileInfo
;
756 PDIR_INDEX_ITEM DirNdx
, DirNdx2
;
757 UDF_DIR_SCAN_CONTEXT ScanContext
;
760 #endif //UDF_PACK_DIRS
762 ValidateFileInfo(FileInfo
);
763 PDIR_INDEX_HDR hDirNdx
= FileInfo
->Dloc
->DirIndex
;
764 if(!hDirNdx
) return STATUS_NOT_A_DIRECTORY
;
765 #ifndef UDF_PACK_DIRS
766 return STATUS_SUCCESS
;
767 #else // UDF_PACK_DIRS
769 // do not pack dirs on unchanged disks
771 return STATUS_SUCCESS
;
773 LBS
= Vcb
->LBlockSize
;
774 Buf
= (int8
*)DbgAllocatePool(PagedPool
, LBS
*2);
775 if(!Buf
) return STATUS_INSUFFICIENT_RESOURCES
;
776 // we shall never touch 1st entry 'cause it can't be deleted
777 Offset
= UDFDirIndex(hDirNdx
,2)->Offset
;
778 DataLocOffset
= FileInfo
->Dloc
->DataLoc
.Offset
;
782 if(!UDFDirIndexInitScan(FileInfo
, &ScanContext
, i
)) {
784 return STATUS_SUCCESS
;
787 ASSERT(FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
);
788 PartNum
= (uint16
)UDFGetPartNumByPhysLba(Vcb
, FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
);
789 ASSERT(PartNum
!= -1);
791 while(DirNdx
= UDFDirIndexScan(&ScanContext
, NULL
)) {
793 if(UDFIsDeleted(DirNdx
))
796 if(!UDFIsDeleted(DirNdx
) ||
798 // move down valid entry
799 status
= UDFReadFile__(Vcb
, FileInfo
, curOffset
= DirNdx
->Offset
,
800 l
= DirNdx
->Length
, FALSE
, Buf
, &ReadBytes
);
801 if(!OS_SUCCESS(status
)) {
805 // remove ImpUse field
806 IUl
= ((PFILE_IDENT_DESC
)Buf
)->lengthOfImpUse
;
807 curFileInfo
= DirNdx
->FileInfo
;
809 if((d
= LBS
- ((curOffset
+ (l
- IUl
) + DataLocOffset
) & (LBS
-1)) ) < sizeof(FILE_IDENT_DESC
)) {
811 // insufficient space at the end of last sector for
812 // next FileIdent's tag. fill it with ImpUse data
814 // generally, all data should be DWORD-aligned, but if it is not so
815 // this opearation will help us to avoid glitches
819 FIl
= ((PFILE_IDENT_DESC
)Buf
)->lengthFileIdent
;
820 // copy filename to upper addr
821 RtlMoveMemory(Buf
+sizeof(FILE_IDENT_DESC
)+d
,
822 Buf
+sizeof(FILE_IDENT_DESC
)+IUl
, FIl
);
823 RtlZeroMemory(Buf
+sizeof(FILE_IDENT_DESC
), d
);
824 ((PFILE_IDENT_DESC
)Buf
)->lengthOfImpUse
= (uint16
)d
;
826 if(curFileInfo
&& curFileInfo
->FileIdent
) {
827 // update stored FI if any
828 if(!MyReallocPool__((int8
*)(curFileInfo
->FileIdent
), l
,
829 (int8
**)&(curFileInfo
->FileIdent
), (l
+IUl
-d
) )) {
831 return STATUS_INSUFFICIENT_RESOURCES
;
833 storedFI
= (int8
*)(curFileInfo
->FileIdent
);
834 RtlMoveMemory(storedFI
+sizeof(FILE_IDENT_DESC
)+d
,
835 storedFI
+sizeof(FILE_IDENT_DESC
)+IUl
, FIl
);
836 RtlZeroMemory(storedFI
+sizeof(FILE_IDENT_DESC
), d
);
837 ((PFILE_IDENT_DESC
)storedFI
)->lengthOfImpUse
= (uint16
)d
;
838 FileInfo
->Dloc
->FELoc
.Modified
= TRUE
;
839 FileInfo
->Dloc
->FE_Flags
|= UDF_FE_FLAG_FE_MODIFIED
;
845 // write modified to new addr
847 (curOffset
!= Offset
)) {
849 UDFSetUpTag(Vcb
, (tag
*)Buf
, (uint16
)l
,
850 UDFPhysLbaToPart(Vcb
, PartNum
,
851 UDFExtentOffsetToLba(Vcb
, FileInfo
->Dloc
->DataLoc
.Mapping
,
852 Offset
, NULL
, NULL
, NULL
, NULL
)));
854 status
= UDFWriteFile__(Vcb
, FileInfo
, Offset
, l
, FALSE
, Buf
, &ReadBytes
);
855 if(!OS_SUCCESS(status
)) {
860 DirNdx2
= UDFDirIndex(hDirNdx
, j
);
862 DirNdx2
->Offset
= Offset
;
865 curFileInfo
->Index
= j
;
866 DirNdx2
->FI_Flags
|= UDF_FI_FLAG_FI_MODIFIED
;
875 if(!OS_SUCCESS(status
= UDFDirIndexTrunc(&(FileInfo
->Dloc
->DirIndex
), dc
))) {
879 // terminator is set by UDFDirIndexTrunc()
880 FileInfo
->Dloc
->DirIndex
->DelCount
= 0;
881 ASSERT(FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
);
883 // now Offset points to EOF. Let's truncate directory
884 return UDFResizeFile__(Vcb
, FileInfo
, Offset
);
885 #endif // UDF_PACK_DIRS
886 } // end UDFPackDirectory__()
889 This routine rebuilds tags for all entries from Dir.
894 IN OUT PUDF_FILE_INFO FileInfo
// source (opened)
902 PUDF_FILE_INFO curFileInfo
;
903 PDIR_INDEX_ITEM DirNdx
;
904 UDF_DIR_SCAN_CONTEXT ScanContext
;
907 ValidateFileInfo(FileInfo
);
908 PDIR_INDEX_HDR hDirNdx
= FileInfo
->Dloc
->DirIndex
;
909 if(!hDirNdx
) return STATUS_NOT_A_DIRECTORY
;
911 // do not pack dirs on unchanged disks
913 return STATUS_SUCCESS
;
915 if( ((hDirNdx
->DIFlags
& UDF_DI_FLAG_INIT_IN_ICB
) ? TRUE
: FALSE
) ==
916 ((FileInfo
->Dloc
->DataLoc
.Offset
) ? TRUE
: FALSE
) ) {
917 return STATUS_SUCCESS
;
921 Buf
= (int8
*)DbgAllocatePool(PagedPool
, Vcb
->LBlockSize
*2);
922 if(!Buf
) return STATUS_INSUFFICIENT_RESOURCES
;
924 Offset
= UDFDirIndex(hDirNdx
,1)->Offset
;
926 if(!UDFDirIndexInitScan(FileInfo
, &ScanContext
, 1)) {
928 return STATUS_SUCCESS
;
931 ASSERT(FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
);
932 PartNum
= (uint16
)UDFGetPartNumByPhysLba(Vcb
, FileInfo
->Dloc
->FELoc
.Mapping
[0].extLocation
);
933 ASSERT(PartNum
!= -1);
935 while(DirNdx
= UDFDirIndexScan(&ScanContext
, NULL
)) {
937 status
= UDFReadFile__(Vcb
, FileInfo
, Offset
= DirNdx
->Offset
,
938 l
= DirNdx
->Length
, FALSE
, Buf
, &ReadBytes
);
939 if(!OS_SUCCESS(status
)) {
943 curFileInfo
= DirNdx
->FileInfo
;
945 UDFSetUpTag(Vcb
, (tag
*)Buf
, (uint16
)l
,
946 UDFPhysLbaToPart(Vcb
, PartNum
,
947 UDFExtentOffsetToLba(Vcb
, FileInfo
->Dloc
->DataLoc
.Mapping
,
948 Offset
, NULL
, NULL
, NULL
, NULL
)));
950 if(curFileInfo
&& curFileInfo
->FileIdent
) {
951 FileInfo
->Dloc
->FELoc
.Modified
= TRUE
;
952 FileInfo
->Dloc
->FE_Flags
|= UDF_FE_FLAG_FE_MODIFIED
;
955 status
= UDFWriteFile__(Vcb
, FileInfo
, Offset
, l
, FALSE
, Buf
, &ReadBytes
);
956 if(!OS_SUCCESS(status
)) {
961 DirNdx
->FI_Flags
|= UDF_FI_FLAG_FI_MODIFIED
;
967 hDirNdx
->DIFlags
&= ~UDF_DI_FLAG_INIT_IN_ICB
;
968 hDirNdx
->DIFlags
|= (FileInfo
->Dloc
->DataLoc
.Offset
? UDF_DI_FLAG_INIT_IN_ICB
: 0);
971 } // end UDFReTagDirectory()
972 #endif //UDF_READ_ONLY_BUILD
975 This routine performs search for specified file in specified directory &
976 returns corresponding offset in extent if found.
981 IN BOOLEAN IgnoreCase
,
982 IN BOOLEAN NotDeleted
,
983 IN PUNICODE_STRING Name
,
984 IN PUDF_FILE_INFO DirInfo
,
985 IN OUT uint_di
* Index
// IN:start index OUT:found file index
988 // PDIR_INDEX_HDR hDirIndex = DirInfo->Dloc->DirIndex;
989 UNICODE_STRING ShortName
;
990 WCHAR ShortNameBuffer
[13];
991 PDIR_INDEX_ITEM DirNdx
;
992 UDF_DIR_SCAN_CONTEXT ScanContext
;
993 uint_di j
=(-1), k
=(-1);
997 UDFBuildHashEntry(Vcb
, Name
, &hashes
, HASH_POSIX
| HASH_ULFN
);
999 if(CanBe8d3
= UDFCanNameBeA8dot3(Name
)) {
1000 ShortName
.MaximumLength
= 13 * sizeof(WCHAR
);
1001 ShortName
.Buffer
= (PWCHAR
)&ShortNameBuffer
;
1004 if(!UDFDirIndexInitScan(DirInfo
, &ScanContext
, (*Index
)))
1005 return STATUS_OBJECT_NAME_NOT_FOUND
;
1007 if(!IgnoreCase
&& !CanBe8d3
) {
1008 // perform case sensetive sequential directory scan
1010 while(DirNdx
= UDFDirIndexScan(&ScanContext
, NULL
)) {
1011 if( (DirNdx
->hashes
.hPosix
== hashes
.hPosix
) &&
1012 DirNdx
->FName
.Buffer
&&
1013 (!RtlCompareUnicodeString(&(DirNdx
->FName
), Name
, FALSE
)) &&
1014 ( (!UDFIsDeleted(DirNdx
)) || (!NotDeleted
) ) ) {
1015 (*Index
) = ScanContext
.i
;
1016 return STATUS_SUCCESS
;
1019 return STATUS_OBJECT_NAME_NOT_FOUND
;
1022 if(hashes
.hPosix
== hashes
.hLfn
) {
1024 while(DirNdx
= UDFDirIndexScan(&ScanContext
, NULL
)) {
1025 if(!DirNdx
->FName
.Buffer
||
1026 (NotDeleted
&& UDFIsDeleted(DirNdx
)) )
1028 if( (DirNdx
->hashes
.hLfn
== hashes
.hLfn
) &&
1029 (!RtlCompareUnicodeString(&(DirNdx
->FName
), Name
, IgnoreCase
)) ) {
1030 (*Index
) = ScanContext
.i
;
1031 return STATUS_SUCCESS
;
1034 !(DirNdx
->FI_Flags
& UDF_FI_FLAG_DOS
) &&
1035 (DirNdx
->hashes
.hDos
== hashes
.hLfn
) &&
1036 (k
== (uint_di
)(-1))) {
1037 UDFDOSName(Vcb
, &ShortName
, &(DirNdx
->FName
), ScanContext
.i
< 2) ;
1038 if(!RtlCompareUnicodeString(&ShortName
, Name
, IgnoreCase
))
1045 while(DirNdx
= UDFDirIndexScan(&ScanContext
, NULL
)) {
1046 // perform sequential directory scan
1047 if(!DirNdx
->FName
.Buffer
||
1048 (NotDeleted
&& UDFIsDeleted(DirNdx
)) )
1050 if( (DirNdx
->hashes
.hPosix
== hashes
.hPosix
) &&
1051 (!RtlCompareUnicodeString(&(DirNdx
->FName
), Name
, FALSE
)) ) {
1052 (*Index
) = ScanContext
.i
;
1053 return STATUS_SUCCESS
;
1055 if( (DirNdx
->hashes
.hLfn
== hashes
.hLfn
) &&
1056 (j
== (uint_di
)(-1)) &&
1057 (!RtlCompareUnicodeString(&(DirNdx
->FName
), Name
, IgnoreCase
)) ) {
1061 !(DirNdx
->FI_Flags
& UDF_FI_FLAG_DOS
) &&
1062 (DirNdx
->hashes
.hDos
== hashes
.hLfn
) &&
1063 (k
== (uint_di
)(-1))) {
1064 UDFDOSName(Vcb
, &ShortName
, &(DirNdx
->FName
), ScanContext
.i
< 2 );
1065 if(!RtlCompareUnicodeString(&ShortName
, Name
, IgnoreCase
)) {
1072 if(j
!= (uint_di
)(-1)) {
1074 return STATUS_SUCCESS
;
1076 if(k
!= (uint_di
)(-1)) {
1078 return STATUS_SUCCESS
;
1081 return STATUS_OBJECT_NAME_NOT_FOUND
;
1083 } // end UDFFindFile()
1086 This routine returns pointer to parent DirIndex
1089 UDFGetDirIndexByFileInfo(
1090 IN PUDF_FILE_INFO FileInfo
1093 ValidateFileInfo(FileInfo
);
1099 if (FileInfo
->ParentFile
) {
1100 ValidateFileInfo(FileInfo
->ParentFile
);
1102 if(UDFIsAStreamDir(FileInfo
))
1104 if(FileInfo
->ParentFile
->Dloc
)
1105 return FileInfo
->ParentFile
->Dloc
->DirIndex
;
1109 return FileInfo
->Dloc
->DirIndex
;
1114 File Data Location support routines (UDFXxxDloc)
1115 This group is responsible for caching FE locations
1116 If requested FE referenced by another FI the file is assumed to be linked
1117 All linked files reference to common Data Location (& attr) structure
1121 Check if given FE is already in use
1129 PUDF_DATALOC_INDEX DlocList
;
1132 if(!(DlocList
= Vcb
->DlocList
) || !Lba
) return (-1);
1133 // scan FE location cache
1135 for(uint32 i
=0; i
<l
; i
++, DlocList
++) {
1136 if(DlocList
->Lba
== Lba
)
1140 } // end UDFFindDloc()
1143 Check if given FE is already stored in memory
1148 IN PUDF_DATALOC_INFO Dloc
1151 PUDF_DATALOC_INDEX DlocList
;
1154 if(!(DlocList
= Vcb
->DlocList
) || !Dloc
) return (-1);
1155 // scan FE location cache
1157 for(uint32 i
=0; i
<l
; i
++, DlocList
++) {
1158 if(DlocList
->Dloc
== Dloc
)
1162 } // end UDFFindDlocInMem()
1165 Find free cache entry
1173 PUDF_DATALOC_INDEX DlocList
;
1176 if(!Vcb
->DlocList
) {
1177 // init FE location cache
1178 if(!(Vcb
->DlocList
= (PUDF_DATALOC_INDEX
)MyAllocatePoolTag__(NonPagedPool
, sizeof(UDF_DATALOC_INDEX
)*DLOC_LIST_GRANULARITY
, MEM_DLOC_NDX_TAG
)))
1180 RtlZeroMemory(Vcb
->DlocList
, DLOC_LIST_GRANULARITY
*sizeof(UDF_DATALOC_INDEX
));
1181 Vcb
->DlocCount
= DLOC_LIST_GRANULARITY
;
1183 // scan for free entry
1184 DlocList
= Vcb
->DlocList
;
1186 for(uint32 i
=0; i
<l
; i
++, DlocList
++) {
1190 // alloc some free entries
1191 if(!MyReallocPool__((int8
*)(Vcb
->DlocList
), Vcb
->DlocCount
*sizeof(UDF_DATALOC_INDEX
),
1192 (int8
**)&(Vcb
->DlocList
), (Vcb
->DlocCount
+DLOC_LIST_GRANULARITY
)*sizeof(UDF_DATALOC_INDEX
))) {
1195 RtlZeroMemory(&(Vcb
->DlocList
[Vcb
->DlocCount
]), DLOC_LIST_GRANULARITY
*sizeof(UDF_DATALOC_INDEX
));
1196 Vcb
->DlocCount
+= DLOC_LIST_GRANULARITY
;
1197 return (Vcb
->DlocCount
- DLOC_LIST_GRANULARITY
);
1198 } // end UDFFindFreeDloc()
1205 IN PUDF_DATALOC_INFO Dloc
1208 UDFAcquireResourceExclusive(&(Vcb
->DlocResource2
),TRUE
);
1209 if(Dloc
->FE_Flags
& UDF_FE_FLAG_UNDER_INIT
) {
1210 UDFReleaseResource(&(Vcb
->DlocResource2
));
1211 return STATUS_SHARING_PAUSED
;
1213 Dloc
->FE_Flags
|= UDF_FE_FLAG_UNDER_INIT
;
1214 UDFReleaseResource(&(Vcb
->DlocResource2
));
1215 return STATUS_SUCCESS
;
1216 } // end UDFAcquireDloc()
1223 IN PUDF_DATALOC_INFO Dloc
1226 UDFAcquireResourceExclusive(&(Vcb
->DlocResource2
),TRUE
);
1227 Dloc
->FE_Flags
&= ~UDF_FE_FLAG_UNDER_INIT
;
1228 UDFReleaseResource(&(Vcb
->DlocResource2
));
1229 return STATUS_SUCCESS
;
1230 } // end UDFReleaseDloc()
1233 Try to store FE location in cache
1234 If it is already in use, caller will be informed about it
1239 IN PUDF_FILE_INFO fi
,
1244 PUDF_DATALOC_INFO Dloc
;
1246 if(!Lba
) return STATUS_INVALID_PARAMETER
;
1247 if(Lba
== (-1)) return STATUS_INVALID_PARAMETER
;
1249 UDFAcquireResourceExclusive(&(Vcb
->DlocResource
),TRUE
);
1251 // check if FE specified is already in use
1252 if((i
= UDFFindDloc(Vcb
, Lba
)) == (-1)) {
1254 if((i
= UDFFindFreeDloc(Vcb
, Lba
)) == (-1)) {
1255 UDFReleaseResource(&(Vcb
->DlocResource
));
1256 return STATUS_INSUFFICIENT_RESOURCES
;
1259 if(!OS_SUCCESS(UDFAcquireDloc(Vcb
, Dloc
= Vcb
->DlocList
[i
].Dloc
))) {
1260 UDFReleaseResource(&(Vcb
->DlocResource
));
1261 return STATUS_SHARING_PAUSED
;
1263 // update caller's structures & exit
1265 UDFReleaseDloc(Vcb
, Dloc
);
1266 #if defined UDF_DBG && !defined _CONSOLE
1267 if(fi
->Dloc
->CommonFcb
) {
1268 ASSERT((uint32
)(fi
->Dloc
->CommonFcb
) != 0xDEADDA7A);
1269 ASSERT(fi
->Dloc
->CommonFcb
->CommonFCBHeader
.NodeTypeCode
== UDF_NODE_TYPE_NT_REQ_FCB
);
1272 UDFReleaseResource(&(Vcb
->DlocResource
));
1273 return STATUS_SUCCESS
;
1275 // allocate common DataLocation (Dloc) descriptor
1276 Dloc
= fi
->Dloc
= (PUDF_DATALOC_INFO
)MyAllocatePoolTag__(UDF_DATALOC_INFO_MT
, sizeof(UDF_DATALOC_INFO
), MEM_DLOC_INF_TAG
);
1278 UDFReleaseResource(&(Vcb
->DlocResource
));
1279 return STATUS_INSUFFICIENT_RESOURCES
;
1281 Vcb
->DlocList
[i
].Lba
= Lba
;
1282 Vcb
->DlocList
[i
].Dloc
= Dloc
;
1283 RtlZeroMemory(Dloc
, sizeof(UDF_DATALOC_INFO
));
1284 Dloc
->LinkedFileInfo
= fi
;
1285 UDFAcquireDloc(Vcb
, Dloc
);
1286 UDFReleaseResource(&(Vcb
->DlocResource
));
1287 return STATUS_SUCCESS
;
1288 } // end UDFStoreDloc()
1291 Remove unreferenced FE location from cache & free allocated memory
1292 This routine must be invoked when there are no more opened files
1293 associated with given FE
1298 IN PUDF_DATALOC_INFO Dloc
1303 UDFAcquireResourceExclusive(&(Vcb
->DlocResource
),TRUE
);
1305 if((i
= UDFFindDlocInMem(Vcb
, Dloc
)) == (-1)) {
1306 // FE specified is not in cache. exit
1307 UDFReleaseResource(&(Vcb
->DlocResource
));
1308 return STATUS_INVALID_PARAMETER
;
1310 // remove from cache
1311 ASSERT(Vcb
->DlocList
);
1312 RtlZeroMemory(&(Vcb
->DlocList
[i
]), sizeof(UDF_DATALOC_INDEX
));
1313 UDFReleaseResource(&(Vcb
->DlocResource
));
1315 return STATUS_SUCCESS
;
1316 } // end UDFRemoveDloc()
1319 Remove unlinked FE location from cache & keep allocated memory
1320 This routine must be invoked when there are no more opened files
1321 associated with given FE
1326 IN PUDF_DATALOC_INFO Dloc
1331 UDFAcquireResourceExclusive(&(Vcb
->DlocResource
),TRUE
);
1333 if((i
= UDFFindDlocInMem(Vcb
, Dloc
)) == (-1)) {
1334 // FE specified is not in cache. exit
1335 UDFReleaseResource(&(Vcb
->DlocResource
));
1336 return STATUS_INVALID_PARAMETER
;
1338 // remove from cache
1339 ASSERT(Vcb
->DlocList
);
1340 RtlZeroMemory(&(Vcb
->DlocList
[i
]), sizeof(UDF_DATALOC_INDEX
));
1341 UDFReleaseResource(&(Vcb
->DlocResource
));
1342 return STATUS_SUCCESS
;
1343 } // end UDFUnlinkDloc()
1346 This routine releases memory allocated for Dloc & removes it from
1347 cache (if it is still there)
1352 IN PUDF_DATALOC_INFO Dloc
1357 UDFAcquireResourceExclusive(&(Vcb
->DlocResource
),TRUE
);
1359 if((i
= UDFFindDlocInMem(Vcb
, Dloc
)) != (-1)) {
1360 ASSERT(Vcb
->DlocList
);
1361 RtlZeroMemory(&(Vcb
->DlocList
[i
]), sizeof(UDF_DATALOC_INDEX
));
1363 UDFReleaseResource(&(Vcb
->DlocResource
));
1365 } // end UDFFreeDloc()
1368 This routine updates Dloc LBA after relocation
1373 IN PUDF_DATALOC_INFO Dloc
,
1379 UDFAcquireResourceExclusive(&(Vcb
->DlocResource
),TRUE
);
1381 if((i
= UDFFindDlocInMem(Vcb
, Dloc
)) != (-1)) {
1382 ASSERT(Vcb
->DlocList
);
1383 Vcb
->DlocList
[i
].Lba
= NewLba
;
1385 UDFReleaseResource(&(Vcb
->DlocResource
));
1387 } // end UDFRelocateDloc()
1397 if(!Vcb
->DlocList
) return;
1398 UDFAcquireResourceExclusive(&(Vcb
->DlocResource
),TRUE
);
1399 for(uint32 i
=0; i
<Vcb
->DlocCount
; i
++) {
1400 if(Vcb
->DlocList
[i
].Dloc
)
1401 MyFreePool__(Vcb
->DlocList
[i
].Dloc
);
1403 MyFreePool__(Vcb
->DlocList
);
1404 Vcb
->DlocList
= NULL
;
1406 UDFReleaseResource(&(Vcb
->DlocResource
));
1407 } // end UDFReleaseDlocList()
1410 This routine walks through Linked/Parallel FI chain and looks for
1411 FE with same Index & Parent File
1414 UDFLocateParallelFI(
1415 PUDF_FILE_INFO di
, // parent FileInfo
1417 PUDF_FILE_INFO fi
// FileInfo to start search from
1420 PUDF_FILE_INFO ParFileInfo
= fi
->NextLinkedFile
;
1421 // PUDF_DATALOC_INFO Dloc = di->Dloc;
1422 while((ParFileInfo
!= fi
) &&
1423 ((ParFileInfo
->ParentFile
!= di
) ||
1424 (ParFileInfo
->Index
!= i
)) ) {
1425 ParFileInfo
= ParFileInfo
->NextLinkedFile
;
1429 } // end UDFLocateParallelFI()
1432 This routine walks through Linked/Parallel FI chain and looks for
1433 FE with same Index & Parent Dloc
1436 UDFLocateAnyParallelFI(
1437 PUDF_FILE_INFO fi
// FileInfo to start search from
1440 if(!fi
->ParentFile
) {
1441 if(fi
->NextLinkedFile
== fi
)
1443 return fi
->NextLinkedFile
;
1445 PUDF_FILE_INFO ParFileInfo
= fi
->NextLinkedFile
;
1446 PUDF_DATALOC_INFO Dloc
= fi
->ParentFile
->Dloc
;
1447 uint_di i
= fi
->Index
;
1448 BOOLEAN NotFound
= TRUE
;
1449 while((ParFileInfo
!= fi
) &&
1451 ((ParFileInfo
->Index
!= i
) ||
1452 (ParFileInfo
->ParentFile
->Dloc
!= Dloc
))) ) {
1453 ParFileInfo
= ParFileInfo
->NextLinkedFile
;
1456 if((ParFileInfo->Index == i) &&
1457 (ParFileInfo->ParentFile->Dloc == Dloc))
1461 return ParFileInfo;*/
1462 return NotFound
? NULL
: ParFileInfo
;
1464 } // end UDFLocateAnyParallelFI()
1467 UDFInsertLinkedFile(
1468 PUDF_FILE_INFO fi
, // FileInfo to be added to chain
1469 PUDF_FILE_INFO fi2
// any FileInfo fro the chain
1472 fi
->NextLinkedFile
= fi2
->NextLinkedFile
;
1473 fi
->PrevLinkedFile
= fi2
;
1474 fi
->NextLinkedFile
->PrevLinkedFile
=
1475 fi
->PrevLinkedFile
->NextLinkedFile
= fi
;
1477 } // end UDFInsertLinkedFile()