Mailing-List: contact cygwin-developers-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-developers-owner AT cygwin DOT com Delivered-To: mailing list cygwin-developers AT cygwin DOT com From: "Gerald S. Williams" To: Subject: True case-sensitive filenames Date: Fri, 17 Jan 2003 17:06:40 -0500 Message-ID: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0028_01C2BE4A.CDA44F30" X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106 Importance: Normal Note-from-DJ: This may be spam This is a multi-part message in MIME format. ------=_NextPart_000_0028_01C2BE4A.CDA44F30 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit The Perl File::Spec thread/rant/whatever on the cygwin list got me thinking. To resolve the Windows case-insensitivity problem (e.g., "makefile" == "Makefile"), Linda W. seemed to suggest creating a new file system driver with a special Cygwin API. I don't know if she really meant that or I just misinterpreted it, but I got to thinking that something like this must already exist for Windows. Sure enough, you can accomplish it using the Native API. To see for myself, I created the attached test, which creates /cygdrive/c/makefile and /cygdrive/c/Makefile. You can even see both files from Cygwin, but when you try to access either one, you will always get Makefile (after you delete it, you get makefile of course). Filenames already are case-sensitive, but the problem is in the opening of files under Windows. This is normally done using a case-insensitive search. The Native API function allows you to choose and actually defaults to using case-sensitive searching. Of course, this would only work for Windows NT/2000/XP, but I think it should be pretty easy to make fhandler_disk_file use case-sensitive searches when opening files. I think this would be a big boon for Cygwin, and worth creating slightly different behavior between NT/2000/XP and 9x/ME. We could even fall back to case-insensitive searching by default, I suppose. There is already some precedent for using Native API calls in the fhandler code: fhandler_dev_raw does it. Any interest in taking this further? -Jerry ------=_NextPart_000_0028_01C2BE4A.CDA44F30 Content-Type: application/octet-stream; name="create_raw.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="create_raw.c" #include =0A= #include =0A= #include =0A= =0A= /* compile as follows: gcc -o create_raw create_raw.c -lntdll */=0A= =0A= typedef struct _IO_STATUS_BLOCK=0A= {=0A= NTSTATUS Status;=0A= ULONG Information;=0A= } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;=0A= =0A= NTSTATUS NTAPI ZwCreateFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,=0A= PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG,=0A= ULONG, ULONG, PVOID, ULONG);=0A= NTSTATUS NTAPI ZwClose (HANDLE);=0A= =0A= #define sys_mbstowcs(_t,_s,_l) = MultiByteToWideChar(CP_ACP,0,(_s),-1,(_t),(_l))=0A= =0A= static void=0A= str2buf2uni (UNICODE_STRING *tgt, WCHAR *buf, const char *srcstr)=0A= {=0A= tgt->Length =3D strlen (srcstr) * sizeof (WCHAR);=0A= tgt->MaximumLength =3D tgt->Length + sizeof(WCHAR);=0A= tgt->Buffer =3D (PWCHAR) buf;=0A= sys_mbstowcs (buf, srcstr, tgt->MaximumLength);=0A= }=0A= =0A= #define _SHARED (FILE_SHARE_READ | FILE_SHARE_WRITE | = FILE_SHARE_DELETE)=0A= #define _CASE_SENSITIVE (0)=0A= =0A= /* NT Create CreateDisposition values */=0A= #define FILE_SUPERSEDE (0)=0A= #define FILE_OPEN (1)=0A= #define FILE_CREATE (2)=0A= #define FILE_OPEN_IF (3)=0A= #define FILE_OVERWRITE (4)=0A= #define FILE_OVERWRITE_IF (5)=0A= /* NT Create CreateOptions bits */=0A= #define FILE_DIRECTORY_FILE (0x00000001)=0A= #define FILE_WRITE_THROUGH (0x00000002)=0A= #define FILE_SEQUENTIAL_ONLY (0x00000004)=0A= #define FILE_NON_DIRECTORY_FILE (0x00000040)=0A= #define FILE_NO_EA_KNOWLEDGE (0x00000200)=0A= #define FILE_EIGHT_DOT_THREE_ONLY (0x00000400)=0A= #define FILE_RANDOM_ACCESS (0x00000800)=0A= #define FILE_DELETE_ON_CLOSE (0x00001000)=0A= /* NT Create SecurityFlags bits */=0A= #define SMB_SECURITY_DYNAMIC_TRACKING (0x01)=0A= #define SMB_SECURITY_EFFECTIVE_ONLY (0x02)=0A= /* NT Create CreateAction return values */=0A= #define FILE_SUPERSEDED (0)=0A= #define FILE_OPENED (1)=0A= #define FILE_CREATED (2)=0A= #define FILE_OVERWRITTEN (3)=0A= #define FILE_EXISTS (4)=0A= #define FILE_DOES_NOT_EXIST (5)=0A= =0A= #define STATUS_OBJECT_NAME_NOT_FOUND 0xC0000034=0A= #define STATUS_OBJECT_PATH_SYNTAX_BAD 0xC000003B=0A= =0A= #define _ACCESS (GENERIC_READ | GENERIC_WRITE)=0A= =0A= int main()=0A= {=0A= UNICODE_STRING dev;=0A= WCHAR devname[MAX_PATH + 1];=0A= OBJECT_ATTRIBUTES attr;=0A= HANDLE h;=0A= HANDLE hd;=0A= IO_STATUS_BLOCK io;=0A= NTSTATUS status;=0A= =0A= /*=0A= * Create /cygdrive/c/makefile=0A= */=0A= str2buf2uni (&dev, devname, "\\??\\C:\\makefile");=0A= InitializeObjectAttributes (&attr, &dev, _CASE_SENSITIVE, NULL, = NULL);=0A= =0A= status =3D ZwCreateFile (&h, _ACCESS, &attr, &io, NULL, = FILE_ATTRIBUTE_NORMAL,=0A= _SHARED, FILE_OPEN_IF, = FILE_NON_DIRECTORY_FILE,=0A= NULL, 0);=0A= =0A= if (!NT_SUCCESS (status))=0A= {=0A= printf("ERROR: %08lx (%08lx, %08lx)\n",=0A= status, io.Status, io.Information);=0A= return 1;=0A= }=0A= =0A= if (!h)=0A= {=0A= printf("ERROR: no handle\n");=0A= return 1;=0A= }=0A= =0A= status =3D ZwClose (h);=0A= =0A= if (!NT_SUCCESS (status))=0A= {=0A= printf("ERROR: %08lx\n", status);=0A= return 1;=0A= }=0A= =0A= /*=0A= * Create /cygdrive/c/Makefile=0A= */=0A= str2buf2uni (&dev, devname, "\\??\\C:\\Makefile");=0A= InitializeObjectAttributes (&attr, &dev, _CASE_SENSITIVE, NULL, = NULL);=0A= =0A= status =3D ZwCreateFile (&h, _ACCESS, &attr, &io, NULL, = FILE_ATTRIBUTE_NORMAL,=0A= _SHARED, FILE_OPEN_IF, = FILE_NON_DIRECTORY_FILE,=0A= NULL, 0);=0A= =0A= if (!NT_SUCCESS (status))=0A= {=0A= printf("ERROR: %08lx (%08lx, %08lx)\n",=0A= status, io.Status, io.Information);=0A= return 1;=0A= }=0A= =0A= if (!h)=0A= {=0A= printf("ERROR: no handle\n");=0A= return 1;=0A= }=0A= =0A= status =3D ZwClose (h);=0A= =0A= if (!NT_SUCCESS (status))=0A= {=0A= printf("ERROR: %08lx\n", status);=0A= return 1;=0A= }=0A= =0A= return 0;=0A= }=0A= ------=_NextPart_000_0028_01C2BE4A.CDA44F30--