* 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:
parent
6c64fb2fda
commit
cbfb7b1b23
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 (); }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue