Subject: CygUtils Version of zip (and Symlinks)
From: Jason Tishler <[email-masked]>
To: Cygwin <[email-masked]>
Date: Tue, 23 May 2000 14:25:14 -0400

Short Version:
===== =======

1. What is the best way to read the contents of a symlink file?  Can I
use open or do I have to resort to CreateFile?

2. Should the cygwin_conv_to_* functions (eg, cygwin_conv_to_win32_path)
be enhanced to optionally not chase symlinks?

Long Version:
==== =======

I have been fiddling around with the Cygwin version of zip that I
downloaded from CygUtils (http://cygutils.netpedia.net/).  My goal
was to "improve" its support for symlinks.  I fairly quickly arrived
at the following very nasty hack that does the job:

    #define SYMLINK_COOKIE "!<symlink>"

    int
    rdsymlnk(path, buf, size)
    const char *path;
    char *buf;
    unsigned size;
    {
      unsigned len = 0;

      strcpy(buf, SYMLINK_COOKIE);
      len = strlen(SYMLINK_COOKIE);
      len += readlink(path, &buf[len], size - len);
      buf[len++] = '\0';
      return len;
    }

Using the above, I now have a version of zip that can generate
archives (using -y and/or -S) that preserve symlinks.  These archives
can be extracted via unzip, WinZip, etc. without losing any contained
symlinks.  I find this great for bootstraping Cygwin installation.

Obviously, using the value of SYMLINK_COOKIE breaks encapsulation and
is a bad way to "read" the contents of a symlink file.  Reading the
open man page (on Solaris), I found out the following:

    If path is a symbolic link and O_CREAT and O_EXCL  are  set,
    the link is not followed.

Although I was skeptical, I tried the above with Cygwin and I wasn't
disappointed -- it didn't work.

Next, I started reading the code in path.cc from the Cygwin winsup
source to see how Cygwin implements readlink().  Sure enough, I found
out that the contents of a symlink is ultimately read via CreateFile
and ReadFile.

So, I decided redo my hack by replacing readlink with a new function
that I call (for argument sake) Cygwin_readlink.  Cygwin_readlink
will use CreateFile to open the symlink file.  Hence, I need to call
cygwin_conv_to_win32_path to convert the POSIX path to a Win32 path.
Unfortunately, this chases the symlink...bummers!  Of course, I can
play games like calling cygwin_conv_to_win32_path on the dirname part
of the path and then concatenate the results with the basename part.

It seems like I'm missing something, so this brings me back to the
short version:

1. What is the best way to read the contents of symlink file?  Can I
use open or do I have to resort to CreateFile?

2. Should the cygwin_conv_to_* functions (eg, cygwin_conv_to_win32_path)
be enhanced to optionally not chase symlinks?

BTW, I will post my zip patches once I figure out the best way to
handle symlinks.

FYI, the current CygUtils version of zip does not properly handle
absolute pathnames as in the following:

    $ zip -r jt.zip /home/jt # H:\ is mounted as /home/jt

It will treat /home/jt above as X:\home\jt, where X is your current
drive, and not as H:\.  Hence, it is missing (at least) one call to
cygwin_conv_to_win32_path.  But, cygwin_conv_to_win32_path chases
symlinks...

Thanks,
Jason

-- 
Jason Tishler
Director, Software Engineering       Phone: +1 (732) 264-8770 x235
Dot Hill Systems Corporation         Fax:   +1 (732) 264-8798
82 Bethany Road, Suite 7             Email: [email-masked]
Hazlet, NJ 07730 USA                 WWW:   http://www.dothill.com

--
Want to unsubscribe from this list?
Send a message to [email-masked]