mirror of https://github.com/FreeRDP/FreeRDP
Replaced chmod with safer fchmod
* Use fchmod so the file may not change underneath * Add unit tests for SetFileAttributesA * Add warning logs for unsupported flags
This commit is contained in:
parent
64403d9d40
commit
c8571dd5fd
|
@ -539,15 +539,80 @@ DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char* append(char* buffer, size_t size, const char* append)
|
||||||
|
{
|
||||||
|
const size_t len = strnlen(buffer, size);
|
||||||
|
if (len == 0)
|
||||||
|
_snprintf(buffer, size, "%s", append);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcat(buffer, "|");
|
||||||
|
strcat(buffer, append);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* flagsToStr(char* buffer, size_t size, DWORD flags)
|
||||||
|
{
|
||||||
|
char strflags[32] = { 0 };
|
||||||
|
if (flags & FILE_ATTRIBUTE_READONLY)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_READONLY");
|
||||||
|
if (flags & FILE_ATTRIBUTE_HIDDEN)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_HIDDEN");
|
||||||
|
if (flags & FILE_ATTRIBUTE_SYSTEM)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_SYSTEM");
|
||||||
|
if (flags & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_DIRECTORY");
|
||||||
|
if (flags & FILE_ATTRIBUTE_ARCHIVE)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_ARCHIVE");
|
||||||
|
if (flags & FILE_ATTRIBUTE_DEVICE)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_DEVICE");
|
||||||
|
if (flags & FILE_ATTRIBUTE_NORMAL)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_NORMAL");
|
||||||
|
if (flags & FILE_ATTRIBUTE_TEMPORARY)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_TEMPORARY");
|
||||||
|
if (flags & FILE_ATTRIBUTE_SPARSE_FILE)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_SPARSE_FILE");
|
||||||
|
if (flags & FILE_ATTRIBUTE_REPARSE_POINT)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_REPARSE_POINT");
|
||||||
|
if (flags & FILE_ATTRIBUTE_COMPRESSED)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_COMPRESSED");
|
||||||
|
if (flags & FILE_ATTRIBUTE_OFFLINE)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_OFFLINE");
|
||||||
|
if (flags & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_NOT_CONTENT_INDEXED");
|
||||||
|
if (flags & FILE_ATTRIBUTE_ENCRYPTED)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_ENCRYPTED");
|
||||||
|
if (flags & FILE_ATTRIBUTE_VIRTUAL)
|
||||||
|
append(buffer, size, "FILE_ATTRIBUTE_VIRTUAL");
|
||||||
|
|
||||||
|
_snprintf(strflags, sizeof(strflags), " [0x%08" PRIx32 "]", flags);
|
||||||
|
strcat(buffer, strflags);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
|
BOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
int fd;
|
||||||
|
BOOL rc = FALSE;
|
||||||
|
|
||||||
if (stat(lpFileName, &st) != 0)
|
if (dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)
|
||||||
{
|
{
|
||||||
return FALSE;
|
char buffer[8192] = { 0 };
|
||||||
|
const char* flags =
|
||||||
|
flagsToStr(buffer, sizeof(buffer), dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
|
||||||
|
WLog_WARN(TAG, "[%s] Unsupported flags %s, ignoring!", __FUNCTION__, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fd = open(lpFileName, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (fstat(fd, &st) != 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
if (dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
if (dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
||||||
{
|
{
|
||||||
st.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
|
st.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
|
||||||
|
@ -557,12 +622,13 @@ BOOL SetFileAttributesA(LPCSTR lpFileName, DWORD dwFileAttributes)
|
||||||
st.st_mode |= S_IWUSR;
|
st.st_mode |= S_IWUSR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chmod(lpFileName, st.st_mode) != 0)
|
if (fchmod(fd, st.st_mode) != 0)
|
||||||
{
|
goto fail;
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
rc = TRUE;
|
||||||
|
fail:
|
||||||
|
close(fd);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
|
BOOL SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
|
||||||
|
@ -570,6 +636,14 @@ BOOL SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
LPSTR lpCFileName;
|
LPSTR lpCFileName;
|
||||||
|
|
||||||
|
if (dwFileAttributes & ~FILE_ATTRIBUTE_READONLY)
|
||||||
|
{
|
||||||
|
char buffer[8192] = { 0 };
|
||||||
|
const char* flags =
|
||||||
|
flagsToStr(buffer, sizeof(buffer), dwFileAttributes & ~FILE_ATTRIBUTE_READONLY);
|
||||||
|
WLog_WARN(TAG, "[%s] Unsupported flags %s, ignoring!", __FUNCTION__, flags);
|
||||||
|
}
|
||||||
|
|
||||||
if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpCFileName, 0, NULL, NULL) <= 0)
|
if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpCFileName, 0, NULL, NULL) <= 0)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
|
|
@ -9,6 +9,7 @@ if (NOT WIN32)
|
||||||
TestFileCreateFile.c
|
TestFileCreateFile.c
|
||||||
TestFileDeleteFile.c
|
TestFileDeleteFile.c
|
||||||
TestFileReadFile.c
|
TestFileReadFile.c
|
||||||
|
TestSetFileAttributes.c
|
||||||
TestFileWriteFile.c
|
TestFileWriteFile.c
|
||||||
TestFilePatternMatch.c
|
TestFilePatternMatch.c
|
||||||
TestFileFindFirstFile.c
|
TestFileFindFirstFile.c
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <winpr/crt.h>
|
||||||
|
#include <winpr/file.h>
|
||||||
|
#include <winpr/path.h>
|
||||||
|
#include <winpr/handle.h>
|
||||||
|
#include <winpr/windows.h>
|
||||||
|
#include <winpr/sysinfo.h>
|
||||||
|
|
||||||
|
static const DWORD allflags[] = {
|
||||||
|
0,
|
||||||
|
FILE_ATTRIBUTE_READONLY,
|
||||||
|
FILE_ATTRIBUTE_HIDDEN,
|
||||||
|
FILE_ATTRIBUTE_SYSTEM,
|
||||||
|
FILE_ATTRIBUTE_DIRECTORY,
|
||||||
|
FILE_ATTRIBUTE_ARCHIVE,
|
||||||
|
FILE_ATTRIBUTE_DEVICE,
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
FILE_ATTRIBUTE_TEMPORARY,
|
||||||
|
FILE_ATTRIBUTE_SPARSE_FILE,
|
||||||
|
FILE_ATTRIBUTE_REPARSE_POINT,
|
||||||
|
FILE_ATTRIBUTE_COMPRESSED,
|
||||||
|
FILE_ATTRIBUTE_OFFLINE,
|
||||||
|
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
|
||||||
|
FILE_ATTRIBUTE_ENCRYPTED,
|
||||||
|
FILE_ATTRIBUTE_VIRTUAL,
|
||||||
|
FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM,
|
||||||
|
FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_DEVICE |
|
||||||
|
FILE_ATTRIBUTE_NORMAL,
|
||||||
|
FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_SPARSE_FILE | FILE_ATTRIBUTE_REPARSE_POINT |
|
||||||
|
FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_OFFLINE,
|
||||||
|
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_VIRTUAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static BOOL test_SetFileAttributesA(void)
|
||||||
|
{
|
||||||
|
BOOL rc = FALSE;
|
||||||
|
HANDLE handle;
|
||||||
|
DWORD x;
|
||||||
|
const DWORD flags[] = { 0, FILE_ATTRIBUTE_READONLY };
|
||||||
|
char* name = GetKnownSubPath(KNOWN_PATH_TEMP, "afsklhjwe4oq5iu432oijrlkejadlkhjaklhfdkahfd");
|
||||||
|
if (!name)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
for (x = 0; x < ARRAYSIZE(allflags); x++)
|
||||||
|
{
|
||||||
|
const DWORD flag = allflags[x];
|
||||||
|
rc = SetFileAttributesA(NULL, flag);
|
||||||
|
if (rc)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
rc = SetFileAttributesA(name, flag);
|
||||||
|
if (rc)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW,
|
||||||
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
goto fail;
|
||||||
|
CloseHandle(handle);
|
||||||
|
|
||||||
|
for (x = 0; x < ARRAYSIZE(flags); x++)
|
||||||
|
{
|
||||||
|
DWORD attr;
|
||||||
|
const DWORD flag = flags[x];
|
||||||
|
rc = SetFileAttributesA(name, flag);
|
||||||
|
if (!rc)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
attr = GetFileAttributesA(name);
|
||||||
|
if (flag != 0)
|
||||||
|
{
|
||||||
|
if ((attr & flag) == 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
DeleteFileA(name);
|
||||||
|
free(name);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL test_SetFileAttributesW(void)
|
||||||
|
{
|
||||||
|
BOOL rc = FALSE;
|
||||||
|
WCHAR* name = NULL;
|
||||||
|
HANDLE handle;
|
||||||
|
DWORD x;
|
||||||
|
const DWORD flags[] = { 0, FILE_ATTRIBUTE_READONLY };
|
||||||
|
char* base = GetKnownSubPath(KNOWN_PATH_TEMP, "afsklhjwe4oq5iu432oijrlkejadlkhjaklhfdkahfd");
|
||||||
|
if (!base)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
ConvertToUnicode(CP_UTF8, 0, base, -1, &name, 0);
|
||||||
|
|
||||||
|
for (x = 0; x < ARRAYSIZE(allflags); x++)
|
||||||
|
{
|
||||||
|
const DWORD flag = allflags[x];
|
||||||
|
rc = SetFileAttributesW(NULL, flag);
|
||||||
|
if (rc)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
rc = SetFileAttributesW(name, flag);
|
||||||
|
if (rc)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle = CreateFileW(name, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW,
|
||||||
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE)
|
||||||
|
goto fail;
|
||||||
|
CloseHandle(handle);
|
||||||
|
|
||||||
|
for (x = 0; x < ARRAYSIZE(flags); x++)
|
||||||
|
{
|
||||||
|
DWORD attr;
|
||||||
|
const DWORD flag = flags[x];
|
||||||
|
rc = SetFileAttributesW(name, flag);
|
||||||
|
if (!rc)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
attr = GetFileAttributesW(name);
|
||||||
|
if (flag != 0)
|
||||||
|
{
|
||||||
|
if ((attr & flag) == 0)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
DeleteFileW(name);
|
||||||
|
free(name);
|
||||||
|
free(base);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TestSetFileAttributes(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
WINPR_UNUSED(argc);
|
||||||
|
WINPR_UNUSED(argv);
|
||||||
|
|
||||||
|
if (!test_SetFileAttributesA())
|
||||||
|
return -1;
|
||||||
|
if (!test_SetFileAttributesW())
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue