0

I did a Google search to see how to check if a given path is valid, preferably using boost.

It brought me here:

How to check if path is valid in boost::filesystem?

Great! I say to myself. I then Google up the boost doc here: http://www.boost.org/doc/libs/1_62_0/libs/filesystem/doc/portability_guide.htm

I then write myself a test:

#include <iostream>
#include <sstream>

#include <boost/filesystem.hpp>

int main()
{
    const std::string test1 = "D:\\Programing Projects\\Git Workspace\\Common\\x64\\Debug";
    const std::string test2 = "D:\\Programing Projects\\Git Workspace\\Common\\x64\\Debug\\";
    const std::string test3 = "D:/Programing Projects/Git Workspace/Common/x64/Debug";
    const std::string test4 = "D:/Programing Projects/Git Workspace/Common/x64/Debug/";

    if (!boost::filesystem::native(test1))
    {
        std::cout << "Boost says the following path is not valid for the native operating system: " << test1 << std::endl;
    }

    if (!boost::filesystem::native(test2))
    {
        std::cout << "Boost says the following path is not valid for the native operating system: " << test2 << std::endl;
    }

    if (!boost::filesystem::native(test3))
    {
    std::cout << "Boost says the following path is not valid for the native operating system: " << test3 << std::endl;
    }

    if (!boost::filesystem::native(test4))
    {
        std::cout << "Boost says the following path is not valid for the native operating system: " << test4 << std::endl;

    }

    return 0;
}

The Test's Output:

Boost says the following path is not valid for the native operating system: D:\Programing Projects\Git Workspace\Common\x64\Debug
Boost says the following path is not valid for the native operating system: D:\Programing Projects\Git Workspace\Common\x64\Debug\
Boost says the following path is not valid for the native operating system: D:/Programing Projects/Git Workspace/Common/x64/Debug
Boost says the following path is not valid for the native operating system: D:/Programing Projects/Git Workspace/Common/x64/Debug/

What is wrong with that path that it says it is not valid for my native Windows 10 operating system?

Community
  • 1
  • 1
Christopher Pisz
  • 3,757
  • 4
  • 29
  • 65
  • What do you mean by "valid" here? – Nicol Bolas Nov 10 '16 at 19:22
  • @Nicol Bolas valid to me would mean the path does not necessarily have to currently point to a file or directory, but it can be used to point to one, once had it been created. That is what I am looking for anyway. Essentially, reject something like "%&?!doesnt resemble a path at all%^!" – Christopher Pisz Nov 10 '16 at 19:27
  • Does the string `test2` intentionally contain `\P` instead of `\\P`? – Dan Mašek Nov 10 '16 at 21:49
  • @Dan No, but it doesn't seem to effect the results. Will edit. – Christopher Pisz Nov 10 '16 at 22:20
  • @ChristopherPisz When I look at the actual [implementation](http://www.boost.org/doc/libs/1_62_0/libs/filesystem/src/portability.cpp), it appears that this function is intended only to validate the individual components of the path, not the whole thing. – Dan Mašek Nov 10 '16 at 22:28

1 Answers1

2

Let's have a look at the implementation of this function.

const char invalid_chars[] =
    "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
    "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
    "<>:\"/\\|";
// note that the terminating '\0' is part of the string - thus the size below
// is sizeof(invalid_chars) rather than sizeof(invalid_chars)-1.  I 
const std::string windows_invalid_chars(invalid_chars, sizeof(invalid_chars));

...

#ifdef BOOST_WINDOWS
    BOOST_FILESYSTEM_DECL bool native(const std::string & name)
    {
      return windows_name(name);
    }
#else
    BOOST_FILESYSTEM_DECL bool native(const std::string & name)
    {
      return  name.size() != 0
        && name[0] != ' '
        && name.find('/') == std::string::npos;
    }
#endif

...

BOOST_FILESYSTEM_DECL bool windows_name(const std::string & name)
{
  return name.size() != 0
    && name[0] != ' '
    && name.find_first_of(windows_invalid_chars) == std::string::npos
    && *(name.end()-1) != ' '
    && (*(name.end()-1) != '.'
      || name.length() == 1 || name == "..");
}

The requirements on Windows are:

  • String is not empty.
  • String does not begin with a space.
  • String does not contain any invalid characters. Those are ASCII codes 0x01 - 0x1F, <, >, :, ", /, \, and |.
  • The string does not end with a space.
  • The string does not begin with a . UNLESS the whole string is either "." or "..".

Otherwise the requirements are:

  • String is not empty.
  • String does not begin with a space.
  • String does not contain /.

Since the path separator is forbidden in both scenarios, we can conclude that this function is only intended to validate the individual components of the path (i.e. directory names, file names), not the full path.

The documentation confirms all this:

A name_check function returns true if its argument is valid as a directory and regular file name for a particular operating or file system. A number of these functions are provided. ...

In your example native would return true for things like

  • "Programing Projects"
  • "Git Workspace"
  • "Common"
  • "x64"
  • "Debug"
Dan Mašek
  • 17,852
  • 6
  • 57
  • 85