问题
I'm trying to figure out how I can test if a file is being redirected to itself, e.g. .\command.exe file1 > file1
In the *nix world, I'd just use something like this:
// Language agnostic...
if (file_dev == out_dev && file_ino == out_ino) {
printf("%s\n", "same file!");
}
But in Windows, if I try to do this:
// This (language) is Go...
// create fileStat...
// now stat stdout
outStat, err := os.Stdout.Stat()
// error check
if os.SameFile(fileStat, outStat) {
fmt.Println("same file!")
}
...I get the IncorrectFunction
error.
I read this (https://stackoverflow.com/a/21070042/2967113) question, and from what I gather you can't stat stdout
?
This is a mostly language agnostic question -- I can translate whatever to Go (the language I'm using). I'm mostly concerned about how, using Windows' ABI (API?), I would find where stdout is being redirected to.
回答1:
This answer is Windows-specific but as you've tagged "windows" I figure that's ok.
I can't help with Go, but in C/C++ you can do something like this:
#include <tchar.h>
#include <Windows.h>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t chPath[MAX_PATH];
if (GetFinalPathNameByHandle(GetStdHandle(STD_OUTPUT_HANDLE), chPath, MAX_PATH, 0))
std::wcout << L"stdout = " << chPath << std::endl;
else
std::cout << "stdout not redirected" << std::endl;
return 0;
}
GetFinalPathNameByHandle
will fail if stdout is a console handle, but if it's been redirected to a file it will return the file path.
回答2:
You can call HANDLE GetStdHandle( DWORD stdHandle ) with STD_INPUT_HANDLE and STD_OUTPUT_HANDLE to open the file handle.
Then call DWORD GetFileType( HANDLE hFile ) to check if the returned type is FILE_TYPE_DISK
Finally, call
DWORD WINAPI GetFinalPathNameByHandle( _In_ HANDLE hFile, _Out_ LPTSTR lpszFilePath, _In_ DWORD cchFilePath, _In_ DWORD dwFlags );
to obtain the file pathname and compare the names for equivalency.
回答3:
Well, first up, I don't think your method in UNIX-land is actually going to protect you.
By the time your code gets to checking devices and inodes, the shell has already truncated the file. It is responsible for processing the output redirections and it does this before your program even starts, so that you're given a fresh file for your output.
I suspect you'd have the same problem in Windows in that cmd.exe
will truncate your file before your script even started running.
Having said that, I believe at some point you're going to have to trust that the user knows what they're doing :-)
The other alternative is, of course, not to do output redirection but instead to require the input and output files as arguments:
cmd.exe myscipt myscript
That way, you could detect if the user was going to write to the input file (using canonicalised file names or inodes) and prevent it.
Although that still won't prevent the user from doing something silly like:
cmd.exe myscipt >myscript
blowing away your script before you get a chance to notify them they should have provided two arguments rather than one.
I think the bottom line is, if the user does output redirection, there's no way for your program to catch it before it's too late.
来源:https://stackoverflow.com/questions/29360969/check-if-windows-file-is-redirected-to-itself