diff options
author | Eric Blake <eblake@redhat.com> | 2009-09-26 19:51:53 +0400 |
---|---|---|
committer | Eric Blake <eblake@redhat.com> | 2009-09-26 19:51:53 +0400 |
commit | 52dba6a5c45e8d8ba1e237a15213311dc11d91fb (patch) | |
tree | 58e8c9e0fea63d08c7f3e63ba3956e3196403d94 /winsup/cygwin/dir.cc | |
parent | 1e6459d3e5248a8253e73b602615820d14ee6483 (diff) |
Fix some POSIX-compliance bugs in link, rename, mkdir.
* syscalls.cc (link): Delete obsolete comment. Reject directories
and missing source up front.
(rename): Use correct errno for trailing '.'. Detect empty
strings. Allow trailing slash to newpath iff oldpath is
directory.
* dir.cc (mkdir): Reject dangling symlink with trailing slash.
* fhandler_disk_file.cc (fhandler_disk_file::link): Reject
trailing slash.
* fhandler.cc (fhandler_base::link): Match Linux errno.
Diffstat (limited to 'winsup/cygwin/dir.cc')
-rw-r--r-- | winsup/cygwin/dir.cc | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc index 2b9125f0b..4bca40cec 100644 --- a/winsup/cygwin/dir.cc +++ b/winsup/cygwin/dir.cc @@ -1,6 +1,7 @@ /* dir.cc: Posix directory-related routines - Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2006, 2007 Red Hat, Inc. + Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2006, 2007, + 2008, 2009 Red Hat, Inc. This file is part of Cygwin. @@ -21,6 +22,7 @@ details. */ #include "dtable.h" #include "cygheap.h" #include "cygtls.h" +#include "tls_pbuf.h" extern "C" int dirfd (DIR *dir) @@ -273,11 +275,30 @@ mkdir (const char *dir, mode_t mode) { int res = -1; fhandler_base *fh = NULL; + tmp_pathbuf tp; myfault efault; if (efault.faulted (EFAULT)) return -1; + /* POSIX says mkdir("symlink-to-missing/") should create the + directory "missing", but Linux rejects it with EEXIST. Copy + Linux behavior for now. */ + + if (!*dir) + { + set_errno (ENOENT); + goto done; + } + if (isdirsep (dir[strlen (dir) - 1])) + { + /* This converts // to /, but since both give EEXIST, we're okay. */ + char *buf; + char *p = stpcpy (buf = tp.c_get (), dir) - 1; + dir = buf; + while (p > dir && isdirsep (*p)) + *p-- = '\0'; + } if (!(fh = build_fh_name (dir, NULL, PC_SYM_NOFOLLOW))) goto done; /* errno already set */; |