Who handles the paths in Cygwin - cygwin

I am curious to find out who handles the paths in cygwin.
For instance if I do the following, it works:
cd C:\
However when I do:
$ pwd
/cygdrive/c
Who is responsible for the discrepancy here?
The reason I am curious is that "cd C:" among'st other tools accept windows paths but when it comes to displaying them they show something different.
If I do include the cygwin bin folder in my path (under regular cmd) then I know it all works as in cmd, so what is it thats causing this convertion, is it the bash/shell?

I am curious to find out who handles the paths in cygwin.
Largely, a small bit of C++ code in winsup/cygwin/path.cc. A particularly important function is normalize_posix_path. This code ends up compiled in the DLL cygwin1.dll which is used by all Cygwin applications.
All paths in Cygwin are "POSIX" paths resolved by the Cygwin DLL itself. The normalize_posix_path function recognizes the presence of certain syntax in paths (drive letter names and backslashes), and arranges for them to be treated as "Win32 paths".
That is the reason why you can feed c:/Users/... to a Cygwin program, as an alternative to /cygdrive/c/Users/....
$ pwd
/cygdrive/c
How this works is that Cygwin maintains a native Win32 current working directory, and so it knows perfectly well that this is C:\. However, this native information is mapped backwards to a POSIX path. Cygwin does this by scanning through its mount table where it sees that C:\ is "mounted" as /cygdrive/c. (The pwd utility is just reporting what Cygwin's implementation of the POSIX getcwd function is returning. The backwards mapping happens inside that function). Note that since Cygwin is operating in a virtual POSIX namespace created by its mount table, that space contains abstract places which have no Win32 native counterpart. For instance, you can cd to the /dev directory where you have entries like tty. This has no native location, and so getcwd will just report the POSIX path. Cygwin tries to keep the Cygwin-internal current working directory in sync with the Win32 one when there is a corespondence; it does so without using the SetCurrentDirectory Win32 function, and without maintaining the concept that Windows drives have individual current working directories.
If I do include the cygwin bin folder in my path (under regular cmd) then I know it all works as in cmd, so what is it thats causing this convertion, is it the bash/shell?
Actually, it does not all work as in cmd! Though Cygwin programs understand "Win32-ish" paths, the support is not complete. You can pass a path like D:file.txt to a truly native Windows program. It resolves via the current directory associated with the D drive, which could be D:\bob\documents, in which case the path stands for D:\bob\documents\file.txt. If there is no such directory then it stands for D:\file.txt. A Cygwin program will not understand this drive-relative path. In fact, D:file.txt won't even be recognized as a drive-letter reference (as of Cygwin 2.5.2). This is because the colon is not followed by a directory separator character (backslash or slash).

Related

Windows Linux Subsystem - File permissions when edited outside bash [duplicate]

As the title suggests, if I paste a c file written somewhere else into the root directory of the Linux Subsystem, I can't compile it.
I did a test where I made two differently titled hello world programs: one in vi that I can get into from the bash interface, and one elsewhere. When I compiled the one made in vi, it worked fine. Trying to do so for the one made elsewhere (after pasting it into the root directory), however, resulted in this:
gcc: error: helloWorld2.c: Input/output error
gcc: fatal error: no input files
compilation terminated
Any help with this would be much appreciated.
Do not change Linux files using Windows apps and tools!
Assuming what you meant by "paste a C file written somewhere else into the root directory of the Linux subsystem" is that you pasted your file into %localappdata%\lxss, this is explicitly unsupported. Files natively created via Linux syscalls in this area have UNIX metadata, which files natively created with Windows tools don't have.
Use /mnt/c (and the like) to access your Windows files from Linux; don't try to modify Linux files from Windows.
Quoting from the Microsoft blog linked at the top of this answer (emphasis from the original):
Therefore, be sure to follow these two rules in order to avoid losing files, and/or corrupting your data:
DO store files in your Windows filesystem that you want to create/modify using Windows tools AND Linux tools
DO NOT create / modify Linux files from Windows apps, tools, scripts or consoles
You cannot copy (by default, who knows how Windows bash is set up!) files into the root directory! Your gcc error is say "no input files", so the copy has most likely failed. Copy the files to your home directory instead, for instance:
cp helloWorld2.c ~/
instead of:
cp helloWorld2.c /

How do I deploy Qt libraries with an application?

This should be really simple, but I'm having trouble. I want to include some shared Qt libraries with my application in the installation folder so the user doesn't have to download Qt separately. On Windows, this seemed to work fine, but Ubuntu complains about not being to find the Qt libraries when they are in the same folder as the application.
How do I add the installation directory to shared library search path?
I was able to add the installation directory to shared library search path by adding the following lines to the .pro file, which set the rpath of the binary to $ORIGIN (the install folder). I needed to add the location of QT libs on my current machine (/usr/lib/qt5.5 and /usr/lib/qt5.5/lib) so that the project would build in QtCreator.
unix:!macx {
# suppress the default RPATH if you wish
QMAKE_LFLAGS_RPATH=
# add your own with quoting gyrations to make sure $ORIGIN gets to the command line unexpanded
QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN\':/usr/lib/qt5.5:/usr/lib/qt5.5/lib"
}
(The unix:!macx line makes it apply to linux only)
Windows, Linux and OSX behave quite differently. Windows is easiest: dump all the dll's in the application dir. OSX is next and Linux is most difficult.
Linux has certain search paths for searching shared objects. These search paths are mainly system libraries and possibly some user libraries. As you do not want to mess around with system files of your user one would prefer to have the shared objects in the application dir. This is possible but you have to tell Linux to read that directory. You can do this with setting the environment variable LD_LIBRARY_PATH. You can do this with a script. See my answer.

Setting Working Directory to Desktop in Cygwin

The current directory on cygwin is home/myuser. I navigated to cygwin and found it has a directory called home/myuser and could not figure out how I would navigate to the desktop. I did not want to add a desktop directory there and I could not navigate above the root folder (cygwin). Any idea on how I could do this?
This is essentially covered in the Cygwin FAQ under "How can I access other drives?". No, you're not trying to access another drive, but you are trying to access a folder outside of the Cygwin tree. As the FAQ item says, Cygwin maps your Windows drives as /cygdrive/<drive-letter>, so your desktop is likely something like /cygdrive/c/Users/<username>/Desktop. Note that the path has changed over the years with various versions of Windows and you didn't specify what version you're running, so it may not be exactly that.
Anyway, what I would do, would be to create a symbolic link to that from my Cygwin home folder. Something like this:
ln -s "/cygdrive/c/Users/<username>/Desktop" Desktop
I put the quotes in because depending on what version of windows you have, this path may include spaces.
You'll probably notice from the FAQ that the Cygwin version of bash accepts DOS-style pathnames, so you can actually do the following:
cd "C:/Users/<username>/Desktop"
But I recommend avoiding such syntax. Not all Cygwin apps understand DOS-style paths, and you'll only end up confusing yourself if you have to try to figure out whether what you're doing will work with a DOS-style path or not. It's best to just use the Unix-style paths for everything when in the Cygwin environment, unless you have a very good reason not to.
Add
cd "/cygdrive/c/Users/<username>/Desktop"
to .bashrc file located in <cygwin install directory>/home/<username>. This will change working directory to desktop every time you open Cygwin terminal.

Why are Cygwin import libraries installed with mode 755?

I have a library that I originally developed for Linux. I am now in the process of porting it to Cygwin. I have noticed that every library on my Cygwin system is installed like this:
DLL (cygfoo.dll) installed to /usr/bin mode 755
Static archive (libfoo.a) installed to /usr/lib mode 644
Import library (libfoo.dll.a) installed to /usr/lib mode 755
The first two make perfect sense to me. DLLs are executables so they should be mode 755. Static archives are not executables, so they are mode 644. The third one, however, seems odd to me. Import libraries are in fact static archives, not executables (ar -t libfoo.dll.a lists the contents of the archive). Shouldn't they also be installed mode 644?
Why is it the convention on Cygwin to install import libraries with mode 755?
Back to 2000:
On NTFS partitions, NT/W2K require the execute permission for DLLs to
allow loading a DLL on process startup.
That's no problem unless a person using ntsec gets a tar archive
packed by a person not using ntsec or packing on a FAT partition.
Since Cygwin fakes the execute permission only for the suffixes "exe",
"bat", "com", DLLs are treated as non executable by the stat() call
when ntsec isn't set.
When a person using ntsec unpacks that tar archive, the start of an
application which requires one of the DLLs from the archive will fail
with the Windows message
"The application failed to initialize properly (0xc0000022)"
which isn't that meaningful for most of the users.
To solve that problem we would have to do a simple step. Fake execute
permissions for DLLs when ntsec isn't set or the file system doesn't
support ACLs (FAT/FAT32).
Here: http://cygwin.com/ml/cygwin-developers/2000-10/msg00044.html
The only answer that occurs to me is that the installer is looking for the ".dll" string in the filename to activate the executable attribute (x) of the copied files... should been looking for /.+\.dll$/ (.dll only at the end).
It is understandable that the impedance mismatch between OS's/filesystems force the installer/copier to have a strategy to decide attribute values at the installer operation (it is easier than have to map a attribute list to the copied file... and in windows only have to look for .exe, .com and .dll)
To confirm this rename your "libfoo.dll.a" to "libfoo.dxx.a" and test it...
This is a Windows requirement: since the .dll file contains code that will be executed, it requires the executable bit to be set.
Remove permission to execute the file, and Windows won't let any of the code inside it be executed, even if the process doing the executing is separate.
Side note: it's a common misconception that there's no +x bit for Windows. That's technically true; Windows doesn't use POSIX rwx permissions, although Cygwin does try to provide an interface that resembles them. Windows does use ACLs (Access Control Lists) for permissions, however, and these do have a concept of "execute permissions", which is what Cygwin maps down to its +x bit.
There's a long discussion on the Cygwin mailing list about this, if you want sources/further reading.
Seems it's just a lazy hack resulting in this behavior for filenames containing ".dll". See hasanyasin's answer for the reasoning behind the "fix" (here).

Accessing a cygwin symlink from windows

I am quite new to cygwin. I created a symlink as follows
$ ln -s /var/www /cygdrive/d/foo
and when I check the D drive via windows, I see a system file called foo. Is there a way to make foo act as a folder for Windows instead of a system file?
Windows won't be able to read Cygwin-created symlinks, but you can create Windows symlinks using Windows commands, and Cygwin will treat those as symlinks.
On Vista and 7, this can be done with 'mklink'. This is a cmd.exe builtin rather than a standalone utility, so if you want to invoke it from a bash shell you have to do 'cmd /c mklink', and of course it will only understand Windows paths.
For XP, the 'Windows Resource Kit Tools' contain a utility called linkd that can be used to create directory links.
Not that I know of. Cygwin doesn't update the OS to have symlinks, rather, it allows you to 'fake' symlinks from within the Cygwin shell. You can set up the shell to use Windows LNK files, which may do what you want, but ...
From the Cygwin Documentation:
Creating shortcuts with cygutils
Another problem area is between
Unix-style links, which link one file
to another, and Microsoft .lnk files,
which provide a shortcut to a file.
They seem similar at first glance but,
in reality, are fairly different. By
default, Cygwin does not create
symlinks as .lnk files, but there's an
option to do that, see the section
called “The CYGWIN environment
variable”. These symlink .lnk files
are compatible with Windows-created
.lnk files, but they are still
different. They do not include much of
the information that is available in a
standard Microsoft shortcut, such as
the working directory, an icon, etc.
The cygutils package includes a
mkshortcut utility for creating
standard native Microsoft .lnk files.
But here's the problem. If Cygwin
handled these native shortcuts like
any other symlink, you could not
archive Microsoft .lnk files into tar
archives and keep all the information
in them. After unpacking, these
shortcuts would have lost all the
extra information and would be no
different than standard Cygwin
symlinks. Therefore these two types of
links are treated differently.
Unfortunately, this means that the
usual Unix way of creating and using
symlinks does not work with native
Windows shortcuts.
One alternative way to call mklink (/d creates directory link) without function:
link_name="/cygdrive/c/TestLink"
target_dir="/cygwin/c/Windows"
cmd /c mklink /d "`cygpath -w \"$link_name\"`" "`cygpath -w \"$target_dir\"`"
This example uses backticks (`command`) for command substitution.

Resources