Skip to content

Commit

Permalink
enh(File): Windows specifics of File::canExecute. Returns false if th…
Browse files Browse the repository at this point in the history
…e file to be executed can't be found using absolutePath.
  • Loading branch information
matejk committed May 23, 2024
1 parent 0f2bb25 commit f97c6c7
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 33 deletions.
1 change: 1 addition & 0 deletions Foundation/include/Poco/File_UNIX.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class FileImpl
void swapImpl(FileImpl& file);
void setPathImpl(const std::string& path);
const std::string& getPathImpl() const;
std::string getExecutablePathImpl() const;
bool existsImpl() const;
bool canReadImpl() const;
bool canWriteImpl() const;
Expand Down
1 change: 1 addition & 0 deletions Foundation/include/Poco/File_VX.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class FileImpl
void swapImpl(FileImpl& file);
void setPathImpl(const std::string& path);
const std::string& getPathImpl() const;
std::string getExecutablePathImpl() const;
bool existsImpl() const;
bool canReadImpl() const;
bool canWriteImpl() const;
Expand Down
1 change: 1 addition & 0 deletions Foundation/include/Poco/File_WIN32U.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class Foundation_API FileImpl
void swapImpl(FileImpl& file);
void setPathImpl(const std::string& path);
const std::string& getPathImpl() const;
std::string getExecutablePathImpl() const;
bool existsImpl() const;
bool canReadImpl() const;
bool canWriteImpl() const;
Expand Down
15 changes: 9 additions & 6 deletions Foundation/src/File.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,21 +109,23 @@ std::string File::absolutePath() const
{
Path curPath(Path::current());
curPath.append(path());
if (File(curPath).exists()) ret = curPath.toString();
if (File(curPath).exists())
ret = curPath.toString();
else
{
const std::string envPath = Environment::get("PATH", "");
const std::string pathSeparator(1, Path::pathSeparator());
if (!envPath.empty())
{
StringTokenizer st(envPath, pathSeparator,
const StringTokenizer st(envPath, pathSeparator,
StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);

for (const auto& p: st)
{
try
{
std::string fileName(p);
if (p.size() && p[p.size()-1] != Path::separator())
if (p.size() && p.back() != Path::separator())
fileName.append(1, Path::separator());
fileName.append(path());
if (File(fileName).exists())
Expand Down Expand Up @@ -180,11 +182,12 @@ bool File::canWrite() const

bool File::canExecute() const
{
// Resolve absolute path from relative and
const auto absPath { absolutePath() };
// Resolve (platform-specific) executable path and absolute path from relative.
const auto execPath { getExecutablePathImpl() };
const auto absPath { File(execPath).absolutePath() };
if (absPath.empty() || !File(absPath).exists())
{
throw Poco::FileNotFoundException(getPathImpl());
return false;
}
return canExecuteImpl(absPath);
}
Expand Down
6 changes: 6 additions & 0 deletions Foundation/src/File_UNIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ void FileImpl::setPathImpl(const std::string& path)
}


std::string FileImpl::getExecutablePathImpl() const
{
return _path;
}


bool FileImpl::existsImpl() const
{
poco_assert (!_path.empty());
Expand Down
6 changes: 6 additions & 0 deletions Foundation/src/File_VX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ void FileImpl::setPathImpl(const std::string& path)
}


std::string FileImpl::getExecutablePathImpl() const
{
return _path;
}


bool FileImpl::existsImpl() const
{
poco_assert (!_path.empty());
Expand Down
14 changes: 14 additions & 0 deletions Foundation/src/File_WIN32U.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "Poco/File_WIN32U.h"
#include "Poco/Exception.h"
#include "Poco/Path.h"
#include "Poco/String.h"
#include "Poco/UnicodeConverter.h"
#include "Poco/UnWindows.h"
Expand Down Expand Up @@ -88,6 +89,19 @@ void FileImpl::setPathImpl(const std::string& path)
convertPath(_path, _upath);
}

std::string FileImpl::getExecutablePathImpl() const
{
// Windows specific: An executable can be invoked without
// the extension .exe, but the file has it nevertheless.
// This function appends extension "exe" if the file path does not have it.
Path p(_path);
if (!p.getExtension().empty())
{
return _path;
}
return p.setExtension("exe"s).toString();
}


bool FileImpl::existsImpl() const
{
Expand Down
51 changes: 24 additions & 27 deletions Foundation/testsuite/src/FileTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,45 +209,42 @@ void FileTest::testExists()
File f("/testfile.dat");
assertFalse (f.exists());
assertFalse (f.existsAnywhere());

try
{
f.canExecute();
failmsg("file does not exist - must throw exception");
}
catch (const Poco::FileNotFoundException&)
{
}
assertFalse (f.canExecute());
}

{
#if defined(POCO_OS_FAMILY_UNIX)
File f("echo");
File f2("/dev/null");
//#elif defined(POCO_OS_FAMILY_WINDOWS)
// std::string buffer(MAX_PATH, 0);
// UINT r = GetSystemDirectoryA(buffer.data(), static_cast<UINT>(buffer.size()));
// if (r)
// {
// Path p(buffer);
// p.makeDirectory().makeAbsolute().makeParent();
// buffer = p.toString();
// buffer.append("win.ini");
// }
// else
// {
// buffer = "c:\\windows\\win.ini";
// }
// File f("cmd.exe");
// File f2(buffer);
//#endif
#elif defined(POCO_OS_FAMILY_WINDOWS)
std::string buffer(MAX_PATH, 0);
UINT r = GetSystemDirectoryA(buffer.data(), static_cast<UINT>(buffer.size()));
if (r)
{
Path p(buffer);
p.makeDirectory().makeAbsolute().makeParent();
buffer = p.toString();
buffer.append("win.ini");
}
else
{
buffer = R"(c:\windows\win.ini)";
}
File f("cmd.exe");
File f2(buffer);

File f3("cmd");
assertTrue (f3.canExecute());
File f4("cmd-nonexistent");
assertFalse (f4.canExecute());
#endif
assertFalse (f.exists());
assertTrue (f.existsAnywhere());
assertTrue (f.canExecute());

assertTrue (f2.exists());
assertTrue (f2.existsAnywhere());
assertFalse (f2.canExecute());
#endif
}
}

Expand Down

0 comments on commit f97c6c7

Please sign in to comment.