Subject: Faster ls -l
From: Dan Holmsand <[email-masked]>
To: [email-masked]
Date: Sun, 26 May 2002 20:41:39 +0200
Newsgroups: gmane.os.cygwin

I've been playing with a modification to Cygwin that makes it treat 
every file that has a "system" attribute as executable.

This has two advantages:

a) ls -l, du, etc. becomes a lot faster, without having to use mount -x, 
since cygwin doesn't have to open every file to determine whether it's 
executable or not. Especially on a network share.

b) Cygwin becomes a little bit more unix-like, for those of us using FAT 
or FAT32 and thus unable to use ntsec.

I've been using this patch for quite some time now, without any bad 
sideeffects (except that you have to chmod +x some scripts, or course).

Use it like this: apply the patch, compile cygwin, set your CYGWIN 
environment variable to include "sysexec" (without that, you get plain 
vanilla cygwin behaviour), use the new dll, and do a "chmod +x" on the 
shell scripts in your path.

However, I'm giving up hope to get the time to become sufficiently 
knowledgeable in cygwin to be able to say that my modifications doesn't 
break anything on other configurations (e.g. together with ntea/ntsec), 
or that doesn't have any other bad side effects.

So if someone wants to try it out, and perhaps create a more formal 
patch based on this: be my guest. Otherwise, mv this to /dev/null...

/dan
--
Dan Holmsand
Index: src/winsup/cygwin/environ.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/environ.cc,v
retrieving revision 1.64
diff -u -r1.64 environ.cc
--- src/winsup/cygwin/environ.cc	25 May 2002 02:22:50 -0000	1.64
+++ src/winsup/cygwin/environ.cc	25 May 2002 19:37:34 -0000
@@ -518,6 +518,7 @@
   {"glob", {func: &glob_init}, isfunc, NULL, {{0}, {s: "normal"}}},
   {"ntea", {&allow_ntea}, justset, NULL, {{FALSE}, {TRUE}}},
   {"ntsec", {&allow_ntsec}, justset, NULL, {{FALSE}, {TRUE}}},
+  {"sysexec", {&allow_sysexec}, justset, NULL, {{FALSE}, {TRUE}}},
   {"smbntsec", {&allow_smbntsec}, justset, NULL, {{FALSE}, {TRUE}}},
   {"reset_com", {&reset_com}, justset, NULL, {{FALSE}, {TRUE}}},
   {"strip_title", {&strip_title_path}, justset, NULL, {{FALSE}, {TRUE}}},
Index: src/winsup/cygwin/fhandler.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler.cc,v
retrieving revision 1.117
diff -u -r1.117 fhandler.cc
--- src/winsup/cygwin/fhandler.cc	24 May 2002 05:44:10 -0000	1.117
+++ src/winsup/cygwin/fhandler.cc	25 May 2002 19:37:35 -0000
@@ -370,6 +370,14 @@
   if (get_device () == FH_SERIAL)
     file_attributes |= FILE_FLAG_OVERLAPPED;
 
+  /* set system attribute if any exec bits are set. perhaps this
+     should be done even if allow_sysexec is false? */
+  if (allow_sysexec) 
+    {
+      if (mode & (S_IXUSR | S_IXGRP | S_IXOTH))
+        file_attributes |= FILE_ATTRIBUTE_SYSTEM;
+    }
+
 #ifdef HIDDEN_DOT_FILES
   if (flags & O_CREAT && get_device () == FH_DISK)
     {
@@ -400,8 +408,20 @@
   if (flags & O_CREAT && get_device () == FH_DISK && allow_ntsec && has_acls ())
     set_security_attribute (mode, &sa, alloca (4096), 4096);
 
-  x = CreateFile (get_win32_name (), access, shared, &sa, creation_distribution,
-		  file_attributes, 0);
+  x = INVALID_HANDLE_VALUE;
+  if (creation_distribution == CREATE_ALWAYS)
+    /* Try to open file without CREATE_ALWAYS, to be able to write to
+       hidden and system files. */
+    x = CreateFileA (get_win32_name (), access, shared,
+                     &sa, TRUNCATE_EXISTING,
+                     file_attributes,
+                     0);
+      
+  if (x == INVALID_HANDLE_VALUE)
+    x = CreateFileA (get_win32_name (), access, shared,
+                     &sa, creation_distribution,
+                     file_attributes,
+                     0);
 
   syscall_printf ("%p = CreateFileA (%s, %p, %p, %p, %p, %p, 0)",
 		  x, get_win32_name (), access, shared, &sa,
Index: src/winsup/cygwin/fhandler_disk_file.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/fhandler_disk_file.cc,v
retrieving revision 1.11
diff -u -r1.11 fhandler_disk_file.cc
--- src/winsup/cygwin/fhandler_disk_file.cc	24 May 2002 05:44:10 -0000	1.11
+++ src/winsup/cygwin/fhandler_disk_file.cc	25 May 2002 19:37:36 -0000
@@ -304,7 +304,7 @@
 	    break;
 	  case FILE_TYPE_DISK:
 	    buf->st_mode |= S_IFREG;
-	    if (!dont_care_if_execable () && !get_execable_p ())
+	    if (!allow_sysexec && !dont_care_if_execable () && !get_execable_p ())
 	      {
 		DWORD cur, done;
 		char magic[3];
Index: src/winsup/cygwin/path.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/path.cc,v
retrieving revision 1.211
diff -u -r1.211 path.cc
--- src/winsup/cygwin/path.cc	25 May 2002 02:22:50 -0000	1.211
+++ src/winsup/cygwin/path.cc	25 May 2002 19:37:38 -0000
@@ -2799,7 +2799,7 @@
       /* Not a symlink, see if executable.  */
       if (*pflags & PATH_ALL_EXEC)
 	/* Nothing to do */;
-      else if (has_exec_chars (cookie_buf, got))
+      else if (allow_sysexec || has_exec_chars (cookie_buf, got))
 	*pflags |= PATH_EXEC;
       else
 	*pflags |= PATH_NOTEXEC;
Index: src/winsup/cygwin/spawn.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/spawn.cc,v
retrieving revision 1.101
diff -u -r1.101 spawn.cc
--- src/winsup/cygwin/spawn.cc	25 May 2002 02:22:50 -0000	1.101
+++ src/winsup/cygwin/spawn.cc	25 May 2002 19:37:39 -0000
@@ -420,13 +420,24 @@
      that it is NOT a script file */
   while (*ext == '\0')
     {
-      HANDLE hnd = CreateFileA (real_path,
-				GENERIC_READ,
-				FILE_SHARE_READ | FILE_SHARE_WRITE,
-				&sec_none_nih,
-				OPEN_EXISTING,
-				FILE_ATTRIBUTE_NORMAL,
-				0);
+      HANDLE hnd;
+
+      if (allow_sysexec) 
+        {
+          if (real_path.exec_state() != is_executable) 
+            {
+              set_errno (EACCES);
+              return -1;
+            }
+        }
+          
+      hnd = CreateFileA (real_path,
+			GENERIC_READ,
+			FILE_SHARE_READ | FILE_SHARE_WRITE,
+			&sec_none_nih,
+			OPEN_EXISTING,
+			FILE_ATTRIBUTE_NORMAL,
+			0);
       if (hnd == INVALID_HANDLE_VALUE)
 	{
 	  __seterrno ();
Index: src/winsup/cygwin/syscalls.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/syscalls.cc,v
retrieving revision 1.190
diff -u -r1.190 syscalls.cc
--- src/winsup/cygwin/syscalls.cc	25 May 2002 02:22:50 -0000	1.190
+++ src/winsup/cygwin/syscalls.cc	25 May 2002 19:37:40 -0000
@@ -40,6 +40,8 @@
 
 SYSTEM_INFO system_info;
 
+BOOL allow_sysexec = FALSE;
+
 /* Close all files and process any queued deletions.
    Lots of unix style applications will open a tmp file, unlink it,
    but never call close.  This function is called by _exit to
@@ -916,6 +918,16 @@
 	(DWORD) win32_path &= ~FILE_ATTRIBUTE_READONLY;
       else
 	(DWORD) win32_path |= FILE_ATTRIBUTE_READONLY;
+
+      /* set system attribute if any exec bits are set. perhaps this
+         should be done even if allow_sysexec is false? */
+      if (allow_sysexec) 
+	{
+	  if (mode & (S_IXUSR | S_IXGRP | S_IXOTH))
+	    (DWORD) win32_path |= FILE_ATTRIBUTE_SYSTEM;
+	  else
+	    (DWORD) win32_path &= ~FILE_ATTRIBUTE_SYSTEM;
+	}
 
       if (S_ISLNK (mode) || S_ISSOCK (mode))
 	(DWORD) win32_path |= FILE_ATTRIBUTE_SYSTEM;
Index: src/winsup/cygwin/winsup.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/winsup.h,v
retrieving revision 1.89
diff -u -r1.89 winsup.h
--- src/winsup/cygwin/winsup.h	2 May 2002 04:13:48 -0000	1.89
+++ src/winsup/cygwin/winsup.h	25 May 2002 19:37:41 -0000
@@ -183,6 +183,7 @@
 int __stdcall writable_directory (const char *file);
 int __stdcall stat_dev (DWORD, int, unsigned long, struct __stat64 *);
 extern BOOL allow_ntsec;
+extern BOOL allow_sysexec;
 
 unsigned long __stdcall hash_path_name (unsigned long hash, const char *name) __attribute__ ((regparm(2)));
 void __stdcall nofinalslash (const char *src, char *dst) __attribute__ ((regparm(2)));

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/