bug#40072: Incorrect escaping on MinGW 32-bit
Jeffrey Walton <[email protected]>
| Newsgroups | gmane.comp.gnu.libtool.bugs |
|---|---|
| Message-ID | <CAH8yC8k0Ev84A7r+7bWPyyPFTxmsMcWbf0SvHaNZN+-=7BCSMA@mail.gmail.com> |
On Sun, Mar 15, 2020 at 10:48 AM Jeffrey Walton <[email protected]> wrote: > > On Sun, Mar 15, 2020 at 9:59 AM Bob Friesenhahn > <[email protected]> wrote: > > > > On Sun, 15 Mar 2020, Jeffrey Walton wrote: > > ... > Maybe libtool can do the same. Supply a small C program, compile it > and call it from the libtool scripts. Its would be quite easy to > supply the path in argv[1], and get back either (1) the original name > (no spaces), (2) a short file name or (3) a quoted long file name. If > the path gets split and shows up in pieces across argv[1]...argv[n-1], > then just combine the pieces because you know what is supposed to > happen. Bob, see what you think about a program like the one attached. The C code will be messier, but it is the same concept. Here's what it returns during testing. The -c options means returns string to use as a C declare. With USE_WINDOWS_API (tested under MSYS): $ ./quote_path.exe "C:\Users\Jeffrey" "Walton\Desktop" C:\Users\JEFFRE~1\Desktop $ ./quote_path.exe -c "C:\Users\Jeffrey" "Walton\Desktop" "C:\\Users\\JEFFRE~1\\Desktop"; $ ./quote_path.exe -c C:\\Users C:\\Users Without USE_WINDOWS_API (tested under MSYS): $ ./quote_path.exe "C:\Users\Jeffrey" "Walton\Desktop" "C:\Users\Jeffrey Walton\Desktop" $ ./quote_path.exe -c "C:\Users\Jeffrey" "Walton\Desktop" "\"C:\\Users\\Jeffrey Walton\\Desktop\""; $ ./quote_path.exe C:\\Users\\Jeffrey Walton\\Desktop "C:\Users\Jeffrey Walton\Desktop" $ ./quote_path.exe -c C:\\Users\\Jeffrey Walton\\Desktop "\"C:\\Users\\Jeffrey Walton\\Desktop\""; $ ./quote_path.exe -c C:\\Users C:\\Users I think offloading to an external program written for the specific problem will probably simplify libtool and its helpers. It will make your life a lot easier. Jeff _______________________________________________ Bug-libtool mailing list [email protected] https://lists.gnu.org/mailman/listinfo/bug-libtool
quote_path.cpp
(text/x-c++src, 2.6 KB)
#include <iostream>
#include <string>
#include <algorithm>
#include <utility>
#include <utility>
#include <cstdlib>
#if defined(_WIN32) || defined(__MINGW32__) || defined(__MSYS__)
#define USE_WINDOWS_API 1
#endif
#if defined(USE_WINDOWS_API)
#include <windows.h>
#endif
// For testing on MinGW32 and MSYS
// #undef USE_WINDOWS_API
std::string escape_slashes(const std::string& str)
{
std::string temp;
temp.reserve(temp.size() + 16);
for (size_t i=0; i<str.size(); ++i)
{
temp += str[i];
if (str[i] == '\\')
temp += '\\';
}
return temp;
}
std::string safe_path_unix(const std::string& str, bool c_declare)
{
std::string the_path(str);
std::string temp_path;
temp_path.reserve(the_path.size()+8);
bool need_quote = the_path.find(' ') != std::string::npos;
if (need_quote && c_declare) {
temp_path += "\"\\\"";
}
else if (need_quote) {
temp_path += "\"";
}
if (c_declare) {
temp_path += escape_slashes(the_path);
}
else {
temp_path += the_path;
}
if (need_quote && c_declare) {
temp_path += "\\\"\";";
}
else if (need_quote) {
temp_path += "\"";
}
std::swap(the_path, temp_path);
return the_path;
}
#if defined(USE_WINDOWS_API)
std::string safe_path_windows(const std::string& str, bool c_declare)
{
std::string the_path(str);
std::string temp_path;
// GetShortPathName returns the size including the NULL for this case
DWORD res1 = GetShortPathName(the_path.c_str(), NULL, 0);
if (res1 == 0) {
// Fallback to Unix escaping
return safe_path_unix(str, c_declare);
}
temp_path.resize((size_t)res1);
// GetShortPathName does not include the NULL for this case
DWORD res2 = GetShortPathName(the_path.c_str(), &temp_path[0], res1);
if (res2 == 0) {
// Fallback to Unix escaping
return safe_path_unix(str, c_declare);
}
// NULL is not included because the buffer was well sized
temp_path.resize(res2);
std::swap(the_path, temp_path);
if (c_declare)
{
temp_path = "\"";
temp_path += escape_slashes(the_path);
temp_path += "\";";
std::swap(the_path, temp_path);
}
return the_path;
}
#endif
int main(int argc, char* argv[])
{
std::string the_path;
bool c_declare = false;
int index = 1;
if (argc == 1) {
std::exit(EXIT_FAILURE);
}
// -c option means format as C declare
if (argv[index][0] == '-' && argv[index][1] == 'c') {
c_declare = true;
index++;
}
// piece paths back together
for (int i=index; i<argc; ++i) {
if (i != index)
the_path += ' ';
the_path += argv[i];
}
#if defined(USE_WINDOWS_API)
the_path = safe_path_windows(the_path, c_declare);
#else
the_path = safe_path_unix(the_path, c_declare);
#endif
std::cout << the_path << std::endl;
return EXIT_SUCCESS;
}