Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Szczególnie istotne jest, aby systemy plików obsługiwały operacje zmiany nazw. Podobny obszar zainteresowania to twarde tworzenie linków dla systemów plików, które obsługują twarde linki. W przypadku operacji zmiany nazwy system plików może usunąć plik (element docelowy operacji zmiany nazwy), który wymaga dodatkowych kontroli zabezpieczeń przez system plików.
Podczas przeglądania struktury kontrolki dla operacji zmiany nazwy jednym z pól struktury jest opcja ReplaceIfExists :
typedef struct _FILE_RENAME_INFORMATION {
BOOLEAN ReplaceIfExists;
HANDLE RootDirectory;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;
Podobnie w strukturze sterowania operacji twardego łącza jednym z pól struktury jest opcja ReplaceIfExists :
typedef struct _FILE_LINK_INFORMATION {
BOOLEAN ReplaceIfExists;
HANDLE RootDirectory;
ULONG FileNameLength;
WCHAR FileName[1];
} FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION;
W obu przypadkach opcja polega na zastąpieniu elementu docelowego operacji, jeśli istnieje. Chociaż system plików FASTFAT nie obsługuje twardych linków, obsługuje operacje zmiany nazw. Tę semantykę i zachowanie można zobaczyć w systemie plików FASTFAT w źródłowym pliku funkcji FatSetRenameInfo (zobacz plik źródłowy Fileinfo.c z przykładów fastfat zawartych w zestawie WDK).
Poniższy przykład kodu do obsługi operacji zmiany nazwy naśladuje sprawdzanie systemu plików w celu usunięcia pliku. W przypadku systemu plików z bardziej niezawodnym modelem zabezpieczeń (na przykład NTFS) ta kontrola wymaga również sprawdzenia zabezpieczeń, aby upewnić się, że obiekt wywołujący może usunąć dany plik (obiekt wywołujący miał odpowiednie uprawnienia wymagane do usunięcia).
//
// The name already exists. Check if the user wants
// to overwrite the name and has access to do the overwrite.
// We cannot overwrite a directory.
//
if ((!ReplaceIfExists) ||
(FlagOn(TargetDirent->Attributes, FAT_DIRENT_ATTR_DIRECTORY)) ||
(FlagOn(TargetDirent->Attributes, FAT_DIRENT_ATTR_READ_ONLY))) {
try_return( Status = STATUS_OBJECT_NAME_COLLISION );
}
//
// Check that the file has no open user handles; otherwise,
// access will be denied. To do the check, search
// the list of FCBs opened under the parent Dcb, and make
// sure that none of the matching FCBs have a nonzero unclean count or
// outstanding image sections.
//
for (Links = TargetDcb->Specific.Dcb.ParentDcbQueue.Flink;
Links != &TargetDcb->Specific.Dcb.ParentDcbQueue; ) {
TempFcb = CONTAINING_RECORD( Links, FCB, ParentDcbLinks );
//
// Advance now. The image section flush may cause the final
// close, which will recursively happen underneath of us here.
// It would be unfortunate if we looked through free memory.
//
Links = Links->Flink;
if ((TempFcb->DirentOffsetWithinDirectory == TargetDirentOffset) &&
((TempFcb->UncleanCount != 0) ||
!MmFlushImageSection( &TempFcb->NonPaged->SectionObjectPointers,
MmFlushForDelete))) {
//
// If there are batch oplocks on this file, then break the
// oplocks before failing the rename.
//
Status = STATUS_ACCESS_DENIED;
if ((NodeType(TempFcb) == FAT_NTC_FCB) &&
FsRtlCurrentBatchOplock( &TempFcb->Specific.Fcb.Oplock )) {
//
// Do all of the cleanup now since the IrpContext
// could go away when this request is posted.
//
FatUnpinBcb( IrpContext, TargetDirentBcb );
Status = FsRtlCheckOplock( &TempFcb->Specific.Fcb.Oplock,
Irp,
IrpContext,
FatOplockComplete,
NULL );
if (Status != STATUS_PENDING) {
Status = STATUS_ACCESS_DENIED;
}
}
try_return( NOTHING );
}
}
//
// OK, this target is finished. Remember the Lfn offset.
//
TargetLfnOffset = TargetDirentOffset -
FAT_LFN_DIRENTS_NEEDED(&TargetLfn) * sizeof(DIRENT);
DeleteTarget = TRUE;
}