Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2005-02-20 00:53:36 +0300
committerCorinna Vinschen <corinna@vinschen.de>2005-02-20 00:53:36 +0300
commit0d75ce965cf46a16585477469bb4edb597a35f00 (patch)
tree7fbe3e9926fae6373ca21014ebd1e24bf5c8bdb6 /winsup/cygwin
parentc2d0b9d89a3406e8905efa8fe58f9d948242e028 (diff)
* fhandler.h (class fhandler_base): Declare new method link.
(class fhandler_socket): Ditto. (class fhandler_disk_file): Ditto. * fhandler.cc (fhandler_base::open): Add FILE_WRITE_ATTRIBUTES to query_write_control access flags. (fhandler_base::link): New method. * fhandler_disk_file.cc (fhandler_disk_file::fchmod): Don't try to open with O_WRONLY since query_write_control includes FILE_WRITE_ATTRIBUTES. (fhandler_disk_file::fchown): Ditto. (fhandler_disk_file::facl): Ditto. (fhandler_disk_file::link): New method. Touch st_ctime on successful link. * fhandler_socket.cc (fhandler_socket::link): New method. * syscalls.cc (link): Move functionality into fhandler method link. Just call this method from here.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog19
-rw-r--r--winsup/cygwin/fhandler.cc9
-rw-r--r--winsup/cygwin/fhandler.h3
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc206
-rw-r--r--winsup/cygwin/fhandler_socket.cc12
-rw-r--r--winsup/cygwin/syscalls.cc185
6 files changed, 232 insertions, 202 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 5c5cc537c..aa47a9064 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,24 @@
2005-02-19 Corinna Vinschen <corinna@vinschen.de>
+ * fhandler.h (class fhandler_base): Declare new method link.
+ (class fhandler_socket): Ditto.
+ (class fhandler_disk_file): Ditto.
+ * fhandler.cc (fhandler_base::open): Add FILE_WRITE_ATTRIBUTES
+ to query_write_control access flags.
+ (fhandler_base::link): New method.
+ * fhandler_disk_file.cc (fhandler_disk_file::fchmod): Don't try to
+ open with O_WRONLY since query_write_control includes
+ FILE_WRITE_ATTRIBUTES.
+ (fhandler_disk_file::fchown): Ditto.
+ (fhandler_disk_file::facl): Ditto.
+ (fhandler_disk_file::link): New method. Touch st_ctime on successful
+ link.
+ * fhandler_socket.cc (fhandler_socket::link): New method.
+ * syscalls.cc (link): Move functionality into fhandler method link.
+ Just call this method from here.
+
+2005-02-19 Corinna Vinschen <corinna@vinschen.de>
+
* fhandler.h (class fhandler_socket): Declare new methods fchown,
fchmod and facl.
* fhandler_socket.cc (fhandler_socket::fstat): Handle AF_LOCAL
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 3fd0bc74b..f846d044e 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -580,7 +580,7 @@ fhandler_base::open (int flags, mode_t mode)
create_options = FILE_OPEN_FOR_BACKUP_INTENT;
break;
case query_write_control:
- access = READ_CONTROL | WRITE_OWNER | WRITE_DAC;
+ access = READ_CONTROL | WRITE_OWNER | WRITE_DAC | FILE_WRITE_ATTRIBUTES;
create_options = FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY;
break;
default:
@@ -1605,3 +1605,10 @@ fhandler_base::ftruncate (_off64_t length)
set_errno (EINVAL);
return -1;
}
+
+int
+fhandler_base::link (const char *newpath)
+{
+ set_errno (EINVAL);
+ return -1;
+}
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 0617a82c5..591c08894 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -264,6 +264,7 @@ class fhandler_base
virtual int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2)));
virtual int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3)));
virtual int __stdcall ftruncate (_off64_t) __attribute__ ((regparm (2)));
+ virtual int __stdcall link (const char *) __attribute__ ((regparm (2)));
virtual int ioctl (unsigned int cmd, void *);
virtual int fcntl (int cmd, void *);
virtual char const *ttyname () { return get_name (); }
@@ -436,6 +437,7 @@ class fhandler_socket: public fhandler_base
int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1)));
int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2)));
int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3)));
+ int __stdcall link (const char *) __attribute__ ((regparm (2)));
bool is_slow () {return 1;}
};
@@ -608,6 +610,7 @@ class fhandler_disk_file: public fhandler_base
int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2)));
int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3)));
int __stdcall ftruncate (_off64_t) __attribute__ ((regparm (2)));
+ int __stdcall link (const char *) __attribute__ ((regparm (2)));
HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, _off64_t off);
int munmap (HANDLE h, caddr_t addr, size_t len);
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 8644e8964..b77ae82fd 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -408,13 +408,9 @@ fhandler_disk_file::fchmod (mode_t mode)
enable_restore_privilege ();
if (!get_io_handle () && pc.has_acls ())
{
- /* Open for writing required to be able to set ctime. */
- if (!(oret = open (O_WRONLY | O_BINARY, 0)))
- {
- query_open (query_write_control);
- if (!(oret = open (O_BINARY, 0)))
- return -1;
- }
+ query_open (query_write_control);
+ if (!(oret = open (O_BINARY, 0)))
+ return -1;
}
if (!allow_ntsec && allow_ntea) /* Not necessary when manipulating SD. */
@@ -440,7 +436,7 @@ fhandler_disk_file::fchmod (mode_t mode)
res = 0;
/* Set ctime on success. */
- if (!res && !query_open ())
+ if (!res)
has_changed (true);
if (oret)
@@ -464,13 +460,9 @@ fhandler_disk_file::fchown (__uid32_t uid, __gid32_t gid)
enable_restore_privilege ();
if (!get_io_handle ())
{
- /* Open for writing required to be able to set ctime. */
- if (!(oret = open (O_WRONLY | O_BINARY, 0)))
- {
- query_open (query_write_control);
- if (!(oret = open (O_BINARY, 0)))
- return -1;
- }
+ query_open (query_write_control);
+ if (!(oret = open (O_BINARY, 0)))
+ return -1;
}
mode_t attrib = 0;
@@ -482,7 +474,7 @@ fhandler_disk_file::fchown (__uid32_t uid, __gid32_t gid)
res = set_file_attribute (pc.has_acls (), get_io_handle (), pc,
uid, gid, attrib);
/* Set ctime on success. */
- if (!res && !query_open ())
+ if (!res)
has_changed (true);
}
@@ -556,16 +548,9 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp)
enable_restore_privilege ();
if (!get_io_handle ())
{
- /* Open for writing required to be able to set ctime. */
- if (cmd == SETACL)
- oret = open (O_WRONLY | O_BINARY, 0);
- if (!oret)
- {
- query_open (cmd == SETACL ? query_write_control
- : query_read_control);
- if (!(oret = open (O_BINARY, 0)))
- return -1;
- }
+ query_open (cmd == SETACL ? query_write_control : query_read_control);
+ if (!(oret = open (O_BINARY, 0)))
+ return -1;
}
switch (cmd)
{
@@ -588,7 +573,7 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp)
}
/* Set ctime on success. */
- if (!res && cmd == SETACL && !query_open ())
+ if (!res && cmd == SETACL)
has_changed (true);
if (oret)
@@ -645,6 +630,173 @@ fhandler_disk_file::ftruncate (_off64_t length)
return res;
}
+int
+fhandler_disk_file::link (const char *newpath)
+{
+ int res = -1;
+ path_conv newpc (newpath, PC_SYM_NOFOLLOW | PC_FULL | PC_POSIX);
+ extern bool allow_winsymlinks;
+
+ if (newpc.error)
+ {
+ set_errno (newpc.case_clash ? ECASECLASH : newpc.error);
+ goto done;
+ }
+
+ if (newpc.exists ())
+ {
+ syscall_printf ("file '%s' exists?", (char *) newpc);
+ set_errno (EEXIST);
+ goto done;
+ }
+
+ if (newpc[strlen (newpc) - 1] == '.')
+ {
+ syscall_printf ("trailing dot, bailing out");
+ set_errno (EINVAL);
+ goto done;
+ }
+
+ /* Shortcut hack. */
+ char new_lnk_buf[CYG_MAX_PATH + 5];
+ if (allow_winsymlinks && pc.is_lnk_symlink () && !newpc.case_clash)
+ {
+ strcpy (new_lnk_buf, newpath);
+ strcat (new_lnk_buf, ".lnk");
+ newpath = new_lnk_buf;
+ newpc.check (newpath, PC_SYM_NOFOLLOW | PC_FULL);
+ }
+
+ query_open (query_write_control);
+ if (!open (O_BINARY, 0))
+ {
+ syscall_printf ("Opening file failed");
+ __seterrno ();
+ goto done;
+ }
+
+ /* Try to make hard link first on Windows NT */
+ if (wincap.has_hard_links ())
+ {
+ if (CreateHardLinkA (newpc, pc, NULL))
+ goto success;
+
+ /* There are two cases to consider:
+ - The FS doesn't support hard links ==> ERROR_INVALID_FUNCTION
+ We copy the file.
+ - CreateHardLinkA is not supported ==> ERROR_PROC_NOT_FOUND
+ In that case (<= NT4) we try the old-style method.
+ Any other error should be taken seriously. */
+ if (GetLastError () == ERROR_INVALID_FUNCTION)
+ {
+ syscall_printf ("FS doesn't support hard links: Copy file");
+ goto docopy;
+ }
+ if (GetLastError () != ERROR_PROC_NOT_FOUND)
+ {
+ syscall_printf ("CreateHardLinkA failed");
+ __seterrno ();
+ close ();
+ goto done;
+ }
+
+ WIN32_STREAM_ID stream_id;
+ DWORD written;
+ LPVOID context;
+ DWORD path_len;
+ DWORD size;
+ WCHAR wbuf[CYG_MAX_PATH];
+ BOOL ret;
+ DWORD write_err;
+
+ path_len = sys_mbstowcs (wbuf, newpc, CYG_MAX_PATH) * sizeof (WCHAR);
+
+ stream_id.dwStreamId = BACKUP_LINK;
+ stream_id.dwStreamAttributes = 0;
+ stream_id.dwStreamNameSize = 0;
+ stream_id.Size.HighPart = 0;
+ stream_id.Size.LowPart = path_len;
+ size = sizeof (WIN32_STREAM_ID) - sizeof (WCHAR**)
+ + stream_id.dwStreamNameSize;
+ context = NULL;
+ write_err = 0;
+ /* Write WIN32_STREAM_ID */
+ ret = BackupWrite (get_handle (), (LPBYTE) &stream_id, size,
+ &written, FALSE, FALSE, &context);
+ if (ret)
+ {
+ /* write the buffer containing the path */
+ /* FIXME: BackupWrite sometimes traps if linkname is invalid.
+ Need to handle. */
+ ret = BackupWrite (get_handle (), (LPBYTE) wbuf, path_len,
+ &written, FALSE, FALSE, &context);
+ if (!ret)
+ {
+ write_err = GetLastError ();
+ syscall_printf ("cannot write linkname, %E");
+ }
+ /* Free context */
+ BackupWrite (get_handle (), NULL, 0, &written,
+ TRUE, FALSE, &context);
+ }
+ else
+ {
+ write_err = GetLastError ();
+ syscall_printf ("cannot write stream_id, %E");
+ }
+
+ if (!ret)
+ {
+ /* Only copy file if FS doesn't support hard links */
+ if (write_err == ERROR_INVALID_FUNCTION)
+ {
+ syscall_printf ("FS doesn't support hard links: Copy file");
+ goto docopy;
+ }
+
+ close ();
+ __seterrno_from_win_error (write_err);
+ goto done;
+ }
+
+ success:
+ res = 0;
+ /* touch st_ctime */
+ has_changed (true);
+ close ();
+ if (!allow_winsymlinks && pc.is_lnk_symlink ())
+ SetFileAttributes (newpc, (DWORD) pc
+ | FILE_ATTRIBUTE_SYSTEM
+ | FILE_ATTRIBUTE_READONLY);
+
+ goto done;
+ }
+docopy:
+ /* do this with a copy */
+ if (CopyFileA (pc, newpc, 1))
+ {
+ res = 0;
+ /* touch st_ctime */
+ has_changed (true);
+ close ();
+ fhandler_disk_file fh;
+ fh.set_name (newpc);
+ fh.query_open (query_write_control);
+ if (fh.open (O_BINARY, 0))
+ {
+ fh.has_changed (true);
+ fh.close ();
+ }
+ }
+ else
+ __seterrno ();
+
+done:
+ syscall_printf ("%d = link (%s, %s)", res, get_name (), newpath);
+ return res;
+}
+
+
fhandler_disk_file::fhandler_disk_file () :
fhandler_base ()
{
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 757c5a76b..7038243e1 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -449,6 +449,18 @@ fhandler_socket::facl (int cmd, int nentries, __aclent32_t *aclbufp)
}
int
+fhandler_socket::link (const char *newpath)
+{
+ if (get_device () == FH_UNIX)
+ {
+ fhandler_disk_file fh;
+ fh.set_name (pc);
+ return fh.link (newpath);
+ }
+ return fhandler_base::link (newpath);
+}
+
+int
fhandler_socket::bind (const struct sockaddr *name, int namelen)
{
int res = -1;
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 18ef7ea00..079775657 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -668,188 +668,25 @@ isatty (int fd)
*/
extern "C" int
-link (const char *a, const char *b)
+link (const char *oldpath, const char *newpath)
{
int res = -1;
- path_conv real_a (a, PC_SYM_NOFOLLOW | PC_FULL);
- path_conv real_b (b, PC_SYM_NOFOLLOW | PC_FULL);
- extern bool allow_winsymlinks;
-
- if (real_a.error)
- {
- set_errno (real_a.error);
- goto done;
- }
-
- if (real_b.error)
- {
- set_errno (real_b.case_clash ? ECASECLASH : real_b.error);
- goto done;
- }
-
- if (real_b.exists ())
- {
- syscall_printf ("file '%s' exists?", (char *) real_b);
- set_errno (EEXIST);
- goto done;
- }
+ fhandler_base *fh;
- if (real_b[strlen (real_b) - 1] == '.')
- {
- syscall_printf ("trailing dot, bailing out");
- set_errno (EINVAL);
- goto done;
- }
+ if (!(fh = build_fh_name (oldpath, NULL, PC_SYM_NOFOLLOW)))
+ goto error;
- /* Shortcut hack. */
- char new_lnk_buf[CYG_MAX_PATH + 5];
- if (allow_winsymlinks && real_a.is_lnk_symlink () && !real_b.case_clash)
+ if (fh->error ())
{
- strcpy (new_lnk_buf, b);
- strcat (new_lnk_buf, ".lnk");
- b = new_lnk_buf;
- real_b.check (b, PC_SYM_NOFOLLOW | PC_FULL);
- }
- /* Try to make hard link first on Windows NT */
- if (wincap.has_hard_links ())
- {
- if (CreateHardLinkA (real_b, real_a, NULL))
- goto success;
-
- /* There are two cases to consider:
- - The FS doesn't support hard links ==> ERROR_INVALID_FUNCTION
- We copy the file.
- - CreateHardLinkA is not supported ==> ERROR_PROC_NOT_FOUND
- In that case (<= NT4) we try the old-style method.
- Any other error should be taken seriously. */
- if (GetLastError () == ERROR_INVALID_FUNCTION)
- {
- syscall_printf ("FS doesn't support hard links: Copy file");
- goto docopy;
- }
- if (GetLastError () != ERROR_PROC_NOT_FOUND)
- {
- syscall_printf ("CreateHardLinkA failed");
- __seterrno ();
- goto done;
- }
-
- HANDLE hFileSource;
-
- WIN32_STREAM_ID StreamId;
- DWORD dwBytesWritten;
- LPVOID lpContext;
- DWORD cbPathLen;
- DWORD StreamSize;
- WCHAR wbuf[CYG_MAX_PATH];
-
- BOOL bSuccess;
- DWORD write_err;
-
- hFileSource = CreateFile (real_a, FILE_WRITE_ATTRIBUTES,
- FILE_SHARE_READ | FILE_SHARE_WRITE /*| FILE_SHARE_DELETE*/,
- &sec_none_nih, // sa
- OPEN_EXISTING, 0, NULL);
-
- if (hFileSource == INVALID_HANDLE_VALUE)
- {
- syscall_printf ("cannot open source, %E");
- goto docopy;
- }
-
- cbPathLen = sys_mbstowcs (wbuf, real_b, CYG_MAX_PATH) * sizeof (WCHAR);
-
- StreamId.dwStreamId = BACKUP_LINK;
- StreamId.dwStreamAttributes = 0;
- StreamId.dwStreamNameSize = 0;
- StreamId.Size.HighPart = 0;
- StreamId.Size.LowPart = cbPathLen;
-
- StreamSize = sizeof (WIN32_STREAM_ID) - sizeof (WCHAR**) +
- StreamId.dwStreamNameSize;
-
- lpContext = NULL;
- write_err = 0;
- /* Write the WIN32_STREAM_ID */
- bSuccess = BackupWrite (
- hFileSource,
- (LPBYTE) &StreamId, // buffer to write
- StreamSize, // number of bytes to write
- &dwBytesWritten,
- FALSE, // don't abort yet
- FALSE, // don't process security
- &lpContext);
-
- if (bSuccess)
- {
- /* write the buffer containing the path */
- /* FIXME: BackupWrite sometimes traps if linkname is invalid.
- Need to handle. */
- bSuccess = BackupWrite (
- hFileSource,
- (LPBYTE) wbuf, // buffer to write
- cbPathLen, // number of bytes to write
- &dwBytesWritten,
- FALSE, // don't abort yet
- FALSE, // don't process security
- &lpContext
- );
-
- if (!bSuccess)
- {
- write_err = GetLastError ();
- syscall_printf ("cannot write linkname, %E");
- }
-
- /* Free context */
- BackupWrite (
- hFileSource,
- NULL, // buffer to write
- 0, // number of bytes to write
- &dwBytesWritten,
- TRUE, // abort
- FALSE, // don't process security
- &lpContext);
- }
- else
- {
- write_err = GetLastError ();
- syscall_printf ("cannot write streamId, %E");
- }
-
- CloseHandle (hFileSource);
-
- if (!bSuccess)
- {
- /* Only copy file if FS doesn't support hard links */
- if (write_err == ERROR_INVALID_FUNCTION)
- {
- syscall_printf ("FS doesn't support hard links: Copy file");
- goto docopy;
- }
-
- __seterrno_from_win_error (write_err);
- goto done;
- }
-
- success:
- res = 0;
- if (!allow_winsymlinks && real_a.is_lnk_symlink ())
- SetFileAttributes (real_b, (DWORD) real_a
- | FILE_ATTRIBUTE_SYSTEM
- | FILE_ATTRIBUTE_READONLY);
-
- goto done;
+ debug_printf ("got %d error from build_fh_name", fh->error ());
+ set_errno (fh->error ());
}
-docopy:
- /* do this with a copy */
- if (CopyFileA (real_a, real_b, 1))
- res = 0;
else
- __seterrno ();
+ res = fh->link (newpath);
-done:
- syscall_printf ("%d = link (%s, %s)", res, a, b);
+ delete fh;
+ error:
+ syscall_printf ("%d = link (%s, %s)", res, oldpath, newpath);
return res;
}