* fhandler_disk_file.cc (fhandler_disk_file::link): Use FILE_ANY_ACCESS.

(fhandler_base::utimes_fs): Fix white space.
	(fhandler_disk_file::lock): Remove 9x blurb from comment.
	(fhandler_disk_file::mkdir): Use NtCreateFile/NtClose instead of
	CreateDirectoryA.
	(fhandler_disk_file::rmdir): Accommodate changes to unlink_nt.
	Simplify post-delete SMB-related tests.  Use NtQueryAttributesFile
	instead of GetFileAttributes.
	* ntdll.h (STATUS_DIRECTORY_NOT_EMPTY): Define.
	(NtQueryAttributesFile): Declare.
	* syscalls.cc (unlink_nt): Return NTSTATUS.  Drop setattrs parameter.
	Never use FILE_DELETE_ON_CLOSE, always use
	NtSetInformationFile(FileDispositionInformation) instead.
	Check for R/O attributes and open file with FILE_WRITE_ATTRIBUTES
	access if any of them are set.  Remove R/O attributes before
	marking for delete if necessary.  Revert them afterwards if necessary.
	(unlink): Accommodate changes to unlink_nt.
This commit is contained in:
Corinna Vinschen
2007-07-29 12:27:22 +00:00
parent 4368984a7b
commit ed7ec849f6
4 changed files with 138 additions and 137 deletions

View File

@ -1094,7 +1094,8 @@ fhandler_disk_file::link (const char *newpath)
NTSTATUS status;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
status = NtOpenFile (&fh, 0, pc.get_object_attr (attr, sec_none_nih), &io,
status = NtOpenFile (&fh, FILE_ANY_ACCESS,
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))
@ -1182,7 +1183,7 @@ fhandler_base::utimes_fs (const struct timeval *tvp)
IO_STATUS_BLOCK io;
FILE_BASIC_INFORMATION fbi;
fbi.CreationTime.QuadPart = 0LL;
fbi.LastAccessTime= lastaccess;
fbi.LastAccessTime = lastaccess;
fbi.LastWriteTime = lastwrite;
fbi.ChangeTime.QuadPart = 0LL;
fbi.FileAttributes = 0;
@ -1318,11 +1319,7 @@ fhandler_disk_file::pwrite (void *buf, size_t count, _off64_t offset)
/* FIXME: The correct way to do this to get POSIX locking semantics is to
keep a linked list of posix lock requests and map them into Win32 locks.
he problem is that Win32 does not deal correctly with overlapping lock
requests. Also another pain is that Win95 doesn't do non-blocking or
non-exclusive locks at all. For '95 just convert all lock requests into
blocking,exclusive locks. This shouldn't break many apps but denying all
locking would. For now just convert to Win32 locks and hope for
the best. */
requests. */
int
fhandler_disk_file::lock (int cmd, struct __flock64 *fl)
@ -1471,17 +1468,31 @@ fhandler_disk_file::mkdir (mode_t mode)
set_security_attribute (S_IFDIR | ((mode & 07777) & ~cygheap->umask),
&sa, sd);
if (CreateDirectoryA (get_win32_name (), &sa))
{
NTSTATUS status;
HANDLE dir;
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
ULONG fattr = FILE_ATTRIBUTE_DIRECTORY;
#ifdef HIDDEN_DOT_FILES
char *c = strrchr (real_dir.get_win32 (), '\\');
if ((c && c[1] == '.') || *get_win32_name () == '.')
SetFileAttributes (get_win32_name (), FILE_ATTRIBUTE_HIDDEN);
UNICODE_STRING basename;
RtlSplitUnicodePath (pc.get_nt_native_path (), NULL, &basename);
if (basename.Buffer[0] == L'.')
fattr |= FILE_ATTRIBUTE_HIDDEN;
#endif
status = NtCreateFile (&dir, FILE_LIST_DIRECTORY | SYNCHRONIZE,
pc.get_object_attr (attr, sa), &io, NULL,
fattr, FILE_SHARE_VALID_FLAGS, FILE_CREATE,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT,
NULL, 0);
if (NT_SUCCESS (status))
{
NtClose (dir);
res = 0;
}
else
__seterrno ();
__seterrno_from_nt_status (status);
return res;
}
@ -1489,47 +1500,43 @@ fhandler_disk_file::mkdir (mode_t mode)
int
fhandler_disk_file::rmdir ()
{
extern DWORD unlink_nt (path_conv &win32_name, bool setattrs);
int res = -1;
extern NTSTATUS unlink_nt (path_conv &pc);
if (!pc.isdir ())
{
set_errno (ENOTDIR);
return -1;
}
/* Even own directories can't be removed if R/O attribute is set. */
if (pc.has_attribute (FILE_ATTRIBUTE_READONLY))
SetFileAttributes (get_win32_name (),
(DWORD) pc & ~FILE_ATTRIBUTE_READONLY);
DWORD err, att = 0;
int rc = !(err = unlink_nt (pc, pc.has_attribute (FILE_ATTRIBUTE_READONLY)));
if (err)
SetLastError (err);
if (isremote () && exists ())
att = GetFileAttributes (get_win32_name ());
/* Sometimes smb indicates failure when it really succeeds, so check for
this case specifically. */
if (rc || att == INVALID_FILE_ATTRIBUTES)
if (!pc.exists ())
{
/* RemoveDirectory on a samba drive doesn't return an error if the
directory can't be removed because it's not empty. Checking for
existence afterwards keeps us informed about success. */
if (!isremote () || att == INVALID_FILE_ATTRIBUTES)
return 0;
err = ERROR_DIR_NOT_EMPTY;
set_errno (ENOENT);
return -1;
}
else
err = GetLastError ();
__seterrno_from_win_error (err);
NTSTATUS status = unlink_nt (pc);
return res;
/* Check for existence of remote dirs after trying to delete them.
Two reasons:
- Sometimes SMB indicates failure when it really succeeds.
- Removeing a directory on a samba drive doesn't return an error if the
directory can't be removed because it's not empty. */
if (isremote ())
{
OBJECT_ATTRIBUTES attr;
FILE_BASIC_INFORMATION fbi;
if (NT_SUCCESS (NtQueryAttributesFile
(pc.get_object_attr (attr, sec_none_nih), &fbi)))
status = STATUS_DIRECTORY_NOT_EMPTY;
else
status = STATUS_SUCCESS;
}
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
return -1;
}
return 0;
}
/* This is the minimal number of entries which fit into the readdir cache.