I have the feeling the C++ filesystem standard is broken on windows. It is heavily based on Boost.filesystem and I just found a serious issue there which (likely) also exists in std::filesystem: https://github.com/boostorg/filesystem/issues/99
The essence is the definition of "root_name" and "root_directory":
root-name(optional): identifies the root on a filesystem with multiple roots (such as "C:" or "//myserver"). In case of ambiguity, the longest sequence of characters that forms a valid root-name is treated as the root-name. The standard library may define additional root-names besides the ones understood by the OS API.
root-directory(optional): a directory separator that, if present, marks this path as absolute. If it is missing (and the first element other than the root name is a file name), then the path is relative and requires another path as the starting location to resolve to a file name.
This requires e.g. "C:\foo\bar.txt" to be decomposed into:
root_name: "C:"
root_directory: "\" or "/" (does this even make sense?)
directory: "foo"
file_name "bar.txt"
The problem now: The first part of this path is not a path, at least not the original one. This comes from the interpretation on windows:
"C:\" is the drive "C"
"C:" is the current working directory on the drive "C"
Minor: How should "\foo\bar.txt" be interpreted on windows according to the above? You have a "root_directory" (which is strangely not a directory but a directory separator) but no "root_name" hence the path cannot be absolute and so you don't have a "root_directory" either. sigh.
So from this I feel that "root_name" and "root_directory" cannot be decomposed (on windows). In "C:\foo" you'll have "C:\" and in "C:foo" you'll have "C:". Or to keep the (strangely defined) "root_directory" you'd need to set decompose "C:\foo" into "C:\", "\" and "foo" and struggle with the latter: Is that an absolute path? Actually it is: "The folder 'foo' in the current working directory on drive C", quite absolute, isn't it?
But well you could say "absolute==independent of current working dir" then the "root_directory" makes sense: It would be "\" for "C:\foo" and empty for "C:foo".
So question: Is the standard wrong in defining "C:" as the "root_name" instead of "C:\" in paths like "C:\foo" or is it simply invalid usage to iterate over components of a path expecting the prefix sums to be "valid"?
Your interpretation of the Windows filesystem is incorrect. The directory C:\ is the root directory of the "C" drive, not "the drive 'C'". This is distinct from C:, which is the current directory of the "C" drive. Just try using the Windows shell and see how C:<stuff> behaves relative to C:\<stuff>. Both will access stuff on that drive, but both will do so starting from different directories.
Think of it in these terms on Windows:
C: means "Go to the current directory of the C drive".
\ at the start of a path (after any root names) means "Go to the root directory of the current drive".
foo\ means "Go into the directory called 'foo' within whatever directory we are currently in".
bar.txt means "The file named 'bar.txt' in whatever directory we are currently in."
Therefore, C:\foo\bar.txt" means: Go to the current directory of the C drive, then go to the root directory of C, then go into the 'foo' directory of the root directory of C, then access the file 'bar.txt' in the 'foo' directory of the root directory of C.
Similarly, C:foo\bar.txt means: Go to the current directory of the C drive, then go into the 'foo' directory of the current directory of C, then access the file 'bar.txt' in the 'foo' directory of the current directory of C.
This is how Windows paths work. This is what it means to type those things in the Windows shell. And thus, this is how Boost/std filesystem paths were designed to work.
But well you could say "absolute==independent of current working dir"
But that's not how std filesystem defines the concept of "absolute path":
Absolute Path A path that unambiguously identifies the location of a file without reference to an additional starting location. The elements of a path that determine if it is absolute are operating system dependent.
So "relative" and "absolute" are implementation-dependent. In Windows, a path is not absolute unless it contains both a root-name and a root-directory. In the Windows filesystem implementation, path("\foo\bar.txt").is_absolute() will be false.
What you're looking for is root_path, see Filesystem TS § 8.4.9, path decomposition:
path root_path() const;
Returns: root_name() / root_directory()
Here's how Microsoft defines it:
Common to both systems is the structure imposed on a pathname once you
get past the root name. For the pathname c:/abc/xyz/def.ext:
The root name is c:.
The root directory is /.
The root path is c:/.
The relative path is abc/xyz/def.ext.
The parent path is c:/abc/xyz.
The filename is def.ext.
The stem is def.
The extension is .ext.
So a truly absolute path would begin with root_name + root_directory, or root_path.
See also system_complete(p) for resolving current directory on other drives:
Effects: Composes an absolute path from p, using the same rules used by the operating system to resolve a path passed as the filename argument to standard library open functions.
[Example: For POSIX based operating systems, system_complete(p) has the same semantics as absolute(p, current_path()).
For Windows based operating systems, system_complete(p) has the same semantics as
absolute(p, current_path()) if p.is_absolute() || !p.has_root_name() or p and
base have the same root_name(). Otherwise it acts like absolute(p, cwd) is the current directory for the p.root_name() drive. This will be the current directory for that drive the last time it was set, and thus may be residue left over from a prior program run by the command processor. Although these semantics are useful, they may be surprising. —end example]
Related
Right now i am using file based session in django to save data.
SESSION_ENGINE = "django.contrib.sessions.backends.file"
As per documentation django saves data in /tmp, but i dont understand what is actual path of this /tmp! Is this a directory in my project or else where?
I think you misread the documentation, the documentation [Django-doc] says:
You might also want to set the SESSION_FILE_PATH setting (which defaults to output from tempfile.gettempdir(), most likely /tmp) to control where Django stores session files. Be sure to check that your Web server has permissions to read and write to this location.
If we check the documentation on the tempfile.gettempdir() [Python-doc] we get:
Return the name of the directory used for temporary files. This
defines the default value for the dir argument to all functions in
this module.
Python searches a standard list of directories to find one which the
calling user can create files in. The list is:
The directory named by the TMPDIR environment variable.
The directory named by the TEMP environment variable.
The directory named by the TMP environment variable.
A platform-specific location:
On Windows, the directories C:\TEMP, C:\TMP, \TEMP, and \TMP, in that order.
On all other platforms, the directories /tmp, /var/tmp, and /usr/tmp, in that order.
As a last resort, the current working directory.
The result of this search is cached, see the description of tempdir
below.
So althought on Unix-based systems (Linux, BSD, Mac OS X, etc.) it will be stored in /tmp, it depends on the operating system.
As for Unix-based file systems, if there is a slash (/) in the front, that means an absolute path, so it is the tmp directory in the root of the filesystem. For more information on Unix file paths, see this article [geeksforgeeks].
If you however set the SESSION_FILE_PATH to a specific path, then that path will be used.
Note that temporary files are, well, temporary. Typically you should not assume that after a reboot, the files are still there.
I have a c++ project that I would like to send to someone in executable form. The issue is the program must read from a .txt that I created (specific deliminators). Currently my program reads from a file path that is specific to my computer,
parseFile("/Users/David/Desktop/FinalProject/Store.txt");
How could I package the .txt file and the executable file together, where the exec. reads specifically from the that .txt on anyone's machine?
Note: I am using Xcode
Change your programs to receive 'file path' as a parameter. Write a note(ReadMe) with the program to specify the file format and added a sample data file with the package
tl;dr: if you just put the text file in the same folder with your executable, you can open it with parseFile("Store.txt");
In most runtime implementations, there is a notion of a "working directory." When you open up an executable via the graphical shell (by double clicking it or something to that effect) the working directory is the same as the directory the executable is in.
Now, if you try to open a file in your program via a path that isn't fully qualified, then the path that gets used will be relative to the working directory.
A fully qualified path is a discrete path that points to a single entity in your filesystem. "/Users/David/Desktop/FinalProject/Store.txt" is one such example, as it starts at root (/ on *nix, DriveLetter:\ on Windows) and says exactly which directories you need to traverse to get to your file.
A path that is not fully qualified (which basically means that it doesn't start at the root of your filesystem) can be used to perform relative file addressing. Most runtimes will assume that any path that is not fully qualified is meant to be relative to the working directory, which basically means that the path that actually gets opened is the result of concatenating your provided path to the end of the working directory.
As an example, if you opened your binary, which is stored as /Users/David/Desktop/FinalProject/a.exe, then the working directory would be set to /Users/David/Desktop/FinalProject/. If your program then tried to open "Store.txt", the runtime would see that you're trying to open a path that isn't fully qualified, so it would assume you meant to open a file relative to the working directory, which would then be /Users/David/Desktop/FinalProject/ + Store.txt, which would be /Users/David/Desktop/FinalProject/Store.txt.
The nice thing about this is that if you move your binary, the working directory moves too. if you move a.exe along with Store.txt to /Users/David/Desktop/FinalProject(copy)/, then when you open /Users/David/Desktop/FinalProject(copy)/a.exe, the working directory will be /Users/David/Desktop/FinalProject(copy)/ now, and now when you call parseFile("Store.txt"), it will instead open up /Users/David/Desktop/FinalProject(copy)/Store.txt. This holds true when moving to other computers, too.
It's worth noting that if your binary is run from a command line utility, the working directory will often be the directory the command line shell is in, rather than the executable's directory. It is, however, a part of the C standard that the first command line parameter to main() should be the name of the executable, and most implementations supply you with the fully qualified path. With some minimal parsing, you can use that to determine what path to use as a base for addressing files.
i found C++ libraries could be included this way:
#include "..\example.h"
#include ".\another_example.h"
what is the dots used for?
They are to indicate the included file paths' are relative to the including file's actual path.
. points to the including file's actual directory
.. points to the including file's actual directories' parent diretory
Double dots stand for the parent directory of the currently entered path.
Single dot stands for the currently entered path on the left side of a dot and is used to show that you want a relative path.
A relative path is a path relative to the working directory of the
user or application, so the full absolute path will not have to be
given.
If you start your path with / (on *nix systems) or DRIVELETTER: (on Windows, e.g. D:) then the path is absolute. If you don't - the path is relative. If path is relative - it automatically prepends the directory of your file to the path entered.
Example:
"dir/././../dir/.." is the directory which contains the original file. The reductions are:
dir/././../dir/.. -> dir/./../dir/.. -> dir/../dir/.. -> /dir/.. -> . -> working directory. We removed ./ because it's alias to the current directory. We removed /dir/.. because we enter a directory with dir and get back with ..
One of the most often used features of ./ (but in the context of a shell, e.g. bash) - it forces to use a relative path instead of calling an executable program in the $PATH variable. For example if you type ls in terminal on *nix it will list the files in the working directory. If you type ./ls it will run executable with the name ls
in the current working directory and execute whatever this program does.
You can read more about path separators in this article on wikipedia
One dot is your current directory and two dots is your parent directory.
Two dots means one directory higher than the current one. For example, if you are in the directory C:\some\directory", "..\" would be "C:\some".
A single dot refers to the current directory. So using the previous example, ".\" would mean "C:\some\directory".
one dot . is for file's directory
2 dots .. are for file's parent directory.
My code uses LoadLibraryA("someDLL.dll"); What is the path it starts searching for the file someDLL.dll?And another question : is LoadLibraryA function case-sensitive?I mean if I have SomeDLL.dll it will not load it?
The MSDN Library article Dynamic-Link Library Search Order specifies the search order for desktop applications when SafeDllSearchMode is enabled, which is the default starting with Windows XP SP2:
The directory from which the application loaded.
The system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The current directory.
The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.
LoadlLibrary article specifies search order in Remarks:
If lpFileName does not include a path and there is more than one
loaded module with the same base name and extension, the function
returns a handle to the module that was loaded first.
If no file name extension is specified in the lpFileName parameter,
the default library extension .dll is appended. However, the file name
string can include a trailing point character (.) to indicate that the
module name has no extension. When no path is specified, the function
searches for loaded modules whose base name matches the base name of
the module to be loaded. If the name matches, the load succeeds.
Otherwise, the function searches for the file. [...]
For more information on the DLL search order, see Dynamic-Link Library
Search Order.
File names are not case sensitive, so NTFS and FAT file names are. It is the fundamental rule to not assume case sensitivity:
Naming Conventions
The following fundamental rules enable applications to create and process valid names for files and directories, regardless of the file system: [...]
Do not assume case sensitivity.
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 12 years ago.
Improve this question
If you look at point (6) here: http://www2.warwick.ac.uk/fac/sci/moac/students/peter_cock/cygwin/part3/
Why should we type ./ before the .exe file in order for it to run?
Why cannot we type hello.exe immediately?
Thanks.
Usually because intelligent people don't have their current directory . on the path :-)
The path is an environment variable like /bin:/usr/bin:/usr/sbin, and it's a list of directories to look in for finding executables, such as when you type in hello.
Unlike Windows, many UNIX shells don't automatically search the current directory for an executable. They must be listed in the path otherwise they are not run.
That's because to do otherwise is actually an attack vector. For example, if you create an ls program in your home directory and tell one of the administrators that there's a funny file in there, they may go to your directory and enter ls to see what's in there.
For a silly administrator that has the current directory before the "real" location of ls, they are now compromised, because your code is running with their full privileges.
That's why they tend not to do that.
Some people (not I) will put . on their path to make their lives easier but, even then, they'll put it at the end so that other locations are searched first.
Administrators don't have the luxury of being that trusting.
Because the current working directory is not in the PATH?
Or at least, that's how things are setup on Unix-style systems, I assume CYGWIN does the same.
On Windows, the current directory is always in the search path for an executable. The search order is "look in the current dir, if not found, look in the directories listed in the PATH environment variable".
From MS site:
The operating system always searches
in the current directory first, before
it searches the directories in the
command path.
(which makes all the warning here of not putting the . in your PATH irrelevant, IMHO)
On Linux this is not the case (for current dir). So, to run an executable which is in your current dir you need to write ./exe_name.
As Cygwin, again AFAIK, is for Windows, the ./ is not needed and seems to be just a copy/paste or preserving the unix-style the writer is used to.
EDIT: this is the issue of the command processor (the shell) as pointed out in comments and as I explain below, so if you are using a Unix-like shell on Windows, you still may need this style.
EDIT: elaborating on .\
. (not ./ to be exact) is an alias to the current directory. On Unix, every newly created directory is not "born" empty but contains 2 children: ., which is a self-reference, and .. which is a reference to the parent directory. Both are just regular directories, as any other. You don't see them when you run the ls command (same as dir on Windows) because names starting with . are special in the sense that they are not displayed by default. However, you can see them by ls -a.
When you run a command at the prompt, if the command is only a (file) name, the system (actually, the shell) searches the PATH for the file with this name.
If the command contains a path (not necessarily an absolute path, e.g. subdir1/exe) the system looks for the executable where you specified. Hence, writing ./exe means file exe in the current dir.
Cygwin is a Unix-like runtime environment and as such follows the way paths are searched for executables in such environments. The default executable search path of Unices does not contain the current directory. Thus if one wants to run an executable not located in one of the directories set in PATH a full path must be given. ./ is a shorthand for the current directory, also called process working directory (pwd). Be advised that it's a very bad idea to have the pwd being included in the executable search path.
Cygwin follows the Unix limitations on executing files in the current working directory. In Unix style terminal environments an executable must have ./ prepended if it is to be executed from the current directory. This is because the current directory "." is not part of the PATH environmment in order to limit the damage done by malware. Cygwin is simply following this convention, it has nothing per say to do with C++ programs
That's just an issue with your 'path' or 'PATH' variable in your shell. (probably your shell is bash, so it'd be PATH.)
echo $PATH
A typical 'user' path to do what you want would start with "." as a path element. This is a minor security risk of course.