* smallprint.cc (__small_vswprintf): Fix uninitialized usage of `w'.
Revamp advisory file locking to avoid cross reference pointers as well as to allow BSD flock semantics. More agressively delete unused nodes and sync objects. * fhandler.h (fhandler_base::ino): Rename from namehash. Fix comment. (fhandler_base::node): Remove. (fhandler_base::unique_id): Add. (fhandler_base::del_my_locks): New method. (get_ino): Rename from get_namehash. Change usage throughout Cygwin. (get_unique_id): New method. * fhandler.cc (fhandler_base::close): Call own del_my_locks method. Fix comment. (fhandler_base::fhandler_base): Accommodate new and changed members. (fhandler_base::fixup_after_fork): Call del_my_locks. (fhandler_base::fixup_after_exec): Ditto for files with close-on-exec flag set. * fhandler_disk_file.cc (get_ino_by_handle): Rename from readdir_get_ino_by_handle. Accommodate throughout. (fhandler_base::open_fs): Fill ino with inode number if FS has good inodes. Allocate a LUID and store in unique_id to recognize file descriptors referencing the same file object. * flock.cc: Drop flock TODO comments. Use explicit types __dev32_t and __ino64_t instead of dev_t and ino_t. (LOCK_OBJ_NAME_LEN): Change to reflect longer lf_id length. (get_obj_handle_count): New method. (lockf_t::lf_id): Change type to long long. (inode_t::get_lock_obj_handle_count): Drop in favor of static function get_obj_handle_count. (inode_t::del_locks): Remove. (inode_t::get): Add create_if_missing flag argument. (inode_t::del_my_locks): Reimplement to handle POSIX and BSD flock locks. Return if node can be deleted or not. (inode_t::~inode_t): Ditto. Close handles to i_dir and i_mtx. (fixup_lockf_after_fork): Remove. (fhandler_base::del_my_locks): New method. (fixup_lockf_after_exec): Check if node can be deleted. (inode_t::get): Only create node if create_if_missing is set. Lock the returned node here before unlocking the node list. (inode_t::get_all_locks_list): Accommodate new lf_id length. (inode_t::create_lock_obj): Ditto. (lockf_t::open_lock_obj): Ditto. Change return type to bool. De-const. Set lf_obj instead of returning a handle. (lockf_t::del_lock_obj): Call SetEvent only if new incoming parameters allow it. Explain how it's supposed to work. (fhandler_disk_file::lock): Only fetch file length in SEEK_END case. Use NtQueryInformationFile(FileStandardInformation) instead of calling fstat_by_handle. Always unlock node before returning. Use fhandler's unique id to create lf_id for BSD flock locks. Rely on node lock from inode_t::get. Call del_lock_obj on removed locks here to allow explicit unlocking. Delete node if no lock exists on the file anymore. (lf_setlock): Get file handle as additional parameter. Handle the fact that lf_getblock now always opens the attached event object. Reactivate erroneously applied patch which deactivates setting thread priority. Additionally handle blocking on BSD flock locks. (lf_clearlock): Get file handle as additional parameter. (lf_getlock): Close event handle opened by lf_getblock. (lf_getblock): Open potentially blocking event object here and check its signal state if it's a BSD flock lock. (lf_wakelock): Get file handle as additional parameter. * fork.cc (frok::child): Drop call to fixup_lockf_after_fork. * ntdll.h (struct _EVENT_BASIC_INFORMATION): Define. (enum _EVENT_INFORMATION_CLASS): Define. (NtQueryEvent): Declare. * fhandler.h (fhandler_base::fs_flags): Remove. (fhandler_base::set_fs_flags): Remove. (fhandler_base::get_fs_flags): Remove. * fhandler.cc (fhandler_base::write): Check for sparse file using pc.fs_flags(). * fhandler_disk_file.cc (fhandler_disk_file::ftruncate): Ditto. The return of the volume serial number in fs_info. * fhandler.h (get_dev): New method. * fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop call to NtQueryVolumeInformationFile(FileFsVolumeInformation). Just use get_dev() method. * fhandler_fifo.cc (fhandler_fifo::open) Use device ID and inode number to generate fifo name. * path.h (fs_info::sernum): New member. (fs_info::serial_number): New method. (path_conv::fs_serial_number): New method. * path.cc (fs_info::update): Fetch volume serial number and store in sernum.
This commit is contained in:
parent
07e2a8f376
commit
636c94d853
|
@ -1,3 +1,91 @@
|
||||||
|
2008-03-31 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* smallprint.cc (__small_vswprintf): Fix uninitialized usage of `w'.
|
||||||
|
|
||||||
|
Revamp advisory file locking to avoid cross reference pointers as well
|
||||||
|
as to allow BSD flock semantics. More agressively delete unused nodes
|
||||||
|
and sync objects.
|
||||||
|
* fhandler.h (fhandler_base::ino): Rename from namehash. Fix comment.
|
||||||
|
(fhandler_base::node): Remove.
|
||||||
|
(fhandler_base::unique_id): Add.
|
||||||
|
(fhandler_base::del_my_locks): New method.
|
||||||
|
(get_ino): Rename from get_namehash. Change usage throughout Cygwin.
|
||||||
|
(get_unique_id): New method.
|
||||||
|
* fhandler.cc (fhandler_base::close): Call own del_my_locks method.
|
||||||
|
Fix comment.
|
||||||
|
(fhandler_base::fhandler_base): Accommodate new and changed members.
|
||||||
|
(fhandler_base::fixup_after_fork): Call del_my_locks.
|
||||||
|
(fhandler_base::fixup_after_exec): Ditto for files with close-on-exec
|
||||||
|
flag set.
|
||||||
|
* fhandler_disk_file.cc (get_ino_by_handle): Rename from
|
||||||
|
readdir_get_ino_by_handle. Accommodate throughout.
|
||||||
|
(fhandler_base::open_fs): Fill ino with inode number if FS has good
|
||||||
|
inodes. Allocate a LUID and store in unique_id to recognize file
|
||||||
|
descriptors referencing the same file object.
|
||||||
|
* flock.cc: Drop flock TODO comments. Use explicit types __dev32_t
|
||||||
|
and __ino64_t instead of dev_t and ino_t.
|
||||||
|
(LOCK_OBJ_NAME_LEN): Change to reflect longer lf_id length.
|
||||||
|
(get_obj_handle_count): New method.
|
||||||
|
(lockf_t::lf_id): Change type to long long.
|
||||||
|
(inode_t::get_lock_obj_handle_count): Drop in favor of static function
|
||||||
|
get_obj_handle_count.
|
||||||
|
(inode_t::del_locks): Remove.
|
||||||
|
(inode_t::get): Add create_if_missing flag argument.
|
||||||
|
(inode_t::del_my_locks): Reimplement to handle POSIX and BSD flock
|
||||||
|
locks. Return if node can be deleted or not.
|
||||||
|
(inode_t::~inode_t): Ditto. Close handles to i_dir and i_mtx.
|
||||||
|
(fixup_lockf_after_fork): Remove.
|
||||||
|
(fhandler_base::del_my_locks): New method.
|
||||||
|
(fixup_lockf_after_exec): Check if node can be deleted.
|
||||||
|
(inode_t::get): Only create node if create_if_missing is set. Lock
|
||||||
|
the returned node here before unlocking the node list.
|
||||||
|
(inode_t::get_all_locks_list): Accommodate new lf_id length.
|
||||||
|
(inode_t::create_lock_obj): Ditto.
|
||||||
|
(lockf_t::open_lock_obj): Ditto. Change return type to bool. De-const.
|
||||||
|
Set lf_obj instead of returning a handle.
|
||||||
|
(lockf_t::del_lock_obj): Call SetEvent only if new incoming parameters
|
||||||
|
allow it. Explain how it's supposed to work.
|
||||||
|
(fhandler_disk_file::lock): Only fetch file length in SEEK_END case.
|
||||||
|
Use NtQueryInformationFile(FileStandardInformation) instead of
|
||||||
|
calling fstat_by_handle. Always unlock node before returning.
|
||||||
|
Use fhandler's unique id to create lf_id for BSD flock locks.
|
||||||
|
Rely on node lock from inode_t::get. Call del_lock_obj on removed
|
||||||
|
locks here to allow explicit unlocking. Delete node if no lock exists
|
||||||
|
on the file anymore.
|
||||||
|
(lf_setlock): Get file handle as additional parameter. Handle the fact
|
||||||
|
that lf_getblock now always opens the attached event object. Reactivate
|
||||||
|
erroneously applied patch which deactivates setting thread priority.
|
||||||
|
Additionally handle blocking on BSD flock locks.
|
||||||
|
(lf_clearlock): Get file handle as additional parameter.
|
||||||
|
(lf_getlock): Close event handle opened by lf_getblock.
|
||||||
|
(lf_getblock): Open potentially blocking event object here and check
|
||||||
|
its signal state if it's a BSD flock lock.
|
||||||
|
(lf_wakelock): Get file handle as additional parameter.
|
||||||
|
* fork.cc (frok::child): Drop call to fixup_lockf_after_fork.
|
||||||
|
* ntdll.h (struct _EVENT_BASIC_INFORMATION): Define.
|
||||||
|
(enum _EVENT_INFORMATION_CLASS): Define.
|
||||||
|
(NtQueryEvent): Declare.
|
||||||
|
|
||||||
|
* fhandler.h (fhandler_base::fs_flags): Remove.
|
||||||
|
(fhandler_base::set_fs_flags): Remove.
|
||||||
|
(fhandler_base::get_fs_flags): Remove.
|
||||||
|
* fhandler.cc (fhandler_base::write): Check for sparse file using
|
||||||
|
pc.fs_flags().
|
||||||
|
* fhandler_disk_file.cc (fhandler_disk_file::ftruncate): Ditto.
|
||||||
|
|
||||||
|
The return of the volume serial number in fs_info.
|
||||||
|
* fhandler.h (get_dev): New method.
|
||||||
|
* fhandler_disk_file.cc (fhandler_base::fstat_by_handle): Drop call to
|
||||||
|
NtQueryVolumeInformationFile(FileFsVolumeInformation). Just use
|
||||||
|
get_dev() method.
|
||||||
|
* fhandler_fifo.cc (fhandler_fifo::open) Use device ID and inode number
|
||||||
|
to generate fifo name.
|
||||||
|
* path.h (fs_info::sernum): New member.
|
||||||
|
(fs_info::serial_number): New method.
|
||||||
|
(path_conv::fs_serial_number): New method.
|
||||||
|
* path.cc (fs_info::update): Fetch volume serial number and store in
|
||||||
|
sernum.
|
||||||
|
|
||||||
2008-03-28 Corinna Vinschen <corinna@vinschen.de>
|
2008-03-28 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* flock.cc (lockf_t::operator new): Add operator taking a pointer. Call
|
* flock.cc (lockf_t::operator new): Add operator taking a pointer. Call
|
||||||
|
|
|
@ -137,7 +137,7 @@ readdir_worker (DIR *dir, dirent *de)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Compute d_ino by combining filename hash with directory hash. */
|
/* Compute d_ino by combining filename hash with directory hash. */
|
||||||
de->d_ino = ((fhandler_base *) dir->__fh)->get_namehash ();
|
de->d_ino = ((fhandler_base *) dir->__fh)->get_ino ();
|
||||||
if (!is_dot && !is_dot_dot)
|
if (!is_dot && !is_dot_dot)
|
||||||
{
|
{
|
||||||
PUNICODE_STRING w32name =
|
PUNICODE_STRING w32name =
|
||||||
|
|
|
@ -736,7 +736,7 @@ fhandler_base::write (const void *ptr, size_t len)
|
||||||
FilePositionInformation))
|
FilePositionInformation))
|
||||||
&& fpi.CurrentByteOffset.QuadPart
|
&& fpi.CurrentByteOffset.QuadPart
|
||||||
>= fsi.EndOfFile.QuadPart + (128 * 1024)
|
>= fsi.EndOfFile.QuadPart + (128 * 1024)
|
||||||
&& get_fs_flags (FILE_SUPPORTS_SPARSE_FILES))
|
&& (pc.fs_flags () & FILE_SUPPORTS_SPARSE_FILES))
|
||||||
{
|
{
|
||||||
/* If the file system supports sparse files and the application
|
/* If the file system supports sparse files and the application
|
||||||
is writing after a long seek beyond EOF, convert the file to
|
is writing after a long seek beyond EOF, convert the file to
|
||||||
|
@ -1004,13 +1004,13 @@ fhandler_base::pwrite (void *, size_t, _off64_t)
|
||||||
int
|
int
|
||||||
fhandler_base::close ()
|
fhandler_base::close ()
|
||||||
{
|
{
|
||||||
extern void del_my_locks (inode_t *);
|
|
||||||
int res = -1;
|
int res = -1;
|
||||||
|
|
||||||
syscall_printf ("closing '%s' handle %p", get_name (), get_handle ());
|
syscall_printf ("closing '%s' handle %p", get_name (), get_handle ());
|
||||||
/* Delete all POSIX locks on the file. */
|
/* Delete all POSIX locks on the file. Delete all flock locks on the
|
||||||
if (node)
|
file if this is the last reference to this file. */
|
||||||
del_my_locks (node);
|
if (unique_id)
|
||||||
|
del_my_locks (false);
|
||||||
if (nohandle () || CloseHandle (get_handle ()))
|
if (nohandle () || CloseHandle (get_handle ()))
|
||||||
res = 0;
|
res = 0;
|
||||||
else
|
else
|
||||||
|
@ -1261,15 +1261,14 @@ fhandler_base::fhandler_base () :
|
||||||
open_status (),
|
open_status (),
|
||||||
access (0),
|
access (0),
|
||||||
io_handle (NULL),
|
io_handle (NULL),
|
||||||
namehash (0),
|
ino (0),
|
||||||
openflags (0),
|
openflags (0),
|
||||||
rabuf (NULL),
|
rabuf (NULL),
|
||||||
ralen (0),
|
ralen (0),
|
||||||
raixget (0),
|
raixget (0),
|
||||||
raixput (0),
|
raixput (0),
|
||||||
rabuflen (0),
|
rabuflen (0),
|
||||||
node (NULL),
|
unique_id (0),
|
||||||
fs_flags (0),
|
|
||||||
archetype (NULL),
|
archetype (NULL),
|
||||||
usecount (0)
|
usecount (0)
|
||||||
{
|
{
|
||||||
|
@ -1340,10 +1339,9 @@ fhandler_base::fixup_after_fork (HANDLE parent)
|
||||||
fork_fixup (parent, io_handle, "io_handle");
|
fork_fixup (parent, io_handle, "io_handle");
|
||||||
if (get_overlapped ())
|
if (get_overlapped ())
|
||||||
setup_overlapped ();
|
setup_overlapped ();
|
||||||
/* POSIX locks are not inherited across fork. The lock structures
|
/* POSIX locks are not inherited across fork. */
|
||||||
are deleted globally in fixup_lockf_after_fork. Here we just
|
if (unique_id)
|
||||||
have to reset the pointer. */
|
del_my_locks (true);
|
||||||
node = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1352,6 +1350,8 @@ fhandler_base::fixup_after_exec ()
|
||||||
debug_printf ("here for '%s'", get_name ());
|
debug_printf ("here for '%s'", get_name ());
|
||||||
if (get_overlapped ())
|
if (get_overlapped ())
|
||||||
setup_overlapped ();
|
setup_overlapped ();
|
||||||
|
if (unique_id && close_on_exec ())
|
||||||
|
del_my_locks (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -125,7 +125,7 @@ class fhandler_base
|
||||||
int access;
|
int access;
|
||||||
HANDLE io_handle;
|
HANDLE io_handle;
|
||||||
|
|
||||||
__ino64_t namehash; /* hashed filename, used as inode num */
|
__ino64_t ino; /* file ID or hashed filename, depends on FS. */
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* File open flags from open () and fcntl () calls */
|
/* File open flags from open () and fcntl () calls */
|
||||||
|
@ -137,9 +137,10 @@ class fhandler_base
|
||||||
size_t raixput;
|
size_t raixput;
|
||||||
size_t rabuflen;
|
size_t rabuflen;
|
||||||
|
|
||||||
inode_t *node; /* Used for advisory file locking. See flock.cc. */
|
/* Used for advisory file locking. See flock.cc. */
|
||||||
|
long long unique_id;
|
||||||
|
void del_my_locks (bool);
|
||||||
|
|
||||||
DWORD fs_flags;
|
|
||||||
HANDLE read_state;
|
HANDLE read_state;
|
||||||
int wait_overlapped (bool&, bool, DWORD *) __attribute__ ((regparm (3)));
|
int wait_overlapped (bool&, bool, DWORD *) __attribute__ ((regparm (3)));
|
||||||
bool setup_overlapped () __attribute__ ((regparm (1)));
|
bool setup_overlapped () __attribute__ ((regparm (1)));
|
||||||
|
@ -231,10 +232,6 @@ class fhandler_base
|
||||||
ReleaseSemaphore (read_state, n, NULL);
|
ReleaseSemaphore (read_state, n, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_fs_flags (DWORD flags) { fs_flags = flags; }
|
|
||||||
bool get_fs_flags (DWORD flagval = UINT32_MAX)
|
|
||||||
{ return (fs_flags & (flagval)); }
|
|
||||||
|
|
||||||
bool get_readahead_valid () { return raixget < ralen; }
|
bool get_readahead_valid () { return raixget < ralen; }
|
||||||
int puts_readahead (const char *s, size_t len = (size_t) -1);
|
int puts_readahead (const char *s, size_t len = (size_t) -1);
|
||||||
int put_readahead (char value);
|
int put_readahead (char value);
|
||||||
|
@ -255,7 +252,9 @@ class fhandler_base
|
||||||
bool has_attribute (DWORD x) const {return pc.has_attribute (x);}
|
bool has_attribute (DWORD x) const {return pc.has_attribute (x);}
|
||||||
const char *get_name () const { return pc.normalized_path; }
|
const char *get_name () const { return pc.normalized_path; }
|
||||||
const char *get_win32_name () { return pc.get_win32 (); }
|
const char *get_win32_name () { return pc.get_win32 (); }
|
||||||
__ino64_t get_namehash () { return namehash ?: namehash = hash_path_name (0, pc.get_nt_native_path ()); }
|
__dev32_t get_dev () { return pc.fs_serial_number (); }
|
||||||
|
__ino64_t get_ino () { return ino ?: ino = hash_path_name (0, pc.get_nt_native_path ()); }
|
||||||
|
long long get_unique_id () const { return unique_id; }
|
||||||
/* Returns name used for /proc/<pid>/fd in buf. */
|
/* Returns name used for /proc/<pid>/fd in buf. */
|
||||||
virtual char *get_proc_fd_name (char *buf);
|
virtual char *get_proc_fd_name (char *buf);
|
||||||
|
|
||||||
|
|
|
@ -169,6 +169,18 @@ is_volume_mountpoint (POBJECT_ATTRIBUTES attr)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline __ino64_t
|
||||||
|
get_ino_by_handle (HANDLE hdl)
|
||||||
|
{
|
||||||
|
IO_STATUS_BLOCK io;
|
||||||
|
FILE_INTERNAL_INFORMATION pfai;
|
||||||
|
|
||||||
|
if (NT_SUCCESS (NtQueryInformationFile (hdl, &io, &pfai, sizeof pfai,
|
||||||
|
FileInternalInformation)))
|
||||||
|
return pfai.FileId.QuadPart;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned __stdcall
|
unsigned __stdcall
|
||||||
path_conv::ndisk_links (DWORD nNumberOfLinks)
|
path_conv::ndisk_links (DWORD nNumberOfLinks)
|
||||||
{
|
{
|
||||||
|
@ -264,23 +276,10 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
/* The entries potentially contain a name of MAX_PATH wide characters. */
|
/* The entries potentially contain a name of MAX_PATH wide characters. */
|
||||||
const DWORD fvi_size = (NAME_MAX + 1) * sizeof (WCHAR)
|
|
||||||
+ sizeof (FILE_FS_VOLUME_INFORMATION);
|
|
||||||
const DWORD fai_size = (NAME_MAX + 1) * sizeof (WCHAR)
|
const DWORD fai_size = (NAME_MAX + 1) * sizeof (WCHAR)
|
||||||
+ sizeof (FILE_ALL_INFORMATION);
|
+ sizeof (FILE_ALL_INFORMATION);
|
||||||
|
|
||||||
PFILE_FS_VOLUME_INFORMATION pfvi = (PFILE_FS_VOLUME_INFORMATION)
|
|
||||||
alloca (fvi_size);
|
|
||||||
PFILE_ALL_INFORMATION pfai = (PFILE_ALL_INFORMATION) alloca (fai_size);
|
PFILE_ALL_INFORMATION pfai = (PFILE_ALL_INFORMATION) alloca (fai_size);
|
||||||
|
|
||||||
status = NtQueryVolumeInformationFile (get_handle (), &io, pfvi, fvi_size,
|
|
||||||
FileFsVolumeInformation);
|
|
||||||
if (!NT_SUCCESS (status))
|
|
||||||
{
|
|
||||||
debug_printf ("%p = NtQueryVolumeInformationFile(%S)", status,
|
|
||||||
pc.get_nt_native_path ());
|
|
||||||
pfvi->VolumeSerialNumber = 0;
|
|
||||||
}
|
|
||||||
status = NtQueryInformationFile (get_handle (), &io, pfai, fai_size,
|
status = NtQueryInformationFile (get_handle (), &io, pfai, fai_size,
|
||||||
FileAllInformation);
|
FileAllInformation);
|
||||||
if (NT_SUCCESS (status))
|
if (NT_SUCCESS (status))
|
||||||
|
@ -298,7 +297,7 @@ fhandler_base::fstat_by_handle (struct __stat64 *buf)
|
||||||
*(FILETIME *) &pfai->BasicInformation.LastAccessTime,
|
*(FILETIME *) &pfai->BasicInformation.LastAccessTime,
|
||||||
*(FILETIME *) &pfai->BasicInformation.LastWriteTime,
|
*(FILETIME *) &pfai->BasicInformation.LastWriteTime,
|
||||||
*(FILETIME *) &pfai->BasicInformation.CreationTime,
|
*(FILETIME *) &pfai->BasicInformation.CreationTime,
|
||||||
pfvi->VolumeSerialNumber,
|
get_dev (),
|
||||||
pfai->StandardInformation.EndOfFile.QuadPart,
|
pfai->StandardInformation.EndOfFile.QuadPart,
|
||||||
pfai->StandardInformation.AllocationSize.QuadPart,
|
pfai->StandardInformation.AllocationSize.QuadPart,
|
||||||
pfai->InternalInformation.FileId.QuadPart,
|
pfai->InternalInformation.FileId.QuadPart,
|
||||||
|
@ -357,7 +356,7 @@ fhandler_base::fstat_by_name (struct __stat64 *buf)
|
||||||
pfdi, fdi_size,
|
pfdi, fdi_size,
|
||||||
FileBothDirectoryInformation,
|
FileBothDirectoryInformation,
|
||||||
TRUE, &basename, TRUE)))
|
TRUE, &basename, TRUE)))
|
||||||
FileId.QuadPart = 0; /* get_namehash is called in fstat_helper. */
|
FileId.QuadPart = 0; /* get_ino is called in fstat_helper. */
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
debug_printf ("%p = NtQueryDirectoryFile(%S)", status,
|
debug_printf ("%p = NtQueryDirectoryFile(%S)", status,
|
||||||
|
@ -491,7 +490,7 @@ fhandler_base::fstat_helper (struct __stat64 *buf,
|
||||||
if (pc.isgood_inode (nFileIndex))
|
if (pc.isgood_inode (nFileIndex))
|
||||||
buf->st_ino = (__ino64_t) nFileIndex;
|
buf->st_ino = (__ino64_t) nFileIndex;
|
||||||
else
|
else
|
||||||
buf->st_ino = get_namehash ();
|
buf->st_ino = get_ino ();
|
||||||
|
|
||||||
buf->st_blksize = PREFERRED_IO_BLKSIZE;
|
buf->st_blksize = PREFERRED_IO_BLKSIZE;
|
||||||
|
|
||||||
|
@ -1047,7 +1046,7 @@ fhandler_disk_file::ftruncate (_off64_t length, bool allow_truncate)
|
||||||
/* Create sparse files only when called through ftruncate, not when
|
/* Create sparse files only when called through ftruncate, not when
|
||||||
called through posix_fallocate. */
|
called through posix_fallocate. */
|
||||||
if (allow_truncate
|
if (allow_truncate
|
||||||
&& get_fs_flags (FILE_SUPPORTS_SPARSE_FILES)
|
&& (pc.fs_flags () & FILE_SUPPORTS_SPARSE_FILES)
|
||||||
&& length >= fsi.EndOfFile.QuadPart + (128 * 1024))
|
&& length >= fsi.EndOfFile.QuadPart + (128 * 1024))
|
||||||
{
|
{
|
||||||
status = NtFsControlFile (get_handle (), NULL, NULL, NULL, &io,
|
status = NtFsControlFile (get_handle (), NULL, NULL, NULL, &io,
|
||||||
|
@ -1272,7 +1271,11 @@ fhandler_base::open_fs (int flags, mode_t mode)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_fs_flags (pc.fs_flags ());
|
if (pc.hasgood_inode ())
|
||||||
|
ino = get_ino_by_handle (get_handle ());
|
||||||
|
/* A unique ID is necessary to recognize fhandler entries which are
|
||||||
|
duplicated by dup(2) or fork(2). */
|
||||||
|
AllocateLocallyUniqueId ((PLUID) &unique_id);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
syscall_printf ("%d = fhandler_disk_file::open (%S, %p)", res,
|
syscall_printf ("%d = fhandler_disk_file::open (%S, %p)", res,
|
||||||
|
@ -1523,18 +1526,6 @@ free_dir:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline __ino64_t
|
|
||||||
readdir_get_ino_by_handle (HANDLE hdl)
|
|
||||||
{
|
|
||||||
IO_STATUS_BLOCK io;
|
|
||||||
FILE_INTERNAL_INFORMATION pfai;
|
|
||||||
|
|
||||||
if (!NtQueryInformationFile (hdl, &io, &pfai, sizeof pfai,
|
|
||||||
FileInternalInformation))
|
|
||||||
return pfai.FileId.QuadPart;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
__ino64_t __stdcall
|
__ino64_t __stdcall
|
||||||
readdir_get_ino (const char *path, bool dot_dot)
|
readdir_get_ino (const char *path, bool dot_dot)
|
||||||
{
|
{
|
||||||
|
@ -1569,7 +1560,7 @@ readdir_get_ino (const char *path, bool dot_dot)
|
||||||
| (pc.is_rep_symlink ()
|
| (pc.is_rep_symlink ()
|
||||||
? FILE_OPEN_REPARSE_POINT : 0))))
|
? FILE_OPEN_REPARSE_POINT : 0))))
|
||||||
{
|
{
|
||||||
ino = readdir_get_ino_by_handle (hdl);
|
ino = get_ino_by_handle (hdl);
|
||||||
NtClose (hdl);
|
NtClose (hdl);
|
||||||
}
|
}
|
||||||
return ino;
|
return ino;
|
||||||
|
@ -1607,7 +1598,7 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
|
||||||
FILE_SHARE_VALID_FLAGS,
|
FILE_SHARE_VALID_FLAGS,
|
||||||
FILE_OPEN_FOR_BACKUP_INTENT))))
|
FILE_OPEN_FOR_BACKUP_INTENT))))
|
||||||
{
|
{
|
||||||
de->d_ino = readdir_get_ino_by_handle (reph);
|
de->d_ino = get_ino_by_handle (reph);
|
||||||
NtClose (reph);
|
NtClose (reph);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1779,13 +1770,13 @@ go_ahead:
|
||||||
|
|
||||||
if (dir->__d_position == 0 && buf->FileNameLength == 2
|
if (dir->__d_position == 0 && buf->FileNameLength == 2
|
||||||
&& FileName[0] == '.')
|
&& FileName[0] == '.')
|
||||||
de->d_ino = readdir_get_ino_by_handle (get_handle ());
|
de->d_ino = get_ino_by_handle (get_handle ());
|
||||||
else if (dir->__d_position == 1 && buf->FileNameLength == 4
|
else if (dir->__d_position == 1 && buf->FileNameLength == 4
|
||||||
&& FileName[0] == L'.' && FileName[1] == L'.')
|
&& FileName[0] == L'.' && FileName[1] == L'.')
|
||||||
if (!(dir->__flags & dirent_isroot))
|
if (!(dir->__flags & dirent_isroot))
|
||||||
de->d_ino = readdir_get_ino (get_name (), true);
|
de->d_ino = readdir_get_ino (get_name (), true);
|
||||||
else
|
else
|
||||||
de->d_ino = readdir_get_ino_by_handle (get_handle ());
|
de->d_ino = get_ino_by_handle (get_handle ());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HANDLE hdl;
|
HANDLE hdl;
|
||||||
|
@ -1796,7 +1787,7 @@ go_ahead:
|
||||||
FILE_SHARE_VALID_FLAGS,
|
FILE_SHARE_VALID_FLAGS,
|
||||||
FILE_OPEN_FOR_BACKUP_INTENT)))
|
FILE_OPEN_FOR_BACKUP_INTENT)))
|
||||||
{
|
{
|
||||||
de->d_ino = readdir_get_ino_by_handle (hdl);
|
de->d_ino = get_ino_by_handle (hdl);
|
||||||
NtClose (hdl);
|
NtClose (hdl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1815,7 +1806,7 @@ go_ahead:
|
||||||
else if (!(dir->__flags & dirent_saw_dot))
|
else if (!(dir->__flags & dirent_saw_dot))
|
||||||
{
|
{
|
||||||
strcpy (de->d_name , ".");
|
strcpy (de->d_name , ".");
|
||||||
de->d_ino = readdir_get_ino_by_handle (get_handle ());
|
de->d_ino = get_ino_by_handle (get_handle ());
|
||||||
dir->__d_position++;
|
dir->__d_position++;
|
||||||
dir->__flags |= dirent_saw_dot;
|
dir->__flags |= dirent_saw_dot;
|
||||||
res = 0;
|
res = 0;
|
||||||
|
@ -1826,7 +1817,7 @@ go_ahead:
|
||||||
if (!(dir->__flags & dirent_isroot))
|
if (!(dir->__flags & dirent_isroot))
|
||||||
de->d_ino = readdir_get_ino (get_name (), true);
|
de->d_ino = readdir_get_ino (get_name (), true);
|
||||||
else
|
else
|
||||||
de->d_ino = readdir_get_ino_by_handle (get_handle ());
|
de->d_ino = get_ino_by_handle (get_handle ());
|
||||||
dir->__d_position++;
|
dir->__d_position++;
|
||||||
dir->__flags |= dirent_saw_dot_dot;
|
dir->__flags |= dirent_saw_dot_dot;
|
||||||
res = 0;
|
res = 0;
|
||||||
|
|
|
@ -68,9 +68,9 @@ fhandler_fifo::open (int flags, mode_t)
|
||||||
char npname[MAX_PATH];
|
char npname[MAX_PATH];
|
||||||
DWORD mode = 0;
|
DWORD mode = 0;
|
||||||
|
|
||||||
/* Generate a semi-unique name to associate with this fifo.
|
/* Generate a semi-unique name to associate with this fifo. */
|
||||||
FIXME: Probably should use "inode" and "dev" from stat for this. */
|
__small_sprintf (npname, "\\\\.\\pipe\\__cygfifo__%08x_%016X",
|
||||||
__small_sprintf (npname, "\\\\.\\pipe\\__cygfifo__%lx", get_namehash ());
|
get_dev (), get_ino ());
|
||||||
|
|
||||||
unsigned low_flags = flags & O_ACCMODE;
|
unsigned low_flags = flags & O_ACCMODE;
|
||||||
if (low_flags == O_RDONLY)
|
if (low_flags == O_RDONLY)
|
||||||
|
|
|
@ -143,7 +143,7 @@ fhandler_netdrive::fstat (struct __stat64 *buf)
|
||||||
fhandler_base::fstat (buf);
|
fhandler_base::fstat (buf);
|
||||||
|
|
||||||
buf->st_mode = S_IFDIR | STD_RBITS | STD_XBITS;
|
buf->st_mode = S_IFDIR | STD_RBITS | STD_XBITS;
|
||||||
buf->st_ino = get_namehash ();
|
buf->st_ino = get_ino ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ fhandler_netdrive::readdir (DIR *dir, dirent *de)
|
||||||
char *bs = strrchr (nro->lpRemoteName, '\\');
|
char *bs = strrchr (nro->lpRemoteName, '\\');
|
||||||
strcpy (de->d_name, bs ? bs + 1 : nro->lpRemoteName);
|
strcpy (de->d_name, bs ? bs + 1 : nro->lpRemoteName);
|
||||||
if (strlen (get_name ()) == 2)
|
if (strlen (get_name ()) == 2)
|
||||||
de->d_ino = hash_path_name (get_namehash (), de->d_name);
|
de->d_ino = hash_path_name (get_ino (), de->d_name);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
de->d_ino = readdir_get_ino (nro->lpRemoteName, false);
|
de->d_ino = readdir_get_ino (nro->lpRemoteName, false);
|
||||||
|
|
|
@ -122,27 +122,6 @@
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
/* Right now we implement flock(2) locks using the POSIX semantics
|
|
||||||
in terms of inheritance and removal of locks.
|
|
||||||
|
|
||||||
TODO: How to implement real BSD flock semantics?
|
|
||||||
|
|
||||||
From the Linux man page:
|
|
||||||
|
|
||||||
Locks created by flock() are associated with an open file table
|
|
||||||
entry. This means that duplicate file descriptors (created by,
|
|
||||||
for example, fork(2) or dup(2)) refer to the same lock, and
|
|
||||||
this lock may be modified or released using any of these
|
|
||||||
descriptors. Furthermore, the lock is released either by an
|
|
||||||
explicit LOCK_UN operation on any of these duplicate
|
|
||||||
descriptors, or when all such descriptors have been closed.
|
|
||||||
|
|
||||||
If a process uses open(2) (or similar) to obtain more than one
|
|
||||||
descriptor for the same file, these descriptors are treated
|
|
||||||
independently by flock(). An attempt to lock the file using
|
|
||||||
one of these file descriptors may be denied by a lock that the
|
|
||||||
calling process has already placed via another descriptor. */
|
|
||||||
|
|
||||||
#define F_WAIT 0x10 /* Wait until lock is granted */
|
#define F_WAIT 0x10 /* Wait until lock is granted */
|
||||||
#define F_FLOCK 0x20 /* Use flock(2) semantics for lock */
|
#define F_FLOCK 0x20 /* Use flock(2) semantics for lock */
|
||||||
#define F_POSIX 0x40 /* Use POSIX semantics for lock */
|
#define F_POSIX 0x40 /* Use POSIX semantics for lock */
|
||||||
|
@ -156,7 +135,7 @@ static NO_COPY muto lockf_guard;
|
||||||
#define INODE_LIST_LOCK() (lockf_guard.init ("lockf_guard")->acquire ())
|
#define INODE_LIST_LOCK() (lockf_guard.init ("lockf_guard")->acquire ())
|
||||||
#define INODE_LIST_UNLOCK() (lockf_guard.release ())
|
#define INODE_LIST_UNLOCK() (lockf_guard.release ())
|
||||||
|
|
||||||
#define LOCK_OBJ_NAME_LEN 56
|
#define LOCK_OBJ_NAME_LEN 64
|
||||||
|
|
||||||
/* This function takes the own process security descriptor DACL and adds
|
/* This function takes the own process security descriptor DACL and adds
|
||||||
SYNCHRONIZE permissions for everyone. This allows all processes
|
SYNCHRONIZE permissions for everyone. This allows all processes
|
||||||
|
@ -298,6 +277,22 @@ get_lock_parent_dir ()
|
||||||
return dir;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the handle count of an object. */
|
||||||
|
static ULONG
|
||||||
|
get_obj_handle_count (HANDLE h)
|
||||||
|
{
|
||||||
|
OBJECT_BASIC_INFORMATION obi;
|
||||||
|
NTSTATUS status;
|
||||||
|
ULONG hdl_cnt = 0;
|
||||||
|
|
||||||
|
status = NtQueryObject (h, ObjectBasicInformation, &obi, sizeof obi, NULL);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
debug_printf ("NtQueryObject: %p\n", status);
|
||||||
|
else
|
||||||
|
hdl_cnt = obi.HandleCount;
|
||||||
|
return hdl_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
/* Per lock class. */
|
/* Per lock class. */
|
||||||
class lockf_t
|
class lockf_t
|
||||||
{
|
{
|
||||||
|
@ -306,8 +301,8 @@ class lockf_t
|
||||||
short lf_type; /* Lock type: F_RDLCK, F_WRLCK */
|
short lf_type; /* Lock type: F_RDLCK, F_WRLCK */
|
||||||
_off64_t lf_start; /* Byte # of the start of the lock */
|
_off64_t lf_start; /* Byte # of the start of the lock */
|
||||||
_off64_t lf_end; /* Byte # of the end of the lock (-1=EOF) */
|
_off64_t lf_end; /* Byte # of the end of the lock (-1=EOF) */
|
||||||
/* We need the Cygwin PID for F_GETLK, the Win PID for synchronization. */
|
long long lf_id; /* Cygwin PID for POSIX locks, a unique id per
|
||||||
pid_t lf_id; /* (P)Id of the resource holding the lock */
|
file table entry for BSD flock locks. */
|
||||||
DWORD lf_wid; /* Win PID of the resource holding the lock */
|
DWORD lf_wid; /* Win PID of the resource holding the lock */
|
||||||
class lockf_t **lf_head; /* Back pointer to the head of the lockf_t list */
|
class lockf_t **lf_head; /* Back pointer to the head of the lockf_t list */
|
||||||
class inode_t *lf_inode; /* Back pointer to the inode_t */
|
class inode_t *lf_inode; /* Back pointer to the inode_t */
|
||||||
|
@ -316,10 +311,11 @@ class lockf_t
|
||||||
|
|
||||||
lockf_t ()
|
lockf_t ()
|
||||||
: lf_flags (0), lf_type (0), lf_start (0), lf_end (0), lf_id (0),
|
: lf_flags (0), lf_type (0), lf_start (0), lf_end (0), lf_id (0),
|
||||||
lf_wid (0), lf_head (NULL), lf_inode (NULL), lf_next (NULL), lf_obj (NULL)
|
lf_wid (0), lf_head (NULL), lf_inode (NULL),
|
||||||
|
lf_next (NULL), lf_obj (NULL)
|
||||||
{}
|
{}
|
||||||
lockf_t (class inode_t *node, class lockf_t **head, short flags, short type,
|
lockf_t (class inode_t *node, class lockf_t **head, short flags, short type,
|
||||||
_off64_t start, _off64_t end, pid_t id, DWORD wid)
|
_off64_t start, _off64_t end, long long id, DWORD wid)
|
||||||
: lf_flags (flags), lf_type (type), lf_start (start), lf_end (end),
|
: lf_flags (flags), lf_type (type), lf_start (start), lf_end (end),
|
||||||
lf_id (id), lf_wid (wid), lf_head (head), lf_inode (node),
|
lf_id (id), lf_wid (wid), lf_head (head), lf_inode (node),
|
||||||
lf_next (NULL), lf_obj (NULL)
|
lf_next (NULL), lf_obj (NULL)
|
||||||
|
@ -337,9 +333,8 @@ class lockf_t
|
||||||
{ cfree (p); }
|
{ cfree (p); }
|
||||||
|
|
||||||
void create_lock_obj ();
|
void create_lock_obj ();
|
||||||
HANDLE open_lock_obj () const;
|
bool open_lock_obj ();
|
||||||
ULONG get_lock_obj_handle_count () const;
|
void del_lock_obj (HANDLE fhdl, bool signal = false);
|
||||||
void del_lock_obj ();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Per inode_t class */
|
/* Per inode_t class */
|
||||||
|
@ -352,16 +347,15 @@ class inode_t
|
||||||
lockf_t *i_lockf; /* List of locks of this process. */
|
lockf_t *i_lockf; /* List of locks of this process. */
|
||||||
lockf_t *i_all_lf; /* Temp list of all locks for this file. */
|
lockf_t *i_all_lf; /* Temp list of all locks for this file. */
|
||||||
|
|
||||||
dev_t i_dev;
|
__dev32_t i_dev; /* Device ID */
|
||||||
ino_t i_ino;
|
__ino64_t i_ino; /* inode number */
|
||||||
private:
|
|
||||||
HANDLE i_dir; /* Not inherited! */
|
|
||||||
HANDLE i_mtx; /* Not inherited! */
|
|
||||||
|
|
||||||
void del_locks (lockf_t **head);
|
private:
|
||||||
|
HANDLE i_dir;
|
||||||
|
HANDLE i_mtx;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inode_t (dev_t dev, ino_t ino);
|
inode_t (__dev32_t dev, __ino64_t ino);
|
||||||
~inode_t ();
|
~inode_t ();
|
||||||
|
|
||||||
void *operator new (size_t size)
|
void *operator new (size_t size)
|
||||||
|
@ -369,68 +363,128 @@ class inode_t
|
||||||
void operator delete (void *p)
|
void operator delete (void *p)
|
||||||
{ cfree (p); }
|
{ cfree (p); }
|
||||||
|
|
||||||
static inode_t *get (dev_t dev, ino_t ino);
|
static inode_t *get (__dev32_t dev, __ino64_t ino, bool create_if_missing);
|
||||||
|
|
||||||
void LOCK () { WaitForSingleObject (i_mtx, INFINITE); }
|
void LOCK () { WaitForSingleObject (i_mtx, INFINITE); }
|
||||||
void UNLOCK () { ReleaseMutex (i_mtx); }
|
void UNLOCK () { ReleaseMutex (i_mtx); }
|
||||||
|
|
||||||
lockf_t *get_all_locks_list ();
|
lockf_t *get_all_locks_list ();
|
||||||
|
|
||||||
void del_my_locks () { LOCK (); del_locks (&i_lockf); UNLOCK ();
|
bool del_my_locks (long long id, HANDLE fhdl);
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Used to delete all locks on a file hold by this process. Called from
|
inode_t::~inode_t ()
|
||||||
close(2). This implements fcntl semantics.
|
|
||||||
TODO: flock(2) semantics. */
|
|
||||||
void
|
|
||||||
del_my_locks (inode_t *node)
|
|
||||||
{
|
{
|
||||||
INODE_LIST_LOCK ();
|
lockf_t *lock, *n_lock;
|
||||||
node->del_my_locks ();
|
for (lock = i_lockf; lock && (n_lock = lock->lf_next, 1); lock = n_lock)
|
||||||
LIST_REMOVE (node, i_next);
|
delete lock;
|
||||||
INODE_LIST_UNLOCK ();
|
NtClose (i_mtx);
|
||||||
|
NtClose (i_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The global inode_t list header. inode_t structs are created when a lock
|
bool
|
||||||
is requested on a file the first time from this process. */
|
inode_t::del_my_locks (long long id, HANDLE fhdl)
|
||||||
/* Called in a forked child to get rid of all inodes and locks hold by the
|
|
||||||
parent process. Child processes don't inherit locks. */
|
|
||||||
void
|
|
||||||
fixup_lockf_after_fork ()
|
|
||||||
{
|
{
|
||||||
inode_t *node, *next_node;
|
lockf_t *lock, *n_lock;
|
||||||
|
lockf_t **prev = &i_lockf;
|
||||||
|
int lc = 0;
|
||||||
|
for (lock = *prev; lock && (n_lock = lock->lf_next, 1); lock = n_lock)
|
||||||
|
{
|
||||||
|
if (lock->lf_flags & F_POSIX)
|
||||||
|
{
|
||||||
|
/* Delete all POSIX locks. */
|
||||||
|
*prev = n_lock;
|
||||||
|
++lc;
|
||||||
|
delete lock;
|
||||||
|
}
|
||||||
|
else if (id && lock->lf_id == id)
|
||||||
|
{
|
||||||
|
int cnt = 0;
|
||||||
|
cygheap_fdenum cfd (true);
|
||||||
|
while (cfd.next () >= 0)
|
||||||
|
if (cfd->get_unique_id () == lock->lf_id && ++cnt > 1)
|
||||||
|
break;
|
||||||
|
/* Delete BSD flock lock when no other fd in this process references
|
||||||
|
it anymore. */
|
||||||
|
if (cnt <= 1)
|
||||||
|
{
|
||||||
|
*prev = n_lock;
|
||||||
|
lock->del_lock_obj (fhdl);
|
||||||
|
delete lock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prev = &lock->lf_next;
|
||||||
|
}
|
||||||
|
return i_lockf == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
LIST_FOREACH_SAFE (node, &cygheap->inode_list, i_next, next_node)
|
/* Used to delete the locks on a file hold by this process. Called from
|
||||||
|
close(2) and fixup_after_fork, as well as from fixup_after_exec in
|
||||||
|
case the close_on_exec flag is set. The whole inode is deleted as
|
||||||
|
soon as no lock exists on it anymore. */
|
||||||
|
void
|
||||||
|
fhandler_base::del_my_locks (bool after_fork)
|
||||||
|
{
|
||||||
|
INODE_LIST_LOCK ();
|
||||||
|
inode_t *node = inode_t::get (get_dev (), get_ino (), false);
|
||||||
|
if (node)
|
||||||
|
{
|
||||||
|
bool no_locks_left =
|
||||||
|
node->del_my_locks (after_fork ? 0 : get_unique_id (), get_handle ());
|
||||||
|
if (no_locks_left)
|
||||||
|
{
|
||||||
|
LIST_REMOVE (node, i_next);
|
||||||
|
node->UNLOCK ();
|
||||||
delete node;
|
delete node;
|
||||||
LIST_INIT (&cygheap->inode_list);
|
}
|
||||||
|
else
|
||||||
|
node->UNLOCK ();
|
||||||
|
}
|
||||||
|
INODE_LIST_UNLOCK ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called in an execed child. The exec'ed process must allow SYNCHRONIZE
|
/* Called in an execed child. The exec'ed process must allow SYNCHRONIZE
|
||||||
access to everyone if at least one inode exists.
|
access to everyone if at least one inode exists.
|
||||||
The lock owner's Windows PID changed and all lock event objects have to
|
The lock owner's Windows PID changed and all POSIX lock event objects
|
||||||
be relabeled so that waiting processes know which process to wait on. */
|
have to be relabeled so that waiting processes know which process to
|
||||||
|
wait on. If the node has been abandoned due to close_on_exec on the
|
||||||
|
referencing fhandlers, remove the inode entirely. */
|
||||||
void
|
void
|
||||||
fixup_lockf_after_exec ()
|
fixup_lockf_after_exec ()
|
||||||
{
|
{
|
||||||
inode_t *node;
|
inode_t *node, *next_node;
|
||||||
|
|
||||||
INODE_LIST_LOCK ();
|
INODE_LIST_LOCK ();
|
||||||
if (LIST_FIRST (&cygheap->inode_list))
|
if (LIST_FIRST (&cygheap->inode_list))
|
||||||
allow_others_to_sync ();
|
allow_others_to_sync ();
|
||||||
LIST_FOREACH (node, &cygheap->inode_list, i_next)
|
LIST_FOREACH_SAFE (node, &cygheap->inode_list, i_next, next_node)
|
||||||
|
{
|
||||||
|
int cnt = 0;
|
||||||
|
cygheap_fdenum cfd (true);
|
||||||
|
while (cfd.next () >= 0)
|
||||||
|
if (cfd->get_dev () == node->i_dev
|
||||||
|
&& cfd->get_ino () == node->i_ino
|
||||||
|
&& ++cnt > 1)
|
||||||
|
break;
|
||||||
|
if (cnt == 0)
|
||||||
|
{
|
||||||
|
LIST_REMOVE (node, i_next);
|
||||||
|
delete node;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
node->LOCK ();
|
node->LOCK ();
|
||||||
for (lockf_t *lock = node->i_lockf; lock; lock = lock->lf_next)
|
for (lockf_t *lock = node->i_lockf; lock; lock = lock->lf_next)
|
||||||
|
if (lock->lf_flags & F_POSIX)
|
||||||
{
|
{
|
||||||
lock->del_lock_obj ();
|
lock->del_lock_obj (NULL);
|
||||||
lock->lf_wid = myself->dwProcessId;
|
lock->lf_wid = myself->dwProcessId;
|
||||||
lock->create_lock_obj ();
|
lock->create_lock_obj ();
|
||||||
}
|
}
|
||||||
node->UNLOCK ();
|
node->UNLOCK ();
|
||||||
}
|
}
|
||||||
LIST_INIT (&cygheap->inode_list);
|
}
|
||||||
INODE_LIST_UNLOCK ();
|
INODE_LIST_UNLOCK ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,7 +492,7 @@ fixup_lockf_after_exec ()
|
||||||
file. The file is specified by the device and inode_t number. If inode_t
|
file. The file is specified by the device and inode_t number. If inode_t
|
||||||
doesn't exist, create it. */
|
doesn't exist, create it. */
|
||||||
inode_t *
|
inode_t *
|
||||||
inode_t::get (dev_t dev, ino_t ino)
|
inode_t::get (__dev32_t dev, __ino64_t ino, bool create_if_missing)
|
||||||
{
|
{
|
||||||
inode_t *node;
|
inode_t *node;
|
||||||
|
|
||||||
|
@ -446,17 +500,19 @@ inode_t::get (dev_t dev, ino_t ino)
|
||||||
LIST_FOREACH (node, &cygheap->inode_list, i_next)
|
LIST_FOREACH (node, &cygheap->inode_list, i_next)
|
||||||
if (node->i_dev == dev && node->i_ino == ino)
|
if (node->i_dev == dev && node->i_ino == ino)
|
||||||
break;
|
break;
|
||||||
if (!node)
|
if (!node && create_if_missing)
|
||||||
{
|
{
|
||||||
node = new inode_t (dev, ino);
|
node = new inode_t (dev, ino);
|
||||||
if (node)
|
if (node)
|
||||||
LIST_INSERT_HEAD (&cygheap->inode_list, node, i_next);
|
LIST_INSERT_HEAD (&cygheap->inode_list, node, i_next);
|
||||||
}
|
}
|
||||||
|
if (node)
|
||||||
|
node->LOCK ();
|
||||||
INODE_LIST_UNLOCK ();
|
INODE_LIST_UNLOCK ();
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
inode_t::inode_t (dev_t dev, ino_t ino)
|
inode_t::inode_t (__dev32_t dev, __ino64_t ino)
|
||||||
: i_lockf (NULL), i_all_lf (NULL), i_dev (dev), i_ino (ino)
|
: i_lockf (NULL), i_all_lf (NULL), i_dev (dev), i_ino (ino)
|
||||||
{
|
{
|
||||||
HANDLE parent_dir;
|
HANDLE parent_dir;
|
||||||
|
@ -493,20 +549,6 @@ inode_t::inode_t (dev_t dev, ino_t ino)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inode_t::~inode_t ()
|
|
||||||
{
|
|
||||||
del_locks (&i_lockf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
inode_t::del_locks (lockf_t **head)
|
|
||||||
{
|
|
||||||
lockf_t *lock, *n_lock;
|
|
||||||
for (lock = *head; lock && (n_lock = lock->lf_next, 1); lock = n_lock)
|
|
||||||
delete lock;
|
|
||||||
*head = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Enumerate all lock event objects for this file and create a lockf_t
|
/* Enumerate all lock event objects for this file and create a lockf_t
|
||||||
list in the i_all_lf member. This list is searched in lf_getblock
|
list in the i_all_lf member. This list is searched in lf_getblock
|
||||||
for locks which potentially block our lock request. */
|
for locks which potentially block our lock request. */
|
||||||
|
@ -535,7 +577,7 @@ inode_t::get_all_locks_list ()
|
||||||
if (f.dbi.ObjectName.Length != LOCK_OBJ_NAME_LEN * sizeof (WCHAR))
|
if (f.dbi.ObjectName.Length != LOCK_OBJ_NAME_LEN * sizeof (WCHAR))
|
||||||
continue;
|
continue;
|
||||||
wchar_t *wc = f.dbi.ObjectName.Buffer, *endptr;
|
wchar_t *wc = f.dbi.ObjectName.Buffer, *endptr;
|
||||||
/* "%02x-%01x-%016X-%016X-%08x-%08x",
|
/* "%02x-%01x-%016X-%016X-%016X-%08x",
|
||||||
lf_flags, lf_type, lf_start, lf_end, lf_id, lf_wid */
|
lf_flags, lf_type, lf_start, lf_end, lf_id, lf_wid */
|
||||||
wc[LOCK_OBJ_NAME_LEN] = L'\0';
|
wc[LOCK_OBJ_NAME_LEN] = L'\0';
|
||||||
short flags = wcstol (wc, &endptr, 16);
|
short flags = wcstol (wc, &endptr, 16);
|
||||||
|
@ -551,8 +593,9 @@ inode_t::get_all_locks_list ()
|
||||||
_off64_t end = (_off64_t) wcstoull (endptr + 1, &endptr, 16);
|
_off64_t end = (_off64_t) wcstoull (endptr + 1, &endptr, 16);
|
||||||
if (end < -1LL || (end > 0 && end < start) || !endptr || *endptr != L'-')
|
if (end < -1LL || (end > 0 && end < start) || !endptr || *endptr != L'-')
|
||||||
continue;
|
continue;
|
||||||
pid_t id = wcstoul (endptr + 1, &endptr, 16);
|
long long id = wcstoll (endptr + 1, &endptr, 16);
|
||||||
if (!endptr || *endptr != L'-')
|
if (!endptr || *endptr != L'-'
|
||||||
|
|| ((flags & F_POSIX) && (id < 1 || id > ULONG_MAX)))
|
||||||
continue;
|
continue;
|
||||||
DWORD wid = wcstoul (endptr + 1, &endptr, 16);
|
DWORD wid = wcstoul (endptr + 1, &endptr, 16);
|
||||||
if (endptr && *endptr != L'\0')
|
if (endptr && *endptr != L'\0')
|
||||||
|
@ -580,12 +623,12 @@ inode_t::get_all_locks_list ()
|
||||||
void
|
void
|
||||||
lockf_t::create_lock_obj ()
|
lockf_t::create_lock_obj ()
|
||||||
{
|
{
|
||||||
WCHAR name[LOCK_OBJ_NAME_LEN];
|
WCHAR name[LOCK_OBJ_NAME_LEN + 1];
|
||||||
UNICODE_STRING uname;
|
UNICODE_STRING uname;
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
__small_swprintf (name, L"%02x-%01x-%016X-%016X-%08x-%08x",
|
__small_swprintf (name, L"%02x-%01x-%016X-%016X-%016X-%08x",
|
||||||
lf_flags & (F_POSIX | F_FLOCK), lf_type, lf_start,
|
lf_flags & (F_POSIX | F_FLOCK), lf_type, lf_start,
|
||||||
lf_end, lf_id, lf_wid);
|
lf_end, lf_id, lf_wid);
|
||||||
RtlInitCountedUnicodeString (&uname, name,
|
RtlInitCountedUnicodeString (&uname, name,
|
||||||
|
@ -599,58 +642,46 @@ lockf_t::create_lock_obj ()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open a lock event object for SYNCHRONIZE access (to wait for it). */
|
/* Open a lock event object for SYNCHRONIZE access (to wait for it). */
|
||||||
HANDLE
|
bool
|
||||||
lockf_t::open_lock_obj () const
|
lockf_t::open_lock_obj ()
|
||||||
{
|
{
|
||||||
WCHAR name[LOCK_OBJ_NAME_LEN];
|
WCHAR name[LOCK_OBJ_NAME_LEN + 1];
|
||||||
UNICODE_STRING uname;
|
UNICODE_STRING uname;
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
HANDLE obj;
|
|
||||||
|
|
||||||
__small_swprintf (name, L"%02x-%01x-%016X-%016X-%08x-%08x",
|
__small_swprintf (name, L"%02x-%01x-%016X-%016X-%016X-%08x",
|
||||||
lf_flags & (F_POSIX | F_FLOCK), lf_type, lf_start,
|
lf_flags & (F_POSIX | F_FLOCK), lf_type, lf_start,
|
||||||
lf_end, lf_id, lf_wid);
|
lf_end, lf_id, lf_wid);
|
||||||
RtlInitCountedUnicodeString (&uname, name,
|
RtlInitCountedUnicodeString (&uname, name,
|
||||||
LOCK_OBJ_NAME_LEN * sizeof (WCHAR));
|
LOCK_OBJ_NAME_LEN * sizeof (WCHAR));
|
||||||
InitializeObjectAttributes (&attr, &uname, 0, lf_inode->i_dir, NULL);
|
InitializeObjectAttributes (&attr, &uname, 0, lf_inode->i_dir, NULL);
|
||||||
status = NtOpenEvent (&obj, FLOCK_EVENT_ACCESS, &attr);
|
status = NtOpenEvent (&lf_obj, FLOCK_EVENT_ACCESS, &attr);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
{
|
{
|
||||||
SetLastError (RtlNtStatusToDosError (status));
|
SetLastError (RtlNtStatusToDosError (status));
|
||||||
return NULL;
|
lf_obj = NULL; /* Paranoia... */
|
||||||
}
|
}
|
||||||
return obj;
|
return lf_obj != NULL;
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the handle count of a lock object. */
|
|
||||||
ULONG
|
|
||||||
lockf_t::get_lock_obj_handle_count () const
|
|
||||||
{
|
|
||||||
OBJECT_BASIC_INFORMATION obi;
|
|
||||||
NTSTATUS status;
|
|
||||||
ULONG hdl_cnt = 0;
|
|
||||||
|
|
||||||
if (lf_obj)
|
|
||||||
{
|
|
||||||
status = NtQueryObject (lf_obj, ObjectBasicInformation,
|
|
||||||
&obi, sizeof obi, NULL);
|
|
||||||
if (!NT_SUCCESS (status))
|
|
||||||
debug_printf ("NtQueryObject: %p\n", status);
|
|
||||||
else
|
|
||||||
hdl_cnt = obi.HandleCount;
|
|
||||||
}
|
|
||||||
return hdl_cnt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Close a lock event handle. The important thing here is to signal it
|
/* Close a lock event handle. The important thing here is to signal it
|
||||||
before closing the handle. This way all threads waiting for this
|
before closing the handle. This way all threads waiting for this
|
||||||
lock can wake up. */
|
lock can wake up. */
|
||||||
void
|
void
|
||||||
lockf_t::del_lock_obj ()
|
lockf_t::del_lock_obj (HANDLE fhdl, bool signal)
|
||||||
{
|
{
|
||||||
if (lf_obj)
|
if (lf_obj)
|
||||||
{
|
{
|
||||||
|
/* Only signal the event if it's either a POSIX lock, or, in case of
|
||||||
|
BSD flock locks, if it's an explicit unlock or if the calling fhandler
|
||||||
|
holds the last reference to the file table entry. The file table
|
||||||
|
entry in UNIX terms is equivalent to the FILE_OBJECT in Windows NT
|
||||||
|
terms. It's what the handle/descriptor references when calling
|
||||||
|
CreateFile/open. Calling DuplicateHandle/dup only creates a new
|
||||||
|
handle/descriptor to the same FILE_OBJECT/file table entry. */
|
||||||
|
if ((lf_flags & F_POSIX) || signal
|
||||||
|
|| (fhdl && get_obj_handle_count (fhdl) <= 1))
|
||||||
SetEvent (lf_obj);
|
SetEvent (lf_obj);
|
||||||
NtClose (lf_obj);
|
NtClose (lf_obj);
|
||||||
lf_obj = NULL;
|
lf_obj = NULL;
|
||||||
|
@ -659,14 +690,14 @@ lockf_t::del_lock_obj ()
|
||||||
|
|
||||||
lockf_t::~lockf_t ()
|
lockf_t::~lockf_t ()
|
||||||
{
|
{
|
||||||
del_lock_obj ();
|
del_lock_obj (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This variable controls the maximum number of processes that will
|
* This variable controls the maximum number of processes that will
|
||||||
* be checked in doing deadlock detection.
|
* be checked in doing deadlock detection.
|
||||||
*/
|
*/
|
||||||
#if 0 /*TODO*/
|
#ifndef __CYGWIN__
|
||||||
#define MAXDEPTH 50
|
#define MAXDEPTH 50
|
||||||
static int maxlockdepth = MAXDEPTH;
|
static int maxlockdepth = MAXDEPTH;
|
||||||
#endif
|
#endif
|
||||||
|
@ -674,13 +705,13 @@ static int maxlockdepth = MAXDEPTH;
|
||||||
#define NOLOCKF (struct lockf_t *)0
|
#define NOLOCKF (struct lockf_t *)0
|
||||||
#define SELF 0x1
|
#define SELF 0x1
|
||||||
#define OTHERS 0x2
|
#define OTHERS 0x2
|
||||||
static int lf_clearlock (lockf_t *, lockf_t **);
|
static int lf_clearlock (lockf_t *, lockf_t **, HANDLE);
|
||||||
static int lf_findoverlap (lockf_t *, lockf_t *, int, lockf_t ***, lockf_t **);
|
static int lf_findoverlap (lockf_t *, lockf_t *, int, lockf_t ***, lockf_t **);
|
||||||
static lockf_t *lf_getblock (lockf_t *, inode_t *node);
|
static lockf_t *lf_getblock (lockf_t *, inode_t *node);
|
||||||
static int lf_getlock (lockf_t *, inode_t *, struct __flock64 *);
|
static int lf_getlock (lockf_t *, inode_t *, struct __flock64 *);
|
||||||
static int lf_setlock (lockf_t *, inode_t *, lockf_t **);
|
static int lf_setlock (lockf_t *, inode_t *, lockf_t **, HANDLE);
|
||||||
static void lf_split (lockf_t *, lockf_t *, lockf_t **);
|
static void lf_split (lockf_t *, lockf_t *, lockf_t **);
|
||||||
static void lf_wakelock (lockf_t *);
|
static void lf_wakelock (lockf_t *, HANDLE);
|
||||||
|
|
||||||
int
|
int
|
||||||
fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
||||||
|
@ -688,7 +719,6 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
||||||
_off64_t start, end, oadd;
|
_off64_t start, end, oadd;
|
||||||
lockf_t *n;
|
lockf_t *n;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
struct __stat64 stat;
|
|
||||||
|
|
||||||
short a_flags = fl->l_type & (F_POSIX | F_FLOCK);
|
short a_flags = fl->l_type & (F_POSIX | F_FLOCK);
|
||||||
short type = fl->l_type & (F_RDLCK | F_WRLCK | F_UNLCK);
|
short type = fl->l_type & (F_RDLCK | F_WRLCK | F_UNLCK);
|
||||||
|
@ -725,9 +755,6 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fstat_by_handle (&stat) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert the flock structure into a start and end.
|
* Convert the flock structure into a start and end.
|
||||||
*/
|
*/
|
||||||
|
@ -743,12 +770,25 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SEEK_END:
|
case SEEK_END:
|
||||||
if (fl->l_start > 0 && stat.st_size > OFF_MAX - fl->l_start)
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
IO_STATUS_BLOCK io;
|
||||||
|
FILE_STANDARD_INFORMATION fsi;
|
||||||
|
|
||||||
|
status = NtQueryInformationFile (get_handle (), &io, &fsi, sizeof fsi,
|
||||||
|
FileStandardInformation);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
__seterrno_from_nt_status (status);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fl->l_start > 0 && fsi.EndOfFile.QuadPart > OFF_MAX - fl->l_start)
|
||||||
{
|
{
|
||||||
set_errno (EOVERFLOW);
|
set_errno (EOVERFLOW);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
start = stat.st_size + fl->l_start;
|
start = fsi.EndOfFile.QuadPart + fl->l_start;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -787,16 +827,14 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
||||||
end = start + oadd;
|
end = start + oadd;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!node)
|
inode_t *node = inode_t::get (get_dev (), get_ino (), true);
|
||||||
{
|
|
||||||
node = inode_t::get (stat.st_dev, stat.st_ino);
|
|
||||||
if (!node)
|
if (!node)
|
||||||
{
|
{
|
||||||
set_errno (ENOLCK);
|
set_errno (ENOLCK);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
need_fork_fixup (true);
|
need_fork_fixup (true);
|
||||||
}
|
|
||||||
/* Unlock the fd table which has been locked in fcntl_worker, otherwise
|
/* Unlock the fd table which has been locked in fcntl_worker, otherwise
|
||||||
a blocking F_SETLKW never wakes up on a signal. */
|
a blocking F_SETLKW never wakes up on a signal. */
|
||||||
cygheap->fdtab.unlock ();
|
cygheap->fdtab.unlock ();
|
||||||
|
@ -810,6 +848,7 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
||||||
{
|
{
|
||||||
if (a_op != F_SETLK)
|
if (a_op != F_SETLK)
|
||||||
{
|
{
|
||||||
|
node->UNLOCK ();
|
||||||
fl->l_type = F_UNLCK;
|
fl->l_type = F_UNLCK;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -823,6 +862,7 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
||||||
clean = new lockf_t ();
|
clean = new lockf_t ();
|
||||||
if (!clean)
|
if (!clean)
|
||||||
{
|
{
|
||||||
|
node->UNLOCK ();
|
||||||
set_errno (ENOLCK);
|
set_errno (ENOLCK);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -831,22 +871,24 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
||||||
* Create the lockf_t structure
|
* Create the lockf_t structure
|
||||||
*/
|
*/
|
||||||
lockf_t *lock = new lockf_t (node, head, a_flags, type, start, end,
|
lockf_t *lock = new lockf_t (node, head, a_flags, type, start, end,
|
||||||
getpid (), myself->dwProcessId);
|
(a_flags & F_FLOCK) ? get_unique_id ()
|
||||||
|
: getpid (),
|
||||||
|
myself->dwProcessId);
|
||||||
if (!lock)
|
if (!lock)
|
||||||
{
|
{
|
||||||
|
node->UNLOCK ();
|
||||||
set_errno (ENOLCK);
|
set_errno (ENOLCK);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
node->LOCK ();
|
|
||||||
switch (a_op)
|
switch (a_op)
|
||||||
{
|
{
|
||||||
case F_SETLK:
|
case F_SETLK:
|
||||||
error = lf_setlock (lock, node, &clean);
|
error = lf_setlock (lock, node, &clean, get_handle ());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case F_UNLCK:
|
case F_UNLCK:
|
||||||
error = lf_clearlock (lock, &clean);
|
error = lf_clearlock (lock, &clean, get_handle ());
|
||||||
lock->lf_next = clean;
|
lock->lf_next = clean;
|
||||||
clean = lock;
|
clean = lock;
|
||||||
break;
|
break;
|
||||||
|
@ -866,9 +908,19 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
||||||
for (lock = clean; lock != NULL; )
|
for (lock = clean; lock != NULL; )
|
||||||
{
|
{
|
||||||
n = lock->lf_next;
|
n = lock->lf_next;
|
||||||
|
lock->del_lock_obj (get_handle (), a_op == F_UNLCK);
|
||||||
delete lock;
|
delete lock;
|
||||||
lock = n;
|
lock = n;
|
||||||
}
|
}
|
||||||
|
if (node->i_lockf == NULL)
|
||||||
|
{
|
||||||
|
INODE_LIST_LOCK ();
|
||||||
|
LIST_REMOVE (node, i_next);
|
||||||
|
node->UNLOCK ();
|
||||||
|
delete node;
|
||||||
|
INODE_LIST_UNLOCK ();
|
||||||
|
}
|
||||||
|
else
|
||||||
node->UNLOCK ();
|
node->UNLOCK ();
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
|
@ -882,7 +934,7 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
|
||||||
* Set a byte-range lock.
|
* Set a byte-range lock.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean)
|
lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
|
||||||
{
|
{
|
||||||
lockf_t *block;
|
lockf_t *block;
|
||||||
lockf_t **head = lock->lf_head;
|
lockf_t **head = lock->lf_head;
|
||||||
|
@ -903,6 +955,10 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean)
|
||||||
node->i_all_lf = (lockf_t *) tp.w_get ();
|
node->i_all_lf = (lockf_t *) tp.w_get ();
|
||||||
while ((block = lf_getblock(lock, node)))
|
while ((block = lf_getblock(lock, node)))
|
||||||
{
|
{
|
||||||
|
DWORD ret;
|
||||||
|
HANDLE obj = block->lf_obj;
|
||||||
|
block->lf_obj = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free the structure and return if nonblocking.
|
* Free the structure and return if nonblocking.
|
||||||
*/
|
*/
|
||||||
|
@ -910,6 +966,8 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean)
|
||||||
{
|
{
|
||||||
lock->lf_next = *clean;
|
lock->lf_next = *clean;
|
||||||
*clean = lock;
|
*clean = lock;
|
||||||
|
if (obj)
|
||||||
|
NtClose (obj);
|
||||||
return EAGAIN;
|
return EAGAIN;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -928,8 +986,12 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean)
|
||||||
intelligent. If it turns out to be too dumb, we might
|
intelligent. If it turns out to be too dumb, we might
|
||||||
have to remove it or to find another method. */
|
have to remove it or to find another method. */
|
||||||
for (lockf_t *lk = node->i_lockf; lk; lk = lk->lf_next)
|
for (lockf_t *lk = node->i_lockf; lk; lk = lk->lf_next)
|
||||||
if ((lk->lf_flags & F_POSIX) && lk->get_lock_obj_handle_count () > 1)
|
if ((lk->lf_flags & F_POSIX) && get_obj_handle_count (lk->lf_obj) > 1)
|
||||||
|
{
|
||||||
|
if (obj)
|
||||||
|
NtClose (obj);
|
||||||
return EDEADLK;
|
return EDEADLK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For flock type locks, we must first remove
|
* For flock type locks, we must first remove
|
||||||
|
@ -939,7 +1001,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean)
|
||||||
if ((lock->lf_flags & F_FLOCK) && lock->lf_type == F_WRLCK)
|
if ((lock->lf_flags & F_FLOCK) && lock->lf_type == F_WRLCK)
|
||||||
{
|
{
|
||||||
lock->lf_type = F_UNLCK;
|
lock->lf_type = F_UNLCK;
|
||||||
(void) lf_clearlock (lock, clean);
|
(void) lf_clearlock (lock, clean, fhdl);
|
||||||
lock->lf_type = F_WRLCK;
|
lock->lf_type = F_WRLCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -947,10 +1009,9 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean)
|
||||||
* Add our lock to the blocked list and sleep until we're free.
|
* Add our lock to the blocked list and sleep until we're free.
|
||||||
* Remember who blocked us (for deadlock detection).
|
* Remember who blocked us (for deadlock detection).
|
||||||
*/
|
*/
|
||||||
/* FIXME? See deadlock recognition above. */
|
/* Cygwin: No locked list. See deadlock recognition above. */
|
||||||
|
|
||||||
/* Wait for the blocking object and its holding process. */
|
/* Wait for the blocking object and its holding process. */
|
||||||
HANDLE obj = block->open_lock_obj ();
|
|
||||||
if (!obj)
|
if (!obj)
|
||||||
{
|
{
|
||||||
/* We can't synchronize on the lock event object.
|
/* We can't synchronize on the lock event object.
|
||||||
|
@ -959,6 +1020,9 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean)
|
||||||
"Win32 pid %lu: %E", block->lf_wid);
|
"Win32 pid %lu: %E", block->lf_wid);
|
||||||
return EDEADLK;
|
return EDEADLK;
|
||||||
}
|
}
|
||||||
|
SetThreadPriority (GetCurrentThread (), priority);
|
||||||
|
if (lock->lf_flags & F_POSIX)
|
||||||
|
{
|
||||||
HANDLE proc = OpenProcess (SYNCHRONIZE, FALSE, block->lf_wid);
|
HANDLE proc = OpenProcess (SYNCHRONIZE, FALSE, block->lf_wid);
|
||||||
if (!proc)
|
if (!proc)
|
||||||
{
|
{
|
||||||
|
@ -971,20 +1035,37 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean)
|
||||||
return EDEADLK;
|
return EDEADLK;
|
||||||
}
|
}
|
||||||
HANDLE w4[3] = { obj, proc, signal_arrived };
|
HANDLE w4[3] = { obj, proc, signal_arrived };
|
||||||
//SetThreadPriority (GetCurrentThread (), priority);
|
|
||||||
node->UNLOCK ();
|
node->UNLOCK ();
|
||||||
DWORD ret = WaitForMultipleObjects (3, w4, FALSE, INFINITE);
|
ret = WaitForMultipleObjects (3, w4, FALSE, INFINITE);
|
||||||
CloseHandle (proc);
|
CloseHandle (proc);
|
||||||
NtClose (obj);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HANDLE w4[2] = { obj, signal_arrived };
|
||||||
|
node->UNLOCK ();
|
||||||
|
/* Unfortunately, since BSD flock locks are not attached to a
|
||||||
|
specific process, we can't recognize an abandoned lock by
|
||||||
|
sync'ing with a process. We have to find out if we're the only
|
||||||
|
process left accessing this event object. */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ret = WaitForMultipleObjects (2, w4, FALSE, 100L);
|
||||||
|
}
|
||||||
|
while (ret == WAIT_TIMEOUT && get_obj_handle_count (obj) > 1);
|
||||||
|
}
|
||||||
node->LOCK ();
|
node->LOCK ();
|
||||||
//SetThreadPriority (GetCurrentThread (), old_prio);
|
NtClose (obj);
|
||||||
|
SetThreadPriority (GetCurrentThread (), old_prio);
|
||||||
switch (ret)
|
switch (ret)
|
||||||
{
|
{
|
||||||
case WAIT_OBJECT_0:
|
case WAIT_OBJECT_0:
|
||||||
case WAIT_OBJECT_0 + 1:
|
/* The lock object has been set to signalled. */
|
||||||
/* The lock object has been set to signalled or the process
|
|
||||||
holding the lock has exited. */
|
|
||||||
break;
|
break;
|
||||||
|
case WAIT_OBJECT_0 + 1:
|
||||||
|
/* For POSIX locks, the process holding the lock has exited. */
|
||||||
|
if (lock->lf_flags & F_POSIX)
|
||||||
|
break;
|
||||||
|
/*FALLTHRU*/
|
||||||
case WAIT_OBJECT_0 + 2:
|
case WAIT_OBJECT_0 + 2:
|
||||||
/* A signal came in. */
|
/* A signal came in. */
|
||||||
_my_tls.call_signal_handler ();
|
_my_tls.call_signal_handler ();
|
||||||
|
@ -1035,7 +1116,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean)
|
||||||
* able to acquire it.
|
* able to acquire it.
|
||||||
* Cygwin: Always wake lock.
|
* Cygwin: Always wake lock.
|
||||||
*/
|
*/
|
||||||
lf_wakelock (overlap);
|
lf_wakelock (overlap, fhdl);
|
||||||
overlap->lf_type = lock->lf_type;
|
overlap->lf_type = lock->lf_type;
|
||||||
overlap->create_lock_obj ();
|
overlap->create_lock_obj ();
|
||||||
lock->lf_next = *clean;
|
lock->lf_next = *clean;
|
||||||
|
@ -1060,7 +1141,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
lf_split (overlap, lock, clean);
|
lf_split (overlap, lock, clean);
|
||||||
lf_wakelock (overlap);
|
lf_wakelock (overlap, fhdl);
|
||||||
overlap->create_lock_obj ();
|
overlap->create_lock_obj ();
|
||||||
lock->create_lock_obj ();
|
lock->create_lock_obj ();
|
||||||
if (lock->lf_next && !lock->lf_next->lf_obj)
|
if (lock->lf_next && !lock->lf_next->lf_obj)
|
||||||
|
@ -1073,7 +1154,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean)
|
||||||
* acquire it, otherwise take the list.
|
* acquire it, otherwise take the list.
|
||||||
* Cygwin: Always wake old lock and create new lock.
|
* Cygwin: Always wake old lock and create new lock.
|
||||||
*/
|
*/
|
||||||
lf_wakelock (overlap);
|
lf_wakelock (overlap, fhdl);
|
||||||
/*
|
/*
|
||||||
* Add the new lock if necessary and delete the overlap.
|
* Add the new lock if necessary and delete the overlap.
|
||||||
*/
|
*/
|
||||||
|
@ -1099,7 +1180,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean)
|
||||||
overlap->lf_next = lock;
|
overlap->lf_next = lock;
|
||||||
overlap->lf_end = lock->lf_start - 1;
|
overlap->lf_end = lock->lf_start - 1;
|
||||||
prev = &lock->lf_next;
|
prev = &lock->lf_next;
|
||||||
lf_wakelock (overlap);
|
lf_wakelock (overlap, fhdl);
|
||||||
overlap->create_lock_obj ();
|
overlap->create_lock_obj ();
|
||||||
lock->create_lock_obj ();
|
lock->create_lock_obj ();
|
||||||
needtolink = 0;
|
needtolink = 0;
|
||||||
|
@ -1114,7 +1195,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean)
|
||||||
lock->lf_next = overlap;
|
lock->lf_next = overlap;
|
||||||
}
|
}
|
||||||
overlap->lf_start = lock->lf_end + 1;
|
overlap->lf_start = lock->lf_end + 1;
|
||||||
lf_wakelock (overlap);
|
lf_wakelock (overlap, fhdl);
|
||||||
lock->create_lock_obj ();
|
lock->create_lock_obj ();
|
||||||
overlap->create_lock_obj ();
|
overlap->create_lock_obj ();
|
||||||
break;
|
break;
|
||||||
|
@ -1131,7 +1212,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean)
|
||||||
* and remove it (or shrink it), then wakeup anyone we can.
|
* and remove it (or shrink it), then wakeup anyone we can.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
lf_clearlock (lockf_t *unlock, lockf_t **clean)
|
lf_clearlock (lockf_t *unlock, lockf_t **clean, HANDLE fhdl)
|
||||||
{
|
{
|
||||||
lockf_t **head = unlock->lf_head;
|
lockf_t **head = unlock->lf_head;
|
||||||
lockf_t *lf = *head;
|
lockf_t *lf = *head;
|
||||||
|
@ -1146,7 +1227,7 @@ lf_clearlock (lockf_t *unlock, lockf_t **clean)
|
||||||
/*
|
/*
|
||||||
* Wakeup the list of locks to be retried.
|
* Wakeup the list of locks to be retried.
|
||||||
*/
|
*/
|
||||||
lf_wakelock (overlap);
|
lf_wakelock (overlap, fhdl);
|
||||||
|
|
||||||
switch (ovcase)
|
switch (ovcase)
|
||||||
{
|
{
|
||||||
|
@ -1208,6 +1289,8 @@ lf_getlock (lockf_t *lock, inode_t *node, struct __flock64 *fl)
|
||||||
node->i_all_lf = (lockf_t *) tp.w_get ();
|
node->i_all_lf = (lockf_t *) tp.w_get ();
|
||||||
if ((block = lf_getblock (lock, node)))
|
if ((block = lf_getblock (lock, node)))
|
||||||
{
|
{
|
||||||
|
if (block->lf_obj)
|
||||||
|
NtClose (block->lf_obj);
|
||||||
fl->l_type = block->lf_type;
|
fl->l_type = block->lf_type;
|
||||||
fl->l_whence = SEEK_SET;
|
fl->l_whence = SEEK_SET;
|
||||||
fl->l_start = block->lf_start;
|
fl->l_start = block->lf_start;
|
||||||
|
@ -1216,7 +1299,7 @@ lf_getlock (lockf_t *lock, inode_t *node, struct __flock64 *fl)
|
||||||
else
|
else
|
||||||
fl->l_len = block->lf_end - block->lf_start + 1;
|
fl->l_len = block->lf_end - block->lf_start + 1;
|
||||||
if (block->lf_flags & F_POSIX)
|
if (block->lf_flags & F_POSIX)
|
||||||
fl->l_pid = block->lf_id;
|
fl->l_pid = (pid_t) block->lf_id;
|
||||||
else
|
else
|
||||||
fl->l_pid = -1;
|
fl->l_pid = -1;
|
||||||
}
|
}
|
||||||
|
@ -1235,6 +1318,8 @@ lf_getblock (lockf_t *lock, inode_t *node)
|
||||||
lockf_t **prev, *overlap;
|
lockf_t **prev, *overlap;
|
||||||
lockf_t *lf = node->get_all_locks_list ();
|
lockf_t *lf = node->get_all_locks_list ();
|
||||||
int ovcase;
|
int ovcase;
|
||||||
|
NTSTATUS status;
|
||||||
|
EVENT_BASIC_INFORMATION ebi;
|
||||||
|
|
||||||
prev = lock->lf_head;
|
prev = lock->lf_head;
|
||||||
while ((ovcase = lf_findoverlap (lf, lock, OTHERS, &prev, &overlap)))
|
while ((ovcase = lf_findoverlap (lf, lock, OTHERS, &prev, &overlap)))
|
||||||
|
@ -1243,7 +1328,20 @@ lf_getblock (lockf_t *lock, inode_t *node)
|
||||||
* We've found an overlap, see if it blocks us
|
* We've found an overlap, see if it blocks us
|
||||||
*/
|
*/
|
||||||
if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK))
|
if ((lock->lf_type == F_WRLCK || overlap->lf_type == F_WRLCK))
|
||||||
|
{
|
||||||
|
/* Open the event object for synchronization. */
|
||||||
|
if (!overlap->open_lock_obj () || (overlap->lf_flags & F_POSIX))
|
||||||
return overlap;
|
return overlap;
|
||||||
|
/* In case of BSD flock locks, check if the event object is
|
||||||
|
signalled. If so, the overlap doesn't actually exist anymore.
|
||||||
|
There are just a few open handles left. */
|
||||||
|
status = NtQueryEvent (overlap->lf_obj, EventBasicInformation,
|
||||||
|
&ebi, sizeof ebi, NULL);
|
||||||
|
if (!NT_SUCCESS (status) || ebi.SignalState == 0)
|
||||||
|
return overlap;
|
||||||
|
NtClose (overlap->lf_obj);
|
||||||
|
overlap->lf_obj = NULL;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Nope, point to the next one on the list and
|
* Nope, point to the next one on the list and
|
||||||
* see if it blocks us
|
* see if it blocks us
|
||||||
|
@ -1275,7 +1373,7 @@ lf_findoverlap (lockf_t *lf, lockf_t *lock, int type, lockf_t ***prev,
|
||||||
while (lf != NOLOCKF)
|
while (lf != NOLOCKF)
|
||||||
{
|
{
|
||||||
if (((type & OTHERS) && lf->lf_id == lock->lf_id)
|
if (((type & OTHERS) && lf->lf_id == lock->lf_id)
|
||||||
/* As on Linux: POSIX locks and flock locks don't interact. */
|
/* As on Linux: POSIX locks and BSD flock locks don't interact. */
|
||||||
|| (lf->lf_flags & (F_POSIX | F_FLOCK))
|
|| (lf->lf_flags & (F_POSIX | F_FLOCK))
|
||||||
!= (lock->lf_flags & (F_POSIX | F_FLOCK)))
|
!= (lock->lf_flags & (F_POSIX | F_FLOCK)))
|
||||||
{
|
{
|
||||||
|
@ -1392,9 +1490,9 @@ lf_split (lockf_t *lock1, lockf_t *lock2, lockf_t **split)
|
||||||
* all threads waiting for this lock.
|
* all threads waiting for this lock.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
lf_wakelock (lockf_t *listhead)
|
lf_wakelock (lockf_t *listhead, HANDLE fhdl)
|
||||||
{
|
{
|
||||||
listhead->del_lock_obj ();
|
listhead->del_lock_obj (fhdl, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -254,7 +254,6 @@ frok::child (volatile char * volatile here)
|
||||||
ld_preload ();
|
ld_preload ();
|
||||||
fixup_hooks_after_fork ();
|
fixup_hooks_after_fork ();
|
||||||
_my_tls.fixup_after_fork ();
|
_my_tls.fixup_after_fork ();
|
||||||
fixup_lockf_after_fork ();
|
|
||||||
wait_for_sigthread (true);
|
wait_for_sigthread (true);
|
||||||
cygwin_finished_initializing = true;
|
cygwin_finished_initializing = true;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -786,7 +786,6 @@ typedef struct _FILE_GET_EA_INFORMATION
|
||||||
CHAR EaName[1];
|
CHAR EaName[1];
|
||||||
} FILE_GET_EA_INFORMATION, *PFILE_GET_EA_INFORMATION;
|
} FILE_GET_EA_INFORMATION, *PFILE_GET_EA_INFORMATION;
|
||||||
|
|
||||||
|
|
||||||
typedef struct _FILE_FULL_EA_INFORMATION
|
typedef struct _FILE_FULL_EA_INFORMATION
|
||||||
{
|
{
|
||||||
ULONG NextEntryOffset;
|
ULONG NextEntryOffset;
|
||||||
|
@ -809,6 +808,17 @@ typedef enum _EVENT_TYPE
|
||||||
SynchronizationEvent
|
SynchronizationEvent
|
||||||
} EVENT_TYPE, *PEVENT_TYPE;
|
} EVENT_TYPE, *PEVENT_TYPE;
|
||||||
|
|
||||||
|
typedef struct _EVENT_BASIC_INFORMATION
|
||||||
|
{
|
||||||
|
EVENT_TYPE EventType;
|
||||||
|
LONG SignalState;
|
||||||
|
} EVENT_BASIC_INFORMATION, *PEVENT_BASIC_INFORMATION;
|
||||||
|
|
||||||
|
typedef enum _EVENT_INFORMATION_CLASS
|
||||||
|
{
|
||||||
|
EventBasicInformation = 0
|
||||||
|
} EVENT_INFORMATION_CLASS, *PEVENT_INFORMATION_CLASS;
|
||||||
|
|
||||||
/* Function declarations for ntdll.dll. These don't appear in any
|
/* Function declarations for ntdll.dll. These don't appear in any
|
||||||
standard Win32 header. */
|
standard Win32 header. */
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@ -865,6 +875,8 @@ extern "C"
|
||||||
BOOLEAN, PULONG, PULONG);
|
BOOLEAN, PULONG, PULONG);
|
||||||
NTSTATUS NTAPI NtQueryEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG,
|
NTSTATUS NTAPI NtQueryEaFile (HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG,
|
||||||
BOOLEAN, PVOID, ULONG, PULONG, BOOLEAN);
|
BOOLEAN, PVOID, ULONG, PULONG, BOOLEAN);
|
||||||
|
NTSTATUS NTAPI NtQueryEvent (HANDLE, EVENT_INFORMATION_CLASS, PVOID, ULONG,
|
||||||
|
PULONG);
|
||||||
NTSTATUS NTAPI NtQueryFullAttributesFile (POBJECT_ATTRIBUTES,
|
NTSTATUS NTAPI NtQueryFullAttributesFile (POBJECT_ATTRIBUTES,
|
||||||
PFILE_NETWORK_OPEN_INFORMATION);
|
PFILE_NETWORK_OPEN_INFORMATION);
|
||||||
NTSTATUS NTAPI NtQueryInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID,
|
NTSTATUS NTAPI NtQueryInformationFile (HANDLE, PIO_STATUS_BLOCK, PVOID,
|
||||||
|
|
|
@ -407,6 +407,10 @@ fs_info::update (PUNICODE_STRING upath, bool exists)
|
||||||
FILE_FS_DEVICE_INFORMATION ffdi;
|
FILE_FS_DEVICE_INFORMATION ffdi;
|
||||||
FILE_FS_OBJECTID_INFORMATION ffoi;
|
FILE_FS_OBJECTID_INFORMATION ffoi;
|
||||||
PFILE_FS_ATTRIBUTE_INFORMATION pffai;
|
PFILE_FS_ATTRIBUTE_INFORMATION pffai;
|
||||||
|
const DWORD fvi_size = (NAME_MAX + 1) * sizeof (WCHAR)
|
||||||
|
+ sizeof (FILE_FS_VOLUME_INFORMATION);
|
||||||
|
PFILE_FS_VOLUME_INFORMATION pfvi = (PFILE_FS_VOLUME_INFORMATION)
|
||||||
|
alloca (fvi_size);
|
||||||
UNICODE_STRING fsname, testname;
|
UNICODE_STRING fsname, testname;
|
||||||
|
|
||||||
InitializeObjectAttributes (&attr, upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
InitializeObjectAttributes (&attr, upath, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||||
|
@ -438,6 +442,9 @@ fs_info::update (PUNICODE_STRING upath, bool exists)
|
||||||
NtClose (vol);
|
NtClose (vol);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
status = NtQueryVolumeInformationFile (vol, &io, pfvi, fvi_size,
|
||||||
|
FileFsVolumeInformation);
|
||||||
|
sernum = NT_SUCCESS (status) ? pfvi->VolumeSerialNumber : 0;
|
||||||
status = NtQueryVolumeInformationFile (vol, &io, &ffdi, sizeof ffdi,
|
status = NtQueryVolumeInformationFile (vol, &io, &ffdi, sizeof ffdi,
|
||||||
FileFsDeviceInformation);
|
FileFsDeviceInformation);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
|
|
|
@ -108,8 +108,9 @@ struct fs_info
|
||||||
unsigned is_netapp : 1;
|
unsigned is_netapp : 1;
|
||||||
unsigned is_cdrom : 1;
|
unsigned is_cdrom : 1;
|
||||||
} status;
|
} status;
|
||||||
|
ULONG sernum;
|
||||||
public:
|
public:
|
||||||
void clear () { memset (&status, 0 , sizeof status); }
|
void clear () { memset (&status, 0 , sizeof status); sernum = 0UL; }
|
||||||
fs_info () { clear (); }
|
fs_info () { clear (); }
|
||||||
|
|
||||||
IMPLEMENT_STATUS_FLAG (DWORD, flags)
|
IMPLEMENT_STATUS_FLAG (DWORD, flags)
|
||||||
|
@ -124,6 +125,7 @@ struct fs_info
|
||||||
IMPLEMENT_STATUS_FLAG (bool, is_nfs)
|
IMPLEMENT_STATUS_FLAG (bool, is_nfs)
|
||||||
IMPLEMENT_STATUS_FLAG (bool, is_netapp)
|
IMPLEMENT_STATUS_FLAG (bool, is_netapp)
|
||||||
IMPLEMENT_STATUS_FLAG (bool, is_cdrom)
|
IMPLEMENT_STATUS_FLAG (bool, is_cdrom)
|
||||||
|
ULONG serial_number () const { return sernum; }
|
||||||
|
|
||||||
bool update (PUNICODE_STRING, bool) __attribute__ ((regparm (3)));
|
bool update (PUNICODE_STRING, bool) __attribute__ ((regparm (3)));
|
||||||
};
|
};
|
||||||
|
@ -266,6 +268,7 @@ class path_conv
|
||||||
bool fs_is_nfs () const {return fs.is_nfs ();}
|
bool fs_is_nfs () const {return fs.is_nfs ();}
|
||||||
bool fs_is_netapp () const {return fs.is_netapp ();}
|
bool fs_is_netapp () const {return fs.is_netapp ();}
|
||||||
bool fs_is_cdrom () const {return fs.is_cdrom ();}
|
bool fs_is_cdrom () const {return fs.is_cdrom ();}
|
||||||
|
ULONG fs_serial_number () const {return fs.serial_number ();}
|
||||||
void set_path (const char *p) {strcpy (path, p);}
|
void set_path (const char *p) {strcpy (path, p);}
|
||||||
void fillin (HANDLE h);
|
void fillin (HANDLE h);
|
||||||
inline size_t size ()
|
inline size_t size ()
|
||||||
|
|
|
@ -451,7 +451,7 @@ __small_vswprintf (PWCHAR dst, const WCHAR *fmt, va_list ap)
|
||||||
fillin:
|
fillin:
|
||||||
if (us->Length / sizeof (WCHAR) < n)
|
if (us->Length / sizeof (WCHAR) < n)
|
||||||
n = us->Length / sizeof (WCHAR);
|
n = us->Length / sizeof (WCHAR);
|
||||||
|
w = us->Buffer;
|
||||||
for (unsigned int i = 0; i < n; i++)
|
for (unsigned int i = 0; i < n; i++)
|
||||||
*dst++ = *w++;
|
*dst++ = *w++;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1204,7 +1204,7 @@ fstat64 (int fd, struct __stat64 *buf)
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
if (!buf->st_ino)
|
if (!buf->st_ino)
|
||||||
buf->st_ino = cfd->get_namehash ();
|
buf->st_ino = cfd->get_ino ();
|
||||||
if (!buf->st_dev)
|
if (!buf->st_dev)
|
||||||
buf->st_dev = cfd->get_device ();
|
buf->st_dev = cfd->get_device ();
|
||||||
if (!buf->st_rdev)
|
if (!buf->st_rdev)
|
||||||
|
@ -1367,7 +1367,7 @@ stat_worker (path_conv &pc, struct __stat64 *buf)
|
||||||
if (!res)
|
if (!res)
|
||||||
{
|
{
|
||||||
if (!buf->st_ino)
|
if (!buf->st_ino)
|
||||||
buf->st_ino = fh->get_namehash ();
|
buf->st_ino = fh->get_ino ();
|
||||||
if (!buf->st_dev)
|
if (!buf->st_dev)
|
||||||
buf->st_dev = fh->get_device ();
|
buf->st_dev = fh->get_device ();
|
||||||
if (!buf->st_rdev)
|
if (!buf->st_rdev)
|
||||||
|
|
Loading…
Reference in New Issue