mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-18 23:12:15 +08:00
* syscalls.cc (try_to_bin): Handle remote shares as well. Just rename
files in this case, instead of moving them to the recycler. Create even more unique filename. Add comment to explain filename. (unlink_nt): Remove code returning with EBUSY on remote shares. Set bin_stat to move_to_bin except on NFS. Add comment to explain.
This commit is contained in:
parent
375dbb9d4c
commit
314c2d2fed
@ -1,3 +1,11 @@
|
||||
2009-12-17 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* syscalls.cc (try_to_bin): Handle remote shares as well. Just rename
|
||||
files in this case, instead of moving them to the recycler. Create
|
||||
even more unique filename. Add comment to explain filename.
|
||||
(unlink_nt): Remove code returning with EBUSY on remote shares.
|
||||
Set bin_stat to move_to_bin except on NFS. Add comment to explain.
|
||||
|
||||
2009-12-17 Eric Blake <ebb9@byu.net>
|
||||
|
||||
* signal.cc (nanosleep): Support 'infinite' sleep times.
|
||||
|
@ -185,61 +185,75 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access)
|
||||
goto out;
|
||||
/* Initialize recycler path. */
|
||||
RtlInitEmptyUnicodeString (&recycler, recyclerbuf, sizeof recyclerbuf);
|
||||
if (wincap.has_recycle_dot_bin ()) /* NTFS and FAT since Vista */
|
||||
RtlAppendUnicodeToString (&recycler, L"\\$Recycle.Bin\\");
|
||||
else if (pc.fs_is_ntfs ()) /* NTFS up to 2K3 */
|
||||
RtlAppendUnicodeToString (&recycler, L"\\RECYCLER\\");
|
||||
else if (pc.fs_is_fat ()) /* FAT up to 2K3 */
|
||||
RtlAppendUnicodeToString (&recycler, L"\\Recycled\\");
|
||||
else
|
||||
goto out;
|
||||
/* Is the file a subdir of the recycler? */
|
||||
RtlInitCountedUnicodeString(&fname, pfni->FileName, pfni->FileNameLength);
|
||||
if (RtlEqualUnicodePathPrefix (&fname, &recycler, TRUE))
|
||||
goto out;
|
||||
/* Is fname the recycler? Temporarily hide trailing backslash. */
|
||||
recycler.Length -= sizeof (WCHAR);
|
||||
if (RtlEqualUnicodeString (&fname, &recycler, TRUE))
|
||||
goto out;
|
||||
|
||||
/* Create root dir path from file name information. */
|
||||
RtlSplitUnicodePath (&fname, &fname, NULL);
|
||||
RtlSplitUnicodePath (pc.get_nt_native_path (), &root, NULL);
|
||||
root.Length -= fname.Length - sizeof (WCHAR);
|
||||
|
||||
/* Open root directory. All recycler bin ops are caseinsensitive. */
|
||||
InitializeObjectAttributes (&attr, &root, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
status = NtOpenFile (&rootdir, FILE_TRAVERSE, &attr, &io,
|
||||
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
|
||||
if (!NT_SUCCESS (status))
|
||||
if (!pc.isremote ())
|
||||
{
|
||||
debug_printf ("NtOpenFile (%S) failed, %08x", &root, status);
|
||||
goto out;
|
||||
}
|
||||
if (wincap.has_recycle_dot_bin ()) /* NTFS and FAT since Vista */
|
||||
RtlAppendUnicodeToString (&recycler, L"\\$Recycle.Bin\\");
|
||||
else if (pc.fs_is_ntfs ()) /* NTFS up to 2K3 */
|
||||
RtlAppendUnicodeToString (&recycler, L"\\RECYCLER\\");
|
||||
else if (pc.fs_is_fat ()) /* FAT up to 2K3 */
|
||||
RtlAppendUnicodeToString (&recycler, L"\\Recycled\\");
|
||||
else
|
||||
goto out;
|
||||
/* Is the file a subdir of the recycler? */
|
||||
RtlInitCountedUnicodeString(&fname, pfni->FileName, pfni->FileNameLength);
|
||||
if (RtlEqualUnicodePathPrefix (&fname, &recycler, TRUE))
|
||||
goto out;
|
||||
/* Is fname the recycler? Temporarily hide trailing backslash. */
|
||||
recycler.Length -= sizeof (WCHAR);
|
||||
if (RtlEqualUnicodeString (&fname, &recycler, TRUE))
|
||||
goto out;
|
||||
|
||||
/* Strip leading backslash */
|
||||
++recycler.Buffer;
|
||||
recycler.Length -= sizeof (WCHAR);
|
||||
/* Store length of recycler base dir, should it be necessary to create it. */
|
||||
recycler_base_len = recycler.Length;
|
||||
/* On NTFS the recycler dir contains user specific subdirs, which are the
|
||||
actual recycle bins per user. The name if this dir is the string
|
||||
representation of the user SID. */
|
||||
if (pc.fs_is_ntfs ())
|
||||
{
|
||||
UNICODE_STRING sid;
|
||||
WCHAR sidbuf[128];
|
||||
/* Unhide trailing backslash. */
|
||||
recycler.Length += sizeof (WCHAR);
|
||||
RtlInitEmptyUnicodeString (&sid, sidbuf, sizeof sidbuf);
|
||||
/* In contrast to what MSDN claims, this function is already available
|
||||
since NT4. */
|
||||
RtlConvertSidToUnicodeString (&sid, cygheap->user.sid (), FALSE);
|
||||
RtlAppendUnicodeStringToString (&recycler, &sid);
|
||||
recycler_user_len = recycler.Length;
|
||||
/* Create root dir path from file name information. */
|
||||
RtlSplitUnicodePath (&fname, &fname, NULL);
|
||||
RtlSplitUnicodePath (pc.get_nt_native_path (), &root, NULL);
|
||||
root.Length -= fname.Length - sizeof (WCHAR);
|
||||
|
||||
/* Open root directory. All recycler bin ops are caseinsensitive. */
|
||||
InitializeObjectAttributes (&attr, &root, OBJ_CASE_INSENSITIVE,
|
||||
NULL, NULL);
|
||||
status = NtOpenFile (&rootdir, FILE_TRAVERSE, &attr, &io,
|
||||
FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT);
|
||||
if (!NT_SUCCESS (status))
|
||||
{
|
||||
debug_printf ("NtOpenFile (%S) failed, %08x", &root, status);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Strip leading backslash */
|
||||
++recycler.Buffer;
|
||||
recycler.Length -= sizeof (WCHAR);
|
||||
/* Store length of recycler base dir, if it's necessary to create it. */
|
||||
recycler_base_len = recycler.Length;
|
||||
/* On NTFS the recycler dir contains user specific subdirs, which are the
|
||||
actual recycle bins per user. The name if this dir is the string
|
||||
representation of the user SID. */
|
||||
if (pc.fs_is_ntfs ())
|
||||
{
|
||||
UNICODE_STRING sid;
|
||||
WCHAR sidbuf[128];
|
||||
/* Unhide trailing backslash. */
|
||||
recycler.Length += sizeof (WCHAR);
|
||||
RtlInitEmptyUnicodeString (&sid, sidbuf, sizeof sidbuf);
|
||||
/* In contrast to what MSDN claims, this function is already available
|
||||
since NT4. */
|
||||
RtlConvertSidToUnicodeString (&sid, cygheap->user.sid (), FALSE);
|
||||
RtlAppendUnicodeStringToString (&recycler, &sid);
|
||||
recycler_user_len = recycler.Length;
|
||||
}
|
||||
RtlAppendUnicodeToString (&recycler, L"\\");
|
||||
}
|
||||
/* Create hopefully unique filename. */
|
||||
RtlAppendUnicodeToString (&recycler, L"\\cyg");
|
||||
/* Create hopefully unique filename.
|
||||
Since we have to stick to the current directory on remote shares, make
|
||||
the new filename at least very unlikely to match by accident. It starts
|
||||
with ".cyg", with "cyg" transposed into the Unicode low surrogate area
|
||||
starting at U+dc00. Use plain ASCII chars on filesystems not supporting
|
||||
Unicode. The rest of the filename is the inode number in hex encoding
|
||||
and a hash of the full NT path in hex. The combination allows to remove
|
||||
multiple hardlinks to the same file. */
|
||||
RtlAppendUnicodeToString (&recycler,
|
||||
pc.fs_flags () & FILE_UNICODE_ON_DISK
|
||||
? L".\xdc63\xdc79\xdc67" : L".cyg");
|
||||
pfii = (PFILE_INTERNAL_INFORMATION) infobuf;
|
||||
status = NtQueryInformationFile (fh, &io, pfii, 65536,
|
||||
FileInternalInformation);
|
||||
@ -250,14 +264,16 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access)
|
||||
goto out;
|
||||
}
|
||||
RtlInt64ToHexUnicodeString (pfii->FileId.QuadPart, &recycler, TRUE);
|
||||
RtlInt64ToHexUnicodeString (hash_path_name (0, pc.get_nt_native_path ()),
|
||||
&recycler, TRUE);
|
||||
/* Shoot. */
|
||||
pfri = (PFILE_RENAME_INFORMATION) infobuf;
|
||||
pfri->ReplaceIfExists = TRUE;
|
||||
pfri->RootDirectory = rootdir;
|
||||
pfri->RootDirectory = pc.isremote () ? NULL : rootdir;
|
||||
pfri->FileNameLength = recycler.Length;
|
||||
memcpy (pfri->FileName, recycler.Buffer, recycler.Length);
|
||||
status = NtSetInformationFile (fh, &io, pfri, 65536, FileRenameInformation);
|
||||
if (status == STATUS_OBJECT_PATH_NOT_FOUND)
|
||||
if (status == STATUS_OBJECT_PATH_NOT_FOUND && !pc.isremote ())
|
||||
{
|
||||
/* Ok, so the recycler and/or the recycler/SID directory don't exist.
|
||||
First reopen root dir with permission to create subdirs. */
|
||||
@ -503,23 +519,12 @@ unlink_nt (path_conv &pc)
|
||||
generated all the time. It looks like wrong file state information
|
||||
is stored within the NFS client, for no apparent reason, which never
|
||||
times out. Opening the file with FILE_SHARE_VALID_FLAGS will work,
|
||||
though, and it is then possible to delete the file quite normally. */
|
||||
though, and it is then possible to delete the file quite normally.
|
||||
|
||||
/* The recycle bin is only accessible locally. For in-use remote
|
||||
files we drop back to just returning EBUSY, except for NFS. */
|
||||
if (pc.isremote () && status == STATUS_SHARING_VIOLATION
|
||||
&& !pc.fs_is_nfs ())
|
||||
{
|
||||
if (fh_ro)
|
||||
{
|
||||
/* Try to reset R/O attribute and close handle. */
|
||||
NtSetAttributesFile (fh_ro, pc.file_attributes ());
|
||||
NtClose (fh_ro);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
/* Only local FS and NFS should arrive here. */
|
||||
if (!pc.isremote ())
|
||||
NFS implements its own mechanism to remove in-use files which
|
||||
looks quite similar to what we do in try_to_bin for remote files.
|
||||
That's why we don't call try_to_bin on NFS. */
|
||||
if (!pc.fs_is_nfs ())
|
||||
bin_stat = move_to_bin;
|
||||
if (!pc.isdir () || pc.isremote ())
|
||||
status = NtOpenFile (&fh, access, &attr, &io,
|
||||
|
Loading…
x
Reference in New Issue
Block a user