In C++ how do i validate a file or folder path? - c++

A user input string for a destination path can potentially contain spaces or other invalid characters.
Example: " C:\users\username\ \directoryname\ "
Note that this has whitespace on both sides of the path as well as an invalid folder name of just a space in the middle. Checking to see if it is an absolute path is insufficient because that only really handles the leading whitespace. Removing trailing whitespace is also insufficient because you're still left with the invalid space-for-folder-name in the middle.
How do i prove that the path is valid before I attempt to do anything with it?

The only way to "prove" the path is valid is to open it.
SHLWAPI provides a set of path functions which can be used to canonicalize the path or verify that a path seems to be valid. This can be useful to reject obviously bad paths but you still cannot trust that the path is valid without going through the file system.
With NTFS, I believe the path you give is actually valid (though Explorer may not allow you to create a directory with only a space.)

The Boost Filesystem library provides helpers to manipulate files, paths and so... Take a look at the simple ls example and the exists function.

I use GetFileAttributes for checking for existence. Works for both folders (look for the FILE_ATTRIBUTE_DIRECTORY flag in the returned value) and for files. I've done this for years, never had a problem.

If you don't want to open the file you can also use something like the access() function on POSIX-like platforms or _access() and friends on Windows. However, I like the Boost.Filesystem method Ricardo pointed out.

Related

Opening file in C++ on Unix: can we avoid case sensitivity? [duplicate]

For example, suppose we have a file called "Hello.txt", then checking if "hello.txt" or "heLLo.txt" exist should both return true.
If you're running Windows or any case-insensitive filesystem, then there's nothing to do but check one casing. If "Hello.txt" exists, then "hEllo.txt" exists (and is the same file) (the difficult problem here is when you want to make sure that the file is spelled with a given casing in the filesystem)
If you're running a case-sensitive filesystem, just take directory name of the current file, list file contents, and compare entries against the current filename, ignoring case.
Take a look at fcaseopen, which demonstrates how to handle case insensitive file operations.
Essentially, the C headers/functions to use are:
From dirent.h, use opendir/readdir/closedir to go thru the files in a directory
From string.h, use strcasecmp to compare two filesnames, ignoring the case of the characters

CreateDirectory not working for server path - c++

I am new to c++. The problem i am facing is with CreateDirectory method.
CreateDirectory("\\ServerName\foldername\",NULL) gives no error but it also doesn't create any directory. However if I write "D:\foldername" instead of "\\ServerName\foldername\" it works perfectly fine.
Any help would be highly appreciable.
"\ServerName\foldername\" is not a valid Windows path
"\\ServerName\foldername\" is valid, but this is the name of the "foldername" share on the "ServerName" network host. This is still not a valid directory you can create.
If ServerName is a valid host name, and if sharename, is a valid share on that host, on which you have write rights, then you could create "\\ServerName\sharename\foldername". But you can't create "\\ServerName\foldername\"
Thanks to Matteo for pointing out that in C strings, the \ must be escaped to \\
You must understand the difference between Fully Qualified vs Relative Paths
For Windows API functions that manipulate files, file names can often be relative to the current directory, while some APIs require a fully qualified path. A file name is relative to the current directory if it does not begin with one of the following:
A UNC name of any format, which always start with two backslash
characters ("\")
A disk designator with a backslash, for example "C:\" or "d:\".
A single backslash, for example, "\directory" or "\file.txt". This is
also referred to as an absolute path.
for more Information refer Naming Files, Paths, and Namespaces

mkdir, pathname with symbol

I have a little problem, I need to make directory from my c code or c++, doesn't matter.
But directory name must contain characters like ':', ' ','.' in general current time,
when I try to create with mkdir() function I get EINVAL error, but from system("mkdir ...") everything is ok.
How can I solve this problem?
Thank you!!!
Different filesystem formats have different rules about what is and is not a valid character. For ext2 and its descendants, A file name may contain any character except for '/' or '\0'.
For FAT filesystem and its descendants, the list of invalid characters is larger, and includes ':'.
Check to see what filesystem format you are using, and try running your program on a different filesystem.

Path and string chopping in Powershell

I'm doing some work involving some automated file moving, and these files contain relative paths that must be maintained. Unfortunately, I'm finding the facilities offered by System.IO.Path, System.String, and Powershell's operators to be a little ill-equipped to handle my work gracefully.
One function that would be very useful to me is the notion of a subtraction of paths, that would work in theory like subtracting vectors. Conceptually, A - B gets you a path from B to A. In the application to paths, D:\A\B\C\D - D:\A\B\ = \C\D. Likewise, D:\A\B\ - D:\A\B\C\D = \..\.. in this case. I can accept, for now, that this only makes sense when one path is wholly contained in the other.
This seems to consist of two steps: 1) determine containment of one path in the other. 2) remove the contained path from the containing path. 3) Optionally, replace folder names with the parent .. symbol based on the sidedness of the operation.
As I am concerned with NTFS, I need both containment and replacement operations to be case-insensitive. For containment, I can use select-string since it is case-insensitive, and allows the -simple switch which allows me to use a path without hacking it apart to escape them for regex.
Removing the string from the other is a little more annoying though. System.IO.Path has nothing for this, System.String's pertinent methods are all case-sensitive, and powershell's operators all require massaging so that the regex will match things.
All this seems like more work than it should be--are there any tools I'm missing that would better handle this?
Determine containment - convert your paths to absolute paths (if not already). You can use Resolve-Path for this. Then you can use $path1.StartsWith($path2, 'OrdinalIgnoreCase') to test for containment.
Remove contained path - $path1.Substring($path2.length)
Replace parent folder names with ... - although I don't have the regex off the top of my head, I'm pretty sure you could do this with a regular expression search/replace using PowerShell's -replace operator
filedirectorypath, on CodePlex, may offer what you need
It's not a PowerShell specific API, but that's no reason not to use it from PowerShell.
Benefits of the NDepend.Helpers.FilePathDirectory over the .NET Framework class System.IO.Path include:
Strongly typed File/Directory path.
Relative / absolute path conversion.
Path normalization API
Path validity check API
Path comparison API
Path browsing API.
Path rebasing API
List of path operations (TryGetCommonRootDirectory, GetListOfUniqueDirsAndUniqueFileNames, list equality…)

white space free path to My Documents

In building a C++ project with the GNU tool chain, make tells me ~
src/Adapter_FS5HyDE.d:1: *** multiple target patterns. Stop.
Search, search, search, and I found out that make thinks that it has multiple targets because the path to my included headers has spaces in it. If you've got your headers stored in some sane place like C:\Program Files then you can take care of this by using the old DOS paths (e.g. C:\PROGRA~1). However, when you have your headers in a truly insane place like My Documents you can get around the problem with MY DOC~1 because there's still a space.
Any idea how to tell my compiler to look in My Documents for headers without make confusing the path as two objects?
(Note: Feel free to throw tomatoes at me for putting header files in My Documents if you'd like, but there is a little rationale for doing that which I don't feel like explaining. If the solution to this question is easy, I'd rather keep it the way it is.)
You can figure out what the old path is by doing a DIR /X in your command prompt.
Or, most of the time you can fake it with the first 6 characters - spaces + ~1 + extension (8.3 paths won't have spaces).
Or, you can use quotes: "C:\Documents and Settings\Administrator\My Documents".
I don't know about make specficially, but the normal way around this is to put quotes around the path i.e.
cd "C:\Program Files\"
does that work?
Side note: the short name (8.3) for the same folder might not be the same on different OS installations. Thus, you can't be sure that C:\Program Files will always be C:\PROGRA~1.
Short names can't contain spaces in them either, so the usual short name for My Documents is MYDOCU~1, not MY DOC~1.
You can find the exact short name for any folder or file (including My Documents) using dir /x <filename>.
If you are using the GNU toolchain from Windows command line (cmd.exe), you should be able to use quotes (") around the folder/file names to work around this problem.
For some folders, including My Documents, you can specify an alternative location. To do this, right-click the folder, select Properties, select Location tab, and away you go. I use this to put my downloads and music on another drive (D:).
Write a wrapper script (e.g. batchfile) to translate the path names to short form.
I have a script "runwin" that does stuff like this - instead of, e.g. gcc <args> I can call runwin gcc <args>;
runwin will make heuristic guesses as to which arguments are filename paths and translate them, then call gcc on the resulting string of arguments.