Check if Windows file is redirected to itself

China☆狼群 提交于 2021-01-28 12:34:59

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!