* 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.
This commit is contained in:
Corinna Vinschen 2006-12-10 16:43:30 +00:00
parent 6c64fb2fda
commit cbfb7b1b23
8 changed files with 151 additions and 42 deletions

View File

@ -1,3 +1,23 @@
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.

View File

@ -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)

View File

@ -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;

View File

@ -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)
{

View File

@ -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 (); }

View File

@ -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)
try_to_bin (path_conv &win32_path, HANDLE h)
{
/* 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. */
NTSTATUS status;
IO_STATUS_BLOCK io;
char recycler[CYG_MAX_PATH + 20];
/* 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;
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;

View File

@ -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));

View File

@ -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
};