aboutsummaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog10
-rw-r--r--winsup/cygwin/autoload.cc1
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc147
-rw-r--r--winsup/cygwin/ntdll.h28
4 files changed, 68 insertions, 118 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index b86eb88..0ddebd5 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,15 @@
2007-07-27 Corinna Vinschen <corinna@vinschen.de>
+ * 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.
+
+2007-07-27 Corinna Vinschen <corinna@vinschen.de>
+
* fhandler_disk_file.cc (fhandler_disk_file::ftruncate): Use
NtQueryInformationFile instead of GetFileSize, NtFsControlFile instead
of DeviceIoControl.
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index c1a2cad..09e645a 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -393,7 +393,6 @@ LoadDLLfuncEx2 (SendARP, 16, iphlpapi, 1, 50)
LoadDLLfunc (CoTaskMemFree, 4, ole32)
-LoadDLLfuncEx (CreateHardLinkA, 12, kernel32, 1)
LoadDLLfuncEx (FindFirstVolumeA, 8, kernel32, 1)
LoadDLLfuncEx (FindNextVolumeA, 12, kernel32, 1)
LoadDLLfuncEx (FindVolumeClose, 4, kernel32, 1)
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 2ab830b..dcbc137 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
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index cb2cccf..aca6725 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -11,17 +11,18 @@
#ifndef STATUS_INVALID_INFO_CLASS
/* Some w32api header file defines this so we need to conditionalize this
define to avoid warnings. */
-#define STATUS_INVALID_INFO_CLASS ((NTSTATUS) 0xc0000003)
+#define STATUS_INVALID_INFO_CLASS ((NTSTATUS) 0xc0000003)
#endif
-#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004)
-#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xc000000d)
-#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xc0000023)
-#define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xc0000043)
-#define STATUS_DELETE_PENDING ((NTSTATUS) 0xc0000056)
-#define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xc00000a1)
-#define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS) 0x00000106)
-#define STATUS_INVALID_LEVEL ((NTSTATUS) 0xc0000148)
-#define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006)
+#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004)
+#define STATUS_INVALID_PARAMETER ((NTSTATUS) 0xc000000d)
+#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS) 0xc0000010)
+#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xc0000023)
+#define STATUS_SHARING_VIOLATION ((NTSTATUS) 0xc0000043)
+#define STATUS_DELETE_PENDING ((NTSTATUS) 0xc0000056)
+#define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xc00000a1)
+#define STATUS_NOT_ALL_ASSIGNED ((NTSTATUS) 0x00000106)
+#define STATUS_INVALID_LEVEL ((NTSTATUS) 0xc0000148)
+#define STATUS_NO_MORE_FILES ((NTSTATUS) 0x80000006)
#define PDI_MODULES 0x01
#define PDI_HEAPS 0x04
#define LDRP_IMAGE_DLL 0x00000004
@@ -581,6 +582,13 @@ typedef struct _FILE_NAME_INFORMATION {
WCHAR FileName[1];
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
+typedef struct _FILE_LINK_INFORMATION {
+ BOOLEAN ReplaceIfExists;
+ HANDLE RootDirectory;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} FILE_LINK_INFORMATION, *PFILE_LINK_INFORMATION;
+
typedef struct _FILE_RENAME_INFORMATION {
BOOLEAN ReplaceIfExists;
HANDLE RootDirectory;