📄 path.c
字号:
return INVALID_ATTR;
if (pvol->v_flags & (VOLF_INVALID | VOLF_UNMOUNTED | VOLF_FROZEN | VOLF_WRITELOCKED)) {
SetLastError(ERROR_ACCESS_DENIED);
FATExit(LOGID_NONE);
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_GetFileAttributesW(%-.64s) returned 0x%x (%d)\n"), pwsFileName, INVALID_ATTR, ERROR_ACCESS_DENIED));
return INVALID_ATTR;
}
// FindFirst will call SetLastError appropriately, so
// all we have to do is bail if it doesn't return a stream.
wcsncpy (wsFName, pwsFileName, MAX_PATH);
wsFName[MAX_PATH] = TEXT('\0'); // Ensure null
// Desktop will remove trailing '\' && '/'
while (wcslen(wsFName) && ((wsFName[wcslen(wsFName)-1] == TEXT('\\')) ||
(wsFName[wcslen(wsFName)-1] == TEXT('/')))) {
// Trim trailing slash
wsFName[wcslen(wsFName)-1] = TEXT('\0');
}
sh.sh_flags = SHF_BYNAME;
FindFirst(pvol, wsFName, &sh, NULL, &fd, NAME_FILE | NAME_DIR, UNKNOWN_CLUSTER);
FATExit(LOGID_NONE);
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS && fd.dwFileAttributes == INVALID_ATTR,(DBGTEXTW("FATFS!FAT_GetFileAttributesW(%-.64s) returned 0x%x (%d)\n"), pwsFileName, fd.dwFileAttributes, fd.dwFileAttributes != INVALID_ATTR? 0 : GetLastError()));
return fd.dwFileAttributes;
}
/* FAT_SetFileAttributesW - Set file/subdirectory attributes
*
* ENTRY
* pvol - pointer to VOLUME
* pwsFileName - pointer to name of existing file/subdirectory
* dwAttributes - new attributes for file/subdirectory
*
* EXIT
* TRUE if successful, FALSE if not (call GetLastError for error code)
*/
BOOL FAT_SetFileAttributesW(PVOLUME pvol, PCWSTR pwsFileName, DWORD dwAttributes)
{
PDSTREAM pstmDir;
SHANDLE sh;
DIRINFO di;
DWORD dw, dwError;
WIN32_FIND_DATAW fd;
DEBUGMSGW(ZONE_APIS,(DBGTEXTW("FATFS!FAT_SetFileAttributesW(0x%x,%d chars: %s)\n"), dwAttributes, wcslen(pwsFileName), pwsFileName));
// NOTE: Even though this call modifies the volume, it never has any impact
// on file system integrity, so we don't waste time logging it (ie, LOGID_NONE).
if (!FATEnter(NULL, LOGID_NONE))
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, pwsFileName, &sh, &di, &fd, NAME_FILE | NAME_DIR, UNKNOWN_CLUSTER);
if (!pstmDir) {
FATExit(LOGID_NONE);
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_SetFileAttributesW(%-.64s) returned FALSE (%d)\n"), pwsFileName, GetLastError()));
return FALSE;
}
// FindFirst calls SetLastError on error, so retrieve what it set, if anything
dwError = GetLastError();
// If FindFirst was successful...
if (fd.dwFileAttributes != INVALID_ATTR) {
if (dwAttributes == FILE_ATTRIBUTE_NORMAL)
dwAttributes = 0;
else
dwAttributes &= ~(FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_INROM);
// NOTE: We don't actually support the TEMPORARY or COMPRESSED
// attributes, but it doesn't hurt anything if they're passed in.
if (dwAttributes & ~(ATTR_CHANGEABLE | FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_COMPRESSED)) {
dwError = ERROR_ACCESS_DENIED;
}
else {
// NOTE: We pass 0 for the size instead of sizeof(DIRENTRY) to disable logging
// of this modification, since we are not logging these particular calls (by virtue
// of LOGID_NONE above).
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
dwAttributes |= FILE_ATTRIBUTE_DIRECTORY;
}
dwError = ModifyStreamBuffer(pstmDir, di.di_pde, 0);
if (!dwError)
di.di_pde->de_attr = (BYTE)dwAttributes;
FILESYSTEMNOTIFICATION(pvol, DB_CEOID_CHANGED, 0, SHCNE_UPDATEITEM, &di.di_sid, &pstmDir->s_sid, NULL, NULL, NULL, DBGTEXTW("FAT_SetFileAttributesW"));
}
}
dw = CloseStream(pstmDir);
if (!dwError)
dwError = dw;
if (dwError) {
error:
SetLastError(dwError);
}
FATExit(LOGID_NONE);
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS && dwError,(DBGTEXTW("FATFS!FAT_SetFileAttributesW(0x%x,%-.64s) returned 0x%x (%d)\n"), dwAttributes, pwsFileName, dwError == ERROR_SUCCESS, dwError));
return dwError == ERROR_SUCCESS;
}
/* FAT_DeleteFileW - Delete file
*
* ENTRY
* pvol - pointer to VOLUME
* pwsFileName - pointer to name of existing file
*
* EXIT
* TRUE if successful, FALSE if not (call GetLastError for error code)
*
* NOTES
* A file marked FILE_ATTRIBUTE_READONLY cannot be deleted. You have to
* remove that attribute first, with SetFileAttributes.
*
* An open file cannot be deleted. All open handles must be closed first.
*
* A subdirectory cannot be deleted with this call either. You have to
* use RemoveDirectory instead.
*/
BOOL FAT_DeleteFileW(PVOLUME pvol, PCWSTR pwsFileName)
{
PDSTREAM pstmDir;
SHANDLE sh;
DIRINFO di;
WIN32_FIND_DATAW fd;
DWORD dwError = ERROR_SUCCESS;
#ifdef SHELL_CALLBACK_NOTIFICATION
CEOIDINFO oiOld;
#endif
DEBUGMSGW(ZONE_APIS,(DBGTEXTW("FATFS!FAT_DeleteFileW(%d chars: %s)\n"), wcslen(pwsFileName), pwsFileName));
if (!FATEnter(pvol, LOGID_DELETEFILE))
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, pwsFileName, &sh, &di, &fd, NAME_FILE, UNKNOWN_CLUSTER);
if (!pstmDir) {
FATExit(LOGID_DELETEFILE);
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_DeleteFileW(%-.64s) returned FALSE (%d)\n"), pwsFileName, GetLastError()));
return FALSE;
}
// If the source file doesn't exist, fail
if (fd.dwFileAttributes == INVALID_ATTR) {
CloseStream(pstmDir);
FATExit(LOGID_DELETEFILE);
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_DeleteFileW(%-.64s) returned FALSE (%d)\n"), pwsFileName, GetLastError()));
return FALSE;
}
// If the source file is R/O or a directory, fail
//
// NOTE: Win95 reports ERROR_FILE_NOT_FOUND if the name is an existing
// directory, whereas NT reports ERROR_ACCESS_DENIED. I find the latter
// to be more sensible. -JTP
if (fd.dwFileAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY)) {
dwError = ERROR_ACCESS_DENIED;
goto exit;
}
// If the source file has any open handles, fail
if (CheckStreamHandles(pstmDir->s_pvol, &di.di_sid)) {
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
dwError = DestroyName(pstmDir, &di);
if (!dwError)
FILESYSTEMNOTIFICATION(pvol, 0, DB_CEOID_FILE_DELETED, SHCNE_DELETE, NULL, NULL, &di.di_sid, &pstmDir->s_sid, &oiOld, DBGTEXTW("FAT_DeleteFileW"));
exit:
CloseStream(pstmDir);
if (dwError) {
error:
SetLastError(dwError);
}
FATExit(LOGID_DELETEFILE);
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS && dwError,(DBGTEXTW("FATFS!FAT_DeleteFileW(%-.64s) returned 0x%x (%d)\n"), pwsFileName, dwError == ERROR_SUCCESS, dwError));
return dwError == ERROR_SUCCESS;
}
/* FAT_MoveFileW
*
* ENTRY
* pvol - pointer to VOLUME
* pwsOldFileName - pointer to name of existing file
* pwsNewFileName - pointer to new name for file
*
* EXIT
* TRUE if successful, FALSE if not (call GetLastError for error code)
*
* NOTES
* We call FindFirst once to obtain the source directory stream for the
* for the existing file, and if it really exists, we call FindFirst
* again to obtain the destination directory stream for the new file,
* verifying that the new name does NOT exist. Then we create the new
* name and destroy the old.
*
* When moving a directory, we must make sure that our traversal
* of the destination path does not cross the source directory, otherwise
* we will end up creating a circular directory chain.
*/
BOOL FAT_MoveFileW(PVOLUME pvol, PCWSTR pwsOldFileName, PCWSTR pwsNewFileName)
{
PBUF pbufSrc;
BYTE bAttrSrc;
WIN32_FIND_DATAW fd;
SHANDLE shSrc, shDst;
DIRINFO diSrc, diDst;
PDSTREAM pstmSrc, pstmDst;
DIRENTRY deClone, *pdeClone;
DWORD dwError = ERROR_SUCCESS;
DWORD clusFail = UNKNOWN_CLUSTER;
#ifdef SHELL_CALLBACK_NOTIFICATION
CEOIDINFO oiOld;
#endif
DEBUGONLY(pdeClone = INVALID_PTR);
DEBUGMSGW(ZONE_APIS,(DBGTEXTW("FATFS!FAT_MoveFileW(%d->%d chars: %s->%s)\n"), wcslen(pwsOldFileName), wcslen(pwsNewFileName), pwsOldFileName, pwsNewFileName));
if (!FATEnter(pvol, LOGID_MOVEFILE))
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;
}
// We add an explicit call to OpenRoot because this function performs
// two path traversals starting at the root, with a lock on the source
// directory while it traverses the destination. So if another thread
// tried to open a file in that source directory at the same time, it would
// block waiting for MoveFile to finish, but MoveFile couldn't finish if
// the other thread currently had a stream open in MoveFile's destination
// path. The explicit OpenRoot prevents all other path-based calls from
// even starting down that path.
OpenRoot(pvol);
shSrc.sh_flags = SHF_BYNAME;
pstmSrc = FindFirst(pvol, pwsOldFileName, &shSrc, &diSrc, &fd, NAME_FILE | NAME_DIR, UNKNOWN_CLUSTER);
if (!pstmSrc) {
CloseRoot(pvol);
FATExit(LOGID_MOVEFILE);
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_MoveFileW(%s->%s) returned FALSE (%d)\n"), pwsOldFileName, pwsNewFileName, GetLastError()));
return FALSE;
}
// If the source file doesn't exist, fail
if (fd.dwFileAttributes == INVALID_ATTR) {
CloseStream(pstmSrc);
CloseRoot(pvol);
FATExit(LOGID_MOVEFILE);
DEBUGMSGW(ZONE_APIS || ZONE_ERRORS,(DBGTEXTW("FATFS!FAT_MoveFileW(%s->%s) returned FALSE (%d)\n"), pwsOldFileName, pwsNewFileName, GetLastError()));
return FALSE;
}
// If the source file has any open handles, fail
#if 0
if (CheckStreamHandles(pstmSrc->s_pvol, &diSrc.di_sid)) {
dwError = ERROR_ACCESS_DENIED;
goto exit3;
}
#endif
bAttrSrc = (BYTE)fd.dwFileAttributes;
// 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 pstmSrc's current buffer is
// in a known state, and we can't tolerate GetSIDInfo mucking that state up.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -