Subject: Re: ln and links
From: [email-masked] (Marcus G. Daniels)

25 Jan 1997 18:47:00 -0800
Approved: [email-masked]
Distribution: cygnus
Message-ID: <[email-masked]>
References: <01BC0B0E.9ACE4BB0@sos>
Original-To: Sergey Okhapkin <[email-masked]>
Original-Cc: "'GNU-Win32'" <[email-masked]>, "'Ron Forrester'" <[email-masked]>
In-Reply-To: Sergey Okhapkin's message of Sat, 25 Jan 1997 21:41:50 +0300
X-Mailer: Gnus v5.3/Emacs 19.34
Original-Sender: [email-masked]

>>>>> "SO" == Sergey Okhapkin <[email-masked]> writes:

RF>  Using b17.1 on Windows NT 4.0 SP2, with a FAT drive, if I am in
RF> /usr/rjf and there is a directory /pub, and I issue the command:

RF> ln -s /pub

SO> B17 does not support symlinks to directories.

But you might find this patch useful...

diff --ignore-all-space -c -r winsup/fhandler.cc /src/winsup/fhandler.cc
*** winsup/fhandler.cc	Tue Dec 10 14:18:50 1996
--- /src/winsup/fhandler.cc	Thu Jan  9 06:27:19 1997
***************
*** 298,304 ****
        syml_p = 0;
      }
  
!   path_conv win32_path (real_path);
    if (win32_path.error)
      {
        set_errno (win32_path.error);
--- 298,304 ----
        syml_p = 0;
      }
  
!   path_conv win32_path (real_path, 0);
    if (win32_path.error)
      {
        set_errno (win32_path.error);
diff --ignore-all-space -c -r winsup/path.cc /src/winsup/path.cc
*** winsup/path.cc	Tue Dec  3 19:23:01 1996
--- /src/winsup/path.cc	Fri Jan 10 00:26:02 1997
***************
*** 136,141 ****
--- 136,192 ----
    return 0;
  }
  
+ 
+ static const char *
+ skip_n_slashes (const char *path, int ind)
+ {
+   int i;
+   const char *ptr = path;
+   for (i = 0 ; i < ind && ptr != NULL; i++)
+     {
+       ptr = strchr (ptr+1, '/');
+       if (ptr)
+         if (ptr[1] == '/')
+           ptr++;
+     }
+   return ptr;
+ }
+ 
+ static int symlink_check_worker (const char *path, char *buf, int buflen, int *syml, int *exec, int follow_mode);
+ 
+ static void
+ symlink_expand (const char *path, char *buf)
+ {
+ 
+   char in[MAX_PATH];
+   char tmp[MAX_PATH];
+   char *next; 
+   int si, tmplen;
+   int exec, syml;
+ 
+   strcpy (in, path);
+   for (si=1; next = (char *)skip_n_slashes (in, si); si++)
+     {
+       *next = '\0';
+       tmplen = symlink_check_worker (in, buf, MAX_PATH - 1, &syml, &exec, -1);
+       *next = '/';
+       if (tmplen > 0)
+         {
+           strcpy (tmp, next);
+           buf[tmplen]='\0';
+ 	  if (buf[0] == '/' || si == 1)
+ 	    strcpy (in, buf);
+ 	  else
+ 	    {
+ 	      const char *prev = skip_n_slashes (in, si - 1);
+ 	      strcpy ((char *)prev + 1, (const char *)buf);
+ 	    }
+ 	  strcat (in, tmp);
+         }
+     }
+   strcpy (buf, in);
+ }
+ 
  /* Convert an arbitrary path SRC to a pure WIN32 path, suitable for passing to
     Win32 API routines.
  
***************
*** 145,157 ****
     If an error occurs, `error' is set to the errno value.
     Otherwise it is set to 0.  */
  
! path_conv::path_conv (const char *src)
  {
    mixed_p = 0;
    silent_p = 0;
    binary_p = 0;
    error = 0;
  
    if (! s->mount.posix_path_p ())
      {
        if (strlen (src) >= MAX_PATH)
--- 196,226 ----
     If an error occurs, `error' is set to the errno value.
     Otherwise it is set to 0.  */
  
! path_conv::path_conv (const char *in_src, int follow_mode)
  {
+   const char *src;
+   char src_[MAX_PATH];
+ 
    mixed_p = 0;
    silent_p = 0;
    binary_p = 0;
    error = 0;
  
+   if (follow_mode > 0)
+     {
+       int exec;
+       symlink_follow (in_src, src_, &exec);
+       src = src_;
+     }
+   else if (follow_mode == 0)
+     {
+       symlink_expand (in_src, src_);
+       src = src_;
+     }
+   else
+     src = in_src;
+ 
+ 
    if (! s->mount.posix_path_p ())
      {
        if (strlen (src) >= MAX_PATH)
***************
*** 1021,1032 ****
  
     If an error occurs -1 is returned and errno is set.  */
  
! int
! symlink_check (const char *path, char *buf, int buflen, int *syml, int *exec)
  {
    int res = -1;
  
!   path_conv pathbuf (path);
    if (pathbuf.error)
      {
        set_errno (pathbuf.error);
--- 1090,1101 ----
  
     If an error occurs -1 is returned and errno is set.  */
  
! static int
! symlink_check_worker (const char *path, char *buf, int buflen, int *syml, int *exec, int follow_mode)
  {
    int res = -1;
  
!   path_conv pathbuf (path, follow_mode);
    if (pathbuf.error)
      {
        set_errno (pathbuf.error);
***************
*** 1110,1115 ****
--- 1179,1191 ----
    return res;
  }
  
+ int
+ symlink_check (const char *path, char *buf, int buflen, int *syml, int *exec)
+ {
+   return symlink_check_worker (path, buf, buflen, syml, exec, 0);
+ }
+ 
+ 
  /* Traverse PATH to its ultimate destination and store that in REALPATH.
     PATH needn't be a symlink (in which case it is copied to REALPATH).
     REALPATH is assumed to be large enough (i.e. MAX_PATH bytes).
***************
*** 1125,1135 ****
     up later but the priority now is on simplicity and correctness.  */
  
  int
! symlink_follow (const char *path, char *realpath, int *exec)
  {
    char buf[MAX_PATH];
    int len;
  
    if (strlen (path) >= MAX_PATH)
      {
        set_errno (ENAMETOOLONG);
--- 1201,1213 ----
     up later but the priority now is on simplicity and correctness.  */
  
  int
! symlink_follow (const char *in_path, char *realpath, int *exec)
  {
    char buf[MAX_PATH];
+   char path[MAX_PATH];
    int len;
  
+   symlink_expand (in_path, path);
    if (strlen (path) >= MAX_PATH)
      {
        set_errno (ENAMETOOLONG);
***************
*** 1147,1152 ****
--- 1225,1232 ----
        /* If that wasn't a symlink, we're done.  */
        if (len == -1 || ! syml_p)
  	{
+           symlink_expand (realpath, buf);
+           strcpy (realpath, buf);
  	  /* We really don't care if an error occurs here.  We just assume
  	     PATH isn't a symlink and let the caller deal with it.  */
  	  if (exec)
diff --ignore-all-space -c -r winsup/path.h /src/winsup/path.h
*** winsup/path.h	Tue Dec  3 19:23:01 1996
--- /src/winsup/path.h	Thu Jan  9 00:58:41 1997
***************
*** 27,33 ****
  
    int error;
  
!   path_conv (const char * const);
    inline char *get_win32 () { return path; }
  };
  
--- 27,33 ----
  
    int error;
  
!   path_conv (const char * const, int follow_mode = 1);
    inline char *get_win32 () { return path; }
  };
  
diff --ignore-all-space -c -r winsup/syscalls.cc /src/winsup/syscalls.cc
*** winsup/syscalls.cc	Tue Dec  3 19:23:03 1996
--- /src/winsup/syscalls.cc	Thu Jan  9 06:15:39 1997
***************
*** 168,174 ****
  {
    int res;
  
!   path_conv win32_name (ourname);
    
    syscall_printf ("_unlink (%s)\n", win32_name.get_win32 ());
  
--- 168,174 ----
  {
    int res;
  
!   path_conv win32_name (ourname, 0);
    
    syscall_printf ("_unlink (%s)\n", win32_name.get_win32 ());
  
***************
*** 477,484 ****
  _link (const char *a, const char *b)
  {
    int res = -1;
!   path_conv real_a (a);
!   path_conv real_b (b);
    
    /* do this with a copy */
    if (CopyFileA (real_a.get_win32 (), real_b.get_win32 (), 1))
--- 477,484 ----
  _link (const char *a, const char *b)
  {
    int res = -1;
!   path_conv real_a (a, 0);
!   path_conv real_b (b, 0);
    
    /* do this with a copy */
    if (CopyFileA (real_a.get_win32 (), real_b.get_win32 (), 1))
***************
*** 496,502 ****
  {
    int res = -1;
  
!   path_conv real_dir (dir);
    
    if (CreateDirectoryA (real_dir.get_win32 (), 0))
      res = 0;
--- 496,502 ----
  {
    int res = -1;
  
!   path_conv real_dir (dir, 0);
    
    if (CreateDirectoryA (real_dir.get_win32 (), 0))
      res = 0;
***************
*** 513,519 ****
  {
    int res = -1;
  
!   path_conv real_dir (dir);
    
    if (RemoveDirectoryA (real_dir.get_win32 ()))
      res = 0;
--- 513,519 ----
  {
    int res = -1;
  
!   path_conv real_dir (dir, 0);
    
    if (RemoveDirectoryA (real_dir.get_win32 ()))
      res = 0;
***************
*** 708,714 ****
  
    debug_printf ("%s (%s, %p)\n", caller, name, buf);
    
!   path_conv real_path (name);
    if (real_path.error)
      {
        set_errno (real_path.error);
--- 708,714 ----
  
    debug_printf ("%s (%s, %p)\n", caller, name, buf);
    
!   path_conv real_path (name, !nofollow);
    if (real_path.error)
      {
        set_errno (real_path.error);
***************
*** 814,821 ****
  int
  _rename (const char *oldpath, const char *newpath)
  {
!   path_conv real_old (oldpath);
!   path_conv real_new (newpath);
    int res;
    int oldatts = GetFileAttributesA (real_old.get_win32 ());
    int newatts = GetFileAttributesA (real_new.get_win32 ());
--- 814,821 ----
  int
  _rename (const char *oldpath, const char *newpath)
  {
!   path_conv real_old (oldpath, 0);
!   path_conv real_new (newpath, 0);
    int res;
    int oldatts = GetFileAttributesA (real_old.get_win32 ());
    int newatts = GetFileAttributesA (real_new.get_win32 ());

-
For help on using this list, send a message to
"[email-masked]" with one line of text: "help".