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>2007-07-27 20:24:07 +0400
committerCorinna Vinschen <corinna@vinschen.de>2007-07-27 20:24:07 +0400
commit745c29fe7b54844aad20e62891624ea9a0063d9a (patch)
treeb3f236ba2c61c5770a49ee224bff7faf666e1505 /winsup/cygwin/fhandler_disk_file.cc
parentf590b14dfdcadb81dbedce81dec30d65b453e555 (diff)
* autoload.cc (CreateHardLinkA): Remove.
* fhandler_disk_file.cc (fhandler_disk_file::link): Drop GetBinaryType test. Just check exe suffix instead. Tune creating new file name. Implement creating hard link using native NT functions which works on all platforms. * ntdll.h (STATUS_INVALID_DEVICE_REQUEST): Define. (struct _FILE_LINK_INFORMATION): Define.
Diffstat (limited to 'winsup/cygwin/fhandler_disk_file.cc')
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc147
1 files changed, 40 insertions, 107 deletions
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 2ab830bc5..dcbc137e9 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -1028,7 +1028,7 @@ fhandler_disk_file::link (const char *newpath)
if (newpc.exists ())
{
- syscall_printf ("file '%s' exists?", (char *) newpc);
+ syscall_printf ("file '%s' exists?", newpc.get_win32 ());
set_errno (EEXIST);
return -1;
}
@@ -1040,141 +1040,74 @@ fhandler_disk_file::link (const char *newpath)
return -1;
}
- char new_buf[CYG_MAX_PATH + 5];
+ char new_buf[strlen (newpath) + 5];
if (!newpc.error && !newpc.case_clash)
{
- DWORD bintype;
int len;
if (allow_winsymlinks && pc.is_lnk_special ())
{
/* Shortcut hack. */
- strcpy (new_buf, newpath);
- strcat (new_buf, ".lnk");
+ stpcpy (stpcpy (new_buf, newpath), ".lnk");
newpath = new_buf;
newpc.check (newpath, PC_SYM_NOFOLLOW);
}
- else if (transparent_exe
- && !pc.isdir ()
- && GetBinaryType (pc, &bintype)
- && (len = strlen (newpc)) > 4
- && !strcasematch ((const char *) newpc + len - 4, ".exe"))
+ else if (!pc.isdir ()
+ && (len = strlen (pc.get_win32 ())) > 4
+ && strcasematch (pc.get_win32 () + len - 4, ".exe")
+ && (len = strlen (newpc.get_win32 ())) > 4
+ && !strcasematch (newpc.get_win32 () + len - 4, ".exe"))
{
/* Executable hack. */
- strcpy (new_buf, newpath);
- strcat (new_buf, ".exe");
+ stpcpy (stpcpy (new_buf, newpath), ".exe");
newpath = new_buf;
newpc.check (newpath, PC_SYM_NOFOLLOW);
}
}
- query_open (query_write_attributes);
- if (!open (O_BINARY, 0))
+ HANDLE fh;
+ NTSTATUS status;
+ OBJECT_ATTRIBUTES attr;
+ IO_STATUS_BLOCK io;
+ status = NtOpenFile (&fh, 0,
+ pc.get_object_attr (attr, sec_none_nih), &io,
+ FILE_SHARE_VALID_FLAGS,
+ FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT);
+ if (!NT_SUCCESS (status))
{
- syscall_printf ("Opening file failed");
- __seterrno ();
+ __seterrno_from_nt_status (status);
return -1;
}
-
- 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)
+ PUNICODE_STRING tgt = newpc.get_nt_native_path ();
+ ULONG size = sizeof (FILE_LINK_INFORMATION) + tgt->Length;
+ PFILE_LINK_INFORMATION pfli = (PFILE_LINK_INFORMATION) alloca (size);
+ pfli->ReplaceIfExists = FALSE;
+ pfli->RootDirectory = NULL;
+ memcpy (pfli->FileName, tgt->Buffer, pfli->FileNameLength = tgt->Length);
+ status = NtSetInformationFile (fh, &io, pfli, size, FileLinkInformation);
+ NtClose (fh);
+ if (!NT_SUCCESS (status))
{
- syscall_printf ("CreateHardLinkA failed");
- __seterrno ();
- close ();
- return -1;
- }
-
- WIN32_STREAM_ID stream_id;
- LPVOID context;
- WCHAR wbuf[CYG_MAX_PATH];
- BOOL ret;
- DWORD written, write_err, path_len, size;
-
- 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");
+ if (status == STATUS_INVALID_DEVICE_REQUEST)
+ {
+ /* FS doesn't support hard links. Try to copy file. */
+ if (!CopyFileA (pc, newpc, TRUE))
+ {
+ __seterrno ();
+ return -1;
+ }
}
- /* 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;
+ else
+ {
+ __seterrno_from_nt_status (status);
+ return -1;
}
-
- close ();
- __seterrno_from_win_error (write_err);
- return -1;
}
-
-success:
- close ();
if (!allow_winsymlinks && pc.is_lnk_special ())
SetFileAttributes (newpc, (DWORD) pc
| FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_READONLY);
return 0;
-
-docopy:
- /* do this with a copy */
- if (!CopyFileA (pc, newpc, 1))
- {
- __seterrno ();
- return -1;
- }
- close ();
- fhandler_disk_file fh (newpc);
- fh.query_open (query_write_attributes);
- if (fh.open (O_BINARY, 0))
- fh.close ();
- return 0;
}
int