Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/flock.cc')
-rw-r--r--winsup/cygwin/flock.cc318
1 files changed, 49 insertions, 269 deletions
diff --git a/winsup/cygwin/flock.cc b/winsup/cygwin/flock.cc
index 4d683cfd4..16233449e 100644
--- a/winsup/cygwin/flock.cc
+++ b/winsup/cygwin/flock.cc
@@ -124,14 +124,7 @@ static NO_COPY muto lockf_guard;
#define INODE_LIST_LOCK() (lockf_guard.init ("lockf_guard")->acquire ())
#define INODE_LIST_UNLOCK() (lockf_guard.release ())
-#define LOCK_DIR_NAME_FMT L"flock-%08x-%016X"
-#define LOCK_DIR_NAME_LEN 31 /* Length of the resulting name */
-#define LOCK_DIR_NAME_DEV_OFF 6 /* Offset to device number */
-#define LOCK_DIR_NAME_INO_OFF 15 /* Offset to inode number */
-
-/* Don't change format without also changing lockf_t::from_obj_name! */
-#define LOCK_OBJ_NAME_FMT L"%02x-%01x-%016X-%016X-%016X-%08x-%04x"
-#define LOCK_OBJ_NAME_LEN 69 /* Length of the resulting name */
+#define LOCK_OBJ_NAME_LEN 69
#define FLOCK_INODE_DIR_ACCESS (DIRECTORY_QUERY \
| DIRECTORY_TRAVERSE \
@@ -164,7 +157,7 @@ allow_others_to_sync ()
at this point because this gets called during initialization when the tls
is not really available. */
#define MAX_PROCESS_SD_SIZE 3072
- PISECURITY_DESCRIPTOR sd = (PISECURITY_DESCRIPTOR) alloca (MAX_PROCESS_SD_SIZE);
+ PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR) alloca (MAX_PROCESS_SD_SIZE);
status = NtQuerySecurityObject (NtCurrentProcess (),
DACL_SECURITY_INFORMATION, sd,
MAX_PROCESS_SD_SIZE, &len);
@@ -176,22 +169,8 @@ allow_others_to_sync ()
/* Create a valid dacl pointer and set its size to be as big as
there's room in the temporary buffer. Note that the descriptor
is in self-relative format. */
- BOOLEAN present, defaulted;
- RtlGetDaclSecurityDescriptor (sd, &present, &dacl, &defaulted);
- if (!present) /* If so, dacl has undefined value. */
- {
- dacl = (PACL) (sd + 1);
- RtlCreateAcl (dacl, MAX_PROCESS_SD_SIZE - sizeof *sd, ACL_REVISION);
- }
- else if (dacl == NULL) /* Everyone has all access anyway */
- {
- done = true;
- return;
- }
- else
- {
- dacl->AclSize = MAX_PROCESS_SD_SIZE - ((PBYTE) dacl - (PBYTE) sd);
- }
+ dacl = (PACL) ((char *) sd + (uintptr_t) sd->Dacl);
+ dacl->AclSize = NT_MAX_PATH * sizeof (WCHAR) - ((char *) dacl - (char *) sd);
/* Allow everyone to SYNCHRONIZE with this process. */
status = RtlAddAccessAllowedAce (dacl, ACL_REVISION, SYNCHRONIZE,
well_known_world_sid);
@@ -246,11 +225,11 @@ struct lockfattr_t
class lockf_t
{
public:
- uint16_t lf_flags; /* Semantics: F_POSIX, F_FLOCK, F_WAIT */
- uint16_t lf_type; /* Lock type: F_RDLCK, F_WRLCK */
+ short lf_flags; /* Semantics: F_POSIX, F_FLOCK, F_WAIT */
+ short lf_type; /* Lock type: F_RDLCK, F_WRLCK */
_off64_t lf_start; /* Byte # of the start of the lock */
_off64_t lf_end; /* Byte # of the end of the lock (-1=EOF) */
- int64_t lf_id; /* Cygwin PID for POSIX locks, a unique id per
+ long long lf_id; /* Cygwin PID for POSIX locks, a unique id per
file table entry for BSD flock locks. */
DWORD lf_wid; /* Win PID of the resource holding the lock */
uint16_t lf_ver; /* Version number of the lock. If a released
@@ -276,9 +255,6 @@ class lockf_t
{}
~lockf_t ();
- bool from_obj_name (class inode_t *node, class lockf_t **head,
- const wchar_t *name);
-
/* Used to create all locks list in a given TLS buffer. */
void *operator new (size_t size, void *p)
{ return p; }
@@ -316,6 +292,10 @@ class inode_t
HANDLE i_mtx;
uint32_t i_cnt; /* # of threads referencing this instance. */
+ void use () { ++i_cnt; }
+ void unuse () { if (i_cnt > 0) --i_cnt; }
+ bool inuse () { return i_cnt > 0; }
+
public:
inode_t (__dev32_t dev, __ino64_t ino);
~inode_t ();
@@ -325,15 +305,11 @@ class inode_t
void operator delete (void *p)
{ cfree (p); }
- static inode_t *get (__dev32_t dev, __ino64_t ino,
- bool create_if_missing, bool lock);
+ static inode_t *get (__dev32_t dev, __ino64_t ino, bool create_if_missing);
void LOCK () { WaitForSingleObject (i_mtx, INFINITE); }
void UNLOCK () { ReleaseMutex (i_mtx); }
- void use () { ++i_cnt; }
- void unuse () { if (i_cnt > 0) --i_cnt; }
- bool inuse () { return i_cnt > 0; }
void notused () { i_cnt = 0; }
void unlock_and_remove_if_unused ();
@@ -414,7 +390,7 @@ inode_t::del_my_locks (long long id, HANDLE fhdl)
void
fhandler_base::del_my_locks (del_lock_called_from from)
{
- inode_t *node = inode_t::get (get_dev (), get_ino (), false, true);
+ inode_t *node = inode_t::get (get_dev (), get_ino (), false);
if (node)
{
/* When we're called from fixup_after_exec, the fhandler is a
@@ -482,7 +458,7 @@ fixup_lockf_after_exec ()
file. The file is specified by the device and inode_t number. If inode_t
doesn't exist, create it. */
inode_t *
-inode_t::get (__dev32_t dev, __ino64_t ino, bool create_if_missing, bool lock)
+inode_t::get (__dev32_t dev, __ino64_t ino, bool create_if_missing)
{
inode_t *node;
@@ -499,7 +475,7 @@ inode_t::get (__dev32_t dev, __ino64_t ino, bool create_if_missing, bool lock)
if (node)
node->use ();
INODE_LIST_UNLOCK ();
- if (node && lock)
+ if (node)
node->LOCK ();
return node;
}
@@ -516,7 +492,7 @@ inode_t::inode_t (__dev32_t dev, __ino64_t ino)
parent_dir = get_shared_parent_dir ();
/* Create a subdir which is named after the device and inode_t numbers
of the given file, in hex notation. */
- int len = __small_swprintf (name, LOCK_DIR_NAME_FMT, dev, ino);
+ int len = __small_swprintf (name, L"flock-%08x-%016X", dev, ino);
RtlInitCountedUnicodeString (&uname, name, len * sizeof (WCHAR));
InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF,
parent_dir, everyone_sd (FLOCK_INODE_DIR_ACCESS));
@@ -540,45 +516,6 @@ inode_t::inode_t (__dev32_t dev, __ino64_t ino)
#define MAX_LOCKF_CNT ((intptr_t)((NT_MAX_PATH * sizeof (WCHAR)) \
/ sizeof (lockf_t)))
-bool
-lockf_t::from_obj_name (inode_t *node, lockf_t **head, const wchar_t *name)
-{
- wchar_t *endptr;
-
- /* "%02x-%01x-%016X-%016X-%016X-%08x-%04x",
- lf_flags, lf_type, lf_start, lf_end, lf_id, lf_wid, lf_ver */
- lf_flags = wcstol (name, &endptr, 16);
- if ((lf_flags & ~(F_FLOCK | F_POSIX)) != 0
- || ((lf_flags & (F_FLOCK | F_POSIX)) == (F_FLOCK | F_POSIX)))
- return false;
- lf_type = wcstol (endptr + 1, &endptr, 16);
- if ((lf_type != F_RDLCK && lf_type != F_WRLCK) || !endptr || *endptr != L'-')
- return false;
- lf_start = (_off64_t) wcstoull (endptr + 1, &endptr, 16);
- if (lf_start < 0 || !endptr || *endptr != L'-')
- return false;
- lf_end = (_off64_t) wcstoull (endptr + 1, &endptr, 16);
- if (lf_end < -1LL
- || (lf_end > 0 && lf_end < lf_start)
- || !endptr || *endptr != L'-')
- return false;
- lf_id = wcstoll (endptr + 1, &endptr, 16);
- if (!endptr || *endptr != L'-'
- || ((lf_flags & F_POSIX) && (lf_id < 1 || lf_id > ULONG_MAX)))
- return false;
- lf_wid = wcstoul (endptr + 1, &endptr, 16);
- if (!endptr || *endptr != L'-')
- return false;
- lf_ver = wcstoul (endptr + 1, &endptr, 16);
- if (endptr && *endptr != L'\0')
- return false;
- lf_head = head;
- lf_inode = node;
- lf_next = NULL;
- lf_obj = NULL;
- return true;
-}
-
lockf_t *
inode_t::get_all_locks_list ()
{
@@ -589,7 +526,7 @@ inode_t::get_all_locks_list ()
} f;
ULONG context;
NTSTATUS status;
- lockf_t newlock, *lock = i_all_lf;
+ lockf_t *lock = i_all_lf;
for (BOOLEAN restart = TRUE;
NT_SUCCESS (status = NtQueryDirectoryObject (i_dir, &f, sizeof f, TRUE,
@@ -598,8 +535,32 @@ inode_t::get_all_locks_list ()
{
if (f.dbi.ObjectName.Length != LOCK_OBJ_NAME_LEN * sizeof (WCHAR))
continue;
- f.dbi.ObjectName.Buffer[LOCK_OBJ_NAME_LEN] = L'\0';
- if (!newlock.from_obj_name (this, &i_all_lf, f.dbi.ObjectName.Buffer))
+ wchar_t *wc = f.dbi.ObjectName.Buffer, *endptr;
+ /* "%02x-%01x-%016X-%016X-%016X-%08x-%04x",
+ lf_flags, lf_type, lf_start, lf_end, lf_id, lf_wid, lf_ver */
+ wc[LOCK_OBJ_NAME_LEN] = L'\0';
+ short flags = wcstol (wc, &endptr, 16);
+ if ((flags & ~(F_FLOCK | F_POSIX)) != 0
+ || ((flags & (F_FLOCK | F_POSIX)) == (F_FLOCK | F_POSIX)))
+ continue;
+ short type = wcstol (endptr + 1, &endptr, 16);
+ if ((type != F_RDLCK && type != F_WRLCK) || !endptr || *endptr != L'-')
+ continue;
+ _off64_t start = (_off64_t) wcstoull (endptr + 1, &endptr, 16);
+ if (start < 0 || !endptr || *endptr != L'-')
+ continue;
+ _off64_t end = (_off64_t) wcstoull (endptr + 1, &endptr, 16);
+ if (end < -1LL || (end > 0 && end < start) || !endptr || *endptr != L'-')
+ continue;
+ long long id = wcstoll (endptr + 1, &endptr, 16);
+ if (!endptr || *endptr != L'-'
+ || ((flags & F_POSIX) && (id < 1 || id > ULONG_MAX)))
+ continue;
+ DWORD wid = wcstoul (endptr + 1, &endptr, 16);
+ if (!endptr || *endptr != L'-')
+ continue;
+ uint16_t ver = wcstoul (endptr + 1, &endptr, 16);
+ if (endptr && *endptr != L'\0')
continue;
if (lock - i_all_lf >= MAX_LOCKF_CNT)
{
@@ -609,7 +570,8 @@ inode_t::get_all_locks_list ()
}
if (lock > i_all_lf)
lock[-1].lf_next = lock;
- new (lock++) lockf_t (newlock);
+ new (lock++) lockf_t (this, &i_all_lf,
+ flags, type, start, end, id, wid, ver);
}
/* If no lock has been found, return NULL. */
if (lock == i_all_lf)
@@ -622,7 +584,7 @@ inode_t::get_all_locks_list ()
POBJECT_ATTRIBUTES
lockf_t::create_lock_obj_attr (lockfattr_t *attr, ULONG flags)
{
- __small_swprintf (attr->name, LOCK_OBJ_NAME_FMT,
+ __small_swprintf (attr->name, L"%02x-%01x-%016X-%016X-%016X-%08x-%04x",
lf_flags & (F_POSIX | F_FLOCK), lf_type, lf_start, lf_end,
lf_id, lf_wid, lf_ver);
RtlInitCountedUnicodeString (&attr->uname, attr->name,
@@ -632,111 +594,6 @@ lockf_t::create_lock_obj_attr (lockfattr_t *attr, ULONG flags)
return &attr->attr;
}
-DWORD WINAPI
-create_lock_in_parent (PVOID param)
-{
- HANDLE lf_obj;
- ULONG size;
- OBJECT_NAME_INFORMATION *ntfn;
- NTSTATUS status;
- wchar_t *lockname, *inodename, *endptr;
- __dev32_t dev;
- __ino64_t ino;
- inode_t *node;
- lockf_t newlock, *lock;
- int cnt;
-
- /* param is the handle to the lock object, created by caller. */
- lf_obj = (HANDLE) param;
- /* Fetch object path from handle. Typically the length of the path
- is 146 characters, starting with
- "\BaseNamedObject\cygwin-1S5-<16-hex-digits>\..." */
- size = sizeof (OBJECT_NAME_INFORMATION) + 256 * sizeof (WCHAR);
- ntfn = (OBJECT_NAME_INFORMATION *) alloca (size);
- memset (ntfn, 0, size);
- status = NtQueryObject (lf_obj, ObjectNameInformation, ntfn, size, &size);
- if (!NT_SUCCESS (status))
- goto err;
- ntfn->Name.Buffer[ntfn->Name.Length / sizeof (WCHAR)] = L'\0';
- /* Sanity check so that we don't peek into unchartered territory. */
- if (ntfn->Name.Length < LOCK_OBJ_NAME_LEN + LOCK_DIR_NAME_LEN + 1)
- goto err;
- /* The names have fixed size, so we know where the substrings start. */
- lockname = ntfn->Name.Buffer + ntfn->Name.Length / sizeof (WCHAR)
- - LOCK_OBJ_NAME_LEN;
- inodename = lockname - LOCK_DIR_NAME_LEN - 1;
- dev = wcstoul (inodename + LOCK_DIR_NAME_DEV_OFF, &endptr, 16);
- if (*endptr != L'-')
- goto err;
- ino = wcstoull (inodename + LOCK_DIR_NAME_INO_OFF, &endptr, 16);
- if (*endptr != L'\\')
- goto err;
- if (!newlock.from_obj_name (NULL, NULL, lockname))
- goto err;
- /* Check if we have an open file handle with the same unique id. */
- {
- cnt = 0;
- cygheap_fdenum cfd (true);
- while (cfd.next () >= 0)
- if (cfd->get_unique_id () == newlock.lf_id && ++cnt > 0)
- break;
- }
- /* If not, close handle and return. */
- if (!cnt)
- {
- NtClose (lf_obj);
- return 0;
- }
- /* otherwise generate inode from directory name... */
- node = inode_t::get (dev, ino, true, false);
- /* ...and generate lock from object name. */
- lock = new lockf_t (newlock);
- lock->lf_inode = node;
- lock->lf_head = &node->i_lockf;
- lock->lf_next = node->i_lockf;
- lock->lf_obj = lf_obj;
- node->i_lockf = lock;
- node->unuse ();
- return 0;
-
-err:
- system_printf ("Adding <%S> lock failed", &ntfn->Name);
- NtClose (lf_obj);
- return 1;
-}
-
-DWORD WINAPI
-delete_lock_in_parent (PVOID param)
-{
- inode_t *node;
- lockf_t *lock, **prev;
-
- /* Scan list of all inodes, and reap stale BSD lock if lf_id matches.
- Remove inode if empty. */
- INODE_LIST_LOCK ();
- LIST_FOREACH (node, &cygheap->inode_list, i_next)
- if (!node->inuse ())
- {
- for (prev = &node->i_lockf, lock = *prev; lock; lock = *prev)
- {
- if ((lock->lf_flags & F_FLOCK) && IsEventSignalled (lock->lf_obj))
- {
- *prev = lock->lf_next;
- delete lock;
- }
- else
- prev = &lock->lf_next;
- }
- if (node->i_lockf == NULL)
- {
- LIST_REMOVE (node, i_next);
- delete node;
- }
- }
- INODE_LIST_UNLOCK ();
- return 0;
-}
-
/* Create the lock event object in the file's subdir in the NT global
namespace. */
void
@@ -772,54 +629,6 @@ lockf_t::create_lock_obj ()
}
}
while (!NT_SUCCESS (status));
- /* For BSD locks, notify the parent process. */
- if (lf_flags & F_FLOCK)
- {
- HANDLE parent_proc, parent_thread, parent_lf_obj;
-
- pinfo p (myself->ppid);
- if (!p) /* No access or not a Cygwin parent. */
- return;
-
- parent_proc = OpenProcess (PROCESS_DUP_HANDLE
- | PROCESS_CREATE_THREAD
- | PROCESS_QUERY_INFORMATION
- | PROCESS_VM_OPERATION
- | PROCESS_VM_WRITE
- | PROCESS_VM_READ,
- FALSE, p->dwProcessId);
- if (!parent_proc)
- {
- debug_printf ("OpenProcess (%u): %E", p->dwProcessId);
- return;
- }
- if (!DuplicateHandle (GetCurrentProcess (), lf_obj, parent_proc,
- &parent_lf_obj, TRUE, 0, DUPLICATE_SAME_ACCESS))
- debug_printf ("DuplicateHandle (lf_obj): %E");
- else
- {
- parent_thread = CreateRemoteThread (parent_proc, NULL, 256 * 1024,
- create_lock_in_parent,
- parent_lf_obj,
- STACK_SIZE_PARAM_IS_A_RESERVATION,
- NULL);
- if (!parent_thread)
- {
- debug_printf ("CreateRemoteThread: %E");
- /* If thread didn't get started, close object handle in parent,
- otherwise suffer handle leaks. */
- DuplicateHandle (parent_proc, parent_lf_obj, parent_proc,
- NULL, 0, FALSE, DUPLICATE_CLOSE_SOURCE);
- }
- else
- {
- /* Must wait to avoid race conditions. */
- WaitForSingleObject (parent_thread, INFINITE);
- CloseHandle (parent_thread);
- }
- }
- CloseHandle (parent_proc);
- }
}
/* Open a lock event object for SYNCHRONIZE access (to wait for it). */
@@ -856,36 +665,7 @@ lockf_t::del_lock_obj (HANDLE fhdl, bool signal)
handle/descriptor to the same FILE_OBJECT/file table entry. */
if ((lf_flags & F_POSIX) || signal
|| (fhdl && get_obj_handle_count (fhdl) <= 1))
- {
- NtSetEvent (lf_obj, NULL);
- /* For BSD locks, notify the parent process. */
- if (lf_flags & F_FLOCK)
- {
- HANDLE parent_proc, parent_thread;
-
- pinfo p (myself->ppid);
- if (p && (parent_proc = OpenProcess (PROCESS_CREATE_THREAD
- | PROCESS_QUERY_INFORMATION
- | PROCESS_VM_OPERATION
- | PROCESS_VM_WRITE
- | PROCESS_VM_READ,
- FALSE, p->dwProcessId)))
- {
- parent_thread = CreateRemoteThread (parent_proc, NULL,
- 256 * 1024, delete_lock_in_parent,
- NULL,
- STACK_SIZE_PARAM_IS_A_RESERVATION,
- NULL);
- if (parent_thread)
- {
- /* Must wait to avoid race conditions. */
- WaitForSingleObject (parent_thread, INFINITE);
- CloseHandle (parent_thread);
- }
- CloseHandle (parent_proc);
- }
- }
- }
+ NtSetEvent (lf_obj, NULL);
close_lock_obj ();
}
}
@@ -1035,7 +815,7 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
restart: /* Entry point after a restartable signal came in. */
- inode_t *node = inode_t::get (get_dev (), get_ino (), true, true);
+ inode_t *node = inode_t::get (get_dev (), get_ino (), true);
if (!node)
{
set_errno (ENOLCK);
@@ -1247,7 +1027,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
timeout = 100L;
DWORD WAIT_SIGNAL_ARRIVED = WAIT_OBJECT_0 + wait_count;
- set_signal_arrived here (w4[wait_count++]);
+ w4[wait_count++] = signal_arrived;
DWORD WAIT_THREAD_CANCELED = WAIT_TIMEOUT + 1;
HANDLE cancel_event = pthread::get_cancel_event ();