?? path.c
字號(hào):
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++
Module Name:
path.c
Abstract:
This file contains the path based API routines for the FAT file system.
Revision History:
--*/
#ifdef PATH_CACHING
#define PARENT_PATH_CACHING
#endif
#include "fatfs.h"
CONST WCHAR szDotDot[3] = TEXTW("..");
/* FAT_CreateDirectoryW - Create a new subdirectory
*
* ENTRY
* pvol - pointer to VOLUME
* pwsPathName - pointer to name of new subdirectory
* lpSecurityAttributes - pointer to security attributes (ignored)
*
* EXIT
* TRUE if successful, FALSE if not (call GetLastError for error code)
*/
BOOL FAT_CreateDirectoryW(PVOLUME pvol, PCWSTR pwsPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
int len;
PWSTR pwsLast;
PDSTREAM pstm, pstmDir;
DIRENTRY adeDir[2];
DWORD dwError;
int flName = NAME_DIR | NAME_NEW | NAME_CREATE | ATTR_DIRECTORY;
DSID sid, sidParent;
DWORD cchFilePath = 0;
DEBUGMSGW(ZONE_APIS,(DBGTEXTW("FATFS!FAT_CreateDirectoryW(%d chars: %-.64s)\r\n"), wcslen(pwsPathName), pwsPathName));
if (!FATEnter(pvol, LOGID_CREATEDIRECTORY))
return FALSE;
if (pvol->v_flags & (VOLF_INVALID | VOLF_UNMOUNTED | VOLF_FROZEN | VOLF_LOCKED)) {
dwError = ERROR_ACCESS_DENIED;
goto error;
}
if (pvol->v_flags & VOLF_READONLY) {
dwError = ERROR_WRITE_PROTECT;
goto error;
}
// The following code would be simpler than OpenPath+OpenName:
//
// OpenName((PDSTREAM)pvol, pwsPathName, 0, &flName);
//
// but we also need to know some information about the parent directory
// stream, so we have to open the path first. And we keep it open across
// creation of the "." and ".." entries, to insure that the cluster of the
// parent directory doesn't change.
pstmDir = OpenPath(pvol, pwsPathName, &pwsLast, &len, flName, UNKNOWN_CLUSTER);
if (!pstmDir) {
FATExit(pvol, LOGID_CREATEDIRECTORY);
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_CreateDirectoryW(%d chars: %-.64s) returned FALSE (%d)\r\n"), wcslen(pwsPathName), pwsPathName, GetLastError()));
return FALSE;
}
ASSERT(pvol == pstmDir->s_pvol);
// If the length of the last element is zero, the caller must be trying to
// (re)create the root directory, which of course already exists.
if (len == 0) {
dwError = ERROR_ALREADY_EXISTS;
goto exit;
}
// If the length of the existing path, plus the length of the proposed
// new directory, plus a separating backslash and a null terminator exceeds the maximum allowed
// directory path, fail the call.
// ASSERT(pstmDir->s_cwPath + (DWORD)len + 1 == wcslen(pwsPathName) + ((pwsPathName[0] != TEXTW('\\')) && (pwsPathName[0] != TEXTW('/'))) - ((pwsLast[len] == TEXT('\\')) || (pwsLast[len] == TEXT('/'))));
cchFilePath = pvol->v_cwsHostRoot + pstmDir->s_cwPath + len + 2;
if (cchFilePath > MAX_PATH || pvol->v_cwsHostRoot > MAX_PATH || len > MAX_PATH) {
dwError = ERROR_FILENAME_EXCED_RANGE;
goto exit;
}
dwError = ERROR_SUCCESS;
#ifdef TFAT
if (pvol->v_fTfat)
LockFAT (pvol);
#endif
PREFAST_SUPPRESS (508, "");
pstm = OpenName(pstmDir, pwsLast, len, &flName);
if (!pstm) {
CloseStream(pstmDir);
FATExit(pvol, LOGID_CREATEDIRECTORY);
#ifdef TFAT
if (pvol->v_fTfat)
UnlockFAT (pvol);
#endif
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_CreateDirectoryW(%d chars: %-.64s) returned FALSE (%d)\r\n"), wcslen(pwsPathName), pwsPathName, GetLastError()));
return FALSE;
}
// When OpenStream (called by OpenName) initialized the stream structure
// for this new directory, since it was a directory, it initialized s_size
// to MAX_DIRSIZE, because the size field in a directory's DIRENTRY is
// never valid. In this case however, we KNOW the size of the stream is
// zero, so we set it to zero to help WriteStreamData realize that it doesn't
// need to read the cluster it's about to write.
pstm->s_size = 0;
// Build the "." and ".." entries now. WriteStreamData is the best choice,
// because it handles lots of stuff, including resizing and not reading
// data we're going to overwrite anyway. NOTE: The FAT32 specification
// dictates that ".." entries that point to their volume's root directory
// should contain 0 in their cluster field, just like FAT12 and FAT16 volumes,
// for better application compatibility. -JTP
CreateDirEntry(pstm, &adeDir[0], NULL, ATTR_DIRECTORY, pstm->s_clusFirst);
CreateDirEntry(pstm, &adeDir[1], NULL, ATTR_DIRECTORY, ISROOTDIR(pstmDir)? NO_CLUSTER : pstmDir->s_clusFirst);
adeDir[0].de_name[0] =
adeDir[1].de_name[0] = adeDir[1].de_name[1] = '.';
WriteStreamData(pstm, 0, adeDir, sizeof(adeDir), NULL, FALSE);
#ifdef TFAT
// TFAT: File the rest of the cluster with volumes, In order to avoid modify the first cluster,
// so new file/dir can be created in the second cluster, moving directories is restricted.
if (pvol->v_fTfat) {
DIRENTRY adeVolume;
DWORD offset;
int iVolumeNo;
CreateDirEntry( pstm, &adeVolume, NULL, ATTR_VOLUME_ID, NO_CLUSTER );
memcpy(adeVolume.de_name, "DONT_DEL000", sizeof (adeVolume.de_name));
for (offset = sizeof(adeDir), iVolumeNo = 0; offset < pvol->v_cbClus; offset += sizeof(adeVolume), iVolumeNo++)
{
adeVolume.de_name[8] = '0' + (iVolumeNo / 100);
adeVolume.de_name[9] = '0' + ((iVolumeNo / 10) % 10);
adeVolume.de_name[10] = '0' + (iVolumeNo % 10);
WriteStreamData(pstm, offset, &adeVolume, sizeof(adeVolume), NULL, FALSE);
}
CommitStream (pstm, TRUE);
}
else
#endif
{
// ZERO the rest of the cluster
WriteStreamData(pstm, sizeof(adeDir), NULL, pvol->v_cbClus-sizeof(adeDir), NULL, FALSE);
}
CloseStream(pstmDir);
pstmDir = NULL;
#ifdef TFAT
if (pvol->v_fTfat) {
UnlockFAT(pvol);
}
#endif
#ifdef PATH_CACHING
PathCacheCreate(pvol, pwsPathName, 0, pstm);
#endif
memcpy (&sid, &pstm->s_sid, sizeof(DSID));
memcpy (&sidParent, &pstm->s_sidParent, sizeof(DSID));
CloseStream(pstm);
FILESYSTEMNOTIFICATION(pvol, DB_CEOID_CREATED, 0, SHCNE_MKDIR, &sid, &sidParent, NULL, NULL, NULL, DBGTEXTW("FAT_CreateDirectoryW"));
exit:
if (pstmDir)
CloseStream(pstmDir);
if (dwError) {
error:
SetLastError(dwError);
}
FATExit(pvol, LOGID_CREATEDIRECTORY);
#ifdef TFAT
if (pvol->v_fTfat && (dwError == ERROR_SUCCESS)) {
dwError = CommitTransactions (pvol);
}
#endif
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS && dwError,(DBGTEXTW("FATFS!FAT_CreateDirectoryW(%d chars: %-.64s) returned 0x%x (%d)\r\n"), wcslen(pwsPathName), pwsPathName, dwError == ERROR_SUCCESS, dwError));
return dwError == ERROR_SUCCESS;
}
/* FAT_RemoveDirectoryW - Destroy an existing subdirectory
*
* ENTRY
* pvol - pointer to VOLUME
* pwsPathName - pointer to name of existing subdirectory
*
* EXIT
* TRUE if successful, FALSE if not (call GetLastError for error code)
*/
BOOL FAT_RemoveDirectoryW(PVOLUME pvol, PCWSTR pwsPathName)
{
PDSTREAM pstmDir;
SHANDLE sh;
DIRINFO di;
WIN32_FIND_DATAW fd;
DWORD dwError = ERROR_SUCCESS;
#ifdef SHELL_CALLBACK_NOTIFICATION
CEOIDINFO oiOld;
#endif
DWORD dwSHCNE = 0;
DSID sidParent;
DEBUGMSGW(ZONE_APIS,(DBGTEXTW("FATFS!FAT_RemoveDirectoryW(%d chars: %-.64s)\r\n"), wcslen(pwsPathName), pwsPathName));
if (!FATEnter(pvol, LOGID_REMOVEDIRECTORY))
return FALSE;
if (pvol->v_flags & (VOLF_INVALID | VOLF_UNMOUNTED | VOLF_FROZEN | VOLF_LOCKED)) {
dwError = ERROR_ACCESS_DENIED;
goto error;
}
if (pvol->v_flags & VOLF_READONLY) {
dwError = ERROR_WRITE_PROTECT;
goto error;
}
// FindFirst will call SetLastError appropriately, so
// all we have to do is bail if it doesn't return a stream.
sh.sh_flags = SHF_BYNAME;
pstmDir = FindFirst(pvol, pwsPathName, &sh, &di, &fd, NAME_DIR, UNKNOWN_CLUSTER);
if (!pstmDir) {
FATExit(pvol, LOGID_REMOVEDIRECTORY);
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_RemoveDirectoryW(%d chars: %-.64s) returned FALSE (%d)\r\n"), wcslen(pwsPathName), pwsPathName, GetLastError()));
return FALSE;
}
if (fd.dwFileAttributes == INVALID_ATTR) {
CloseStream(pstmDir);
FATExit(pvol, LOGID_REMOVEDIRECTORY);
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_RemoveDirectoryW(%d chars: %-.64s) returned FALSE (%d)\r\n"), wcslen(pwsPathName), pwsPathName, GetLastError()));
return FALSE;
}
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
dwError = ERROR_ACCESS_DENIED;
goto exit;
}
// Retrieve the fully-qualified pathname of the source, in case we need
// it for the FILESYSTEMNOTIFICATION at the end of the function. We have to
// do the wacky buffer holding/unholding because pstmDir's current buffer is
// in a known state, and we can't tolerate GetSIDInfo mucking that state up.
#ifdef SHELL_CALLBACK_NOTIFICATION
if (pfnShell && ZONE_SHELLMSGS) {
PBUF pbuf = pstmDir->s_pbufCur;
HoldBuffer(pbuf);
GetSIDInfo(pvol, &di.di_sid, &oiOld);
ReleaseStreamBuffer(pstmDir, FALSE);
AssignStreamBuffer(pstmDir, pbuf, FALSE);
UnholdBuffer(pbuf);
}
#endif
// Before we can kill the DIRENTRY, we need to open it as a
// stream and call FindNext to see if there are any files in it.
if (di.di_clusEntry != UNKNOWN_CLUSTER) {
ASSERT(di.di_clusEntry != FAT_PSEUDO_CLUSTER &&
di.di_clusEntry != ROOT_PSEUDO_CLUSTER);
sh.sh_pstm = OpenStream(pstmDir->s_pvol,
di.di_clusEntry,
&di.di_sid,
pstmDir, &di, OPENSTREAM_CREATE);
if (sh.sh_pstm) {
sh.sh_pos = 0;
sh.sh_flags = SHF_BYNAME | SHF_WILD;
sh.sh_cwPattern = 1;
sh.sh_awcPattern[0] = TEXTW('*');
dwError = FindNext(&sh, NULL, &fd);
if (!dwError) {
CloseStream(sh.sh_pstm);
dwError = ERROR_DIR_NOT_EMPTY;
goto exit;
}
// Check for search handles to this directory
if (sh.sh_pstm->s_dlOpenHandles.pfhNext != (PFHANDLE)&sh.sh_pstm->s_dlOpenHandles) {
CloseStream(sh.sh_pstm);
dwError = ERROR_SHARING_VIOLATION;
goto exit;
}
CloseStream(sh.sh_pstm);
}
}
// If we're still here, then the directory stream is empty (except for
// "." and ".." entries, which we didn't ask FindNext to find anyway), so
// we can nuke the DIRENTRY and its associated clusters.
dwError = DestroyName(pstmDir, &di);
// TEST_BREAK
PWR_BREAK_NOTIFY(31);
if (!dwError) {
dwSHCNE = SHCNE_RMDIR;
memcpy (&sidParent, &pstmDir->s_sid, sizeof(DSID));
#ifdef PATH_CACHING
if (PathCacheInvalidate(pvol, pwsPathName)) {
#ifdef PARENT_PATH_CACHING
if (!ISROOTDIR(pstmDir)) {
sh.sh_pstm = pstmDir;
sh.sh_pos = 0;
sh.sh_flags = SHF_BYNAME | SHF_DOTDOT;
sh.sh_cwPattern = ARRAYSIZE(szDotDot)-1;
memcpy(sh.sh_awcPattern, szDotDot, sizeof(szDotDot));
if (FindNext(&sh, &di, &fd) == ERROR_SUCCESS &&
di.di_clusEntry != UNKNOWN_CLUSTER) {
sh.sh_pstm = OpenStream(pstmDir->s_pvol,
di.di_clusEntry, NULL,
NULL, NULL, OPENSTREAM_CREATE);
if (sh.sh_pstm) {
PathCacheCreate(pvol, pwsPathName, -2, sh.sh_pstm);
CloseStream(sh.sh_pstm);
}
}
}
#endif // PARENT_PATH_CACHING
}
#endif // PATH_CACHING
}
exit:
CloseStream(pstmDir);
if (dwSHCNE)
FILESYSTEMNOTIFICATION(pvol, 0, DB_CEOID_DIRECTORY_DELETED, dwSHCNE, NULL, NULL, &di.di_sid, &sidParent, &oiOld, DBGTEXTW("FAT_RemoveDirectoryW"));
if (dwError) {
error:
SetLastError(dwError);
}
FATExit(pvol, LOGID_REMOVEDIRECTORY);
#ifdef TFAT
if (pvol->v_fTfat && (dwError == ERROR_SUCCESS))
dwError = CommitTransactions (pvol);
#endif
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS && dwError,(DBGTEXTW("FATFS!FAT_RemoveDirectoryW(%d chars: %-.64s) returned 0x%x (%d)\r\n"), wcslen(pwsPathName), pwsPathName, dwError == ERROR_SUCCESS, dwError));
return dwError == ERROR_SUCCESS;
}
/* FAT_GetFileAttributesW - Get file/subdirectory attributes
*
* ENTRY
* pvol - pointer to VOLUME
* pwsFileName - pointer to name of existing file/subdirectory
*
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -