📄 unix.c
字号:
/* -*- 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.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape Portable Runtime (NSPR). * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include "primpl.h"#include <string.h>#include <signal.h>#include <unistd.h>#include <fcntl.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <unistd.h>#include <sys/utsname.h>#ifdef _PR_POLL_AVAILABLE#include <poll.h>#endif/* To get FIONREAD */#if defined(NCR) || defined(UNIXWARE) || defined(NEC) || defined(SNI) \ || defined(SONY)#include <sys/filio.h>#endif#if defined(NTO)#include <sys/statvfs.h>#endif/* * Make sure _PRSockLen_t is 32-bit, because we will cast a PRUint32* or * PRInt32* pointer to a _PRSockLen_t* pointer. */#if defined(HAVE_SOCKLEN_T)#define _PRSockLen_t socklen_t#elif defined(IRIX) || defined(HPUX) || defined(OSF1) || defined(SOLARIS) \ || defined(AIX4_1) || defined(LINUX) || defined(SONY) \ || defined(BSDI) || defined(SCO) || defined(NEC) || defined(SNI) \ || defined(SUNOS4) || defined(NCR) || defined(DARWIN) \ || defined(NEXTSTEP) || defined(QNX)#define _PRSockLen_t int#elif (defined(AIX) && !defined(AIX4_1)) || defined(FREEBSD) \ || defined(NETBSD) || defined(OPENBSD) || defined(UNIXWARE) \ || defined(DGUX) || defined(VMS) || defined(NTO)#define _PRSockLen_t size_t#else#error "Cannot determine architecture"#endif/*** 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;static PRInt64 minus_one;sigset_t timer_set;#if !defined(_PR_PTHREADS)static sigset_t empty_set;#ifdef SOLARIS#include <sys/file.h>#include <sys/filio.h>#endif#ifndef PIPE_BUF#define PIPE_BUF 512#endif/* * _nspr_noclock - if set clock interrupts are disabled */int _nspr_noclock = 1;#ifdef IRIXextern PRInt32 _nspr_terminate_on_error;#endif/* * There is an assertion in this code that NSPR's definition of PRIOVec * is bit compatible with UNIX' definition of a struct iovec. This is * applicable to the 'writev()' operations where the types are casually * cast to avoid warnings. */int _pr_md_pipefd[2] = { -1, -1 };static char _pr_md_pipebuf[PIPE_BUF];static PRInt32 local_io_wait(PRInt32 osfd, PRInt32 wait_flag, PRIntervalTime timeout);_PRInterruptTable _pr_interruptTable[] = { { "clock", _PR_MISSED_CLOCK, _PR_ClockInterrupt, }, { 0 }};PR_IMPLEMENT(void) _MD_unix_init_running_cpu(_PRCPU *cpu){ PR_INIT_CLIST(&(cpu->md.md_unix.ioQ)); cpu->md.md_unix.ioq_max_osfd = -1; cpu->md.md_unix.ioq_timeout = PR_INTERVAL_NO_TIMEOUT;}PRStatus _MD_open_dir(_MDDir *d, const char *name){int err; d->d = opendir(name); if (!d->d) { err = _MD_ERRNO(); _PR_MD_MAP_OPENDIR_ERROR(err); return PR_FAILURE; } return PR_SUCCESS;}PRInt32 _MD_close_dir(_MDDir *d){int rv = 0, err; if (d->d) { rv = closedir(d->d); if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_CLOSEDIR_ERROR(err); } } return rv;}char * _MD_read_dir(_MDDir *d, PRIntn flags){struct dirent *de;int err; for (;;) { /* * XXX: readdir() is not MT-safe. There is an MT-safe version * readdir_r() on some systems. */ de = readdir(d->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[0] == '.')) continue; break; } return de->d_name;}PRInt32 _MD_delete(const char *name){PRInt32 rv, err;#ifdef UNIXWARE sigset_t set, oset;#endif#ifdef UNIXWARE sigfillset(&set); sigprocmask(SIG_SETMASK, &set, &oset);#endif rv = unlink(name);#ifdef UNIXWARE sigprocmask(SIG_SETMASK, &oset, NULL);#endif if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_UNLINK_ERROR(err); } 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, PRAccessHow 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_mkdir(const char *name, PRIntn mode){int rv, 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_read(PRFileDesc *fd, void *buf, PRInt32 amount){PRThread *me = _PR_MD_CURRENT_THREAD();PRInt32 rv, err;#ifndef _PR_USE_POLLfd_set rd;#elsestruct pollfd pfd;#endif /* _PR_USE_POLL */PRInt32 osfd = fd->secret->md.osfd;#ifndef _PR_USE_POLL FD_ZERO(&rd); FD_SET(osfd, &rd);#else pfd.fd = osfd; pfd.events = POLLIN;#endif /* _PR_USE_POLL */ while ((rv = read(osfd,buf,amount)) == -1) { err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, PR_INTERVAL_NO_TIMEOUT)) < 0) goto done; } else {#ifndef _PR_USE_POLL while ((rv = _MD_SELECT(osfd + 1, &rd, NULL, NULL, NULL)) == -1 && (err = _MD_ERRNO()) == EINTR) { /* retry _MD_SELECT() if it is interrupted */ }#else /* _PR_USE_POLL */ while ((rv = _MD_POLL(&pfd, 1, -1)) == -1 && (err = _MD_ERRNO()) == EINTR) { /* retry _MD_POLL() if it is interrupted */ }#endif /* _PR_USE_POLL */ if (rv == -1) { break; } } if (_PR_PENDING_INTERRUPT(me)) break; } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); } else { _PR_MD_MAP_READ_ERROR(err); } }done: return(rv);}PRInt32 _MD_write(PRFileDesc *fd, const void *buf, PRInt32 amount){PRThread *me = _PR_MD_CURRENT_THREAD();PRInt32 rv, err;#ifndef _PR_USE_POLLfd_set wd;#elsestruct pollfd pfd;#endif /* _PR_USE_POLL */PRInt32 osfd = fd->secret->md.osfd;#ifndef _PR_USE_POLL FD_ZERO(&wd); FD_SET(osfd, &wd);#else pfd.fd = osfd; pfd.events = POLLOUT;#endif /* _PR_USE_POLL */ while ((rv = write(osfd,buf,amount)) == -1) { err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_WRITE, PR_INTERVAL_NO_TIMEOUT)) < 0) goto done; } else {#ifndef _PR_USE_POLL while ((rv = _MD_SELECT(osfd + 1, NULL, &wd, NULL, NULL)) == -1 && (err = _MD_ERRNO()) == EINTR) { /* retry _MD_SELECT() if it is interrupted */ }#else /* _PR_USE_POLL */ while ((rv = _MD_POLL(&pfd, 1, -1)) == -1 && (err = _MD_ERRNO()) == EINTR) { /* retry _MD_POLL() if it is interrupted */ }#endif /* _PR_USE_POLL */ if (rv == -1) { break; } } if (_PR_PENDING_INTERRUPT(me)) break; } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); } else { _PR_MD_MAP_WRITE_ERROR(err); } }done: return(rv);}PRInt32 _MD_fsync(PRFileDesc *fd){PRInt32 rv, err;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -