OSDN Git Service

* dir.cc (readdir): Fix shortcut==symlink condition.
authorcorinna <corinna>
Fri, 2 Mar 2001 11:41:09 +0000 (11:41 +0000)
committercorinna <corinna>
Fri, 2 Mar 2001 11:41:09 +0000 (11:41 +0000)
        * environ.cc: Add extern decl for `allow_winsymlinks'.
        (struct parse_thing): Add entry for `[no]winsymlinks'.
        * path.cc (symlink): Change to be able to create both,
        symlink==shortcut and symlink==systemfile, dependent of
        the setting of `allow_winsymlinks'.
        * security.cc (cygwin_logon_user): Add debug output.
        * shortcut.c: Add defines from path.h.
        (has_exec_chars): Copy from path.h.
        (check_shortcut): Check for executable file condition if not a
        shortcut.

winsup/cygwin/ChangeLog
winsup/cygwin/dir.cc
winsup/cygwin/environ.cc
winsup/cygwin/path.cc
winsup/cygwin/security.cc
winsup/cygwin/shortcut.c

index eb57313..111e0ce 100644 (file)
@@ -1,3 +1,17 @@
+Fri Mar  2 12:33:00 2001  Corinna Vinschen <corinna@vinschen.de>
+
+       * dir.cc (readdir): Fix shortcut==symlink condition.
+       * environ.cc: Add extern decl for `allow_winsymlinks'.
+       (struct parse_thing): Add entry for `[no]winsymlinks'.
+       * path.cc (symlink): Change to be able to create both,
+       symlink==shortcut and symlink==systemfile, dependent of
+       the setting of `allow_winsymlinks'.
+       * security.cc (cygwin_logon_user): Add debug output.
+       * shortcut.c: Add defines from path.h.
+       (has_exec_chars): Copy from path.h.
+       (check_shortcut): Check for executable file condition if not a
+       shortcut.
+
 Thu Mar  1 21:06:07 2001  Christopher Faylor <cgf@cygnus.com>
 
        * exceptions.cc (sig_handle_tty_stop): Ignore attempts to suspend a
index c88fbfc..29d8084 100644 (file)
@@ -174,12 +174,21 @@ readdir (DIR * dir)
   /* We get here if `buf' contains valid data.  */
   strcpy (dir->__d_dirent->d_name, buf.cFileName);
 
+  /* Check for Windows shortcut. If it's a Cygwin or U/WIN
+     symlink, drop the .lnk suffix. */
   if (buf.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
     {
       char *c = dir->__d_dirent->d_name;
       int len = strlen (c);
       if (!strcasecmp (c + len - 4, ".lnk"))
-        c[len - 4] = '\0';
+        {
+         char fbuf[MAX_PATH + 1];
+         strcpy (fbuf, dir->__d_dirname);
+         strcat (fbuf + strlen (fbuf) - 1, dir->__d_dirent->d_name);
+         path_conv fpath (fbuf, PC_SYM_NOFOLLOW);
+         if (fpath.issymlink ())
+            c[len - 4] = '\0';
+        }
     }
 
   /* Compute d_ino by combining filename hash with the directory hash
index 1e160b5..df4c60f 100644 (file)
@@ -30,6 +30,7 @@ extern BOOL allow_glob;
 extern BOOL ignore_case_with_glob;
 extern BOOL allow_ntea;
 extern BOOL allow_smbntsec;
+extern BOOL allow_winsymlinks;
 extern BOOL strip_title_path;
 extern DWORD chunksize;
 BOOL reset_com = TRUE;
@@ -454,6 +455,7 @@ struct parse_thing
   {"strip_title", {&strip_title_path}, justset, NULL, {{FALSE}, {TRUE}}},
   {"title", {&display_title}, justset, NULL, {{FALSE}, {TRUE}}},
   {"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},
+  {"winsymlinks", {&allow_winsymlinks}, justset, NULL, {{FALSE}, {TRUE}}},
   {NULL, {0}, justset, 0, {{0}, {0}}}
 };
 
index 681664d..5355f19 100644 (file)
@@ -2192,24 +2192,30 @@ endmntent (FILE *)
 
 /* Create a symlink from FROMPATH to TOPATH. */
 
+/* If TRUE create symlinks as Windows shortcuts, if FALSE create symlinks
+   as normal files with magic number and system bit set. */
+int allow_winsymlinks = TRUE;
+
 extern "C"
 int
 symlink (const char *topath, const char *frompath)
 {
   HANDLE h;
   int res = -1;
-
-#if 0
-  path_conv win32_path (frompath, PC_SYM_NOFOLLOW);
-#else
+  path_conv win32_path, win32_topath;
   char from[MAX_PATH + 5];
-  strcpy (from, frompath);
-  strcat (from, ".lnk");
-  path_conv win32_path (from, PC_SYM_NOFOLLOW);
-  path_conv win32_topath;
   char cwd[MAX_PATH + 1], *cp = NULL, c = 0;
   char w32topath[MAX_PATH + 1];
-#endif
+  DWORD written;
+
+  if (allow_winsymlinks)
+    {
+      strcpy (from, frompath);
+      strcat (from, ".lnk");
+      win32_path.check (from, PC_SYM_NOFOLLOW);
+    }
+  else
+    win32_path.check (frompath, PC_SYM_NOFOLLOW);
 
   if (win32_path.error)
     {
@@ -2237,86 +2243,83 @@ symlink (const char *topath, const char *frompath)
       goto done;
     }
 
-#if 0
+  if (allow_winsymlinks)
+    {
+      if (!isabspath (topath))
+       {
+         getcwd (cwd, MAX_PATH + 1);
+         if ((cp = strrchr (from, '/')) || (cp = strrchr (from, '\\')))
+           {
+             c = *cp;
+             *cp = '\0';
+             chdir (from);
+           }
+         backslashify (topath, w32topath, 0);
+       }
+      if (!cp || GetFileAttributes (w32topath) == (DWORD)-1)
+       {
+         win32_topath.check (topath, PC_SYM_NOFOLLOW);
+         if (!cp || win32_topath.error != ENOENT)
+           strcpy (w32topath, win32_topath);
+       }
+      if (cp)
+       {
+         *cp = c;
+         chdir (cwd);
+       }
+    }
+
   h = CreateFileA(win32_path, GENERIC_WRITE, 0, &sec_none_nih,
                  CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
   if (h == INVALID_HANDLE_VALUE)
       __seterrno ();
   else
     {
-      DWORD written;
-      /* This is the old technique creating a symlink.
-         Preserved to have a fallback. */
-      char buf[sizeof (SYMLINK_COOKIE) + MAX_PATH + 10];
+      BOOL success;
+
+      if (allow_winsymlinks)
+       {
+         create_shortcut_header ();
+         /* Don't change the datatypes of `len' and `win_len' since
+            their sizeof is used when writing. */
+         unsigned short len = strlen (topath);
+         unsigned short win_len = strlen (w32topath);
+         success = WriteFile (h, shortcut_header, SHORTCUT_HDR_SIZE,
+                              &written, NULL)
+                   && written == SHORTCUT_HDR_SIZE
+                   && WriteFile (h, &len, sizeof len, &written, NULL)
+                   && written == sizeof len
+                   && WriteFile (h, topath, len, &written, NULL)
+                   && written == len
+                   && WriteFile (h, &win_len, sizeof win_len, &written, NULL)
+                   && written == sizeof win_len
+                   && WriteFile (h, w32topath, win_len, &written, NULL)
+                   && written == win_len;
+       }
+      else
+       {
+         /* This is the old technique creating a symlink. */
+         char buf[sizeof (SYMLINK_COOKIE) + MAX_PATH + 10];
 
-      __small_sprintf (buf, "%s%s", SYMLINK_COOKIE, topath);
-      DWORD len = strlen (buf) + 1;
+         __small_sprintf (buf, "%s%s", SYMLINK_COOKIE, topath);
+         DWORD len = strlen (buf) + 1;
 
-      /* Note that the terminating nul is written.  */
-      if (WriteFile (h, buf, len, &written, NULL) || written != len)
+         /* Note that the terminating nul is written.  */
+         success = WriteFile (h, buf, len, &written, NULL)
+                   || written != len;
+
+       }
+      if (success)
        {
          CloseHandle (h);
          set_file_attribute (win32_path.has_acls (),
                              win32_path.get_win32 (),
                              S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
-         SetFileAttributesA (win32_path.get_win32 (), FILE_ATTRIBUTE_SYSTEM);
+         SetFileAttributesA (win32_path.get_win32 (),
+                             allow_winsymlinks ? FILE_ATTRIBUTE_READONLY
+                                               : FILE_ATTRIBUTE_SYSTEM);
          res = 0;
        }
-#else
-  if (!isabspath (topath))
-    {
-      getcwd (cwd, MAX_PATH + 1);
-      if ((cp = strrchr (from, '/')) || (cp = strrchr (from, '\\')))
-       {
-         c = *cp;
-         *cp = '\0';
-         chdir (from);
-       }
-      backslashify (topath, w32topath, 0);
-    }
-  if (!cp || GetFileAttributes (w32topath) == (DWORD)-1)
-    {
-      win32_topath.check (topath, PC_SYM_NOFOLLOW);
-      if (!cp || win32_topath.error != ENOENT)
-        strcpy (w32topath, win32_topath);
-    }
-  if (cp)
-    {
-      *cp = c;
-      chdir (cwd);
-    }
-
-  h = CreateFileA(win32_path, GENERIC_WRITE, 0, &sec_none_nih,
-                 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
-  if (h == INVALID_HANDLE_VALUE)
-      __seterrno ();
-  else
-    {
-      DWORD written;
-      create_shortcut_header ();
-      /* Don't change the datatypes of `len' and `win_len' since
-         their sizeof is used later. */
-      unsigned short len = strlen (topath);
-      unsigned short win_len = strlen (w32topath);
-      if (WriteFile (h, shortcut_header, SHORTCUT_HDR_SIZE, &written, NULL)
-          && written == SHORTCUT_HDR_SIZE
-         && WriteFile (h, &len, sizeof len, &written, NULL)
-         && written == sizeof len
-         && WriteFile (h, topath, len, &written, NULL)
-         && written == len
-         && WriteFile (h, &win_len, sizeof win_len, &written, NULL)
-         && written == sizeof win_len
-         && WriteFile (h, w32topath, win_len, &written, NULL)
-         && written == win_len)
-        {
-          CloseHandle (h);
-          set_file_attribute (win32_path.has_acls (),
-                              win32_path.get_win32 (),
-                              S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
-          SetFileAttributesA (win32_path.get_win32 (), FILE_ATTRIBUTE_READONLY);
-          res = 0;
-       }
-#endif
       else
        {
          __seterrno ();
index 334c1af..bef29d2 100644 (file)
@@ -457,6 +457,7 @@ cygwin_logon_user (const struct passwd *pw, const char *password)
   HANDLE hToken;
 
   strcpy (usernamebuf, pw->pw_name);
+  debug_printf ("pw_gecos = %x (%s)", pw->pw_gecos, pw->pw_gecos);
   if (pw->pw_gecos)
     {
       if ((c = strstr (pw->pw_gecos, "U-")) != NULL &&
@@ -475,6 +476,7 @@ cygwin_logon_user (const struct passwd *pw, const char *password)
       *c = '\0';
       nt_user = c + 1;
     }
+  debug_printf ("LogonUserA (%s, %s, %s, ...)", nt_user, nt_domain, password);
   if (!LogonUserA (nt_user, nt_domain, (char *) password,
                    LOGON32_LOGON_INTERACTIVE,
                    LOGON32_PROVIDER_DEFAULT,
index 5f632f0..6851f12 100644 (file)
@@ -18,8 +18,24 @@ details. */
 #include <errno.h>
 #include "shortcut.h"
 
+/* TODO:
+   Currently duplicated from path.h. Later rearrangement of path.h
+   to allow including from plain C would be better. */
 /* This is needed to avoid including path.h which is a pure C++ header. */
-#define PATH_SYMLINK MOUNT_SYMLINK
+#define PATH_SYMLINK    MOUNT_SYMLINK
+#define PATH_EXEC       MOUNT_EXEC
+#define PATH_CYGWIN_EXEC MOUNT_CYGWIN_EXEC
+#define PATH_ALL_EXEC   PATH_CYGWIN_EXEC | PATH_EXEC
+
+/* TODO: Ditto. */
+static BOOL
+has_exec_chars (const char *buf, int len)
+{
+  return len >= 2 &&
+        ((buf[0] == '#' && buf[1] == '!') ||
+         (buf[0] == ':' && buf[1] == '\n') ||
+         (buf[0] == 'M' && buf[1] == 'Z'));
+}
 
 char shortcut_header[SHORTCUT_HDR_SIZE];
 BOOL shortcut_initalized = FALSE;
@@ -57,9 +73,11 @@ check_shortcut (const char *path, DWORD fileattr, HANDLE h,
   IPersistFile *ppf = NULL;
   WCHAR wc_path[MAX_PATH];
   char full_path[MAX_PATH];
+  char file_header[SHORTCUT_HDR_SIZE];
   WIN32_FIND_DATA wfd;
   DWORD len = 0;
   int res = 0;
+  DWORD got = 0;
 
   /* Initialize COM library. */
   CoInitialize (NULL);
@@ -78,24 +96,22 @@ check_shortcut (const char *path, DWORD fileattr, HANDLE h,
   hres = ppf->lpVtbl->Load (ppf, wc_path, STGM_READ);
   if (FAILED (hres))
     goto close_it;
+  /* Read the files header information. This is used to check for a
+     Cygwin or U/WIN shortcut or later to check for executable files. */
+  if (! ReadFile (h, file_header, SHORTCUT_HDR_SIZE, &got, 0))
+    {
+      *error = EIO;
+      goto close_it;
+    }
   /* Try the description (containing a POSIX path) first. */
   if (fileattr & FILE_ATTRIBUTE_READONLY)
     {
-      /* An additional check is needed to prove if it's a shortcut
-         really created by Cygwin or U/WIN. */
-      char file_header[SHORTCUT_HDR_SIZE];
-      DWORD got;
-
-      if (! ReadFile (h, file_header, SHORTCUT_HDR_SIZE, &got, 0))
-       {
-          *error = EIO;
-         goto close_it;
-       }
+      /* Check header if the shortcut is really created by Cygwin or U/WIN. */
       if (got == SHORTCUT_HDR_SIZE && !cmp_shortcut_header (file_header))
         {
          hres = psl->lpVtbl->GetDescription (psl, contents, MAX_PATH);
          if (FAILED (hres))
-           goto close_it;
+           goto file_not_symlink;
          len = strlen (contents);
        }
     }
@@ -119,15 +135,21 @@ check_shortcut (const char *path, DWORD fileattr, HANDLE h,
       /* Set relative path inside of IShellLink interface. */
       hres = psl->lpVtbl->SetRelativePath (psl, full_path, 0);
       if (FAILED (hres))
-       goto close_it;
+       goto file_not_symlink;
       /* Get the path to the shortcut target. */
       hres = psl->lpVtbl->GetPath (psl, contents, MAX_PATH, &wfd, 0);
       if (FAILED(hres))
-       goto close_it;
+       goto file_not_symlink;
     }
   res = strlen (contents);
   if (res) /* It's a symlink.  */
     *pflags = PATH_SYMLINK;
+  goto close_it;
+
+file_not_symlink:
+  /* Not a symlink, see if executable.  */
+  if (!(*pflags & PATH_ALL_EXEC) && has_exec_chars (file_header, got))
+    *pflags |= PATH_EXEC;
 
 close_it:
   /* Release the pointer to IPersistFile. */