Special filenames
Prev | Chapter 3. Using Cygwin | Next

## Special filenames

### Special files in /etc

Certain files in Cygwin's `/etc` directory are read by Cygwin before the mount table has been established. The list of files is

      /etc/fstab
      /etc/fstab.d/$USER
      /etc/passwd
      /etc/group

These file are read using native Windows NT functions which have no notion of Cygwin symlinks or POSIX paths. For that reason there are a few requirements as far as `/etc` is concerned.

To access these files, the Cygwin DLL evaluates it's own full Windows path, strips off the innermost directory component and adds "\etc". Let's assume the Cygwin DLL is installed as `C:\cygwin\bin\cygwin1.dll`. First the DLL name as well as the innermost directory (`bin`) is stripped off: `C:\cygwin\`. Then "etc" and the filename to look for is attached: `C:\cygwin\etc\fstab`. So the /etc directory must be parallel to the directory in which the cygwin1.dll exists and `/etc` must not be a Cygwin symlink pointing to another directory. Consequentially none of the files from the above list, including the directory `/etc/fstab.d` is allowed to be a Cygwin symlink either.

However, native NTFS symlinks and reparse points are transparent when accessing the above files so all these files as well as `/etc` itself may be NTFS symlinks.

Last but not least, make sure that these files are world-readable. Every process of any user account has to read these files potentially, so world-readability is essential. The only exception are the user specific files `/etc/fstab.d/$USER`, which only have to be readable by the $USER user account itself.

### Invalid filenames

Filenames invalid under Win32 are not necessarily invalid under Cygwin. There are a few rules which apply to Windows filenames. Most notably, DOS device names like `AUX`, `COM1`, `LPT1` or `PRN` (to name a few) cannot be used as filename or extension in a native Win32 application. So filenames like `prn.txt` or `foo.aux` are invalid filenames for native Win32 applications.

This restriction doesn't apply to Cygwin applications. Cygwin can create and access files with such names just fine. Just don't try to use these files with native Win32 applications.

### Forbidden characters in filenames

Some characters are disallowed in filenames on Windows filesystems. These forbidden characters are the ASCII control characters from ASCII value 1 to 31, plus the following characters which have a special meaning in the Win32 API:

      "   *   :   <   >   ?   |   \

Cygwin can't fix this, but it has a method to workaround this restriction. All of the above characters, except for the backslash, are converted to special UNICODE characters in the range 0xf000 to 0xf0ff (the "Private use area") when creating or accessing files by adding 0xf000 to the forbidden characters' code points.

The backslash has to be exempt from this conversion, because Cygwin accepts Win32 filenames including backslashes as path separators on input. Converting backslashes using the above method would make this impossible.

Additionally Win32 filenames can't contain trailing dots and spaces for DOS backward compatibility. When trying to create files with trailing dots or spaces, all of them are removed before the file is created. This restriction only affects native Win32 applications. Cygwin applications can create and access files with trailing dots and spaces without problems.

An exception from this rule are some network filesystems (NetApp, NWFS) which choke on these filenames. They return with an error like "No such file or directory" when trying to create such files. Cygwin recognizes these filesystems and works around this problem by applying the same rule as for the other forbidden characters. Leading spaces and trailing dots and spaces will be converted to UNICODE characters in the private use area. This behaviour can be switched on explicitely for a filesystem or a directory tree by using the mount option `dos`.

### Filenames with unusual (foreign) characters

Windows filesystems use Unicode encoded as UTF-16 to store filename information. If you don't use the UTF-8 character set (see the section called “Internationalization”) then there's a chance that a filename is using one or more characters which have no representation in the character set you're using.

### Note

In the default "C" locale, Cygwin creates filenames using the UTF-8 charset. This will always result in some valid filename by default, but again might impose problems when switching to a non-"C" or non-"UTF-8" charset.

### Note

To avoid this scenario altogether, always use UTF-8 as the character set.

If you don't want or can't use UTF-8 as character set for whatever reason, you will nevertheless be able to access the file. How does that work? When Cygwin converts the filename from UTF-16 to your character set, it recognizes characters which can't be converted. If that occurs, Cygwin replaces the non-convertible character with a special character sequence. The sequence starts with an ASCII CAN character (hex code 0x18, equivalent Control-X), followed by the UTF-8 representation of the character. The result is a filename containing some ugly looking characters. While it doesn't look nice, it is nice, because Cygwin knows how to convert this filename back to UTF-16. The filename will be converted using your usual character set. However, when Cygwin recognizes an ASCII CAN character, it skips over the ASCII CAN and handles the following bytes as a UTF-8 character. Thus, the filename is symmetrically converted back to UTF-16 and you can access the file.

### Note

Please be aware that this method is not entirely foolproof. In some character set combinations it might not work for certain native characters.

Only by using the UTF-8 charset you can avoid this problem safely.

### Case sensitive filenames

In the Win32 subsystem filenames are only case-preserved, but not case-sensitive. You can't access two files in the same directory which only differ by case, like `Abc` and `aBc`. While NTFS (and some remote filesystems) support case-sensitivity, the NT kernel does not support it by default. Rather, you have to tweak a registry setting and reboot. For that reason, case-sensitivity can not be supported by Cygwin, unless you change that registry value.

If you really want case-sensitivity in Cygwin, you can switch it on by setting the registry value

    HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\kernel\obcaseinsensitive

to 0 and reboot the machine.

### Note

When installing Microsoft's Services For Unix (SFU), you're asked if you want to use case-sensitive filenames. If you answer "yes" at this point, the installer will change the aforementioned registry value to 0, too. So, if you have SFU installed, there's some chance that the registry value is already set to case sensitivity.

After you set this registry value to 0, Cygwin will be case-sensitive by default on NTFS and NFS filesystems. However, there are limitations: while two programs `Abc.exe` and `aBc.exe` can be created and accessed like other files, starting applications is still case-insensitive due to Windows limitations and so the program you try to launch may not be the one actually started. Also, be aware that using two filenames which only differ by case might result in some weird interoperability issues with native Win32 applications. You're using case-sensitivity at your own risk. You have been warned!

Even if you use case-sensitivity, it might be feasible to switch to case-insensitivity for certain paths for better interoperability with native Win32 applications (even if it's just Windows Explorer). You can do this on a per-mount point base, by using the "posix=0" mount option in `/etc/fstab`, or your `/etc/fstab.d/$USER` file.

`/cygdrive` paths are case-insensitive by default. The reason is that the native Windows %PATH% environment variable is not always using the correct case for all paths in it. As a result, if you use case-sensitivity on the `/cygdrive` prefix, your shell might claim that it can't find Windows commands like attrib or net. To ease the pain, the `/cygdrive` path is case-insensitive by default and you have to use the "posix=1" setting explicitly in `/etc/fstab` or `/etc/fstab.d/$USER` to switch it to case-sensitivity, or you have to make sure that the native Win32 %PATH% environment variable is using the correct case for all paths throughout.

Note that mount points as well as device names and virtual paths like /proc are always case-sensitive! The only exception are the subdirectories and filenames under /proc/registry, /proc/registry32 and /proc/registry64. Registry access is always case-insensitive. Read on for more information.

### Case sensitive directories

Windows 10 1803 introduced a new feature: NTFS directories can be marked as case-sensitive, independently of the `obcaseinsensitive` registry key discussed in the previous section. This new per-directory case-sensitivity requires setting a flag in the NTFS filesystem header which is, unfortunately, undocumented. The result is that you have to activate `Windows Subsystem for Linux` (`WSL`), a feature available via `Programs and Features` -> `Turn Windows features on or off`. You only have to activate `WSL`, you don't have to install any actual Linux. After turning `WSL` on and performing the compulsory reboot, case-sensitive directories are activated.

Of course, there's a drawback. While these case-sensitive directories work like charm on the local machine, there are massive interoperability problems when trying to access these directories from remote machines at the time of writing this. We opened a bug report for that at Microsoft's WSL issue tracker, if you're interested in the details.

### Note

If you want case-sensitivity and need interoperability with remote machines, better stick to switching the kernel to case-sensitivity as outlined in the section called “Case sensitive filenames”

With `WSL` activated and starting with Cygwin 3.0.0, Cygwin's mkdir system call automatically created all directories below the Cygwin installation directory as case-sensitive. With Cygwin 3.0.2, this feature had been disabled again for hopefully obvious reasons.

However, you can still use Cygwin's new chattr(1) tool with the `-C` option to control case-sensitivity of directories on NTFS filesystems.

Please keep in mind that switching off case-sensitivity on a directory has a condition attached to it: If the directory contains two files which only differ in case (e. g., `foo` and `FOO`), Windows refuses to convert the dir back to case-insensitive. First you have to fix the filename collision, i. e., you have to rename one of these files.

### POSIX devices

While there is no need to create a POSIX `/dev` directory, the directory is automatically created as part of a Cygwin installation. It's existence is often a prerequisit to run certain applications which create symbolic links, fifos, or UNIX sockets in `/dev`. Also, the directories `/dev/shm` and `/dev/mqueue` are required to exist to use named POSIX semaphores, shared memory, and message queues, so a system without a real `/dev` directory is functionally crippled.

Apart from that, Cygwin automatically simulates POSIX devices internally. The `/dev` directory is automagically populated with existing POSIX devices by Cygwin in a way comparable with a udev based virtual `/dev` directory under Linux.

Cygwin supports the following character devices commonly found on POSIX systems:

    /dev/null
    /dev/zero
    /dev/full

    /dev/console	Pseudo device name for the current console window of a session.
    		Cygwin's /dev/console is not quite comparable with the console
    		device on UNIX machines.

    /dev/cons0      Console sessions are numbered from  /dev/cons0 upwards.
    /dev/cons1	Console device names are pseudo device names, only accessible
    ...		from processes within this very console session.  This is due
    		to a restriction in Windows.

    /dev/tty	The current controlling tty of a session.

    /dev/ptmx	Pseudo tty master device.

    /dev/pty0	Pseudo ttys are numbered from /dev/pty0 upwards as they are
    /dev/pty1	requested.
    ...

    /dev/ttyS0	Serial communication devices.  ttyS0 == Win32 COM1,
    /dev/ttyS1	ttyS1 == COM2, etc.
    ...

    /dev/pipe
    /dev/fifo

    /dev/kmsg	Kernel message pipe, for usage with sys logger services.

    /dev/random	Random number generator.
    /dev/urandom

    /dev/dsp	Default sound device of the system.

Cygwin also has several Windows-specific devices:

    /dev/com1	The serial ports, starting with COM1 which is the same as ttyS0.
    /dev/com2	Please use /dev/ttySx instead.
    ...

    /dev/conin	Same as Windows CONIN$.
    /dev/conout	Same as Windows CONOUT$.
    /dev/clipboard	The Windows clipboard, text only
    /dev/windows	The Windows message queue.

Block devices are accessible by Cygwin processes using fixed POSIX device names. These POSIX device names are generated using a direct conversion from the POSIX namespace to the internal NT namespace. E.g. the first harddisk is the NT internal device \device\harddisk0\partition0 or the first partition on the third harddisk is \device\harddisk2\partition1. The first floppy in the system is \device\floppy0, the first CD-ROM is \device\cdrom0 and the first tape drive is \device\tape0.

The mapping from physical device to the name of the device in the internal NT namespace can be found in various places. For hard disks and CD/DVD drives, the Windows "Disk Management" utility (part of the "Computer Management" console) shows that the mapping of "Disk 0" is \device\harddisk0. "CD-ROM 2" is \device\cdrom2. Another place to find this mapping is the "Device Management" console. Disks have a "Location" number, tapes have a "Tape Symbolic Name", etc. Unfortunately, the places where this information is found is not very well-defined.

For external disks (USB-drives, CF-cards in a cardreader, etc) you can use Cygwin to show the mapping. `/proc/partitions` contains a list of raw drives known to Cygwin. The df command shows a list of drives and their respective sizes. If you match the information between `/proc/partitions` and the df output, you should be able to figure out which external drive corresponds to which raw disk device name.

Raw devices of partitions protected by BitLocker provide access to the decrypted NTFS image. If the partition is locked, read attempts fail with `Permission denied`. The corresponding block range from the raw device of the full disk provides access to the encrypted image as stored on the disk.

### Note

Apart from tape devices which are not block devices and are by default accessed directly, accessing mass storage devices raw is something you should only do if you know what you're doing and know how to handle the information. Writing to a raw mass storage device you should only do if you really know what you're doing and are aware of the fact that any mistake can destroy important information, for the device, and for you. So, please, handle this ability with care.

Important: Windows may allow raw read and write access to partitions (for example `/dev/sda2`) even from unprivileged processes. This is usually the case for partitions on "removable" drives like USB flash drives or regular SATA/NVMe drives behind USB docking stations. If chkdsk X: works, raw access to the same partition is possible from the same user account. You have been warned.

Last but not least, the mapping from POSIX /dev namespace to internal NT namespace is as follows:

    POSIX device name     Internal NT device name

    /dev/st0	      \device\tape0, rewind
    /dev/nst0	      \device\tape0, no-rewind
    /dev/st1	      \device\tape1
    /dev/nst1	      \device\tape1
    ...
    /dev/st15
    /dev/nst15

    /dev/fd0	      \device\floppy0
    /dev/fd1	      \device\floppy1
    ...
    /dev/fd15

    /dev/sr0	      \device\cdrom0
    /dev/sr1	      \device\cdrom1
    ...
    /dev/sr15

    /dev/scd0	      \device\cdrom0
    /dev/scd1	      \device\cdrom1
    ...
    /dev/scd15

    /dev/sda	      \device\harddisk0\partition0	(whole disk)
    /dev/sda1	      \device\harddisk0\partition1	(first partition)
    ...
    /dev/sda15	      \device\harddisk0\partition15	(fifteenth partition)

    /dev/sdb	      \device\harddisk1\partition0
    /dev/sdb1	      \device\harddisk1\partition1

    [up to]

    /dev/sddx	      \device\harddisk127\partition0
    /dev/sddx1	      \device\harddisk127\partition1
    ...
    /dev/sddx15	      \device\harddisk127\partition15

if you don't like these device names, feel free to create symbolic links as they are created on Linux systems for convenience:

    ln -s /dev/sr0 /dev/cdrom
    ln -s /dev/nst0 /dev/tape
    ...

### The .exe extension

Win32 executable filenames end with `.exe` but the `.exe` need not be included in the command, so that traditional UNIX names can be used. However, for programs that end in `.bat` and `.com`, you cannot omit the extension.

As a side effect, the ls filename gives information about `filename.exe` if `filename.exe` exists and `filename` does not. In the same situation the function call `stat("filename",..)` gives information about `filename.exe`. The two files can be distinguished by examining their inodes, as demonstrated below.

    bash$ ls *
    a      a.exe     b.exe
    bash$ ls -i a a.exe
    445885548 a       435996602 a.exe
    bash$ ls -i b b.exe
    432961010 b       432961010 b.exe

If a shell script `myprog` and a program `myprog.exe` coexist in a directory, the shell script has precedence and is selected for execution of myprog. Note that this was quite the reverse up to Cygwin 1.5.19. It has been changed for consistency with the rest of Cygwin.

The gcc compiler produces an executable named `filename.exe` when asked to produce `filename`. This allows many makefiles written for UNIX systems to work well under Cygwin.

### The /proc filesystem

Cygwin, like Linux and other similar operating systems, supports the `/proc` virtual filesystem. The files in this directory are representations of various aspects of your system, for example the command `cat /proc/cpuinfo` displays information such as what model and speed processor you have.

One unique aspect of the Cygwin `/proc` filesystem is `/proc/registry`, see next section.

The Cygwin `/proc` is not as complete as the one in Linux, but it provides significant capabilities. The `procps` package contains several utilities that use it.

### The /proc/registry filesystem

The `/proc/registry` filesystem provides read-only access to the Windows registry. It displays each `KEY` as a directory and each `VALUE` as a file. As anytime you deal with the Windows registry, use caution since changes may result in an unstable or broken system. There are additionally subdirectories called `/proc/registry32` and `/proc/registry64`. They are identical to `/proc/registry` on 32 bit host OSes. On 64 bit host OSes, `/proc/registry32` opens the 32 bit processes view on the registry, while `/proc/registry64` opens the 64 bit processes view.

Reserved characters ('/', '\', ':', and '%') or reserved names (`.` and `..`) are converted by percent-encoding:

    bash$ regtool list -v '\HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices'
    ...
    \DosDevices\C: (REG_BINARY) = cf a8 97 e8 00 08 fe f7
    ...
    bash$ cd /proc/registry/HKEY_LOCAL_MACHINE/SYSTEM
    bash$ ls -l MountedDevices
    ...
    -r--r----- 1 Admin SYSTEM  12 Dec 10 11:20 %5CDosDevices%5CC%3A
    ...
    bash$ od -t x1 MountedDevices/%5CDosDevices%5CC%3A
    0000000 cf a8 97 e8 00 08 fe f7 01 00 00 00

The unnamed (default) value of a key can be accessed using the filename `@`.

If a registry key contains a subkey and a value with the same name `foo`, Cygwin displays the subkey as `foo` and the value as `foo%val`.

### The @pathnames

To circumvent the limitations on shell line length in the native Windows command shells, Cygwin programs, when invoked by non-Cygwin processes, expand their arguments starting with "@" in a special way. If a file `pathname` exists, the argument `@pathname` expands recursively to the content of `pathname`. Double quotes can be used inside the file to delimit strings containing blank space. In the following example compare the behaviors /bin/echo when run from bash and from the Windows command prompt.

Example 3.3. Using @pathname

    bash$ /bin/echo  'This   is   "a     long"  line' > mylist
    bash$ /bin/echo @mylist
    @mylist
    bash$ cmd
    c:\> c:\cygwin\bin\echo @mylist
    This is a     long line

Prev | Up | Next
File permissions | Home | proc