Re: [Patch] unlink

2004-10-31 Thread Pierre A. Humblet
At 06:47 PM 10/31/2004 -0500, you wrote:
>On Sun, Oct 31, 2004 at 10:14:48AM -0500, Pierre A. Humblet wrote:
>>At 11:36 PM 10/30/2004 -0400, Christopher Faylor wrote:
>>>On Sat, Oct 30, 2004 at 10:30:54PM -0400, Pierre A. Humblet wrote:
At 01:39 PM 10/30/2004 -0400, you wrote:
>On Fri, Oct 29, 2004 at 06:01:51PM -0400, Pierre A. Humblet wrote:
>>Here is a patch that should allow unlink() to handle
>>nul etc.. on local disks.
>>
>>It's a cut and paste of Corinna's open on NT and the
>>existing CreateFile.
>> 
>>It works on normal files. I haven't tested with the
>>special names because I forgot how to create them !
>>Feedback welcome.
>>
>>X This should NOT be applied in 1.5.12 XX
>>
>>Pierre
>>
>>2004-10-29  Pierre Humblet <[EMAIL PROTECTED]>
>>
>>  * syscalls.cc (nt_delete): New function.
>>  (unlink): Call nt_delete instead of CreateFile and remove
>>  unreachable code.
>
>Corinna suggested something similar to me a couple of months ago but I
>wanted to wait for things to settle down somewhat after the original
>use of NtCreateFile.
>
>On reflection, however, wouldn't it be a little easier just to prepend
>the path being deleted with a: \\.\ so that "rm nul" would eventually
>translate to DeleteFile("\\.\c:\foo\null") (I'm not using true C
>backslash quoting here)?  I don't know if that would work on Windows 9x,
>though.

That would work on NT, but then one would need to check if the input
path didn't already have the form //./xx, worry about exceeding max 
pathlength, etc...
>>>
>>>Other than being able to delete special filenames is there any other
>>>benefit to using NtCreateFile to delete files?
>>
>>I can only think of speed. But I don't see a downside either, given that
>>we use it in open().
>>
>>>If path length was an issue we could use '//?/' instead since the length
>>>restriction is a lot larger there.  So, it would be something like:
>>>
>>>  char *path;
>>>  char newpath[strlen (win32_name) + 4] = "?\";
>>>  if  (win32_name[0] != '\\')
>>>  path = strcat (newpath, win32_name);
>>>  else
>>>  path = win32_name;
>>>
>>>and then you'd use path throughout from then on.
>>
>>Have you tried it? According to MSDN you need to use the Unicode version
>>if you do that.
>
>Yes.  I created and deleted a file using '//?/d:/nul' from the command line.

It's interesting that //?/ also works as an escape with the ascii version.
But on re-reading MSDN, the unicode version should only be needed when
the pathlength exceeds 260 chars.
BTW, don't try that on WinME. I ended up having to power the PC down.

Pierre



Re: [Patch] unlink

2004-10-31 Thread Christopher Faylor
On Sun, Oct 31, 2004 at 10:14:48AM -0500, Pierre A. Humblet wrote:
>At 11:36 PM 10/30/2004 -0400, Christopher Faylor wrote:
>>On Sat, Oct 30, 2004 at 10:30:54PM -0400, Pierre A. Humblet wrote:
>>>At 01:39 PM 10/30/2004 -0400, you wrote:
On Fri, Oct 29, 2004 at 06:01:51PM -0400, Pierre A. Humblet wrote:
>Here is a patch that should allow unlink() to handle
>nul etc.. on local disks.
>
>It's a cut and paste of Corinna's open on NT and the
>existing CreateFile.
> 
>It works on normal files. I haven't tested with the
>special names because I forgot how to create them !
>Feedback welcome.
>
>X This should NOT be applied in 1.5.12 XX
>
>Pierre
>
>2004-10-29  Pierre Humblet <[EMAIL PROTECTED]>
>
>   * syscalls.cc (nt_delete): New function.
>   (unlink): Call nt_delete instead of CreateFile and remove
>   unreachable code.

Corinna suggested something similar to me a couple of months ago but I
wanted to wait for things to settle down somewhat after the original
use of NtCreateFile.

On reflection, however, wouldn't it be a little easier just to prepend
the path being deleted with a: \\.\ so that "rm nul" would eventually
translate to DeleteFile("\\.\c:\foo\null") (I'm not using true C
backslash quoting here)?  I don't know if that would work on Windows 9x,
though.
>>>
>>>That would work on NT, but then one would need to check if the input
>>>path didn't already have the form //./xx, worry about exceeding max 
>>>pathlength, etc...
>>
>>Other than being able to delete special filenames is there any other
>>benefit to using NtCreateFile to delete files?
>
>I can only think of speed. But I don't see a downside either, given that
>we use it in open().
>
>>If path length was an issue we could use '//?/' instead since the length
>>restriction is a lot larger there.  So, it would be something like:
>>
>>  char *path;
>>  char newpath[strlen (win32_name) + 4] = "?\";
>>  if  (win32_name[0] != '\\')
>>  path = strcat (newpath, win32_name);
>>  else
>>  path = win32_name;
>>
>>and then you'd use path throughout from then on.
>
>Have you tried it? According to MSDN you need to use the Unicode version
>if you do that.

Yes.  I created and deleted a file using '//?/d:/nul' from the command line.

cgf


Re: [Patch] unlink

2004-10-31 Thread Pierre A. Humblet
At 11:36 PM 10/30/2004 -0400, Christopher Faylor wrote:
>On Sat, Oct 30, 2004 at 10:30:54PM -0400, Pierre A. Humblet wrote:
>>At 01:39 PM 10/30/2004 -0400, you wrote:
>>>On Fri, Oct 29, 2004 at 06:01:51PM -0400, Pierre A. Humblet wrote:
Here is a patch that should allow unlink() to handle
nul etc.. on local disks.

It's a cut and paste of Corinna's open on NT and the
existing CreateFile.
 
It works on normal files. I haven't tested with the
special names because I forgot how to create them !
Feedback welcome.

X This should NOT be applied in 1.5.12 XX

Pierre

2004-10-29  Pierre Humblet <[EMAIL PROTECTED]>

* syscalls.cc (nt_delete): New function.
(unlink): Call nt_delete instead of CreateFile and remove
unreachable code.
>>>
>>>Corinna suggested something similar to me a couple of months ago but I
>>>wanted to wait for things to settle down somewhat after the original
>>>use of NtCreateFile.
>>>
>>>On reflection, however, wouldn't it be a little easier just to prepend
>>>the path being deleted with a: \\.\ so that "rm nul" would eventually
>>>translate to DeleteFile("\\.\c:\foo\null") (I'm not using true C
>>>backslash quoting here)?  I don't know if that would work on Windows 9x,
>>>though.
>>
>>That would work on NT, but then one would need to check if the input
>>path didn't already have the form //./xx, worry about exceeding max 
>>pathlength, etc...
>
>Other than being able to delete special filenames is there any other
>benefit to using NtCreateFile to delete files?

I can only think of speed. But I don't see a downside either, given that
we use it in open().

>If path length was an issue we could use '//?/' instead since the length
>restriction is a lot larger there.  So, it would be something like:
>
>  char *path;
>  char newpath[strlen (win32_name) + 4] = "?\";
>  if  (win32_name[0] != '\\')
>  path = strcat (newpath, win32_name);
>  else
>  path = win32_name;
>
>and then you'd use path throughout from then on.

Have you tried it? According to MSDN you need to use the Unicode version
if you do that.

"In the ANSI version of this function, the name is limited to MAX_PATH 
characters. To extend this limit to 32,767 wide characters, call the Unicode 
version of the function and prepend "\\?\" to the path"

Pierre



Re: [Patch] unlink

2004-10-31 Thread Reini Urban
Pierre A. Humblet schrieb:
It works on normal files. I haven't tested with the
special names because I forgot how to create them !
Feedback welcome.
works fine on w2k.
attached is a test to create such files.
unlink works fine on these.
didn't test with wchar and unicode files yet, just char.
but coreutils/findutils don't work with unicode files anyway.
(just testing findutils-4.1.20)
On reflection, however, wouldn't it be a little easier just to prepend
the path being deleted with a: \\.\ so that "rm nul" would eventually
translate to DeleteFile("\\.\c:\foo\null") (I'm not using true C
backslash quoting here)?  I don't know if that would work on Windows 9x,
though.
// c++ -I../src/winsup/cygwin -o testcreate testcreate.cc -lntdll 
#include "winsup.h"
#include 
#include 
#include "ntdll.h"

//#define NTCREATE
#undef NTCREATE

NTSTATUS 
  NtCreateDirectoryObject(
OUT PHANDLE  DirectoryHandle,
IN ACCESS_MASK  DesiredAccess,
IN POBJECT_ATTRIBUTES  ObjectAttributes
);

#ifndef NTCREATE
static HANDLE
create (char *path)
{
  HANDLE hFile; 
  char pwd[CYG_MAX_PATH], dev[CYG_MAX_PATH];
  int len;

  //create (".\\c:\\con");
  if (len = GetCurrentDirectoryA (CYG_MAX_PATH, pwd)) {
strcpy(dev, ".\\");
strcat(dev, pwd);
strcat(dev, "\\");
strcat(dev, path);
  }
  hFile = CreateFile(dev, // file to create
 GENERIC_WRITE,  // open for writing
 0,  // do not share
 NULL,   // default security
 CREATE_ALWAYS,  // overwrite existing
 FILE_ATTRIBUTE_NORMAL | // normal file
 FILE_FLAG_OVERLAPPED,   // asynchronous I/O
 NULL);  // no attr. template
  if (hFile == INVALID_HANDLE_VALUE) return 0;
  printf("%s created\n", path);
  CloseHandle(hFile);
  return hFile;
}

#else
static HANDLE
nt_create (WCHAR *wpath)
{
  WCHAR pwd[2*CYG_MAX_PATH];
  UNICODE_STRING upath = {0, sizeof (wpath), wpath};
  //UNICODE_STRING cpath = {0, 2, L"."};

  int len;
  HANDLE x, root = NULL;
  OBJECT_ATTRIBUTES attr;
  IO_STATUS_BLOCK io;
  NTSTATUS status;
  
  if (len = GetCurrentDirectoryW (2*CYG_MAX_PATH, pwd)) {
UNICODE_STRING upwd = {0, sizeof (pwd), pwd};
InitializeObjectAttributes (&attr, &upwd, OBJ_CASE_INSENSITIVE, NULL, NULL);
NtOpenFile(&root, STANDARD_RIGHTS_ALL, &attr, &io, 0, 0);
  }
  InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, root, NULL);
  // 
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devnotes/winprog/ntcreatefile.asp
  status = NtCreateFile (&x, STANDARD_RIGHTS_ALL, &attr, &io, NULL, 
FILE_ATTRIBUTE_NORMAL, 
 FILE_SHARE_READ, FILE_OPEN, FILE_DELETE_ON_CLOSE, NULL, 0);
  if (!NT_SUCCESS (status))
{
  printf("error creating %ls\n", wpath);
  return 0;
}
  else {
CloseHandle(x);
return x;
  }
}
#endif

int main(int argc, char** argv)
{
#ifndef NTCREATE
  create ("con");
  create ("com");
  create ("nul");
  create ("aux");
  create ("prn");
  create ("lpt1");
  create ("...");
#else
  nt_create (L"con");
  nt_create (L"nul");
  nt_create (L"aux");
  nt_create (L"prn");
  nt_create (L"lpt1");
  nt_create (L"...");
#endif
  return(0);
}


Re: [Patch] unlink

2004-10-30 Thread Christopher Faylor
On Sat, Oct 30, 2004 at 10:30:54PM -0400, Pierre A. Humblet wrote:
>At 01:39 PM 10/30/2004 -0400, you wrote:
>>On Fri, Oct 29, 2004 at 06:01:51PM -0400, Pierre A. Humblet wrote:
>>>Here is a patch that should allow unlink() to handle
>>>nul etc.. on local disks.
>>>
>>>It's a cut and paste of Corinna's open on NT and the
>>>existing CreateFile.
>>> 
>>>It works on normal files. I haven't tested with the
>>>special names because I forgot how to create them !
>>>Feedback welcome.
>>>
>>>X This should NOT be applied in 1.5.12 XX
>>>
>>>Pierre
>>>
>>>2004-10-29  Pierre Humblet <[EMAIL PROTECTED]>
>>>
>>> * syscalls.cc (nt_delete): New function.
>>> (unlink): Call nt_delete instead of CreateFile and remove
>>> unreachable code.
>>
>>Corinna suggested something similar to me a couple of months ago but I
>>wanted to wait for things to settle down somewhat after the original
>>use of NtCreateFile.
>>
>>On reflection, however, wouldn't it be a little easier just to prepend
>>the path being deleted with a: \\.\ so that "rm nul" would eventually
>>translate to DeleteFile("\\.\c:\foo\null") (I'm not using true C
>>backslash quoting here)?  I don't know if that would work on Windows 9x,
>>though.
>
>That would work on NT, but then one would need to check if the input
>path didn't already have the form //./xx, worry about exceeding max 
>pathlength, etc...

Other than being able to delete special filenames is there any other
benefit to using NtCreateFile to delete files?

If path length was an issue we could use '//?/' instead since the length
restriction is a lot larger there.  So, it would be something like:

  char *path;
  char newpath[strlen (win32_name) + 4] = "?\";
  if  (win32_name[0] != '\\')
  path = strcat (newpath, win32_name);
  else
  path = win32_name;

and then you'd use path throughout from then on.

We could use a technique like this for other things, like rename, to enable
it to manipulate accidentally-created special files.

OTOH, I just had an idea about how to use //?/ on NT so that we could
have longer path names.  I have to mull it over a little to see if it
would work or not, though.  I have an airplane trip tomorrow that would
be perfect for this kind of mulling.

cgf


Re: [Patch] unlink

2004-10-30 Thread Pierre A. Humblet
At 01:39 PM 10/30/2004 -0400, you wrote:
>On Fri, Oct 29, 2004 at 06:01:51PM -0400, Pierre A. Humblet wrote:
>>Here is a patch that should allow unlink() to handle
>>nul etc.. on local disks.
>>
>>It's a cut and paste of Corinna's open on NT and the
>>existing CreateFile.
>> 
>>It works on normal files. I haven't tested with the
>>special names because I forgot how to create them !
>>Feedback welcome.
>>
>>X This should NOT be applied in 1.5.12 XX
>>
>>Pierre
>>
>>2004-10-29  Pierre Humblet <[EMAIL PROTECTED]>
>>
>>  * syscalls.cc (nt_delete): New function.
>>  (unlink): Call nt_delete instead of CreateFile and remove
>>  unreachable code.
>
>Corinna suggested something similar to me a couple of months ago but I
>wanted to wait for things to settle down somewhat after the original
>use of NtCreateFile.
>
>On reflection, however, wouldn't it be a little easier just to prepend
>the path being deleted with a: \\.\ so that "rm nul" would eventually
>translate to DeleteFile("\\.\c:\foo\null") (I'm not using true C
>backslash quoting here)?  I don't know if that would work on Windows 9x,
>though.

That would work on NT, but then one would need to check if the input
path didn't already have the form //./xx, worry about exceeding max 
pathlength, etc... The patch cleanly handles all of that, is symmetrical
to file creation, and is very efficient. I cleaned it up a little and
tested readonly hard links and other weird cases.
It's good to go but I still wouldn't include it in 1.5.12 if it's
coming out this weekend.

Pierre

2004-10-31  Pierre Humblet <[EMAIL PROTECTED]>

* syscalls.cc (nt_delete): New function.
(unlink): Call nt_delete instead of CreateFile and remove
unreachable code.

Index: syscalls.cc
===
RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v
retrieving revision 1.349
diff -u -p -b -r1.349 syscalls.cc
--- syscalls.cc 28 Oct 2004 01:46:01 -  1.349
+++ syscalls.cc 31 Oct 2004 02:10:49 -
@@ -39,6 +39,8 @@ details. */
 #include 
 #include  /* for UNLEN */
 #include 
+#include 
+#include "ntdll.h"

 #undef fstat
 #undef lstat
@@ -127,6 +129,30 @@ dup2 (int oldfd, int newfd)
   return cygheap->fdtab.dup2 (oldfd, newfd);
 }

+static HANDLE
+nt_delete (path_conv & pc)
+{
+  WCHAR wpath[CYG_MAX_PATH + 10];
+  UNICODE_STRING upath = {0, sizeof (wpath), wpath};
+  pc.get_nt_native_path (upath);
+
+  HANDLE x;
+  OBJECT_ATTRIBUTES attr;
+  IO_STATUS_BLOCK io;
+  NTSTATUS status;
+
+  InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
+  status = NtCreateFile (&x, DELETE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ, FILE_OPEN, FILE_DELETE_ON_CLOSE, NULL, 0);
+  if (!NT_SUCCESS (status))
+{
+  __seterrno_from_win_error (RtlNtStatusToDosError (status));
+  return INVALID_HANDLE_VALUE;
+}
+  else
+return x;
+}
+
 extern "C" int
 unlink (const char *ourname)
 {
@@ -192,30 +218,17 @@ unlink (const char *ourname)
  Microsoft KB 837665 describes this problem as a bug in 2K3, but I have
  reproduced it on shares on Samba 2.2.8, Samba 3.0.2, NT4SP6, XP64SP1 and
  2K3 and in all cases, DeleteFile works, "delete on close" does not. */
-  if (!win32_name.isremote () && wincap.has_delete_on_close ())
+  if (!win32_name.isremote () && wincap.is_winnt ())
 {
-  HANDLE h;
-  h = CreateFile (win32_name, 0, FILE_SHARE_READ, &sec_none_nih,
- OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
+  HANDLE h = nt_delete (win32_name);
   if (h != INVALID_HANDLE_VALUE)
{
- if (wincap.has_hard_links () && setattrs)
+ if (setattrs && wincap.has_hard_links ())
(void) SetFileAttributes (win32_name, (DWORD) win32_name);
  BOOL res = CloseHandle (h);
- syscall_printf ("%d = CloseHandle (%p)", res, h);
- if (GetFileAttributes (win32_name) == INVALID_FILE_ATTRIBUTES
- || !win32_name.isremote ())
-   {
- syscall_printf ("CreateFile (FILE_FLAG_DELETE_ON_CLOSE) succeeded");
+ syscall_printf ("%p = nt_delete (). %d = CloseHandle ()", h, res);
  goto ok;
}
- else
-   {
- syscall_printf ("CreateFile (FILE_FLAG_DELETE_ON_CLOSE) failed");
- if (setattrs)
-   SetFileAttributes (win32_name, (DWORD) win32_name & 
~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM));
-   }
-   }
 }

   /* Try a delete with attributes reset */


Re: [Patch] unlink

2004-10-30 Thread Christopher Faylor
On Fri, Oct 29, 2004 at 06:01:51PM -0400, Pierre A. Humblet wrote:
>Here is a patch that should allow unlink() to handle
>nul etc.. on local disks.
>
>It's a cut and paste of Corinna's open on NT and the
>existing CreateFile.
> 
>It works on normal files. I haven't tested with the
>special names because I forgot how to create them !
>Feedback welcome.
>
>X This should NOT be applied in 1.5.12 XX
>
>Pierre
>
>2004-10-29  Pierre Humblet <[EMAIL PROTECTED]>
>
>   * syscalls.cc (nt_delete): New function.
>   (unlink): Call nt_delete instead of CreateFile and remove
>   unreachable code.

Corinna suggested something similar to me a couple of months ago but I
wanted to wait for things to settle down somewhat after the original
use of NtCreateFile.

On reflection, however, wouldn't it be a little easier just to prepend
the path being deleted with a: \\.\ so that "rm nul" would eventually
translate to DeleteFile("\\.\c:\foo\null") (I'm not using true C
backslash quoting here)?  I don't know if that would work on Windows 9x,
though.

cgf


[Patch] unlink

2004-10-29 Thread Pierre A. Humblet
Here is a patch that should allow unlink() to handle
nul etc.. on local disks.

It's a cut and paste of Corinna's open on NT and the
existing CreateFile.
 
It works on normal files. I haven't tested with the
special names because I forgot how to create them !
Feedback welcome.

X This should NOT be applied in 1.5.12 XX

Pierre

2004-10-29  Pierre Humblet <[EMAIL PROTECTED]>

* syscalls.cc (nt_delete): New function.
(unlink): Call nt_delete instead of CreateFile and remove
unreachable code.Index: syscalls.cc
===
RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v
retrieving revision 1.349
diff -u -p -r1.349 syscalls.cc
--- syscalls.cc 28 Oct 2004 01:46:01 -  1.349
+++ syscalls.cc 29 Oct 2004 21:27:04 -
@@ -39,6 +39,8 @@ details. */
 #include 
 #include  /* for UNLEN */
 #include 
+#include 
+#include "ntdll.h"
 
 #undef fstat
 #undef lstat
@@ -127,6 +129,32 @@ dup2 (int oldfd, int newfd)
   return cygheap->fdtab.dup2 (oldfd, newfd);
 }
 
+static HANDLE
+nt_delete (path_conv & pc)
+{
+  WCHAR wpath[CYG_MAX_PATH + 10];
+  UNICODE_STRING upath = {0, sizeof (wpath), wpath};
+  pc.get_nt_native_path (upath);
+
+  HANDLE x;
+  OBJECT_ATTRIBUTES attr;
+  IO_STATUS_BLOCK io;
+  NTSTATUS status;
+
+  InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
+ NULL, NULL);
+   
+  status = NtCreateFile (&x, DELETE, &attr, &io, NULL, FILE_ATTRIBUTE_NORMAL, 
+ FILE_SHARE_READ, FILE_OPEN, FILE_DELETE_ON_CLOSE, NULL, 0);
+  if (!NT_SUCCESS (status))
+{
+  __seterrno_from_win_error (RtlNtStatusToDosError (status));
+  return INVALID_HANDLE_VALUE;
+}
+  else
+return x;
+}
+
 extern "C" int
 unlink (const char *ourname)
 {
@@ -192,29 +220,17 @@ unlink (const char *ourname)
  Microsoft KB 837665 describes this problem as a bug in 2K3, but I have
  reproduced it on shares on Samba 2.2.8, Samba 3.0.2, NT4SP6, XP64SP1 and
  2K3 and in all cases, DeleteFile works, "delete on close" does not. */
-  if (!win32_name.isremote () && wincap.has_delete_on_close ())
+  if (!win32_name.isremote () && wincap.is_winnt ())
 {
-  HANDLE h;
-  h = CreateFile (win32_name, 0, FILE_SHARE_READ, &sec_none_nih,
- OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
+  HANDLE h = nt_delete (win32_name);
   if (h != INVALID_HANDLE_VALUE)
{
  if (wincap.has_hard_links () && setattrs)
(void) SetFileAttributes (win32_name, (DWORD) win32_name);
  BOOL res = CloseHandle (h);
  syscall_printf ("%d = CloseHandle (%p)", res, h);
- if (GetFileAttributes (win32_name) == INVALID_FILE_ATTRIBUTES
- || !win32_name.isremote ())
-   {
- syscall_printf ("CreateFile (FILE_FLAG_DELETE_ON_CLOSE) succeeded");
- goto ok;
-   }
- else
-   {
- syscall_printf ("CreateFile (FILE_FLAG_DELETE_ON_CLOSE) failed");
- if (setattrs)
-   SetFileAttributes (win32_name, (DWORD) win32_name & 
~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM));
-   }
+ syscall_printf ("nt_delete () succeeded");
+ goto ok;
}
 }