This is the mail archive of the
cygwin-developers@sourceware.cygnus.com
mailing list for the Cygwin project.
Re: symlink() bug + patch
Applied.
I especially like the fact that you used CreateFile/WriteFile rather
than using open/_write. There was no need for the extra overhead in
this case.
Thanks,
cgf
On Sat, Dec 25, 1999 at 04:43:15PM +0900, Kazuhiro Fujieda wrote:
>The following patch against the latest snapshot really makes
>symlink() cause EEXIST if the `frompath' is already a file or
>a symlink.
>
>--- path.cc- Sun Dec 19 13:57:13 1999
>+++ path.cc Sat Dec 25 16:24:29 1999
>@@ -1983,10 +1983,17 @@ extern "C"
> int
> symlink (const char *topath, const char *frompath)
> {
>- int fd;
>+ HANDLE h;
> int res = -1;
>
>- syscall_printf ("symlink (%s, %s)", topath, frompath);
>+ path_conv win32_path (frompath, SYMLINK_NOFOLLOW);
>+ if (win32_path.error)
>+ {
>+ set_errno (win32_path.error);
>+ goto done;
>+ }
>+
>+ syscall_printf ("symlink (%s, %s)", topath, win32_path.get_win32 ());
>
> if (topath[0] == 0)
> {
>@@ -1999,25 +2006,35 @@ symlink (const char *topath, const char
> goto done;
> }
>
>- fd = _open (frompath, O_WRONLY | O_CREAT | O_BINARY | O_EXCL, 0);
>- if (fd >= 0)
>+ if (win32_path.is_device () ||
>+ win32_path.file_attributes () != (DWORD) -1)
>+ {
>+ set_errno (EEXIST);
>+ goto done;
>+ }
>+
>+ h = CreateFileA(win32_path.get_win32 (), GENERIC_WRITE, 0, &sec_none_nih,
>+ CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
>+ if (h == INVALID_HANDLE_VALUE)
>+ __seterrno ();
>+ else
> {
> char buf[sizeof (SYMLINK_COOKIE) + MAX_PATH + 10];
>
> __small_sprintf (buf, "%s%s", SYMLINK_COOKIE, topath);
>- int len = strlen (buf) + 1;
>+ DWORD len = strlen (buf) + 1;
>
> /* Note that the terminating nul is written. */
>- if (_write (fd, buf, len) != len)
>+ DWORD written;
>+ if (!WriteFile (h, buf, len, &written, NULL) || written != len)
> {
>- int saved_errno = get_errno ();
>- _close (fd);
>- _unlink (frompath);
>- set_errno (saved_errno);
>+ __seterrno ();
>+ CloseHandle (h);
>+ DeleteFileA (win32_path.get_win32 ());
> }
> else
> {
>- _close (fd);
>+ CloseHandle (h);
> chmod (frompath, S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
> res = 0;
> }