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
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2006-12-10 19:43:30 +0300
committerCorinna Vinschen <corinna@vinschen.de>2006-12-10 19:43:30 +0300
commitcbfb7b1b23fe1e382298b45cbcb214c8d088ac77 (patch)
treef6d910bd202c12e32ec9561900b61b35ecdaca60 /winsup
parent6c64fb2fda86ae252db928f9e5595463b2ae36c5 (diff)
* autoload.cc (SHFileOperationA): Drop definition.
* ntdll.h (struct _FILE_RENAME_INFORMATION): Define. * path.cc (fs_info::update): Note length of rootdir prefix in root_len. (get_nt_native_path): New function, taking over functionality of path_conv::get_nt_native_path. (path_conv::get_nt_native_path): Just call get_nt_native_path. * path.h (get_nt_native_path): Declare. (struct fs_info): New member root_len. (fs_info::length): New inline method returning root_len. (path_conv::rootdir): New inline method returning rootdir prefix. * syscalls.cc (try_to_bin): Rewrite using only system calls. (unlink_nt): Call try_to_bin with additional handle to open file parameter. (statvfs): Use path_conv::rootdir method. * wincap.h: Define has_recycle_dot_bin throughout. * wincap.cc: Ditto.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog20
-rw-r--r--winsup/cygwin/autoload.cc1
-rw-r--r--winsup/cygwin/ntdll.h7
-rw-r--r--winsup/cygwin/path.cc11
-rw-r--r--winsup/cygwin/path.h16
-rw-r--r--winsup/cygwin/syscalls.cc127
-rw-r--r--winsup/cygwin/wincap.cc13
-rw-r--r--winsup/cygwin/wincap.h2
8 files changed, 153 insertions, 44 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 79abea9bf..b947ae2df 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,25 @@
2006-12-10 Corinna Vinschen <corinna@vinschen.de>
+ * autoload.cc (SHFileOperationA): Drop definition.
+ * ntdll.h (struct _FILE_RENAME_INFORMATION): Define.
+ * path.cc (fs_info::update): Note length of rootdir prefix in
+ root_len.
+ (get_nt_native_path): New function, taking over functionality of
+ path_conv::get_nt_native_path.
+ (path_conv::get_nt_native_path): Just call get_nt_native_path.
+ * path.h (get_nt_native_path): Declare.
+ (struct fs_info): New member root_len.
+ (fs_info::length): New inline method returning root_len.
+ (path_conv::rootdir): New inline method returning rootdir prefix.
+ * syscalls.cc (try_to_bin): Rewrite using only system calls.
+ (unlink_nt): Call try_to_bin with additional handle to open file
+ parameter.
+ (statvfs): Use path_conv::rootdir method.
+ * wincap.h: Define has_recycle_dot_bin throughout.
+ * wincap.cc: Ditto.
+
+2006-12-10 Corinna Vinschen <corinna@vinschen.de>
+
* fhandler.cc (rootdir): Clarify comment.
2006-12-10 Corinna Vinschen <corinna@vinschen.de>
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 2a0653174..1e7fb783a 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -527,7 +527,6 @@ LoadDLLfuncEx (Wow64DisableWow64FsRedirection, 4, kernel32, 1)
LoadDLLfuncEx (Wow64RevertWow64FsRedirection, 4, kernel32, 1)
LoadDLLfunc (SHGetDesktopFolder, 4, shell32)
-LoadDLLfunc (SHFileOperationA, 4, shell32)
LoadDLLfuncEx (waveOutGetNumDevs, 0, winmm, 1)
LoadDLLfuncEx (waveOutOpen, 24, winmm, 1)
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index a72965905..180ed99b0 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -506,6 +506,13 @@ typedef struct _FILE_NAME_INFORMATION {
WCHAR FileName[1];
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;
+typedef struct _FILE_RENAME_INFORMATION {
+ BOOLEAN ReplaceIfExists;
+ HANDLE RootDirectory;
+ ULONG FileNameLength;
+ WCHAR FileName[1];
+} FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION;
+
typedef struct _FILE_ALL_INFORMATION {
FILE_BASIC_INFORMATION BasicInformation;
FILE_STANDARD_INFORMATION StandardInformation;
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 49d3aecc3..9b8cd0d78 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -389,7 +389,7 @@ fs_info::update (const char *win32_path)
char root_dir [CYG_MAX_PATH];
bool ret;
- if (!rootdir (win32_path, root_dir))
+ if (!::rootdir (win32_path, root_dir))
{
debug_printf ("Cannot get root component of path %s", win32_path);
clear ();
@@ -411,6 +411,7 @@ fs_info::update (const char *win32_path)
++idx;
}
name_hash = tmp_name_hash;
+ root_len = strlen (root_dir);
/* I have no idea why, but some machines require SeChangeNotifyPrivilege
to access volume information. */
@@ -549,7 +550,7 @@ path_conv::set_normalized_path (const char *path_copy, bool strip_tail)
}
PUNICODE_STRING
-path_conv::get_nt_native_path (UNICODE_STRING &upath)
+get_nt_native_path (const char *path, UNICODE_STRING &upath)
{
if (path[0] != '\\') /* X:\... or NUL, etc. */
{
@@ -572,6 +573,12 @@ path_conv::get_nt_native_path (UNICODE_STRING &upath)
return &upath;
}
+PUNICODE_STRING
+path_conv::get_nt_native_path (UNICODE_STRING &upath)
+{
+ return ::get_nt_native_path (path, upath);
+}
+
void
warn_msdos (const char *src)
{
diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h
index e011575f2..9b4c85ea2 100644
--- a/winsup/cygwin/path.h
+++ b/winsup/cygwin/path.h
@@ -15,6 +15,8 @@ details. */
#include <fcntl.h>
#include <ntdef.h>
+extern PUNICODE_STRING get_nt_native_path (const char *, UNICODE_STRING &);
+
inline bool
has_attribute (DWORD attributes, DWORD attribs_to_test)
{
@@ -85,6 +87,7 @@ class symlink_info;
struct fs_info
{
private:
+ int root_len;
__ino64_t name_hash;
struct status_flags
{
@@ -106,6 +109,7 @@ struct fs_info
void clear ()
{
name_hash = 0;
+ root_len = 0;
flags () = serial () = 0;
is_remote_drive (false);
has_buggy_open (false);
@@ -121,6 +125,7 @@ struct fs_info
}
inline DWORD& flags () {return status.flags;};
inline DWORD& serial () {return status.serial;};
+ inline int length () const {return root_len;}
IMPLEMENT_STATUS_FLAG (bool, is_remote_drive)
IMPLEMENT_STATUS_FLAG (bool, has_buggy_open)
@@ -150,6 +155,17 @@ class path_conv
device dev;
bool case_clash;
+ int rootdir (char *buf) const
+ {
+ if (!fs.length ())
+ return fs.length ();
+ strncpy (buf, path, fs.length ());
+ /* The length is always stored with trailing backslash. Make sure the
+ backslash is actually present in the returned path. */
+ buf[fs.length () - 1] = '\\';
+ buf[fs.length ()] = '\0';
+ return fs.length ();
+ }
bool isremote () const {return fs.is_remote_drive ();}
bool has_acls () const {return fs.has_acls (); }
bool hasgood_inode () const {return fs.hasgood_inode (); }
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index e126588cb..8111d270d 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -139,47 +139,92 @@ dup2 (int oldfd, int newfd)
return cygheap->fdtab.dup2 (oldfd, newfd);
}
-#ifndef FOF_NORECURSION
-#define FOF_NORECURSION 0x1000
-#endif
-#ifndef FOF_NORECURSEREPARSE
-#define FOF_NORECURSEREPARSE 0x8000
-#endif
-
static void
-try_to_bin (const char *win32_path)
-{
-/* TODO: Using SHFileOperation for this functionality is incredibly slow.
- Given the fact that we have an open handle to the file at this
- point, there must be some quicker way to move the file to the
- bin or something bin-like. I keep this activated to remind me
- by its slowness, that this can't go into a release version as
- is. Back to the drawing board. */
-
- /* The op.pFrom parameter must be double \0 terminated since it's not
- just a filename, but a list of filenames. If the double \0 is
- missing, SHFileOperationA returns with error number 1026 (which is
- not a valid system error number). */
- char file[CYG_MAX_PATH + 1] = { 0 };
- SHFILEOPSTRUCT op;
- int ret;
+try_to_bin (path_conv &win32_path, HANDLE h)
+{
+ NTSTATUS status;
+ IO_STATUS_BLOCK io;
+ char recycler[CYG_MAX_PATH + 20];
+
+ char *c = recycler + win32_path.rootdir (recycler);
+ if (wincap.has_recycle_dot_bin ())
+ {
+ strcpy (c, "$Recycle.Bin"); /* NTFS and FAT since Vista */
+ c += 12;
+ }
+ else if (win32_path.fs_is_ntfs ())
+ {
+ strcpy (c, "RECYCLER"); /* NTFS up to 2K3 */
+ c += 8;
+ }
+ else if (win32_path.fs_is_fat ())
+ {
+ strcpy (c, "Recycled"); /* FAT up to 2K3 */
+ c += 8;
+ }
+ else
+ return;
- op.hwnd = NULL;
- op.wFunc = FO_DELETE;
- op.pFrom = strcpy (file, win32_path);
- op.pTo = NULL;
- op.fFlags = FOF_ALLOWUNDO
- | FOF_NOCONFIRMATION
- | FOF_NOCONFIRMMKDIR
- | FOF_NOERRORUI
- | FOF_NORECURSION
- | FOF_NORECURSEREPARSE
- | FOF_SILENT;
- op.fAnyOperationsAborted = FALSE;
- op.hNameMappings = NULL;
- op.lpszProgressTitle = NULL;
- ret = SHFileOperationA (&op);
- debug_printf ("SHFileOperation (%s) = %d\n", win32_path, ret);
+ /* Yes, we can really do that. Typically the recycle bin is created
+ by the first user actually using the bin. The permissions are the
+ default permissions propagated from the root directory. */
+ if (GetFileAttributes (recycler) == INVALID_FILE_ATTRIBUTES)
+ {
+ if (!CreateDirectory (recycler, NULL))
+ {
+ debug_printf ("Can't create folder %s, %E", recycler);
+ return;
+ }
+ SetFileAttributes (recycler,
+ FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+ }
+
+#if 0
+ /* The default settings for the top level recycle bin are so that
+ everybody has the right to create files in it. Should that be
+ insufficient at one point, we can enable the following code to
+ move the file into the user's own bin subdir. At this point,
+ I'm going to opt for speed, though. */
+ if (win32_path.fs_is_ntfs ())
+ {
+ *c++ = '\\';
+ cygheap->user.get_windows_id (c);
+ while (*c)
+ ++c;
+ if (GetFileAttributes (recycler) == INVALID_FILE_ATTRIBUTES)
+ {
+ if (!CreateDirectory (recycler,
+ sec_user ((PSECURITY_ATTRIBUTES) alloca (1024),
+ cygheap->user.sid ())))
+ {
+ debug_printf ("Can't create folder %s, %E", recycler);
+ return;
+ }
+ SetFileAttributes (recycler,
+ FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+ }
+ }
+#endif
+
+ /* Create hopefully unique filename. */
+ __small_sprintf (c, "\\cyg%016X", hash_path_name (myself->uid,
+ win32_path.get_win32 ()));
+ c += 20;
+
+ /* Length of thr WCHAR path in bytes. */
+ ULONG len = 2 * (c - recycler);
+ /* Choose size big enough to fit a local native NT path into it. */
+ ULONG size = sizeof (FILE_RENAME_INFORMATION) + len + 10;
+ PFILE_RENAME_INFORMATION pfri = (PFILE_RENAME_INFORMATION) alloca (size);
+
+ pfri->ReplaceIfExists = TRUE;
+ pfri->RootDirectory = NULL;
+ UNICODE_STRING uname = { 0, len + 10, pfri->FileName };
+ get_nt_native_path (recycler, uname);
+ pfri->FileNameLength = uname.Length;
+ status = NtSetInformationFile (h, &io, pfri, size, FileRenameInformation);
+ if (!NT_SUCCESS (status))
+ debug_printf ("Move %s to %s failed, status = %p", status);
}
static DWORD
@@ -238,7 +283,7 @@ unlink_nt (path_conv &win32_name, bool setattrs)
SetFileAttributes (win32_name, (DWORD) win32_name);
if (!win32_name.isremote ())
- try_to_bin (win32_name.get_win32 ());
+ try_to_bin (win32_name, h);
DWORD lasterr = 0;
@@ -1848,7 +1893,7 @@ statvfs (const char *fname, struct statvfs *sfs)
}
path_conv full_path (fname, PC_SYM_FOLLOW);
- if (!rootdir (full_path, root))
+ if (!full_path.rootdir (root))
{
set_errno (ENOTDIR);
return -1;
diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc
index 939e41585..730263415 100644
--- a/winsup/cygwin/wincap.cc
+++ b/winsup/cygwin/wincap.cc
@@ -71,6 +71,7 @@ static NO_COPY wincaps wincap_unknown = {
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
+ has_recycle_dot_bin:false,
};
static NO_COPY wincaps wincap_95 = {
@@ -133,6 +134,7 @@ static NO_COPY wincaps wincap_95 = {
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
+ has_recycle_dot_bin:false,
};
static NO_COPY wincaps wincap_95osr2 = {
@@ -195,6 +197,7 @@ static NO_COPY wincaps wincap_95osr2 = {
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
+ has_recycle_dot_bin:false,
};
static NO_COPY wincaps wincap_98 = {
@@ -257,6 +260,7 @@ static NO_COPY wincaps wincap_98 = {
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
+ has_recycle_dot_bin:false,
};
static NO_COPY wincaps wincap_98se = {
@@ -319,6 +323,7 @@ static NO_COPY wincaps wincap_98se = {
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
+ has_recycle_dot_bin:false,
};
static NO_COPY wincaps wincap_me = {
@@ -381,6 +386,7 @@ static NO_COPY wincaps wincap_me = {
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
+ has_recycle_dot_bin:false,
};
static NO_COPY wincaps wincap_nt3 = {
@@ -443,6 +449,7 @@ static NO_COPY wincaps wincap_nt3 = {
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
needs_count_in_si_lpres2:false,
+ has_recycle_dot_bin:false,
};
static NO_COPY wincaps wincap_nt4 = {
@@ -505,6 +512,7 @@ static NO_COPY wincaps wincap_nt4 = {
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
needs_count_in_si_lpres2:false,
+ has_recycle_dot_bin:false,
};
static NO_COPY wincaps wincap_nt4sp4 = {
@@ -567,6 +575,7 @@ static NO_COPY wincaps wincap_nt4sp4 = {
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
needs_count_in_si_lpres2:false,
+ has_recycle_dot_bin:false,
};
static NO_COPY wincaps wincap_2000 = {
@@ -629,6 +638,7 @@ static NO_COPY wincaps wincap_2000 = {
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:true,
needs_count_in_si_lpres2:false,
+ has_recycle_dot_bin:false,
};
static NO_COPY wincaps wincap_xp = {
@@ -691,6 +701,7 @@ static NO_COPY wincaps wincap_xp = {
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
+ has_recycle_dot_bin:false,
};
static NO_COPY wincaps wincap_2003 = {
@@ -753,6 +764,7 @@ static NO_COPY wincaps wincap_2003 = {
has_mandatory_integrity_control:false,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:false,
+ has_recycle_dot_bin:false,
};
static NO_COPY wincaps wincap_vista = {
@@ -815,6 +827,7 @@ static NO_COPY wincaps wincap_vista = {
has_mandatory_integrity_control:true,
needs_logon_sid_in_sid_list:false,
needs_count_in_si_lpres2:true,
+ has_recycle_dot_bin:true,
};
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));
diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h
index 2928f8d62..896f61109 100644
--- a/winsup/cygwin/wincap.h
+++ b/winsup/cygwin/wincap.h
@@ -72,6 +72,7 @@ struct wincaps
unsigned has_mandatory_integrity_control : 1;
unsigned needs_logon_sid_in_sid_list : 1;
unsigned needs_count_in_si_lpres2 : 1;
+ unsigned has_recycle_dot_bin : 1;
};
class wincapc
@@ -150,6 +151,7 @@ public:
bool IMPLEMENT (has_mandatory_integrity_control)
bool IMPLEMENT (needs_logon_sid_in_sid_list)
bool IMPLEMENT (needs_count_in_si_lpres2)
+ bool IMPLEMENT (has_recycle_dot_bin)
#undef IMPLEMENT
};