...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <Windows.h>
void func(const TCHAR *file_name) {
HANDLE hFile = CreateFile(
file_name,
GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL
);
if (hFile == INVALID_HANDLE_VALUE) {
/* Handle error */
} else if (GetFileType(hFile) != FILE_TYPE_DISK) {
/* Handle error */
CloseHandle(hFile);
} else {
/* Operate on the file */
CloseHandle(hFile);
}
} |
...
Microsoft documents a list of reserved identifiers that represent devices and have a device namespace to be used specifically by devices [MSDN]. The isReservedName() function below in this compliant solution can be used to determine if a specified path refers to a device:. Care must be taken to avoid a TOCTOU race condition when first testing a pathname using the isReservedName() function and then later operating on that pathname.
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <ctype.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
static bool isReservedName(const char *path) {
/* This list of reserved names comes from MSDN */
static const char *reserved[] = {
"nul", "con", "prn", "aux",
"com1", "com2", "com3",
"com4", "com5", "com6",
"com7", "com8", "com9",
"lpt1", "lpt2", "lpt3",
"lpt4", "lpt5", "lpt6",
"lpt7", "lpt8", "lpt9"
};
char *lower;
char *temp;
bool ret = false;
/*
* First, check to see if this is a device namespace, which
* always starts with \\.\, since device namespaces are not
* legal file paths.
*/
temp = strstr(path, "\\\\.\\");
if (temp == path) {
return true;
}
/*
* Because Windows uses a case-insensitive file system, operate
* on a lowercase version of the given filename. Note: this
* ignores globalization issues and assumes ASCII
* characters.
*/
lower = (char *)malloc(strlen(path) + 1);
if (!lower) {
return false;
}
temp = lower;
while (*path) {
*lower++ = tolower(*path++);
}
lower = temp;
/* Compare against the list of ancient reserved names */
for (size_t i = 0; !ret &&
i < sizeof(reserved) / sizeof(*reserved); ++i) {
if (0 == strcmp(lower, reserved[i])) {
ret = true;
}
}
free(lower);
return ret;
} |
...