summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwtc%netscape.com <devnull@localhost>1999-01-25 23:52:00 +0000
committerwtc%netscape.com <devnull@localhost>1999-01-25 23:52:00 +0000
commit880ef565fedb4b848d0b8d8f8387ea7254a856a8 (patch)
tree4c8e91aab26a99821868b93c98fe5bb44f0ff4b5
parentcff6f10be0633a163f45e1001921a7760adcba0c (diff)
downloadnspr-hg-880ef565fedb4b848d0b8d8f8387ea7254a856a8.tar.gz
Added BeOS files contributed by Matthew Zahorik <maz@albany.net>.
-rw-r--r--pr/src/bthreads/Makefile31
-rw-r--r--pr/src/bthreads/bsrcs.mk25
-rw-r--r--pr/src/bthreads/btcmon.c405
-rw-r--r--pr/src/bthreads/btcvar.c161
-rw-r--r--pr/src/bthreads/btlocks.c89
-rw-r--r--pr/src/bthreads/btmisc.c80
-rw-r--r--pr/src/bthreads/btmon.c192
-rw-r--r--pr/src/bthreads/btsem.c100
-rw-r--r--pr/src/bthreads/btthread.c780
-rw-r--r--pr/src/bthreads/objs.mk18
-rw-r--r--pr/src/md/beos/Makefile28
-rw-r--r--pr/src/md/beos/bcpu.c31
-rw-r--r--pr/src/md/beos/beos.c240
-rw-r--r--pr/src/md/beos/beos_errors.c1535
-rw-r--r--pr/src/md/beos/bfile.c783
-rw-r--r--pr/src/md/beos/bmemory.c18
-rw-r--r--pr/src/md/beos/bmisc.c92
-rw-r--r--pr/src/md/beos/bmmap.c39
-rw-r--r--pr/src/md/beos/bnet.c648
-rw-r--r--pr/src/md/beos/bproc.c39
-rw-r--r--pr/src/md/beos/bseg.c35
-rw-r--r--pr/src/md/beos/bsrcs.mk27
-rw-r--r--pr/src/md/beos/btime.c51
-rw-r--r--pr/src/md/beos/objs.mk18
24 files changed, 5465 insertions, 0 deletions
diff --git a/pr/src/bthreads/Makefile b/pr/src/bthreads/Makefile
new file mode 100644
index 00000000..704b0445
--- /dev/null
+++ b/pr/src/bthreads/Makefile
@@ -0,0 +1,31 @@
+#
+# The contents of this file are subject to the Mozilla Public License
+# Version 1.0 (the "MPL"); you may not use this file except in
+# compliance with the MPL. You may obtain a copy of the MPL at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the MPL is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+# for the specific language governing rights and limitations under the
+# MPL.
+#
+
+#! gmake
+
+MOD_DEPTH = ../../..
+
+include $(MOD_DEPTH)/config/config.mk
+
+include bsrcs.mk
+CSRCS += $(BTCSRCS)
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(DIST)/include/private -I$(DIST)/include
+
+include $(MOD_DEPTH)/config/rules.mk
+
+export:: $(TARGETS)
+
+install:: export
+
diff --git a/pr/src/bthreads/bsrcs.mk b/pr/src/bthreads/bsrcs.mk
new file mode 100644
index 00000000..54a31d30
--- /dev/null
+++ b/pr/src/bthreads/bsrcs.mk
@@ -0,0 +1,25 @@
+#
+# The contents of this file are subject to the Mozilla Public License
+# Version 1.0 (the "MPL"); you may not use this file except in
+# compliance with the MPL. You may obtain a copy of the MPL at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the MPL is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+# for the specific language governing rights and limitations under the
+# MPL.
+#
+
+# this file lists the source files to be compiled (used in Makefile) and
+# then enumerated as object files (in objs.mk) for inclusion in the NSPR
+# shared library
+
+BTCSRCS = \
+ btthread.c \
+ btlocks.c \
+ btcvar.c \
+ btmon.c \
+ btsem.c \
+ btcmon.c \
+ btmisc.c \
+ $(NULL)
diff --git a/pr/src/bthreads/btcmon.c b/pr/src/bthreads/btcmon.c
new file mode 100644
index 00000000..295a939c
--- /dev/null
+++ b/pr/src/bthreads/btcmon.c
@@ -0,0 +1,405 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include <kernel/OS.h>
+
+#include "primpl.h"
+
+/*
+** Most of this is ripped out of ../threads/prcmon.c
+*/
+
+PRLock *_pr_mcacheLock;
+#define _PR_NEW_LOCK_MCACHE() (_pr_mcacheLock = PR_NewLock())
+#define _PR_LOCK_MCACHE() PR_Lock(_pr_mcacheLock)
+#define _PR_UNLOCK_MCACHE() PR_Unlock(_pr_mcacheLock)
+
+typedef struct MonitorCacheEntryStr MonitorCacheEntry;
+
+struct MonitorCacheEntryStr {
+ MonitorCacheEntry* next;
+ void* address;
+ PRMonitor* mon;
+ long cacheEntryCount;
+};
+
+static PRUint32 hash_mask;
+static PRUintn num_hash_buckets;
+static PRUintn num_hash_buckets_log2;
+static MonitorCacheEntry **hash_buckets;
+static MonitorCacheEntry *free_entries;
+static PRUintn num_free_entries;
+static PRBool expanding;
+int _pr_mcache_ready;
+
+#define HASH(address) \
+ ((PRUint32) ( ((PRUptrdiff)(address) >> 2) ^ \
+ ((PRUptrdiff)(address) >> 10) ) \
+ & hash_mask)
+
+/*
+** Expand the monitor cache. This grows the hash buckets and allocates a
+** new chunk of cache entries and throws them on the free list. We keep
+** as many hash buckets as there are entries.
+**
+** Because we call malloc and malloc may need the monitor cache, we must
+** ensure that there are several free monitor cache entries available for
+** malloc to get. FREE_THRESHOLD is used to prevent monitor cache
+** starvation during monitor cache expansion.
+*/
+
+#define FREE_THRESHOLD 5
+
+static PRStatus ExpandMonitorCache(PRUintn new_size_log2)
+{
+ MonitorCacheEntry **old_hash_buckets, *p;
+ PRUintn i, entries, old_num_hash_buckets, added;
+ MonitorCacheEntry **new_hash_buckets, *new_entries;
+
+ entries = 1L << new_size_log2;
+
+ /*
+ ** Expand the monitor-cache-entry free list
+ */
+
+ new_entries = (MonitorCacheEntry*)PR_CALLOC(
+ entries * sizeof(MonitorCacheEntry));
+ if (NULL == new_entries) return PR_FAILURE;
+
+ /*
+ ** Allocate system monitors for the new monitor cache entries. If we
+ ** run out of system monitors, break out of the loop.
+ */
+ for (i = 0, added = 0, p = new_entries; i < entries; i++, p++, added++)
+ {
+ p->mon = PR_NewMonitor();
+ if (!p->mon) break;
+ }
+ if (added != entries)
+ {
+ if (added == 0)
+ {
+ /* Totally out of system monitors. Lossage abounds */
+ PR_DELETE(new_entries);
+ return PR_FAILURE;
+ }
+
+ /*
+ ** We were able to allocate some of the system monitors. Use
+ ** realloc to shrink down the new_entries memory
+ */
+ p = (MonitorCacheEntry*)PR_REALLOC(
+ new_entries, added * sizeof(MonitorCacheEntry));
+ if (p == 0)
+ {
+ /*
+ ** Total lossage. We just leaked a bunch of system monitors
+ ** all over the floor. This should never ever happen.
+ */
+ PR_ASSERT(p != 0);
+ return PR_FAILURE;
+ }
+ }
+
+ /*
+ ** Now that we have allocated all of the system monitors, build up
+ ** the new free list. We can just update the free_list because we own
+ ** the mcache-lock and we aren't calling anyone who might want to use
+ ** it.
+ */
+ for (i = 0, p = new_entries; i < added - 1; i++, p++) p->next = p + 1;
+ p->next = free_entries;
+ free_entries = new_entries;
+ num_free_entries += added;
+
+ /* Try to expand the hash table */
+ new_hash_buckets = (MonitorCacheEntry**)PR_CALLOC(
+ entries * sizeof(MonitorCacheEntry*));
+ if (NULL == new_hash_buckets)
+ {
+ /*
+ ** Partial lossage. In this situation we don't get any more hash
+ ** buckets, which just means that the table lookups will take
+ ** longer. This is bad, but not fatal
+ */
+ PR_LOG(_pr_cmon_lm, PR_LOG_WARNING,
+ ("unable to grow monitor cache hash buckets"));
+ return PR_SUCCESS;
+ }
+
+ /*
+ ** Compute new hash mask value. This value is used to mask an address
+ ** until it's bits are in the right spot for indexing into the hash
+ ** table.
+ */
+ hash_mask = entries - 1;
+
+ /*
+ ** Expand the hash table. We have to rehash everything in the old
+ ** table into the new table. */
+ old_hash_buckets = hash_buckets;
+ old_num_hash_buckets = num_hash_buckets;
+ for (i = 0; i < old_num_hash_buckets; i++)
+ {
+ p = old_hash_buckets[i];
+ while (p)
+ {
+ MonitorCacheEntry *next = p->next;
+
+ /* Hash based on new table size, and then put p in the new table
+ */
+ PRUintn hash = HASH(p->address);
+ p->next = new_hash_buckets[hash];
+ new_hash_buckets[hash] = p;
+
+ p = next;
+ }
+ }
+
+ /*
+ ** Switch over to new hash table and THEN call free of the old
+ ** table. Since free might re-enter _pr_mcache_lock, things would
+ ** break terribly if it used the old hash table.
+ */
+
+ hash_buckets = new_hash_buckets;
+ num_hash_buckets = entries;
+ num_hash_buckets_log2 = new_size_log2;
+ PR_DELETE(old_hash_buckets);
+
+ PR_LOG(_pr_cmon_lm, PR_LOG_NOTICE,
+ ("expanded monitor cache to %d (buckets %d)",
+ num_free_entries, entries));
+
+ return PR_SUCCESS;
+} /* ExpandMonitorCache */
+
+/*
+** Lookup a monitor cache entry by address. Return a pointer to the
+** pointer to the monitor cache entry on success, null on failure.
+*/
+static MonitorCacheEntry **LookupMonitorCacheEntry(void *address)
+{
+ PRUintn hash;
+ MonitorCacheEntry **pp, *p;
+
+ hash = HASH(address);
+ pp = hash_buckets + hash;
+ while ((p = *pp) != 0) {
+ if (p->address == address) {
+ if (p->cacheEntryCount > 0)
+ return pp;
+ else
+ return NULL;
+ }
+ pp = &p->next;
+ }
+ return NULL;
+}
+
+/*
+** Try to create a new cached monitor. If it's already in the cache,
+** great - return it. Otherwise get a new free cache entry and set it
+** up. If the cache free space is getting low, expand the cache.
+*/
+static PRMonitor *CreateMonitor(void *address)
+{
+ PRUintn hash;
+ MonitorCacheEntry **pp, *p;
+
+ hash = HASH(address);
+ pp = hash_buckets + hash;
+ while ((p = *pp) != 0) {
+ if (p->address == address) goto gotit;
+
+ pp = &p->next;
+ }
+
+ /* Expand the monitor cache if we have run out of free slots in the table */
+ if (num_free_entries < FREE_THRESHOLD)
+ {
+ /* Expand monitor cache */
+
+ /*
+ ** This function is called with the lock held. So what's the 'expanding' ** boolean all about? Seems a bit redundant.
+ */
+ if (!expanding)
+ {
+ PRStatus rv;
+
+ expanding = PR_TRUE;
+ rv = ExpandMonitorCache(num_hash_buckets_log2 + 1);
+ expanding = PR_FALSE;
+ if (PR_FAILURE == rv) return NULL;
+
+ /* redo the hash because it'll be different now */
+ hash = HASH(address);
+ }
+ else
+ {
+ /*
+ ** We are in process of expanding and we need a cache
+ ** monitor. Make sure we have enough!
+ */
+ PR_ASSERT(num_free_entries > 0);
+ }
+ }
+
+ /* Make a new monitor */ p = free_entries;
+ free_entries = p->next;
+ num_free_entries--;
+ p->address = address;
+ p->next = hash_buckets[hash];
+ hash_buckets[hash] = p;
+ PR_ASSERT(p->cacheEntryCount == 0);
+
+ gotit:
+ p->cacheEntryCount++;
+ return p->mon;
+}
+
+/* this is needed by prinit for some reason */
+void
+_PR_InitCMon (void)
+{
+ _PR_NEW_LOCK_MCACHE();
+ ExpandMonitorCache(3);
+ _pr_mcache_ready = 1;
+}
+
+/**
+** Like PR_EnterMonitor except use the "address" to find a monitor in the
+** monitor cache. If successful, returns the PRMonitor now associated
+** with "address". Note that you must PR_CExitMonitor the address to
+** release the monitor cache entry (otherwise the monitor cache will fill
+** up). This call will return NULL if the monitor cache needs to be
+** expanded and the system is out of memory.
+*/
+PR_IMPLEMENT(PRMonitor*)
+ PR_CEnterMonitor (void *address)
+{
+ PRMonitor *mon;
+
+ _PR_LOCK_MCACHE();
+ mon = CreateMonitor( address );
+ _PR_UNLOCK_MCACHE();
+
+ if( !mon ) return( NULL );
+
+ PR_EnterMonitor( mon );
+ return( mon );
+}
+
+/*
+** Like PR_ExitMonitor except use the "address" to find a monitor in the
+** monitor cache.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_CExitMonitor (void *address)
+{
+ MonitorCacheEntry **pp, *p;
+ PRStatus status = PR_SUCCESS;
+
+ _PR_LOCK_MCACHE();
+ pp = LookupMonitorCacheEntry(address);
+ if (pp != NULL) {
+ p = *pp;
+ if (--p->cacheEntryCount == 0) {
+ /*
+ ** Nobody is using the system monitor. Put it on the cached free
+ ** list. We are safe from somebody trying to use it because we
+ ** have the mcache locked.
+ */
+ p->address = 0; /* defensive move */
+ *pp = p->next; /* unlink from hash_buckets */
+ p->next = free_entries; /* link into free list */
+ free_entries = p;
+ num_free_entries++; /* count it as free */
+ }
+ status = PR_ExitMonitor(p->mon);
+ } else {
+ status = PR_FAILURE;
+ }
+ _PR_UNLOCK_MCACHE();
+
+ return status;
+}
+
+/*
+** Like PR_Wait except use the "address" to find a monitor in the
+** monitor cache.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_CWait (void *address, PRIntervalTime timeout)
+{
+ MonitorCacheEntry **pp;
+ PRMonitor *mon;
+
+ _PR_LOCK_MCACHE();
+ pp = LookupMonitorCacheEntry(address);
+ mon = pp ? ((*pp)->mon) : NULL;
+ _PR_UNLOCK_MCACHE();
+
+ if (mon == NULL)
+ return PR_FAILURE;
+ else
+ {
+ return PR_Wait( mon, timeout );
+ }
+}
+
+/*
+** Like PR_Notify except use the "address" to find a monitor in the
+** monitor cache.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_CNotify (void *address)
+{
+ MonitorCacheEntry **pp;
+ PRMonitor *mon;
+
+ _PR_LOCK_MCACHE();
+ pp = LookupMonitorCacheEntry(address);
+ mon = pp ? ((*pp)->mon) : NULL;
+ _PR_UNLOCK_MCACHE();
+
+ if (mon == NULL)
+ return PR_FAILURE;
+ else
+ {
+ return PR_Notify(mon);
+ }
+}
+
+/*
+** Like PR_NotifyAll except use the "address" to find a monitor in the
+** monitor cache.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_CNotifyAll (void *address)
+{
+ MonitorCacheEntry **pp;
+ PRMonitor *mon;
+
+ _PR_LOCK_MCACHE();
+ pp = LookupMonitorCacheEntry(address);
+ mon = pp ? ((*pp)->mon) : NULL;
+ _PR_UNLOCK_MCACHE();
+
+ if (mon == NULL)
+ return PR_FAILURE;
+ else
+ {
+ return PR_NotifyAll(mon);
+ }
+}
diff --git a/pr/src/bthreads/btcvar.c b/pr/src/bthreads/btcvar.c
new file mode 100644
index 00000000..bdb594c5
--- /dev/null
+++ b/pr/src/bthreads/btcvar.c
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include <kernel/OS.h>
+
+#include "primpl.h"
+
+/*
+** Create a new condition variable.
+**
+** "lock" is the lock used to protect the condition variable.
+**
+** Condition variables are synchronization objects that threads can use
+** to wait for some condition to occur.
+**
+** This may fail if memory is tight or if some operating system resource
+** is low. In such cases, a NULL will be returned.
+*/
+PR_IMPLEMENT(PRCondVar*)
+ PR_NewCondVar (PRLock *lock)
+{
+ PRCondVar *cv = PR_NEW( PRCondVar );
+ PR_ASSERT( NULL != lock );
+ if( NULL != cv )
+ {
+ cv->lock = lock;
+ PR_ASSERT((cv->isem = create_sem( 1, "nspr_sem")) >= B_NO_ERROR );
+ }
+ return cv;
+} /* PR_NewCondVar */
+
+/*
+** Destroy a condition variable. There must be no thread
+** waiting on the condvar. The caller is responsible for guaranteeing
+** that the condvar is no longer in use.
+**
+*/
+PR_IMPLEMENT(void)
+ PR_DestroyCondVar (PRCondVar *cvar)
+{
+ PR_ASSERT( delete_sem( cvar->isem ) == B_NO_ERROR );
+ PR_DELETE( cvar );
+}
+
+/*
+** The thread that waits on a condition is blocked in a "waiting on
+** condition" state until another thread notifies the condition or a
+** caller specified amount of time expires. The lock associated with
+** the condition variable will be released, which must have be held
+** prior to the call to wait.
+**
+** Logically a notified thread is moved from the "waiting on condition"
+** state and made "ready." When scheduled, it will attempt to reacquire
+** the lock that it held when wait was called.
+**
+** The timeout has two well known values, PR_INTERVAL_NO_TIMEOUT and
+** PR_INTERVAL_NO_WAIT. The former value requires that a condition be
+** notified (or the thread interrupted) before it will resume from the
+** wait. If the timeout has a value of PR_INTERVAL_NO_WAIT, the effect
+** is to release the lock, possibly causing a rescheduling within the
+** runtime, then immediately attempting to reacquire the lock and resume.
+**
+** Any other value for timeout will cause the thread to be rescheduled
+** either due to explicit notification or an expired interval. The latter
+** must be determined by treating time as one part of the monitored data
+** being protected by the lock and tested explicitly for an expired
+** interval.
+**
+** Returns PR_FAILURE if the caller has not locked the lock associated
+** with the condition variable or the thread was interrupted (PR_Interrupt()).
+** The particular reason can be extracted with PR_GetError().
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_WaitCondVar (PRCondVar *cvar, PRIntervalTime timeout)
+{
+ status_t result;
+
+ /*
+ ** This is an entirely stupid bug, but... If you call
+ ** acquire_sem_etc with a timeout of exactly 1,000,000 microseconds
+ ** it returns immediately with B_NO_ERROR. 1,000,010 microseconds
+ ** returns as expected. Running BeOS/Intel R3.1 at this time.
+ ** Forwarded to Be, Inc. for resolution, Bug ID 980624-225956
+ **
+ ** Update: Be couldn't reproduce it, but removing timeout++ still
+ ** exhibits the problem on BeOS/Intel R4 and BeOS/PPC R4.
+ */
+
+ timeout++;
+
+ PR_Unlock( cvar->lock );
+
+ if( PR_INTERVAL_NO_WAIT != timeout )
+ {
+ if( PR_INTERVAL_NO_TIMEOUT == timeout )
+ {
+ if( acquire_sem( cvar->isem ) != B_NO_ERROR ) return PR_FAILURE;
+
+ } else
+ {
+ result = acquire_sem_etc( cvar->isem, 1, B_TIMEOUT, PR_IntervalToMicroseconds( timeout ) );
+ if( result != B_NO_ERROR && result != B_TIMED_OUT )
+ return PR_FAILURE;
+ }
+ }
+
+ PR_Lock( cvar->lock );
+
+ return PR_SUCCESS;
+}
+
+/*
+** Notify ONE thread that is currently waiting on 'cvar'. Which thread is
+** dependent on the implementation of the runtime. Common sense would dictate
+** that all threads waiting on a single condition have identical semantics,
+** therefore which one gets notified is not significant.
+**
+** The calling thead must hold the lock that protects the condition, as
+** well as the invariants that are tightly bound to the condition, when
+** notify is called.
+**
+** Returns PR_FAILURE if the caller has not locked the lock associated
+** with the condition variable.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_NotifyCondVar (PRCondVar *cvar)
+{
+ if( release_sem( cvar->isem ) != B_NO_ERROR ) return PR_FAILURE;
+
+ return PR_SUCCESS;
+}
+
+/*
+** Notify all of the threads waiting on the condition variable. The order
+** that the threads are notified is indeterminant. The lock that protects
+** the condition must be held.
+**
+** Returns PR_FAILURE if the caller has not locked the lock associated
+** with the condition variable.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_NotifyAllCondVar (PRCondVar *cvar)
+{
+ sem_info semInfo;
+
+ if( get_sem_info( cvar->isem, &semInfo ) != B_NO_ERROR )
+ return PR_FAILURE;
+
+ if( release_sem_etc( cvar->isem, semInfo.count, 0 ) != B_NO_ERROR )
+ return PR_FAILURE;
+}
diff --git a/pr/src/bthreads/btlocks.c b/pr/src/bthreads/btlocks.c
new file mode 100644
index 00000000..d7f90694
--- /dev/null
+++ b/pr/src/bthreads/btlocks.c
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+/*
+** File: btlocks.c
+** Description: Implemenation for thread locks using bthreads
+** Exports: prlock.h
+*/
+
+#include "primpl.h"
+
+#include <string.h>
+#include <sys/time.h>
+
+void
+_PR_InitLocks (void)
+{
+}
+
+PR_IMPLEMENT(PRLock*)
+ PR_NewLock (void)
+{
+ PRLock *lock;
+ status_t semresult;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ lock = PR_NEWZAP(PRLock);
+ if (lock != NULL) {
+
+ lock->benaphoreCount = 0;
+ lock->semaphoreID = create_sem( 0, "nsprLockSem" );
+ if( lock->semaphoreID < B_NO_ERROR ) {
+
+ PR_DELETE( lock );
+ lock = NULL;
+ }
+ }
+
+ return lock;
+}
+
+PR_IMPLEMENT(void)
+ PR_DestroyLock (PRLock* lock)
+{
+ PR_ASSERT(NULL != lock);
+ PR_ASSERT(delete_sem(lock->semaphoreID) == B_NO_ERROR);
+ PR_DELETE(lock);
+}
+
+PR_IMPLEMENT(void)
+ PR_Lock (PRLock* lock)
+{
+ PR_ASSERT(lock != NULL);
+
+ if( atomic_add( &lock->benaphoreCount, 1 ) > 0 ) {
+
+ if( acquire_sem(lock->semaphoreID ) != B_NO_ERROR ) {
+
+ atomic_add( &lock->benaphoreCount, -1 );
+ return;
+ }
+ }
+
+ lock->owner = find_thread( NULL );
+}
+
+PR_IMPLEMENT(PRStatus)
+ PR_Unlock (PRLock* lock)
+{
+ PR_ASSERT(lock != NULL);
+ lock->owner = NULL;
+ if( atomic_add( &lock->benaphoreCount, -1 ) > 1 ) {
+
+ release_sem( lock->semaphoreID );
+ }
+
+ return PR_SUCCESS;
+}
diff --git a/pr/src/bthreads/btmisc.c b/pr/src/bthreads/btmisc.c
new file mode 100644
index 00000000..f0ec4807
--- /dev/null
+++ b/pr/src/bthreads/btmisc.c
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include "primpl.h"
+#include <stdio.h>
+
+// void _PR_InitCPUs(void) {PT_LOG("_PR_InitCPUs")}
+// void _MD_StartInterrupts(void) {PT_LOG("_MD_StartInterrupts")}
+
+/* this is a total hack.. */
+
+struct protoent* getprotobyname(const char* name)
+{
+ return 0;
+}
+
+struct protoent* getprotobynumber(int number)
+{
+ return 0;
+}
+
+/* this is needed by prinit for some reason */
+void
+_PR_InitStacks (void)
+{
+}
+
+/* this is needed by prinit for some reason */
+void
+_PR_InitTPD (void)
+{
+}
+
+/*
+** Create extra virtual processor threads. Generally used with MP systems.
+*/
+PR_IMPLEMENT(void)
+ PR_SetConcurrency (PRUintn numCPUs)
+{
+}
+
+/*
+** Set thread recycle mode to on (1) or off (0)
+*/
+PR_IMPLEMENT(void)
+ PR_SetThreadRecycleMode (PRUint32 flag)
+{
+}
+
+/*
+** Get context registers, return with error for now.
+*/
+
+PR_IMPLEMENT(PRWord *)
+_MD_HomeGCRegisters( PRThread *t, int isCurrent, int *np )
+{
+ return 0;
+}
+
+PR_IMPLEMENT(void *)
+PR_GetSP( PRThread *t )
+{
+ return 0;
+}
+
+PR_IMPLEMENT(PRStatus)
+PR_EnumerateThreads( PREnumerator func, void *arg )
+{
+ return PR_FAILURE;
+}
diff --git a/pr/src/bthreads/btmon.c b/pr/src/bthreads/btmon.c
new file mode 100644
index 00000000..81e7ed0d
--- /dev/null
+++ b/pr/src/bthreads/btmon.c
@@ -0,0 +1,192 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include <kernel/OS.h>
+
+#include "primpl.h"
+
+/*
+** Create a new monitor. Monitors are re-entrant locks with a single built-in
+** condition variable.
+**
+** This may fail if memory is tight or if some operating system resource
+** is low.
+*/
+PR_IMPLEMENT(PRMonitor*)
+ PR_NewMonitor (void)
+{
+ PRMonitor *mon;
+ PRCondVar *cvar;
+ PRLock *lock;
+
+ mon = PR_NEWZAP( PRMonitor );
+ if( mon )
+ {
+ lock = PR_NewLock();
+ if( !lock )
+ {
+ PR_DELETE( mon );
+ return( 0 );
+ }
+
+ cvar = PR_NewCondVar( lock );
+ if( !cvar )
+ {
+ PR_DestroyLock( lock );
+ PR_DELETE( mon );
+ return( 0 );
+ }
+
+ mon->cvar = cvar;
+ mon->name = NULL;
+ }
+
+ return( mon );
+}
+
+PR_IMPLEMENT(PRMonitor*) PR_NewNamedMonitor(const char* name)
+{
+ PRMonitor* mon = PR_NewMonitor();
+ mon->name = name;
+ return mon;
+}
+
+/*
+** Destroy a monitor. The caller is responsible for guaranteeing that the
+** monitor is no longer in use. There must be no thread waiting on the
+** monitor's condition variable and that the lock is not held.
+**
+*/
+PR_IMPLEMENT(void)
+ PR_DestroyMonitor (PRMonitor *mon)
+{
+ PR_DestroyLock( mon->cvar->lock );
+ PR_DestroyCondVar( mon->cvar );
+ PR_DELETE( mon );
+}
+
+/*
+** Enter the lock associated with the monitor. If the calling thread currently
+** is in the monitor, the call to enter will silently succeed. In either case,
+** it will increment the entry count by one.
+*/
+PR_IMPLEMENT(void)
+ PR_EnterMonitor (PRMonitor *mon)
+{
+ if( mon->cvar->lock->owner == find_thread( NULL ) )
+ {
+ mon->entryCount++;
+
+ } else
+ {
+ PR_Lock( mon->cvar->lock );
+ mon->entryCount = 1;
+ }
+}
+
+/*
+** Decrement the entry count associated with the monitor. If the decremented
+** entry count is zero, the monitor is exited. Returns PR_FAILURE if the
+** calling thread has not entered the monitor.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_ExitMonitor (PRMonitor *mon)
+{
+ if( mon->cvar->lock->owner != find_thread( NULL ) )
+ {
+ return( PR_FAILURE );
+ }
+ if( --mon->entryCount == 0 )
+ {
+ return( PR_Unlock( mon->cvar->lock ) );
+ }
+ return( PR_SUCCESS );
+}
+
+/*
+** Wait for a notify on the monitor's condition variable. Sleep for "ticks"
+** amount of time (if "ticks" is PR_INTERVAL_NO_TIMEOUT then the sleep is
+** indefinite).
+**
+** While the thread is waiting it exits the monitor (as if it called
+** PR_ExitMonitor as many times as it had called PR_EnterMonitor). When
+** the wait has finished the thread regains control of the monitors lock
+** with the same entry count as before the wait began.
+**
+** The thread waiting on the monitor will be resumed when the monitor is
+** notified (assuming the thread is the next in line to receive the
+** notify) or when the "ticks" timeout elapses.
+**
+** Returns PR_FAILURE if the caller has not entered the monitor.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_Wait (PRMonitor *mon, PRIntervalTime ticks)
+{
+ PRUint32 entryCount;
+ PRUintn status;
+ PRThread *meThread;
+ thread_id me = find_thread( NULL );
+ meThread = PR_GetCurrentThread();
+
+ if( mon->cvar->lock->owner != me ) return( PR_FAILURE );
+
+ entryCount = mon->entryCount;
+ mon->entryCount = 0;
+
+ status = PR_WaitCondVar( mon->cvar, ticks );
+
+ mon->entryCount = entryCount;
+
+ return( status );
+}
+
+/*
+** Notify a thread waiting on the monitor's condition variable. If a thread
+** is waiting on the condition variable (using PR_Wait) then it is awakened
+** and attempts to reenter the monitor.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_Notify (PRMonitor *mon)
+{
+ if( mon->cvar->lock->owner != find_thread( NULL ) )
+ {
+ return( PR_FAILURE );
+ }
+
+ PR_NotifyCondVar( mon->cvar );
+ return( PR_SUCCESS );
+}
+
+/*
+** Notify all of the threads waiting on the monitor's condition variable.
+** All of threads waiting on the condition are scheduled to reenter the
+** monitor.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_NotifyAll (PRMonitor *mon)
+{
+ if( mon->cvar->lock->owner != find_thread( NULL ) )
+ {
+ return( PR_FAILURE );
+ }
+
+ PR_NotifyAllCondVar( mon->cvar );
+ return( PR_SUCCESS );
+}
+
+PR_IMPLEMENT(PRIntn)
+ PR_GetMonitorEntryCount(PRMonitor *mon)
+{
+ return( mon->entryCount );
+}
+
diff --git a/pr/src/bthreads/btsem.c b/pr/src/bthreads/btsem.c
new file mode 100644
index 00000000..3e7cbe8a
--- /dev/null
+++ b/pr/src/bthreads/btsem.c
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include <kernel/OS.h>
+
+#include "primpl.h"
+
+/*
+** Create a new semaphore object.
+*/
+PR_IMPLEMENT(PRSemaphore*)
+ PR_NewSem (PRUintn value)
+{
+ PRSemaphore *semaphore;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ semaphore = PR_NEWZAP(PRSemaphore);
+ if (NULL != semaphore) {
+ if ((semaphore->sem = create_sem(value, "nspr_sem")) < B_NO_ERROR)
+ return NULL;
+ else
+ return semaphore;
+ }
+ return NULL;
+}
+
+/*
+** Destroy the given semaphore object.
+**
+*/
+PR_IMPLEMENT(void)
+ PR_DestroySem (PRSemaphore *sem)
+{
+ PR_ASSERT(sem != NULL);
+ PR_ASSERT(delete_sem(sem->sem) == B_NO_ERROR);
+ PR_DELETE(sem);
+}
+
+/*
+** Wait on a Semaphore.
+**
+** This routine allows a calling thread to wait or proceed depending upon
+** the state of the semahore sem. The thread can proceed only if the
+** counter value of the semaphore sem is currently greater than 0. If the
+** value of semaphore sem is positive, it is decremented by one and the
+** routine returns immediately allowing the calling thread to continue. If
+** the value of semaphore sem is 0, the calling thread blocks awaiting the
+** semaphore to be released by another thread.
+**
+** This routine can return PR_PENDING_INTERRUPT if the waiting thread
+** has been interrupted.
+*/
+PR_IMPLEMENT(PRStatus)
+ PR_WaitSem (PRSemaphore *sem)
+{
+ PR_ASSERT(sem != NULL);
+ if (acquire_sem(sem->sem) == B_NO_ERROR)
+ return PR_SUCCESS;
+ else
+ return PR_FAILURE;
+}
+
+/*
+** This routine increments the counter value of the semaphore. If other
+** threads are blocked for the semaphore, then the scheduler will
+** determine which ONE thread will be unblocked.
+*/
+PR_IMPLEMENT(void)
+ PR_PostSem (PRSemaphore *sem)
+{
+ PR_ASSERT(sem != NULL);
+ PR_ASSERT(release_sem(sem->sem) == B_NO_ERROR);
+}
+
+/*
+** Returns the value of the semaphore referenced by sem without affecting
+** the state of the semaphore. The value represents the semaphore value
+** at the time of the call, but may not be the actual value when the
+** caller inspects it.
+*/
+PR_IMPLEMENT(PRUintn)
+ PR_GetValueSem (PRSemaphore *sem)
+{
+ sem_info info;
+
+ PR_ASSERT(sem != NULL);
+ get_sem_info(sem->sem, &info);
+ return info.count;
+}
diff --git a/pr/src/bthreads/btthread.c b/pr/src/bthreads/btthread.c
new file mode 100644
index 00000000..5f5e6564
--- /dev/null
+++ b/pr/src/bthreads/btthread.c
@@ -0,0 +1,780 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include <kernel/OS.h>
+
+#include "prlog.h"
+#include "primpl.h"
+#include "prcvar.h"
+#include "prpdce.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+
+#define BT_THREAD_PRIMORD 0x01 /* this is the primordial thread */
+#define BT_THREAD_SYSTEM 0x02 /* this is a system thread */
+
+struct _BT_Bookeeping
+{
+ PRLock *ml; /* a lock to protect ourselves */
+ PRCondVar *cv; /* used to signal global things */
+ PRInt32 threadCount; /* user thred count */
+
+} bt_book = { 0 };
+
+/*
+** A structure at the root of the thread private data. Each member of
+** the array keys[] points to a hash table based on the thread's ID.
+*/
+
+struct _BT_PrivateData
+{
+ PRLock *lock; /* A lock to coordinate access */
+ struct _BT_PrivateHash *keys[128]; /* Up to 128 keys, pointing to a hash table */
+
+} bt_privateRoot = { 0 };
+
+/*
+** A dynamically allocated structure that contains 256 hash buckets that
+** contain a linked list of thread IDs. The hash is simply the last 8 bits
+** of the thread_id. ( current thread_id & 0x000000FF )
+*/
+
+struct _BT_PrivateHash
+{
+ void (PR_CALLBACK *destructor)(void *arg); /* The destructor */
+ struct _BT_PrivateEntry *next[256]; /* Pointer to the first element in the list */
+};
+
+/*
+** A dynamically allocated structure that is a member of a linked list of
+** thread IDs.
+*/
+
+struct _BT_PrivateEntry
+{
+ struct _BT_PrivateEntry *next; /* Pointer to the next thread */
+ thread_id threadID; /* The BeOS thread ID */
+ void *data; /* The data */
+};
+
+PRUint32 _bt_mapPriority( PRThreadPriority priority );
+PR_IMPLEMENT(void *) _bt_getThreadPrivate(PRUintn index);
+
+void
+_PR_InitThreads (PRThreadType type, PRThreadPriority priority,
+ PRUintn maxPTDs)
+{
+ PRThread *primordialThread;
+ PRLock *tempLock;
+ PRUintn tempKey;
+ PRUint32 beThreadPriority;
+
+ /*
+ ** Create a NSPR structure for our primordial thread.
+ */
+
+ primordialThread = PR_NEWZAP(PRThread);
+ if( NULL == primordialThread )
+ {
+ PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
+ return;
+ }
+
+ /*
+ ** Set the priority to the desired level.
+ */
+
+ beThreadPriority = _bt_mapPriority( priority );
+
+ set_thread_priority( find_thread( NULL ), beThreadPriority );
+
+ primordialThread->state |= BT_THREAD_PRIMORD;
+ primordialThread->priority = priority;
+
+ /*
+ ** Initialize the thread tracking data structures
+ */
+
+ bt_privateRoot.lock = PR_NewLock();
+ if( NULL == bt_privateRoot.lock )
+ {
+ PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
+ return;
+ }
+
+ /*
+ ** Grab a key. We're guaranteed to be key #0, since we are
+ ** always the first one in.
+ */
+
+ if( PR_NewThreadPrivateIndex( &tempKey, NULL ) != PR_SUCCESS )
+ {
+ PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
+ return;
+ }
+
+ PR_ASSERT( tempKey == 0 );
+
+ /*
+ ** Stuff our new PRThread structure into our thread specific
+ ** slot.
+ */
+
+ if( PR_SetThreadPrivate( (PRUint8) 0, (void *) primordialThread ) == PR_FAILURE )
+ {
+ PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
+ return;
+ }
+
+ /*
+ ** Allocate some memory to hold our global lock. We never clean it
+ ** up later, but BeOS automatically frees memory when the thread
+ ** dies.
+ */
+
+ bt_book.ml = PR_NewLock();
+ if( NULL == bt_book.ml )
+ {
+ PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
+ return;
+ }
+
+ tempLock = PR_NewLock();
+ if( NULL == tempLock )
+ {
+ PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
+ return;
+ }
+
+ bt_book.cv = PR_NewCondVar( tempLock );
+ if( NULL == bt_book.cv )
+ {
+ PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
+ return;
+ }
+}
+
+PRUint32
+_bt_mapPriority( PRThreadPriority priority )
+{
+ switch( priority )
+ {
+ case PR_PRIORITY_LOW: return( B_LOW_PRIORITY );
+ case PR_PRIORITY_NORMAL: return( B_NORMAL_PRIORITY );
+ case PR_PRIORITY_HIGH: return( B_DISPLAY_PRIORITY );
+ case PR_PRIORITY_URGENT: return( B_URGENT_DISPLAY_PRIORITY );
+ default: return( B_NORMAL_PRIORITY );
+ }
+}
+
+/**
+ * This is a wrapper that all threads invoke that allows us to set some
+ * things up prior to a thread's invocation and clean up after a thread has
+ * exited.
+ */
+static void*
+_bt_root (void* arg)
+{
+ PRThread *thred = (PRThread*)arg;
+ PRIntn rv;
+ void *privData;
+ status_t result;
+ int i;
+
+ struct _BT_PrivateHash *hashTable;
+
+ /* Set within the current thread the pointer to our object. This
+ object will be deleted when the thread termintates. */
+
+ PR_ASSERT( PR_SetThreadPrivate( 0, (void *) thred ) == PR_SUCCESS );
+
+ thred->startFunc(thred->arg); /* run the dang thing */
+
+ /*
+ ** Call the destructor, if available.
+ */
+
+ PR_Lock( bt_privateRoot.lock );
+
+ for( i = 0; i < 128; i++ )
+ {
+ hashTable = bt_privateRoot.keys[i];
+
+ if( hashTable != NULL )
+ {
+ if( hashTable->destructor != NULL )
+ {
+ privData = _bt_getThreadPrivate( i );
+
+ if( privData != NULL )
+ {
+ PR_Unlock( bt_privateRoot.lock );
+ hashTable->destructor( privData );
+ PR_Lock( bt_privateRoot.lock );
+ }
+ }
+ }
+ }
+
+ PR_Unlock( bt_privateRoot.lock );
+
+ /* decrement our thread counters */
+
+ PR_Lock( bt_book.ml );
+
+ if (thred->state & BT_THREAD_SYSTEM) {
+#if 0
+ bt_book.system -= 1;
+#endif
+ } else
+ {
+ bt_book.threadCount--;
+
+ if( 0 == bt_book.threadCount )
+ {
+ PR_NotifyAllCondVar(bt_book.cv);
+ }
+ }
+
+ PR_Unlock( bt_book.ml );
+
+ if( thred->md.is_joinable == 1 )
+ {
+ /*
+ ** This is a joinable thread. Keep suspending
+ ** until is_joining is set to 1
+ */
+
+ if( thred->md.is_joining == 0 )
+ {
+ suspend_thread( thred->md.tid );
+ }
+ }
+
+ /* delete the thread object */
+ PR_DELETE(thred);
+
+ PR_ASSERT( PR_SetThreadPrivate( (PRUint8) 0, (void *) NULL ) == PR_SUCCESS );
+ exit_thread( NULL );
+}
+
+PR_IMPLEMENT(PRThread*)
+ PR_CreateThread (PRThreadType type, void (*start)(void* arg), void* arg,
+ PRThreadPriority priority, PRThreadScope scope,
+ PRThreadState state, PRUint32 stackSize)
+{
+ PRUint32 bePriority;
+
+ PRThread* thred = PR_NEWZAP(PRThread);
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ if (thred != NULL) {
+ thred->arg = arg;
+ thred->startFunc = start;
+ thred->priority = priority;
+
+ if( state == PR_JOINABLE_THREAD )
+ {
+ thred->md.is_joinable = 1;
+ }
+ else
+ {
+ thred->md.is_joinable = 0;
+ }
+
+ thred->md.is_joining = 0;
+
+ /* keep some books */
+
+ PR_Lock( bt_book.ml );
+
+ if (PR_SYSTEM_THREAD == type) {
+ thred->state |= BT_THREAD_SYSTEM;
+#if 0
+ bt_book.system += 1;
+#endif
+ } else {
+ bt_book.threadCount++;
+ }
+
+ PR_Unlock( bt_book.ml );
+
+ bePriority = _bt_mapPriority( priority );
+
+ thred->md.tid = spawn_thread((thread_func)_bt_root, "moz-thread",
+ bePriority, thred);
+ if (thred->md.tid < B_OK) {
+ PR_SetError(PR_UNKNOWN_ERROR, thred->md.tid);
+ PR_DELETE(thred);
+ thred = NULL;
+ }
+
+ if (resume_thread(thred->md.tid) < B_OK) {
+ PR_SetError(PR_UNKNOWN_ERROR, 0);
+ PR_DELETE(thred);
+ thred = NULL;
+ }
+
+ } else {
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+ }
+
+ return thred;
+}
+
+PR_IMPLEMENT(PRStatus)
+ PR_JoinThread (PRThread* thred)
+{
+ status_t eval, status;
+
+ PR_ASSERT(thred != NULL);
+
+ if( thred->md.is_joinable != 1 )
+ {
+ PR_SetError( PR_UNKNOWN_ERROR, 0 );
+ return( PR_FAILURE );
+ }
+
+ thred->md.is_joining = 1;
+
+ status = wait_for_thread(thred->md.tid, &eval);
+
+ if (status < B_NO_ERROR) {
+
+ PR_SetError(PR_UNKNOWN_ERROR, status);
+ return PR_FAILURE;
+ }
+
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRThread*)
+ PR_GetCurrentThread ()
+{
+ void* thred;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ thred = PR_GetThreadPrivate( (PRUint8) 0 );
+ PR_ASSERT(NULL != thred);
+
+ return (PRThread*)thred;
+}
+
+PR_IMPLEMENT(PRThreadScope)
+ PR_GetThreadScope (const PRThread* thred)
+{
+ PR_ASSERT(thred != NULL);
+ return PR_GLOBAL_THREAD;
+}
+
+PR_IMPLEMENT(PRThreadType)
+ PR_GetThreadType (const PRThread* thred)
+{
+ PR_ASSERT(thred != NULL);
+ return (thred->state & BT_THREAD_SYSTEM) ?
+ PR_SYSTEM_THREAD : PR_USER_THREAD;
+}
+
+PR_IMPLEMENT(PRThreadState)
+ PR_GetThreadState (const PRThread* thred)
+{
+ PR_ASSERT(thred != NULL);
+ return PR_JOINABLE_THREAD;
+}
+
+PR_IMPLEMENT(PRThreadPriority)
+ PR_GetThreadPriority (const PRThread* thred)
+{
+ PR_ASSERT(thred != NULL);
+ return thred->priority;
+} /* PR_GetThreadPriority */
+
+PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred,
+ PRThreadPriority newPri)
+{
+ PRUint32 bePriority;
+
+ PR_ASSERT( thred != NULL );
+
+ thred->priority = newPri;
+ bePriority = _bt_mapPriority( newPri );
+ set_thread_priority( thred->md.tid, bePriority );
+}
+
+PR_IMPLEMENT(PRStatus)
+ PR_NewThreadPrivateIndex (PRUintn* newIndex,
+ PRThreadPrivateDTOR destructor)
+{
+ PRUintn index;
+ struct _BT_PrivateHash *tempPointer;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ /*
+ ** Grab the lock, or hang until it is free. This is critical code,
+ ** and only one thread at a time should be going through it.
+ */
+
+ PR_Lock( bt_privateRoot.lock );
+
+ /*
+ ** Run through the array of keys, find the first one that's zero.
+ ** Exit if we hit the top of the array.
+ */
+
+ index = 0;
+
+ while( bt_privateRoot.keys[index] != 0 )
+ {
+ index++;
+
+ if( 128 == index )
+ {
+ PR_Unlock( bt_privateRoot.lock );
+ return( PR_FAILURE );
+ }
+ }
+
+ /*
+ ** Index has the first available zeroed slot. Allocate a
+ ** _BT_PrivateHash structure, all zeroed. Assuming that goes
+ ** well, return the index.
+ */
+
+ tempPointer = PR_NEWZAP( struct _BT_PrivateHash );
+
+ if( 0 == tempPointer ) {
+
+ PR_Unlock( bt_privateRoot.lock );
+ return( PR_FAILURE );
+ }
+
+ bt_privateRoot.keys[index] = tempPointer;
+ tempPointer->destructor = destructor;
+
+ PR_Unlock( bt_privateRoot.lock );
+
+ *newIndex = index;
+
+ return( PR_SUCCESS );
+}
+
+PR_IMPLEMENT(PRStatus)
+ PR_SetThreadPrivate (PRUintn index, void* priv)
+{
+ thread_id currentThread;
+ PRUint8 hashBucket;
+ void *tempPointer;
+
+ struct _BT_PrivateHash *hashTable;
+ struct _BT_PrivateEntry *currentEntry;
+ struct _BT_PrivateEntry *previousEntry;
+
+ /*
+ ** Sanity checking
+ */
+
+ if( index < 0 || index > 127 ) return( PR_FAILURE );
+
+ /*
+ ** Grab the thread ID for this thread. Assign it to a hash bucket.
+ */
+
+ currentThread = find_thread( NULL );
+ hashBucket = currentThread & 0x000000FF;
+
+ /*
+ ** Lock out all other threads then grab the proper hash table based
+ ** on the passed index.
+ */
+
+ PR_Lock( bt_privateRoot.lock );
+
+ hashTable = bt_privateRoot.keys[index];
+
+ if( 0 == hashTable )
+ {
+ PR_Unlock( bt_privateRoot.lock );
+ return( PR_FAILURE );
+ }
+
+ /*
+ ** Search through the linked list the end is reached or an existing
+ ** entry is found.
+ */
+
+ currentEntry = hashTable->next[ hashBucket ];
+ previousEntry = NULL;
+
+ while( currentEntry != 0 )
+ {
+ if( currentEntry->threadID == currentThread )
+ {
+ /*
+ ** Found a structure previously created for this thread.
+ ** Is there a destructor to be called?
+ */
+
+ if( hashTable->destructor != NULL )
+ {
+ if( currentEntry->data != NULL )
+ {
+ PR_Unlock( bt_privateRoot.lock );
+ hashTable->destructor( currentEntry->data );
+ PR_Lock( bt_privateRoot.lock );
+ }
+ }
+
+ /*
+ ** If the data was not NULL, and there was a destructor,
+ ** it has already been called. Overwrite the existing
+ ** data and return with success.
+ */
+
+ currentEntry->data = priv;
+ PR_Unlock( bt_privateRoot.lock );
+ return( PR_SUCCESS );
+ }
+
+ previousEntry = currentEntry;
+ currentEntry = previousEntry->next;
+ }
+
+ /*
+ ** If we're here, we didn't find an entry for this thread. Create
+ ** one and attach it to the end of the list.
+ */
+
+ currentEntry = PR_NEWZAP( struct _BT_PrivateEntry );
+
+ if( 0 == currentEntry )
+ {
+ PR_Unlock( bt_privateRoot.lock );
+ return( PR_FAILURE );
+ }
+
+ currentEntry->threadID = currentThread;
+ currentEntry->data = priv;
+
+ if( 0 == previousEntry )
+ {
+ /*
+ ** This is a special case. This is the first entry in the list
+ ** so set the hash table to point to this entry.
+ */
+
+ hashTable->next[ hashBucket ] = currentEntry;
+ }
+ else
+ {
+ previousEntry->next = currentEntry;
+ }
+
+ PR_Unlock( bt_privateRoot.lock );
+
+ return( PR_SUCCESS );
+}
+
+PR_IMPLEMENT(void*)
+ _bt_getThreadPrivate(PRUintn index)
+{
+ thread_id currentThread;
+ PRUint8 hashBucket;
+ void *tempPointer;
+
+ struct _BT_PrivateHash *hashTable;
+ struct _BT_PrivateEntry *currentEntry;
+
+ /*
+ ** Sanity checking
+ */
+
+ if( index < 0 || index > 127 ) return( NULL );
+
+ /*
+ ** Grab the thread ID for this thread. Assign it to a hash bucket.
+ */
+
+ currentThread = find_thread( NULL );
+ hashBucket = currentThread & 0x000000FF;
+
+ /*
+ ** Grab the proper hash table based on the passed index.
+ */
+
+ hashTable = bt_privateRoot.keys[index];
+
+ if( 0 == hashTable )
+ {
+ return( NULL );
+ }
+
+ /*
+ ** Search through the linked list the end is reached or an existing
+ ** entry is found.
+ */
+
+ currentEntry = hashTable->next[ hashBucket ];
+
+ while( currentEntry != 0 )
+ {
+ if( currentEntry->threadID == currentThread )
+ {
+ /*
+ ** Found a structure previously created for this thread.
+ ** Copy out the data, unlock, and return.
+ */
+
+ tempPointer = currentEntry->data;
+ return( tempPointer );
+ }
+
+ currentEntry = currentEntry->next;
+ }
+
+ /*
+ ** Ooops, we ran out of entries. This thread isn't listed.
+ */
+
+ return( NULL );
+}
+
+PR_IMPLEMENT(void*)
+ PR_GetThreadPrivate (PRUintn index)
+{
+ void *returnValue;
+
+ PR_Lock( bt_privateRoot.lock );
+ returnValue = _bt_getThreadPrivate( index );
+ PR_Unlock( bt_privateRoot.lock );
+
+ return( returnValue );
+}
+
+
+PR_IMPLEMENT(PRStatus)
+ PR_Interrupt (PRThread* thred)
+{
+ PRIntn rv;
+
+ PR_ASSERT(thred != NULL);
+ rv = resume_thread( thred->md.tid );
+
+ if( rv == B_BAD_THREAD_STATE )
+ {
+ /*
+ ** We have a thread that's not suspended, but is
+ ** blocked. Suspend it THEN resume it. The
+ ** function call that's hanging will return
+ ** B_INTERRUPTED
+ */
+
+ rv = suspend_thread( thred->md.tid );
+ if( rv != B_NO_ERROR )
+ {
+ PR_SetError( PR_UNKNOWN_ERROR, rv );
+ return( PR_FAILURE );
+ }
+ rv = resume_thread( thred->md.tid );
+ if( rv != B_NO_ERROR )
+ {
+ PR_SetError( PR_UNKNOWN_ERROR, rv );
+ return( PR_FAILURE );
+ }
+ }
+
+ if( rv != B_NO_ERROR )
+ {
+ PR_SetError( PR_UNKNOWN_ERROR, rv );
+ return( PR_FAILURE );
+ }
+
+ return( PR_SUCCESS );
+}
+
+PR_IMPLEMENT(void)
+ PR_ClearInterrupt ()
+{
+}
+
+PR_IMPLEMENT(PRStatus)
+ PR_Yield ()
+{
+ /* we just sleep for long enough to cause a reschedule (100
+ microseconds) */
+ snooze(100);
+}
+
+#define BT_MILLION 1000000UL
+
+PR_IMPLEMENT(PRStatus)
+ PR_Sleep (PRIntervalTime ticks)
+{
+ bigtime_t tps;
+ status_t status;
+
+ if (!_pr_initialized) _PR_ImplicitInitialization();
+
+ tps = PR_IntervalToMicroseconds( ticks );
+
+ status = snooze(tps);
+ if (status == B_NO_ERROR) return PR_SUCCESS;
+
+ PR_SetError(PR_NOT_IMPLEMENTED_ERROR, status);
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+ PR_Cleanup ()
+{
+ PRThread *me = PR_CurrentThread();
+
+ PR_ASSERT(me->state & BT_THREAD_PRIMORD);
+ if ((me->state & BT_THREAD_PRIMORD) == 0) {
+ return PR_FAILURE;
+ }
+
+ PR_Lock( bt_book.ml );
+
+ while( bt_book.threadCount > 0 )
+ {
+ PR_Unlock( bt_book.ml );
+ PR_WaitCondVar(bt_book.cv, PR_INTERVAL_NO_TIMEOUT);
+ PR_Lock( bt_book.ml );
+ }
+
+ PR_Unlock( bt_book.ml );
+
+#if 0
+ /* I am not sure if it's safe to delete the cv and lock here, since
+ * there may still be "system" threads around. If this call isn't
+ * immediately prior to exiting, then there's a problem. */
+ if (0 == bt_book.system) {
+ PR_DestroyCondVar(bt_book.cv); bt_book.cv = NULL;
+ PR_DestroyLock(bt_book.ml); bt_book.ml = NULL;
+ }
+ PR_DELETE(me);
+#endif
+
+ return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(void)
+ PR_ProcessExit (PRIntn status)
+{
+ exit(status);
+}
diff --git a/pr/src/bthreads/objs.mk b/pr/src/bthreads/objs.mk
new file mode 100644
index 00000000..01f2b63d
--- /dev/null
+++ b/pr/src/bthreads/objs.mk
@@ -0,0 +1,18 @@
+#
+# The contents of this file are subject to the Mozilla Public License
+# Version 1.0 (the "MPL"); you may not use this file except in
+# compliance with the MPL. You may obtain a copy of the MPL at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the MPL is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+# for the specific language governing rights and limitations under the
+# MPL.
+#
+
+# This makefile appends to the variable OBJS the bthread object modules
+# that will be part of the nspr20 library.
+
+include bthreads/bsrcs.mk
+
+OBJS += $(BTCSRCS:%.c=bthreads/$(OBJDIR)/%.$(OBJ_SUFFIX))
diff --git a/pr/src/md/beos/Makefile b/pr/src/md/beos/Makefile
new file mode 100644
index 00000000..ef9b5e6c
--- /dev/null
+++ b/pr/src/md/beos/Makefile
@@ -0,0 +1,28 @@
+#
+# The contents of this file are subject to the Mozilla Public License
+# Version 1.0 (the "MPL"); you may not use this file except in
+# compliance with the MPL. You may obtain a copy of the MPL at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the MPL is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+# for the specific language governing rights and limitations under the
+# MPL.
+#
+
+MOD_DEPTH = ../../../..
+
+include $(MOD_DEPTH)/config/config.mk
+
+include bsrcs.mk
+CSRCS += $(MDCSRCS)
+
+TARGETS = $(OBJS)
+
+INCLUDES = -I$(DIST)/include/private -I$(DIST)/include
+
+include $(MOD_DEPTH)/config/rules.mk
+
+export:: $(TARGETS)
+
+install:: export
diff --git a/pr/src/md/beos/bcpu.c b/pr/src/md/beos/bcpu.c
new file mode 100644
index 00000000..ca29cf8e
--- /dev/null
+++ b/pr/src/md/beos/bcpu.c
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http:// www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include "primpl.h"
+
+PR_EXTERN(void) _PR_MD_INIT_CPUS();
+PR_EXTERN(void) _PR_MD_WAKEUP_CPUS();
+PR_EXTERN(void) _PR_MD_START_INTERRUPTS(void);
+PR_EXTERN(void) _PR_MD_STOP_INTERRUPTS(void);
+PR_EXTERN(void) _PR_MD_DISABLE_CLOCK_INTERRUPTS(void);
+PR_EXTERN(void) _PR_MD_BLOCK_CLOCK_INTERRUPTS(void);
+PR_EXTERN(void) _PR_MD_UNBLOCK_CLOCK_INTERRUPTS(void);
+PR_EXTERN(void) _PR_MD_CLOCK_INTERRUPT(void);
+PR_EXTERN(void) _PR_MD_INIT_STACK(PRThreadStack *ts, PRIntn redzone);
+PR_EXTERN(void) _PR_MD_CLEAR_STACK(PRThreadStack* ts);
+PR_EXTERN(PRInt32) _PR_MD_GET_INTSOFF(void);
+PR_EXTERN(void) _PR_MD_SET_INTSOFF(PRInt32 _val);
+PR_EXTERN(_PRCPU*) _PR_MD_CURRENT_CPU(void);
+PR_EXTERN(void) _PR_MD_SET_CURRENT_CPU(_PRCPU *cpu);
+PR_EXTERN(void) _PR_MD_INIT_RUNNING_CPU(_PRCPU *cpu);
+PR_EXTERN(PRInt32) _PR_MD_PAUSE_CPU(PRIntervalTime timeout);
diff --git a/pr/src/md/beos/beos.c b/pr/src/md/beos/beos.c
new file mode 100644
index 00000000..73c7a4e1
--- /dev/null
+++ b/pr/src/md/beos/beos.c
@@ -0,0 +1,240 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include "primpl.h"
+
+#include <signal.h>
+#include <unistd.h>
+#include <memory.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+/*
+ * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or
+ * PRInt32* pointer to a _PRSockLen_t* pointer.
+ */
+#define _PRSockLen_t int
+
+/*
+** Global lock variable used to bracket calls into rusty libraries that
+** aren't thread safe (like libc, libX, etc).
+*/
+static PRLock *_pr_rename_lock = NULL;
+static PRMonitor *_pr_Xfe_mon = NULL;
+
+/*
+ * Variables used by the GC code, initialized in _MD_InitSegs().
+ * _pr_zero_fd should be a static variable. Unfortunately, there is
+ * still some Unix-specific code left in function PR_GrowSegment()
+ * in file memory/prseg.c that references it, so it needs
+ * to be a global variable for now.
+ */
+PRInt32 _pr_zero_fd = -1;
+static PRLock *_pr_md_lock = NULL;
+
+sigset_t timer_set;
+
+void _PR_UnixInit()
+{
+ struct sigaction sigact;
+ int rv;
+
+ sigemptyset(&timer_set);
+
+ sigact.sa_handler = SIG_IGN;
+ sigemptyset(&sigact.sa_mask);
+ sigact.sa_flags = 0;
+ rv = sigaction(SIGPIPE, &sigact, 0);
+ PR_ASSERT(0 == rv);
+
+ _pr_rename_lock = PR_NewLock();
+ PR_ASSERT(NULL != _pr_rename_lock);
+ _pr_Xfe_mon = PR_NewMonitor();
+ PR_ASSERT(NULL != _pr_Xfe_mon);
+}
+
+/*
+ *-----------------------------------------------------------------------
+ *
+ * PR_Now --
+ *
+ * Returns the current time in microseconds since the epoch.
+ * The epoch is midnight January 1, 1970 GMT.
+ * The implementation is machine dependent. This is the Unix
+ * implementation.
+ * Cf. time_t time(time_t *tp)
+ *
+ *-----------------------------------------------------------------------
+ */
+
+PR_IMPLEMENT(PRTime)
+PR_Now(void)
+{
+ struct timeval tv;
+ PRInt64 s, us, s2us;
+
+ GETTIMEOFDAY(&tv);
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_I2L(s, tv.tv_sec);
+ LL_I2L(us, tv.tv_usec);
+ LL_MUL(s, s, s2us);
+ LL_ADD(s, s, us);
+ return s;
+}
+
+PRIntervalTime
+_PR_UNIX_GetInterval()
+{
+ struct timeval time;
+ PRIntervalTime ticks;
+
+ (void)GETTIMEOFDAY(&time); /* fallicy of course */
+ ticks = (PRUint32)time.tv_sec * PR_MSEC_PER_SEC; /* that's in milliseconds */
+ ticks += (PRUint32)time.tv_usec / PR_USEC_PER_MSEC; /* so's that */
+ return ticks;
+} /* _PR_SUNOS_GetInterval */
+
+PRIntervalTime _PR_UNIX_TicksPerSecond()
+{
+ return 1000; /* this needs some work :) */
+}
+
+/************************************************************************/
+
+/*
+** Special hacks for xlib. Xlib/Xt/Xm is not re-entrant nor is it thread
+** safe. Unfortunately, neither is mozilla. To make these programs work
+** in a pre-emptive threaded environment, we need to use a lock.
+*/
+
+void PR_XLock()
+{
+ PR_EnterMonitor(_pr_Xfe_mon);
+}
+
+void PR_XUnlock()
+{
+ PR_ExitMonitor(_pr_Xfe_mon);
+}
+
+PRBool PR_XIsLocked()
+{
+ return (PR_InMonitor(_pr_Xfe_mon)) ? PR_TRUE : PR_FALSE;
+}
+
+void PR_XWait(int ms)
+{
+ PR_Wait(_pr_Xfe_mon, PR_MillisecondsToInterval(ms));
+}
+
+void PR_XNotify(void)
+{
+ PR_Notify(_pr_Xfe_mon);
+}
+
+void PR_XNotifyAll(void)
+{
+ PR_NotifyAll(_pr_Xfe_mon);
+}
+
+#if !defined(BEOS)
+#ifdef HAVE_BSD_FLOCK
+
+#include <sys/file.h>
+
+PR_IMPLEMENT(PRStatus)
+_MD_LOCKFILE (PRInt32 f)
+{
+ PRInt32 rv;
+ rv = flock(f, LOCK_EX);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_TLOCKFILE (PRInt32 f)
+{
+ PRInt32 rv;
+ rv = flock(f, LOCK_EX|LOCK_NB);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_UNLOCKFILE (PRInt32 f)
+{
+ PRInt32 rv;
+ rv = flock(f, LOCK_UN);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+#else
+
+PR_IMPLEMENT(PRStatus)
+_MD_LOCKFILE (PRInt32 f)
+{
+ PRInt32 rv;
+ rv = lockf(f, F_LOCK, 0);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_TLOCKFILE (PRInt32 f)
+{
+ PRInt32 rv;
+ rv = lockf(f, F_TLOCK, 0);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PR_IMPLEMENT(PRStatus)
+_MD_UNLOCKFILE (PRInt32 f)
+{
+ PRInt32 rv;
+ rv = lockf(f, F_ULOCK, 0);
+ if (rv == 0)
+ return PR_SUCCESS;
+ _PR_MD_MAP_LOCKF_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+#endif
+
+PR_IMPLEMENT(PRStatus)
+ _MD_GETHOSTNAME (char *name, PRUint32 namelen)
+{
+ PRIntn rv;
+
+ rv = gethostname(name, namelen);
+ if (0 == rv) {
+ return PR_SUCCESS;
+ }
+ _PR_MD_MAP_GETHOSTNAME_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+#endif
diff --git a/pr/src/md/beos/beos_errors.c b/pr/src/md/beos/beos_errors.c
new file mode 100644
index 00000000..e47b1ce9
--- /dev/null
+++ b/pr/src/md/beos/beos_errors.c
@@ -0,0 +1,1535 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include "prtypes.h"
+#include "md/_unix_errors.h"
+#include "prerror.h"
+#include <errno.h>
+
+void _MD_unix_map_opendir_error(int err)
+{
+ switch (err) {
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EMFILE:
+ PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case ENFILE:
+ PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_closedir_error(int err)
+{
+ switch (err) {
+ case EINVAL:
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_readdir_error(int err)
+{
+
+ switch (err) {
+ case ENOENT:
+ PR_SetError(PR_NO_MORE_FILES_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#ifdef IRIX
+#ifdef IRIX5_3
+#else
+ case EDIRCORRUPTED:
+ PR_SetError(PR_DIRECTORY_CORRUPTED_ERROR, err);
+ break;
+#endif
+#endif
+#ifdef EOVERFLOW
+ case EOVERFLOW:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+#endif
+ case EINVAL:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+#ifdef EBADMSG
+ case EBADMSG:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+#endif
+ case EDEADLK:
+ PR_SetError(PR_DEADLOCK_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ENOLCK:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+#ifdef ENOLINK
+ case ENOLINK:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+#endif
+ case ENXIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_unlink_error(int err)
+{
+ switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EBUSY:
+ PR_SetError(PR_FILESYSTEM_MOUNTED_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+ case EPERM:
+ PR_SetError(PR_IS_DIRECTORY_ERROR, err);
+ break;
+ case EROFS:
+ PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err);
+ break;
+#if !defined(OSF1) && !defined(FREEBSD) && !defined(BSDI) && !defined(RHAPSODY) && !defined(BEOS)
+ case EMULTIHOP:
+ case ENOLINK:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_stat_error(int err)
+{
+ switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case ETIMEDOUT:
+#if !defined(OSF1) && !defined(FREEBSD) && !defined(BSDI) && !defined(RHAPSODY) && !defined(BEOS)
+ case EMULTIHOP:
+ case ENOLINK:
+#endif
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+#ifdef EOVERFLOW
+ case EOVERFLOW:
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_fstat_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case ETIMEDOUT:
+#ifdef ENOLINK
+ case ENOLINK:
+#endif
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+#ifdef EOVERFLOW
+ case EOVERFLOW:
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_rename_error(int err)
+{
+ switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EBUSY:
+ PR_SetError(PR_FILESYSTEM_MOUNTED_ERROR, err);
+ break;
+#ifdef EDQUOT
+ case EDQUOT:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+#endif
+ case EEXIST:
+ PR_SetError(PR_DIRECTORY_NOT_EMPTY_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case EISDIR:
+ PR_SetError(PR_IS_DIRECTORY_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+#if !defined(OSF1) && !defined(FREEBSD) && !defined(BSDI) && !defined(RHAPSODY) && !defined(BEOS)
+ case EMULTIHOP:
+ case ENOLINK:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+#endif
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ENOSPC:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+ case EROFS:
+ PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err);
+ break;
+ case EXDEV:
+ PR_SetError(PR_NOT_SAME_DEVICE_ERROR, err);
+ break;
+ case EMLINK:
+ PR_SetError(PR_MAX_DIRECTORY_ENTRIES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_access_error(int err)
+{
+ switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+#if !defined(OSF1) && !defined(FREEBSD) && !defined(BSDI) && !defined(RHAPSODY) && !defined(BEOS)
+ case EMULTIHOP:
+ case ENOLINK:
+#endif
+ case ETIMEDOUT:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+ case EROFS:
+ PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_mkdir_error(int err)
+{
+ switch (err) {
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EEXIST:
+ PR_SetError(PR_FILE_EXISTS_ERROR, err);
+ break;
+ case EROFS:
+ PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+ case EMLINK:
+ PR_SetError(PR_MAX_DIRECTORY_ENTRIES_ERROR, err);
+ break;
+ case ENOSPC:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+#ifdef EDQUOT
+ case EDQUOT:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+#endif
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+#if !defined(OSF1) && !defined(FREEBSD) && !defined(BSDI) && !defined(RHAPSODY) && !defined(BEOS)
+ case EMULTIHOP:
+ case ENOLINK:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_rmdir_error(int err)
+{
+
+ switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EBUSY:
+ PR_SetError(PR_FILESYSTEM_MOUNTED_ERROR, err);
+ break;
+ case EEXIST:
+ PR_SetError(PR_DIRECTORY_NOT_EMPTY_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_DIRECTORY_NOT_EMPTY_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+#if !defined(OSF1) && !defined(FREEBSD) && !defined(BSDI) && !defined(RHAPSODY) && !defined(BEOS)
+ case EMULTIHOP:
+ case ENOLINK:
+#endif
+ case ETIMEDOUT:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+ case EROFS:
+ PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_read_error(int err)
+{
+ switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#ifdef EBADMSG
+ case EBADMSG:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+#endif
+ case EDEADLK:
+ PR_SetError(PR_DEADLOCK_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_METHOD_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ENOLCK:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ case ENXIO:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EISDIR:
+ PR_SetError(PR_IS_DIRECTORY_ERROR, err);
+ break;
+ case ECONNRESET:
+ case EPIPE:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+#ifdef ENOLINK
+ case ENOLINK:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_write_error(int err)
+{
+ switch (err) {
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EDEADLK:
+ PR_SetError(PR_DEADLOCK_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EFBIG:
+ PR_SetError(PR_FILE_TOO_BIG_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_METHOD_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case ENOLCK:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ case ENOSPC:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+ case ENXIO:
+ PR_SetError(PR_INVALID_METHOD_ERROR, err);
+ break;
+ case ERANGE:
+ PR_SetError(PR_INVALID_METHOD_ERROR, err);
+ break;
+ case ETIMEDOUT:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ case ECONNRESET:
+ case EPIPE:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+#ifdef EDQUOT
+ case EDQUOT:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+#endif
+#ifdef ENOLINK
+ case ENOLINK:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_lseek_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case ESPIPE:
+ PR_SetError(PR_INVALID_METHOD_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_fsync_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#ifdef ENOLINK
+ case ENOLINK:
+#endif
+ case ETIMEDOUT:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_METHOD_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_close_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+#ifdef ENOLINK
+ case ENOLINK:
+#endif
+ case ETIMEDOUT:
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_socket_error(int err)
+{
+ switch (err) {
+ case EPROTONOSUPPORT:
+ PR_SetError(PR_PROTOCOL_NOT_SUPPORTED_ERROR, err);
+ break;
+ case EMFILE:
+ PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case ENFILE:
+ PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+#if !defined(SCO)
+ case ENOBUFS:
+#endif /* !defined(SCO) */
+ case ENOMEM:
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_socketavailable_error(int err)
+{
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+}
+
+void _MD_unix_map_recv_error(int err)
+{
+ switch (err) {
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ break;
+ case ECONNRESET:
+ case EPIPE:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_recvfrom_error(int err)
+{
+ switch (err) {
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ case ECONNRESET:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_send_error(int err)
+{
+ switch (err) {
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+#if !defined(BEOS)
+ case EMSGSIZE:
+#endif
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+#if !defined(SCO)
+ case ENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif /* !defined(SCO) */
+ case ECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case EISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ case ECONNRESET:
+ case EPIPE:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_sendto_error(int err)
+{
+ switch (err) {
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+#if !defined(BEOS)
+ case EMSGSIZE:
+#endif
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+#if !defined(SCO)
+ case ENOBUFS:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif /* !defined(SCO) */
+ case ECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case EISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ case ECONNRESET:
+ case EPIPE:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_writev_error(int err)
+{
+ switch (err) {
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case ECONNRESET:
+ case EPIPE:
+ PR_SetError(PR_CONNECT_RESET_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_accept_error(int err)
+{
+ switch (err) {
+ case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ PR_SetError(PR_WOULD_BLOCK_ERROR, err);
+ break;
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+#if !defined(BEOS)
+ case EOPNOTSUPP:
+#endif
+ case ENODEV:
+ PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EMFILE:
+ PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case ENFILE:
+ PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+#ifdef EPROTO
+ case EPROTO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_connect_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EADDRNOTAVAIL:
+ PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err);
+ break;
+ case EINPROGRESS:
+ PR_SetError(PR_IN_PROGRESS_ERROR, err);
+ break;
+ case EALREADY:
+ PR_SetError(PR_ALREADY_INITIATED_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case EAFNOSUPPORT:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ case EISCONN:
+ PR_SetError(PR_IS_CONNECTED_ERROR, err);
+ break;
+ case ETIMEDOUT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, err);
+ break;
+ case ECONNREFUSED:
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+ break;
+ case ENETUNREACH:
+ PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, err);
+ break;
+ case EADDRINUSE:
+ PR_SetError(PR_ADDRESS_IN_USE_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ /*
+ * UNIX domain sockets are not supported in NSPR
+ */
+ case EACCES:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EIO:
+#if defined(UNIXWARE) || defined(SNI) || defined(NEC)
+ /*
+ * On some platforms, if we connect to a port on
+ * the local host (the loopback address) that no
+ * process is listening on, we get EIO instead
+ * of ECONNREFUSED.
+ */
+ PR_SetError(PR_CONNECT_REFUSED_ERROR, err);
+#else
+ PR_SetError(PR_IO_ERROR, err);
+#endif
+ break;
+ case ELOOP:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ case ENOENT:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ case ENXIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case EPROTOTYPE:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_bind_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EADDRNOTAVAIL:
+ PR_SetError(PR_ADDRESS_NOT_AVAILABLE_ERROR, err);
+ break;
+ case EADDRINUSE:
+ PR_SetError(PR_ADDRESS_IN_USE_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_SOCKET_ADDRESS_IS_BOUND_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ /*
+ * UNIX domain sockets are not supported in NSPR
+ */
+ case EIO:
+ case EISDIR:
+ case ELOOP:
+ case ENOENT:
+ case ENOTDIR:
+ case EROFS:
+ PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_listen_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+#if !defined(BEOS)
+ case EOPNOTSUPP:
+ PR_SetError(PR_NOT_TCP_SOCKET_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_shutdown_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case ENOTCONN:
+ PR_SetError(PR_NOT_CONNECTED_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_socketpair_error(int err)
+{
+ switch (err) {
+ case EMFILE:
+ PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case ENOMEM:
+#ifdef ENOSR
+ case ENOSR:
+#endif
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case EAFNOSUPPORT:
+ case EPROTONOSUPPORT:
+#if !defined(BEOS)
+ case EOPNOTSUPP:
+#endif
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_getsockname_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#if !defined(SCO)
+ case ENOBUFS:
+#endif /* !defined(SCO) */
+ case ENOMEM:
+#ifdef ENOSR
+ case ENOSR:
+#endif
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_getpeername_error(int err)
+{
+
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case ENOTCONN:
+ PR_SetError(PR_NOT_CONNECTED_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+#if !defined(SCO)
+ case ENOBUFS:
+#endif /* !defined(SCO) */
+ case ENOMEM:
+#ifdef ENOSR
+ case ENOSR:
+#endif
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_getsockopt_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case ENOPROTOOPT:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ break;
+ case ENOMEM:
+#ifdef ENOSR
+ case ENOSR:
+#endif
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_setsockopt_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+#if !defined(BEOS)
+ case ENOTSOCK:
+ PR_SetError(PR_NOT_SOCKET_ERROR, err);
+ break;
+#endif
+ case ENOPROTOOPT:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_BUFFER_OVERFLOW_ERROR, err);
+ break;
+ case ENOMEM:
+#ifdef ENOSR
+ case ENOSR:
+#endif
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_open_error(int err)
+{
+ switch (err) {
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case EAGAIN:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case EBUSY:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case EEXIST:
+ PR_SetError(PR_FILE_EXISTS_ERROR, err);
+ break;
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ case EIO:
+ PR_SetError(PR_IO_ERROR, err);
+ break;
+ case EISDIR:
+ PR_SetError(PR_IS_DIRECTORY_ERROR, err);
+ break;
+ case ELOOP:
+ PR_SetError(PR_LOOP_ERROR, err);
+ break;
+ case EMFILE:
+ PR_SetError(PR_PROC_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case ENAMETOOLONG:
+ PR_SetError(PR_NAME_TOO_LONG_ERROR, err);
+ break;
+ case ENFILE:
+ PR_SetError(PR_SYS_DESC_TABLE_FULL_ERROR, err);
+ break;
+ case ENODEV:
+ case ENOENT:
+ case ENXIO:
+ PR_SetError(PR_FILE_NOT_FOUND_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ENOSPC:
+ PR_SetError(PR_NO_DEVICE_SPACE_ERROR, err);
+ break;
+#ifdef ENOSR
+ case ENOSR:
+#endif
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case ENOTDIR:
+ PR_SetError(PR_NOT_DIRECTORY_ERROR, err);
+ break;
+ case EPERM:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ETIMEDOUT:
+#if !defined(OSF1) && !defined(FREEBSD) && !defined(BSDI) && !defined(RHAPSODY) && !defined(BEOS)
+ case EMULTIHOP:
+ case ENOLINK:
+#endif
+ PR_SetError(PR_REMOTE_FILE_ERROR, err);
+ break;
+ case EROFS:
+ PR_SetError(PR_READ_ONLY_FILESYSTEM_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_mmap_error(int err)
+{
+
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EAGAIN:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, err);
+ break;
+ case ENOMEM:
+ PR_SetError(PR_OUT_OF_MEMORY_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_gethostname_error(int err)
+{
+ switch (err) {
+ case EFAULT:
+ PR_SetError(PR_ACCESS_FAULT_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_select_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EINTR:
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, err);
+ break;
+ case EINVAL:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_poll_error(int err)
+{
+ PRErrorCode prerror;
+ switch (err) {
+ case EAGAIN:
+ prerror = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case EINVAL:
+ prerror = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case EFAULT:
+ prerror = PR_ACCESS_FAULT_ERROR;
+ break;
+ default:
+ prerror = PR_UNKNOWN_ERROR;
+ break;
+ }
+ PR_SetError(prerror, err);
+}
+
+void _MD_unix_map_flock_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ case EINVAL:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EWOULDBLOCK:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+void _MD_unix_map_lockf_error(int err)
+{
+ switch (err) {
+ case EBADF:
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, err);
+ break;
+ case EACCES:
+ PR_SetError(PR_FILE_IS_LOCKED_ERROR, err);
+ break;
+ case EDEADLK:
+ PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, err);
+ break;
+ default:
+ PR_SetError(PR_UNKNOWN_ERROR, err);
+ break;
+ }
+}
+
+#ifdef HPUX11
+void _MD_hpux_map_sendfile_error(int oserror)
+{
+ PRErrorCode prerror;
+
+ switch (oserror) {
+ case ENOTSOCK:
+ prerror = PR_NOT_SOCKET_ERROR;
+ break;
+ case EFAULT:
+ prerror = PR_ACCESS_FAULT_ERROR;
+ break;
+ case ENOBUFS:
+ prerror = PR_INSUFFICIENT_RESOURCES_ERROR;
+ break;
+ case EINVAL:
+ prerror = PR_INVALID_ARGUMENT_ERROR;
+ break;
+ case ENOTCONN:
+ prerror = PR_NOT_CONNECTED_ERROR;
+ break;
+ case EPIPE:
+ prerror = PR_CONNECT_RESET_ERROR;
+ break;
+ case ENOMEM:
+ prerror = PR_OUT_OF_MEMORY_ERROR;
+ break;
+ case EOPNOTSUPP:
+ prerror = PR_NOT_TCP_SOCKET_ERROR;
+ break;
+ default:
+ prerror = PR_UNKNOWN_ERROR;
+ }
+ PR_SetError(prerror, oserror);
+}
+#endif /* HPUX11 */
diff --git a/pr/src/md/beos/bfile.c b/pr/src/md/beos/bfile.c
new file mode 100644
index 00000000..e22ec4c0
--- /dev/null
+++ b/pr/src/md/beos/bfile.c
@@ -0,0 +1,783 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http:// www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include "primpl.h"
+
+/*
+** Global lock variable used to bracket calls into rusty libraries that
+** aren't thread safe (like libc, libX, etc).
+*/
+static PRLock *_pr_rename_lock = NULL;
+
+void
+_MD_InitIO (void)
+{
+}
+
+PRStatus
+_MD_open_dir (_MDDir *md,const char *name)
+{
+int err;
+
+ md->d = opendir(name);
+ if (!md->d) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_OPENDIR_ERROR(err);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+char*
+_MD_read_dir (_MDDir *md, PRIntn flags)
+{
+struct dirent *de;
+int err;
+
+ for (;;) {
+ /*
+ * XXX: readdir() is not MT-safe
+ */
+ de = readdir(md->d);
+
+ if (!de) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_READDIR_ERROR(err);
+ return 0;
+ }
+
+ if ((flags & PR_SKIP_DOT) &&
+ (de->d_name[0] == '.') && (de->d_name[1] == 0))
+ continue;
+
+ if ((flags & PR_SKIP_DOT_DOT) &&
+ (de->d_name[0] == '.') && (de->d_name[1] == '.') &&
+ (de->d_name[2] == 0))
+ continue;
+
+ if ((flags & PR_SKIP_HIDDEN) && (de->d_name[1] == '.'))
+ continue;
+
+ break;
+ }
+ return de->d_name;
+}
+
+
+PRInt32
+_MD_close_dir (_MDDir *md)
+{
+int rv = 0, err;
+
+ if (md->d) {
+ rv = closedir(md->d);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_CLOSEDIR_ERROR(err);
+ }
+ }
+ return(rv);
+}
+
+void
+_MD_make_nonblock (PRFileDesc *fd)
+{
+ int blocking = 1;
+ setsockopt(fd->secret->md.osfd, SOL_SOCKET, SO_NONBLOCK, &blocking, sizeof(blocking));
+
+}
+
+PRInt32
+_MD_open (const char *name, PRIntn flags, PRIntn mode)
+{
+ PRInt32 osflags;
+ PRInt32 rv, err;
+
+ if (flags & PR_RDWR) {
+ osflags = O_RDWR;
+ } else if (flags & PR_WRONLY) {
+ osflags = O_WRONLY;
+ } else {
+ osflags = O_RDONLY;
+ }
+
+ if (flags & PR_APPEND)
+ osflags |= O_APPEND;
+ if (flags & PR_TRUNCATE)
+ osflags |= O_TRUNC;
+ if (flags & PR_SYNC) {
+/* Ummmm. BeOS doesn't appear to
+ support sync in any way shape or
+ form. */
+ return PR_NOT_IMPLEMENTED_ERROR;
+ }
+
+ /*
+ ** On creations we hold the 'create' lock in order to enforce
+ ** the semantics of PR_Rename. (see the latter for more details)
+ */
+ if (flags & PR_CREATE_FILE)
+ {
+ osflags |= O_CREAT ;
+ if (NULL !=_pr_rename_lock)
+ PR_Lock(_pr_rename_lock);
+ }
+
+ rv = open(name, osflags, mode);
+
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_OPEN_ERROR(err);
+ }
+
+ if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock))
+ PR_Unlock(_pr_rename_lock);
+ return rv;
+}
+
+PRInt32
+_MD_close_file (PRInt32 osfd)
+{
+PRInt32 rv, err;
+
+ rv = close(osfd);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_CLOSE_ERROR(err);
+ }
+ return(rv);
+}
+
+PRInt32
+_MD_read (PRFileDesc *fd, void *buf, PRInt32 amount)
+{
+ PRInt32 rv, err;
+ PRInt32 osfd = fd->secret->md.osfd;
+
+ rv = read( osfd, buf, amount );
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_READ_ERROR(err);
+ }
+ return(rv);
+}
+
+PRInt32
+_MD_write (PRFileDesc *fd, const void *buf, PRInt32 amount)
+{
+ PRInt32 rv, err;
+ PRInt32 osfd = fd->secret->md.osfd;
+
+ rv = write( osfd, buf, amount );
+
+ if( rv < 0 ) {
+
+ err = _MD_ERRNO();
+ _PR_MD_MAP_WRITE_ERROR(err);
+ }
+ return( rv );
+}
+
+PRInt32
+_MD_writev (PRFileDesc *fd, struct PRIOVec *iov, PRInt32 iov_size,
+ PRIntervalTime timeout)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+PRInt32
+_MD_lseek (PRFileDesc *fd, PRInt32 offset, int whence)
+{
+PRInt32 rv, err;
+
+ rv = lseek (fd->secret->md.osfd, offset, whence);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_LSEEK_ERROR(err);
+ }
+ return( rv );
+}
+
+PRInt64
+_MD_lseek64 (PRFileDesc *fd, PRInt64 offset, int whence)
+{
+PRInt32 rv, err;
+
+/* According to the BeOS headers, lseek accepts a
+ * variable of type off_t for the offset, and off_t
+ * is defined to be a 64-bit value. So no special
+ * cracking needs to be done on "offset".
+ */
+
+ rv = lseek (fd->secret->md.osfd, offset, whence);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_LSEEK_ERROR(err);
+ }
+ return( rv );
+}
+
+PRInt32
+_MD_fsync (PRFileDesc *fd)
+{
+PRInt32 rv, err;
+
+ rv = fsync(fd->secret->md.osfd);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_FSYNC_ERROR(err);
+ }
+ return(rv);
+}
+
+PRInt32
+_MD_delete (const char *name)
+{
+PRInt32 rv, err;
+
+ rv = unlink(name);
+ if (rv == -1)
+ {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_UNLINK_ERROR(err);
+ }
+ return (rv);
+}
+
+PRInt32
+_MD_getfileinfo (const char *fn, PRFileInfo *info)
+{
+struct stat sb;
+PRInt32 rv, err;
+PRInt64 s, s2us;
+
+ rv = stat(fn, &sb);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_STAT_ERROR(err);
+ } else if (info) {
+ if (S_IFREG & sb.st_mode)
+ info->type = PR_FILE_FILE;
+ else if (S_IFDIR & sb.st_mode)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+
+ /* Must truncate file size for the 32 bit
+ version */
+ info->size = (sb.st_size & 0xffffffff);
+ LL_I2L(s, sb.st_mtime);
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_MUL(s, s, s2us);
+ info->modifyTime = s;
+ LL_I2L(s, sb.st_ctime);
+ LL_MUL(s, s, s2us);
+ info->creationTime = s;
+ }
+ return rv;
+}
+
+PRInt32
+_MD_getfileinfo64 (const char *fn, PRFileInfo64 *info)
+{
+struct stat sb;
+PRInt32 rv, err;
+PRInt64 s, s2us;
+
+ rv = stat(fn, &sb);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_STAT_ERROR(err);
+ } else if (info) {
+ if (S_IFREG & sb.st_mode)
+ info->type = PR_FILE_FILE;
+ else if (S_IFDIR & sb.st_mode)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+
+ /* For the 64 bit version we can use
+ * the native st_size without modification
+ */
+ info->size = sb.st_size;
+ LL_I2L(s, sb.st_mtime);
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_MUL(s, s, s2us);
+ info->modifyTime = s;
+ LL_I2L(s, sb.st_ctime);
+ LL_MUL(s, s, s2us);
+ info->creationTime = s;
+ }
+ return rv;
+}
+
+PRInt32
+_MD_getopenfileinfo (const PRFileDesc *fd, PRFileInfo *info)
+{
+ struct stat sb;
+ PRInt64 s, s2us;
+ PRInt32 rv, err;
+
+ rv = fstat(fd->secret->md.osfd, &sb);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_FSTAT_ERROR(err);
+ } else if (info) {
+ if (info) {
+ if (S_IFREG & sb.st_mode)
+ info->type = PR_FILE_FILE ;
+ else if (S_IFDIR & sb.st_mode)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+ /* Use lower 32 bits of file size */
+ info->size = ( sb.st_size & 0xffffffff);
+ LL_I2L(s, sb.st_mtime);
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_MUL(s, s, s2us);
+ info->modifyTime = s;
+ LL_I2L(s, sb.st_ctime);
+ LL_MUL(s, s, s2us);
+ info->creationTime = s;
+ }
+ }
+ return rv;
+}
+
+PRInt32
+_MD_getopenfileinfo64 (const PRFileDesc *fd, PRFileInfo64 *info)
+{
+ struct stat sb;
+ PRInt64 s, s2us;
+ PRInt32 rv, err;
+
+ rv = fstat(fd->secret->md.osfd, &sb);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_FSTAT_ERROR(err);
+ } else if (info) {
+ if (info) {
+ if (S_IFREG & sb.st_mode)
+ info->type = PR_FILE_FILE ;
+ else if (S_IFDIR & sb.st_mode)
+ info->type = PR_FILE_DIRECTORY;
+ else
+ info->type = PR_FILE_OTHER;
+ info->size = sb.st_size;
+ LL_I2L(s, sb.st_mtime);
+ LL_I2L(s2us, PR_USEC_PER_SEC);
+ LL_MUL(s, s, s2us);
+ info->modifyTime = s;
+ LL_I2L(s, sb.st_ctime);
+ LL_MUL(s, s, s2us);
+ info->creationTime = s;
+ }
+ }
+ return rv;
+}
+
+PRInt32
+_MD_rename (const char *from, const char *to)
+{
+ PRInt32 rv = -1, err;
+
+ /*
+ ** This is trying to enforce the semantics of WINDOZE' rename
+ ** operation. That means one is not allowed to rename over top
+ ** of an existing file. Holding a lock across these two function
+ ** and the open function is known to be a bad idea, but ....
+ */
+ if (NULL != _pr_rename_lock)
+ PR_Lock(_pr_rename_lock);
+ if (0 == access(to, F_OK))
+ PR_SetError(PR_FILE_EXISTS_ERROR, 0);
+ else
+ {
+ rv = rename(from, to);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_RENAME_ERROR(err);
+ }
+ }
+ if (NULL != _pr_rename_lock)
+ PR_Unlock(_pr_rename_lock);
+ return rv;
+}
+
+PRInt32
+_MD_access (const char *name, PRIntn how)
+{
+PRInt32 rv, err;
+int amode;
+
+ switch (how) {
+ case PR_ACCESS_WRITE_OK:
+ amode = W_OK;
+ break;
+ case PR_ACCESS_READ_OK:
+ amode = R_OK;
+ break;
+ case PR_ACCESS_EXISTS:
+ amode = F_OK;
+ break;
+ default:
+ PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+ rv = -1;
+ goto done;
+ }
+ rv = access(name, amode);
+
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_ACCESS_ERROR(err);
+ }
+
+done:
+ return(rv);
+}
+
+PRInt32
+_MD_stat (const char *name, struct stat *buf)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+PRInt32
+_MD_mkdir (const char *name, PRIntn mode)
+{
+ status_t rv;
+ int err;
+
+ /*
+ ** This lock is used to enforce rename semantics as described
+ ** in PR_Rename. Look there for more fun details.
+ */
+ if (NULL !=_pr_rename_lock)
+ PR_Lock(_pr_rename_lock);
+
+ rv = mkdir(name, mode);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_MKDIR_ERROR(err);
+ }
+ if (NULL !=_pr_rename_lock)
+ PR_Unlock(_pr_rename_lock);
+ return rv;
+}
+
+PRInt32
+_MD_rmdir (const char *name)
+{
+int rv, err;
+
+ rv = rmdir(name);
+ if (rv == -1) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_RMDIR_ERROR(err);
+ }
+ return rv;
+}
+
+PRInt32
+_MD_pr_poll (PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
+{
+ PRPollDesc *pd, *epd;
+ PRInt32 n, err, pdcnt;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ fd_set rd, wt, ex;
+ struct timeval tv, *tvp = NULL;
+ int maxfd = -1;
+ int rv;
+
+ ConnectListNode currentConnectList[64];
+ int currentConnectListCount = 0;
+ int i,j;
+ int connectResult = 0;
+ int connectError = 0;
+
+ /*
+ * For restarting _MD_SELECT() if it is interrupted by a signal.
+ * We use these variables to figure out how much time has elapsed
+ * and how much of the timeout still remains.
+ */
+ PRIntervalTime start, elapsed, remaining;
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wt);
+ FD_ZERO(&ex);
+
+ for (pd = pds, epd = pd + npds; pd < epd; pd++) {
+ PRInt32 osfd;
+ PRInt16 in_flags = pd->in_flags;
+ PRFileDesc *bottom = pd->fd;
+
+ if ((NULL == bottom) || (in_flags == 0)) {
+ continue;
+ }
+ while (bottom->lower != NULL) {
+ bottom = bottom->lower;
+ }
+ osfd = bottom->secret->md.osfd;
+
+ if( (in_flags & PR_POLL_WRITE) || (in_flags & PR_POLL_EXCEPT) ) {
+
+ PR_Lock( _connectLock );
+
+ for( i = 0; i < connectCount; i++ ) {
+
+ if( connectList[i].osfd == osfd ) {
+
+ memcpy( &currentConnectList[currentConnectListCount], &connectList[i], sizeof( connectList[i] ) );
+ currentConnectListCount++;
+ break;
+ }
+ }
+
+ PR_Unlock( _connectLock );
+ }
+
+ if (in_flags & PR_POLL_READ) {
+ FD_SET(osfd, &rd);
+ if( osfd > maxfd ) maxfd = osfd;
+ }
+ }
+ if (timeout != PR_INTERVAL_NO_TIMEOUT) {
+ tv.tv_sec = PR_IntervalToSeconds(timeout);
+ tv.tv_usec = PR_IntervalToMicroseconds(timeout) % PR_USEC_PER_SEC;
+ tvp = &tv;
+ start = PR_IntervalNow();
+ }
+
+ if( currentConnectListCount > 0 ) {
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000L;
+ tvp = &tv;
+ start = PR_IntervalNow();
+ }
+
+retry:
+ if( currentConnectListCount > 0 ) {
+
+ for( i = 0; i < currentConnectListCount; i++ ) {
+
+ connectResult = connect( currentConnectList[i].osfd,
+ &currentConnectList[i].addr,
+ &currentConnectList[i].addrlen );
+ connectError = _MD_ERRNO();
+
+ if( ( connectResult < 0 ) &&
+ ( connectError == EINTR ||
+ connectError == EWOULDBLOCK ||
+ connectError == EINPROGRESS ||
+ connectError == EALREADY ) ) {
+
+ continue;
+ }
+
+ PR_Lock( _connectLock );
+
+ for( j = 0; j < connectCount; j++ ) {
+
+ if( connectList[j].osfd == currentConnectList[i].osfd ) {
+
+ if( j == ( connectCount - 1 ) ) {
+
+ connectList[j].osfd = -1;
+
+ } else {
+
+ for( ; j < connectCount; j++ )
+ memcpy( &connectList[j], &connectList[j+1], sizeof( connectList[j] ) );
+ }
+ connectCount--;
+ break;
+ }
+ }
+
+ PR_Unlock( _connectLock );
+
+ FD_ZERO( &rd );
+ FD_SET( currentConnectList[i].osfd, &wt );
+ FD_SET( currentConnectList[i].osfd, &ex );
+ n = 1;
+ goto afterselect;
+ }
+ }
+
+ if( maxfd == -1 ) {
+ snooze( 100000L );
+ goto retry;
+ }
+ n = select(maxfd + 1, &rd, NULL, NULL, tvp);
+afterselect:
+ if ( (n == -1 && errno == EINTR) || (n == 0 && currentConnectListCount > 0 ) ) {
+ if (timeout == PR_INTERVAL_NO_TIMEOUT) {
+ goto retry;
+ } else {
+ elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
+ if (elapsed > timeout) {
+ n = 0; /* timed out */
+ } else {
+ remaining = timeout - elapsed;
+ tv.tv_sec = PR_IntervalToSeconds(remaining);
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ remaining - PR_SecondsToInterval(tv.tv_sec));
+ goto retry;
+ }
+ }
+ }
+
+ if (n > 0) {
+ n = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++) {
+ PRInt32 osfd;
+ PRInt16 in_flags = pd->in_flags;
+ PRInt16 out_flags = 0;
+ PRFileDesc *bottom = pd->fd;
+
+ if ((NULL == bottom) || (in_flags == 0)) {
+ pd->out_flags = 0;
+ continue;
+ }
+ while (bottom->lower != NULL) {
+ bottom = bottom->lower;
+ }
+ osfd = bottom->secret->md.osfd;
+
+ if ((in_flags & PR_POLL_READ) && FD_ISSET(osfd, &rd)) {
+ out_flags |= PR_POLL_READ;
+ }
+ if ((in_flags & PR_POLL_WRITE) && FD_ISSET(osfd, &wt)) {
+ out_flags |= PR_POLL_WRITE;
+ }
+ if ((in_flags & PR_POLL_EXCEPT) && FD_ISSET(osfd, &ex)) {
+ out_flags |= PR_POLL_EXCEPT;
+ }
+
+ if ( FD_ISSET(osfd, &wt) && FD_ISSET(osfd, &ex ) ) {
+
+ bottom->secret->md.connectReturnValue = connectResult;
+ bottom->secret->md.connectReturnError = connectError;
+ bottom->secret->md.connectValueValid = PR_TRUE;
+ }
+
+ pd->out_flags = out_flags;
+ if (out_flags) {
+ n++;
+ }
+ }
+ PR_ASSERT(n > 0);
+ } else if (n < 0) {
+ err = _MD_ERRNO();
+ if (err == EBADF) {
+ /* Find the bad fds */
+ n = 0;
+ for (pd = pds, epd = pd + npds; pd < epd; pd++) {
+ int optval;
+ int optlen = sizeof(optval);
+ PRFileDesc *bottom = pd->fd;
+
+ pd->out_flags = 0;
+ if ((NULL == bottom) || (pd->in_flags == 0)) {
+ continue;
+ }
+ while (bottom->lower != NULL) {
+ bottom = bottom->lower;
+ }
+#if 0
+/*
+ * BeOS doesn't have this feature of getsockopt.
+*/
+ if (getsockopt(bottom->secret->md.osfd, SOL_SOCKET,
+ SO_TYPE, (char *) &optval, &optlen) == -1) {
+ PR_ASSERT(_MD_ERRNO() == ENOTSOCK);
+ if (_MD_ERRNO() == ENOTSOCK) {
+ pd->out_flags = PR_POLL_NVAL;
+ n++;
+ }
+ }
+#endif
+ }
+ PR_ASSERT(n > 0);
+ } else {
+ PR_ASSERT(err != EINTR); /* should have been handled above */
+ _PR_MD_MAP_SELECT_ERROR(err);
+ }
+ }
+ return n;
+}
+
+/*
+ * File locking.
+ */
+
+PRStatus
+_MD_lockfile (PRInt32 osfd)
+{
+ PRInt32 rv;
+ struct flock linfo;
+
+ linfo.l_type =
+ linfo.l_whence = SEEK_SET;
+ linfo.l_start = 0;
+ linfo.l_len = 0;
+
+ rv = fcntl(osfd, F_SETLKW, &linfo);
+ if (rv == 0)
+ return PR_SUCCESS;
+
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PRStatus
+_MD_tlockfile (PRInt32 osfd)
+{
+ PRInt32 rv;
+ struct flock linfo;
+
+ linfo.l_type =
+ linfo.l_whence = SEEK_SET;
+ linfo.l_start = 0;
+ linfo.l_len = 0;
+
+ rv = fcntl(osfd, F_SETLK, &linfo);
+ if (rv == 0)
+ return PR_SUCCESS;
+
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
+PRStatus
+_MD_unlockfile (PRInt32 osfd)
+{
+ PRInt32 rv;
+ struct flock linfo;
+
+ linfo.l_type =
+ linfo.l_whence = SEEK_SET;
+ linfo.l_start = 0;
+ linfo.l_len = 0;
+
+ rv = fcntl(osfd, F_UNLCK, &linfo);
+
+ if (rv == 0)
+ return PR_SUCCESS;
+
+ _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
+ return PR_FAILURE;
+}
+
diff --git a/pr/src/md/beos/bmemory.c b/pr/src/md/beos/bmemory.c
new file mode 100644
index 00000000..c14696d8
--- /dev/null
+++ b/pr/src/md/beos/bmemory.c
@@ -0,0 +1,18 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http:// www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include "primpl.h"
+
+PR_EXTERN(void) _PR_MD_INIT_SEGS(void);
+PR_EXTERN(PRStatus) _PR_MD_ALLOC_SEGMENT(PRSegment *seg, PRUint32 size, void *vaddr);
+PR_EXTERN(void) _PR_MD_FREE_SEGMENT(PRSegment *seg);
diff --git a/pr/src/md/beos/bmisc.c b/pr/src/md/beos/bmisc.c
new file mode 100644
index 00000000..977ed68d
--- /dev/null
+++ b/pr/src/md/beos/bmisc.c
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http:// www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include "primpl.h"
+
+#include <stdlib.h>
+
+PRLock *_connectLock = NULL;
+PRUint32 connectCount = 0;
+ConnectListNode connectList[64];
+
+void
+_MD_cleanup_before_exit (void)
+{
+}
+
+void
+_MD_exit (PRIntn status)
+{
+ exit(status);
+}
+
+void
+_MD_early_init (void)
+{
+}
+
+static PRLock *monitor = NULL;
+
+void
+_MD_final_init (void)
+{
+ _connectLock = PR_NewLock();
+ PR_ASSERT(NULL != _connectLock);
+ connectCount = 0;
+}
+
+void
+_MD_AtomicInit (void)
+{
+ if (monitor == NULL) {
+ monitor = PR_NewLock();
+ }
+}
+
+/*
+** This is exceedingly messy. atomic_add returns the last value, NSPR expects the new value.
+** We just add or subtract 1 from the result. The actual memory update is atomic.
+*/
+
+PRInt32
+_MD_AtomicAdd( PRInt32 *ptr, PRInt32 val )
+{
+ return( ( atomic_add( (long *)ptr, val ) ) + val );
+}
+
+PRInt32
+_MD_AtomicIncrement( PRInt32 *val )
+{
+ return( ( atomic_add( (long *)val, 1 ) ) + 1 );
+}
+
+PRInt32
+_MD_AtomicDecrement( PRInt32 *val )
+{
+ return( ( atomic_add( (long *)val, -1 ) ) - 1 );
+}
+
+PRInt32
+_MD_AtomicSet( PRInt32 *val, PRInt32 newval )
+{
+ PRInt32 rv;
+
+ if (!_pr_initialized) {
+ _PR_ImplicitInitialization();
+ }
+ PR_Lock(monitor);
+ rv = *val;
+ *val = newval;
+ PR_Unlock(monitor);
+ return rv;
+}
diff --git a/pr/src/md/beos/bmmap.c b/pr/src/md/beos/bmmap.c
new file mode 100644
index 00000000..572b25fc
--- /dev/null
+++ b/pr/src/md/beos/bmmap.c
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http:// www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include "primpl.h"
+
+PR_EXTERN(PRStatus)
+_PR_MD_CREATE_FILE_MAP(PRFileMap *fmap, PRInt64 size)
+{
+ return PR_FAILURE;
+}
+
+PR_EXTERN(void *)
+_PR_MD_MEM_MAP(PRFileMap *fmap, PRInt64 offset, PRUint32 len)
+{
+ PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
+ return 0;
+}
+
+PR_EXTERN(PRStatus)
+_PR_MD_MEM_UNMAP(void *addr, PRUint32 size)
+{
+ return PR_FAILURE;
+}
+
+PR_EXTERN(PRStatus)
+_PR_MD_CLOSE_FILE_MAP(PRFileMap *fmap)
+{
+ return PR_FAILURE;
+}
diff --git a/pr/src/md/beos/bnet.c b/pr/src/md/beos/bnet.c
new file mode 100644
index 00000000..069f5adb
--- /dev/null
+++ b/pr/src/md/beos/bnet.c
@@ -0,0 +1,648 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http:// www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include "primpl.h"
+
+#include <signal.h>
+#include <unistd.h>
+#include <memory.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+/*
+ * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or
+ * PRInt32* pointer to a _PRSockLen_t* pointer.
+ */
+#define _PRSockLen_t int
+
+/*
+** Global lock variable used to bracket calls into rusty libraries that
+** aren't thread safe (like libc, libX, etc).
+*/
+static PRLock *_pr_rename_lock = NULL;
+static PRMonitor *_pr_Xfe_mon = NULL;
+
+/*
+** This is a support routine to handle "deferred" i/o on sockets.
+** It uses "select", so it is subject to all of the BeOS limitations
+** (only READ notification, only sockets)
+*/
+#define READ_FD 1
+#define WRITE_FD 2
+
+static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv = -1;
+ struct timeval tv, *tvp;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+ PRIntervalTime epoch, now, elapsed, remaining;
+ PRInt32 syserror;
+ fd_set rd_wr;
+
+ switch (timeout) {
+ case PR_INTERVAL_NO_WAIT:
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ break;
+ case PR_INTERVAL_NO_TIMEOUT:
+ /*
+ * This is a special case of the 'default' case below.
+ * Please see the comments there.
+ */
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ tvp = &tv;
+ FD_ZERO(&rd_wr);
+ do {
+ FD_SET(osfd, &rd_wr);
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, tvp);
+ else
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, tvp);
+ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+ if (syserror == EBADF) {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
+ } else {
+ PR_SetError(PR_UNKNOWN_ERROR, syserror);
+ }
+ if( _PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ break;
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ default:
+ now = epoch = PR_IntervalNow();
+ remaining = timeout;
+ tvp = &tv;
+ FD_ZERO(&rd_wr);
+ do {
+ /*
+ * We block in _MD_SELECT for at most
+ * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds,
+ * so that there is an upper limit on the delay
+ * before the interrupt bit is checked.
+ */
+ tv.tv_sec = PR_IntervalToSeconds(remaining);
+ if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) {
+ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS;
+ tv.tv_usec = 0;
+ } else {
+ tv.tv_usec = PR_IntervalToMicroseconds(
+ remaining -
+ PR_SecondsToInterval(tv.tv_sec));
+ }
+ FD_SET(osfd, &rd_wr);
+ if (fd_type == READ_FD)
+ rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, tvp);
+ else
+ rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, tvp);
+ /*
+ * we don't consider EINTR a real error
+ */
+ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) {
+ if (syserror == EBADF) {
+ PR_SetError(PR_BAD_DESCRIPTOR_ERROR, EBADF);
+ } else {
+ PR_SetError(PR_UNKNOWN_ERROR, syserror);
+ }
+ break;
+ }
+ if (_PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
+ rv = -1;
+ break;
+ }
+ /*
+ * We loop again if _MD_SELECT timed out or got interrupted
+ * by a signal, and the timeout deadline has not passed yet.
+ */
+ if (rv == 0 || (rv == -1 && syserror == EINTR)) {
+ /*
+ * If _MD_SELECT timed out, we know how much time
+ * we spent in blocking, so we can avoid a
+ * PR_IntervalNow() call.
+ */
+ if (rv == 0) {
+ now += PR_SecondsToInterval(tv.tv_sec)
+ + PR_MicrosecondsToInterval(tv.tv_usec);
+ } else {
+ now = PR_IntervalNow();
+ }
+ elapsed = (PRIntervalTime) (now - epoch);
+ if (elapsed >= timeout) {
+ PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
+ rv = -1;
+ break;
+ } else {
+ remaining = timeout - elapsed;
+ }
+ }
+ } while (rv == 0 || (rv == -1 && syserror == EINTR));
+ break;
+ }
+ return(rv);
+}
+
+
+
+PRInt32
+_MD_recv (PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_READ) {
+ _PR_MD_MAP_RECV_ERROR(EPIPE);
+ return -1;
+ }
+
+ while ((rv = recv(osfd, buf, amount, flags)) == -1) {
+ err = _MD_ERRNO();
+
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ /* If socket was supposed to be blocking,
+ wait a while for the condition to be
+ satisfied. */
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){
+ continue;
+
+ } else {
+ break;
+ }
+ }
+
+ if (rv < 0) {
+ _PR_MD_MAP_RECV_ERROR(err);
+ }
+
+done:
+ return(rv);
+}
+
+PRInt32
+_MD_recvfrom (PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
+ PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ while ((*addrlen = PR_NETADDR_SIZE(addr)),
+ ((rv = recvfrom(osfd, buf, amount, flags,
+ (struct sockaddr *) addr,
+ (_PRSockLen_t *)addrlen)) == -1)) {
+ err = _MD_ERRNO();
+
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+ continue;
+
+ } else {
+ break;
+ }
+ }
+
+ if (rv < 0) {
+ _PR_MD_MAP_RECVFROM_ERROR(err);
+ }
+
+done:
+ return(rv);
+}
+
+PRInt32
+_MD_send (PRFileDesc *fd, const void *buf, PRInt32 amount, PRInt32 flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ if (fd->secret->md.sock_state & BE_SOCK_SHUTDOWN_WRITE)
+ {
+ _PR_MD_MAP_SEND_ERROR(EPIPE);
+ return -1;
+ }
+
+ while ((rv = send(osfd, buf, amount, flags)) == -1) {
+ err = _MD_ERRNO();
+
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+
+ if( _PR_PENDING_INTERRUPT(me)) {
+
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+
+ /* in UNIX implementations, you could do a socket_io_wait here.
+ * but since BeOS doesn't yet support WRITE notification in select,
+ * you're spanked.
+ */
+ snooze( 10000L );
+ continue;
+
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+ continue;
+
+ } else {
+ break;
+ }
+ }
+
+ if (rv < 0) {
+ _PR_MD_MAP_SEND_ERROR(err);
+ }
+
+ return(rv);
+}
+
+PRInt32
+_MD_sendto (PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
+ const PRNetAddr *addr, PRUint32 addrlen, PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ while ((rv = sendto(osfd, buf, amount, flags,
+ (struct sockaddr *) addr, addrlen)) == -1) {
+ err = _MD_ERRNO();
+
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+
+ printf( "This should be a blocking sendto call!!!\n" );
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+ continue;
+
+ } else {
+ break;
+ }
+ }
+
+ if (rv < 0) {
+ _PR_MD_MAP_SENDTO_ERROR(err);
+ }
+
+ return(rv);
+}
+
+PRInt32
+_MD_accept (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ while ((rv = accept(osfd, (struct sockaddr *) addr,
+ (_PRSockLen_t *)addrlen)) == -1) {
+ err = _MD_ERRNO();
+
+ if ((err == EAGAIN) || (err == EWOULDBLOCK)) {
+ if (fd->secret->nonblocking) {
+ break;
+ }
+ /* If it's SUPPOSED to be a blocking thread, wait
+ * a while to see if the triggering condition gets
+ * satisfied.
+ */
+ /* Assume that we're always using a native thread */
+ if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0)
+ goto done;
+ } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))) {
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ if (addr) addr->raw.family = AF_INET;
+
+ if (rv < 0) {
+ _PR_MD_MAP_ACCEPT_ERROR(err);
+ }
+done:
+#ifdef _PR_HAVE_SOCKADDR_LEN
+ if (rv != -1) {
+ /* Mask off the first byte of struct sockaddr (the length field) */
+ if (addr) {
+ *((unsigned char *) addr) = 0;
+#ifdef IS_LITTLE_ENDIAN
+ addr->raw.family = ntohs(addr->raw.family);
+#endif
+ }
+ }
+#endif /* _PR_HAVE_SOCKADDR_LEN */
+ return(rv);
+}
+
+PRInt32
+_MD_connect (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen,
+ PRIntervalTime timeout)
+{
+ PRInt32 osfd = fd->secret->md.osfd;
+ PRInt32 rv, err;
+ PRThread *me = _PR_MD_CURRENT_THREAD();
+
+ fd->secret->md.connectValueValid = PR_FALSE;
+
+retry:
+ if ((rv = connect(osfd, (struct sockaddr *)addr, addrlen)) == -1) {
+ err = _MD_ERRNO();
+ fd->secret->md.connectReturnValue = rv;
+ fd->secret->md.connectReturnError = err;
+ fd->secret->md.connectValueValid = PR_TRUE;
+
+ if( err == EINTR ) {
+
+ if( _PR_PENDING_INTERRUPT(me)) {
+
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+ snooze( 100000L );
+ goto retry;
+ }
+
+ if(!fd->secret->nonblocking && ((err == EINPROGRESS) || (err==EAGAIN) || (err==EALREADY))) {
+
+ /*
+ ** There's no timeout on this connect, but that's not
+ ** a big deal, since the connect times out anyways
+ ** after 30 seconds. Just sleep for 1/10th of a second
+ ** and retry until we go through or die.
+ */
+
+ if( _PR_PENDING_INTERRUPT(me)) {
+ me->flags &= ~_PR_INTERRUPT;
+ PR_SetError( PR_PENDING_INTERRUPT_ERROR, 0);
+ return -1;
+ }
+
+ goto retry;
+ }
+
+ if( fd->secret->nonblocking && ((err == EAGAIN) || (err == EINPROGRESS))) {
+ PR_Lock(_connectLock);
+ connectList[connectCount].osfd = osfd;
+ memcpy(&connectList[connectCount].addr, addr, addrlen);
+ connectList[connectCount].addrlen = addrlen;
+ connectList[connectCount].timeout = timeout;
+ connectCount++;
+ PR_Unlock(_connectLock);
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ return rv;
+ }
+
+ _PR_MD_MAP_CONNECT_ERROR(err);
+ }
+
+ return rv;
+}
+
+PRInt32
+_MD_bind (PRFileDesc *fd, const PRNetAddr *addr, PRUint32 addrlen)
+{
+ PRInt32 rv, err;
+
+ rv = bind(fd->secret->md.osfd, (struct sockaddr *) addr, (int )addrlen);
+
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_BIND_ERROR(err);
+ }
+
+ return(rv);
+}
+
+PRInt32
+_MD_listen (PRFileDesc *fd, PRIntn backlog)
+{
+ PRInt32 rv, err;
+
+ /* Bug workaround! Setting listen to 0 on Be accepts no connections.
+ ** On most UN*Xes this sets the default.
+ */
+
+ if( backlog == 0 ) backlog = 5;
+
+ rv = listen(fd->secret->md.osfd, backlog);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_LISTEN_ERROR(err);
+ }
+
+ return(rv);
+}
+
+PRInt32
+_MD_shutdown (PRFileDesc *fd, PRIntn how)
+{
+ PRInt32 rv, err;
+
+ if (how == PR_SHUTDOWN_SEND)
+ fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_WRITE;
+ else if (how == PR_SHUTDOWN_RCV)
+ fd->secret->md.sock_state = BE_SOCK_SHUTDOWN_READ;
+ else if (how == PR_SHUTDOWN_BOTH) {
+ fd->secret->md.sock_state = (BE_SOCK_SHUTDOWN_WRITE | BE_SOCK_SHUTDOWN_READ);
+ }
+
+ return 0;
+}
+
+PRInt32
+_MD_socketpair (int af, int type, int flags, PRInt32 *osfd)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+PRInt32
+_MD_close_socket (PRInt32 osfd)
+{
+ closesocket( osfd );
+}
+
+PRStatus
+_MD_getsockname (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
+{
+ PRInt32 rv, err;
+
+ rv = getsockname(fd->secret->md.osfd,
+ (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
+
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_GETSOCKNAME_ERROR(err);
+ }
+
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+PRStatus
+_MD_getpeername (PRFileDesc *fd, PRNetAddr *addr, PRUint32 *addrlen)
+{
+ PRInt32 rv, err;
+
+ rv = getpeername(fd->secret->md.osfd,
+ (struct sockaddr *) addr, (_PRSockLen_t *)addrlen);
+
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_GETPEERNAME_ERROR(err);
+ }
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+PRStatus
+_MD_getsockopt (PRFileDesc *fd, PRInt32 level,
+ PRInt32 optname, char* optval, PRInt32* optlen)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+
+#if 0
+ PRInt32 rv, err;
+
+ rv = getsockopt(fd->secret->md.osfd, level, optname,
+ optval, (_PRSockLen_t *)optlen);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_GETSOCKOPT_ERROR(err);
+ }
+
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+#endif
+}
+
+PRStatus
+_MD_setsockopt (PRFileDesc *fd, PRInt32 level,
+ PRInt32 optname, const char* optval, PRInt32 optlen)
+{
+ PRInt32 rv, err;
+
+ rv = setsockopt(fd->secret->md.osfd, level, optname, optval, optlen);
+ if (rv < 0) {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SETSOCKOPT_ERROR(err);
+ }
+ return rv==0?PR_SUCCESS:PR_FAILURE;
+}
+
+PRInt32
+_MD_accept_read (PRFileDesc *sd, PRInt32 *newSock, PRNetAddr **raddr,
+ void *buf, PRInt32 amount, PRIntervalTime timeout)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+PRInt32
+_MD_transmitfile (PRFileDesc *sock, PRFileDesc *file, const void *headers, PRInt32 hlen, PRInt32 flags, PRIntervalTime timeout)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+PRInt32
+_MD_socket (int af, int type, int flags)
+{
+ PRInt32 osfd, err;
+
+ osfd = socket( af, type, 0 );
+
+ if( -1 == osfd ) {
+
+ err = _MD_ERRNO();
+ _PR_MD_MAP_SOCKET_ERROR( err );
+ }
+
+ return( osfd );
+}
+
+PRInt32
+_MD_socketavailable (PRFileDesc *fd)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+PRInt32
+_MD_get_socket_error (void)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+PRStatus
+_MD_gethostname (char *name, PRUint32 namelen)
+{
+PRInt32 rv, err;
+
+ rv = gethostname(name, namelen);
+ if (rv == 0)
+ {
+ err = _MD_ERRNO();
+ _PR_MD_MAP_GETHOSTNAME_ERROR(err);
+ return PR_FAILURE;
+ }
+ return PR_SUCCESS;
+}
+
+PRInt32
+_MD_beos_get_nonblocking_connect_error(PRFileDesc *fd)
+{
+ int rv;
+ int flags = 0;
+
+ if( fd->secret->md.connectValueValid == PR_TRUE )
+
+ if( fd->secret->md.connectReturnValue == -1 )
+
+ return fd->secret->md.connectReturnError;
+ else
+ return 0; /* No error */
+
+ rv = recv(fd->secret->md.osfd, NULL, 0, flags);
+ PR_ASSERT(-1 == rv || 0 == rv);
+ if (-1 == rv && errno != EAGAIN && errno != EWOULDBLOCK) {
+ return errno;
+ }
+ return 0; /* no error */
+}
diff --git a/pr/src/md/beos/bproc.c b/pr/src/md/beos/bproc.c
new file mode 100644
index 00000000..01e5236d
--- /dev/null
+++ b/pr/src/md/beos/bproc.c
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http:// www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include "primpl.h"
+
+PRProcess*
+_MD_create_process (const char *path, char *const *argv,
+ char *const *envp, const PRProcessAttr *attr)
+{
+ return NULL;
+}
+
+PRStatus
+_MD_detach_process (PRProcess *process)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+PRStatus
+_MD_wait_process (PRProcess *process, PRInt32 *exitCode)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+PRStatus
+_MD_kill_process (PRProcess *process)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
diff --git a/pr/src/md/beos/bseg.c b/pr/src/md/beos/bseg.c
new file mode 100644
index 00000000..36ef7448
--- /dev/null
+++ b/pr/src/md/beos/bseg.c
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http:// www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include "primpl.h"
+
+void
+_PR_InitSegs (void)
+{
+}
+
+PR_IMPLEMENT(void)
+ _MD_init_segs (void)
+{
+}
+
+PR_IMPLEMENT(PRStatus)
+ _MD_alloc_segment (PRSegment *seg, PRUint32 size, void *vaddr)
+{
+ return PR_NOT_IMPLEMENTED_ERROR;
+}
+
+PR_IMPLEMENT(void)
+ _MD_free_segment (PRSegment *seg)
+{
+}
diff --git a/pr/src/md/beos/bsrcs.mk b/pr/src/md/beos/bsrcs.mk
new file mode 100644
index 00000000..1851e20b
--- /dev/null
+++ b/pr/src/md/beos/bsrcs.mk
@@ -0,0 +1,27 @@
+#
+# The contents of this file are subject to the Mozilla Public License
+# Version 1.0 (the "MPL"); you may not use this file except in
+# compliance with the MPL. You may obtain a copy of the MPL at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the MPL is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+# for the specific language governing rights and limitations under the
+# MPL.
+#
+
+# this file lists the source files to be compiled (used in Makefile) and
+# then enumerated as object files (in objs.mk) for inclusion in the NSPR
+# shared library
+
+MDCSRCS = \
+ beos.c \
+ beos_errors.c \
+ bfile.c \
+ bmisc.c \
+ bnet.c \
+ bproc.c \
+ bseg.c \
+ btime.c \
+ bmmap.c \
+ $(NULL)
diff --git a/pr/src/md/beos/btime.c b/pr/src/md/beos/btime.c
new file mode 100644
index 00000000..a80a1d61
--- /dev/null
+++ b/pr/src/md/beos/btime.c
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; c-basic-offset: 4 -*- */
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.0 (the "MPL"); you may not use this file except in
+ * compliance with the MPL. You may obtain a copy of the MPL at
+ * http:// www.mozilla.org/MPL/
+ *
+ * Software distributed under the MPL is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+ * for the specific language governing rights and limitations under the
+ * MPL.
+ */
+
+#include "primpl.h"
+#include <kernel/OS.h>
+
+static bigtime_t start;
+
+PRTime
+_MD_now (void)
+{
+ return (PRTime)real_time_clock_usecs();
+}
+
+void
+_MD_interval_init (void)
+{
+ /* grab the base interval time */
+ start = real_time_clock_usecs();
+}
+
+PRIntervalTime
+_MD_get_interval (void)
+{
+ return( (PRIntervalTime) real_time_clock_usecs() / 10 );
+
+#if 0
+ /* return the number of tens of microseconds that have elapsed since
+ we were initialized */
+ bigtime_t now = real_time_clock_usecs();
+ now -= start;
+ now /= 10;
+ return (PRIntervalTime)now;
+#endif
+}
+
+PRIntervalTime
+_MD_interval_per_sec (void)
+{
+ return 100000L;
+}
diff --git a/pr/src/md/beos/objs.mk b/pr/src/md/beos/objs.mk
new file mode 100644
index 00000000..fcca42fd
--- /dev/null
+++ b/pr/src/md/beos/objs.mk
@@ -0,0 +1,18 @@
+#
+# The contents of this file are subject to the Mozilla Public License
+# Version 1.0 (the "MPL"); you may not use this file except in
+# compliance with the MPL. You may obtain a copy of the MPL at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the MPL is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the MPL
+# for the specific language governing rights and limitations under the
+# MPL.
+#
+
+# This makefile appends to the variable OBJS the platform-dependent
+# object modules that will be part of the nspr20 library.
+
+include md/beos/bsrcs.mk
+
+OBJS += $(MDCSRCS:%.c=md/beos/$(OBJDIR)/%.$(OBJ_SUFFIX))