⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 io.c

📁 快速开发
💻 C
📖 第 1 页 / 共 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 library. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s):  Silicon Graphics, Inc. *  * Portions created by SGI are Copyright (C) 2000-2001 Silicon * Graphics, Inc.  All Rights Reserved. *  * 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. *//* * This file is derived directly from Netscape Communications Corporation, * and consists of extensive modifications made during the year(s) 1999-2000. */#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/uio.h>#include <sys/time.h>#include <sys/resource.h>#include <fcntl.h>#include <signal.h>#include <errno.h>#include "common.h"#if EAGAIN != EWOULDBLOCK#define _IO_NOT_READY_ERROR  ((errno == EAGAIN) || (errno == EWOULDBLOCK))#else#define _IO_NOT_READY_ERROR  (errno == EAGAIN)#endif#define _LOCAL_MAXIOV  16/* File descriptor object free list */static _st_netfd_t *_st_netfd_freelist = NULL;/* Maximum number of file descriptors that the process can open */static int _st_osfd_limit = -1;static void _st_netfd_free_aux_data(_st_netfd_t *fd);int _st_io_init(void){  struct sigaction sigact;  struct rlimit rlim;  int fdlim;  /* Ignore SIGPIPE */  sigact.sa_handler = SIG_IGN;  sigemptyset(&sigact.sa_mask);  sigact.sa_flags = 0;  if (sigaction(SIGPIPE, &sigact, NULL) < 0)    return -1;  /* Set maximum number of open file descriptors */  if (getrlimit(RLIMIT_NOFILE, &rlim) < 0)    return -1;  fdlim = (*_st_eventsys->fd_getlimit)();  if (fdlim > 0 && rlim.rlim_max > fdlim) {    rlim.rlim_max = fdlim;  }  rlim.rlim_cur = rlim.rlim_max;  if (setrlimit(RLIMIT_NOFILE, &rlim) < 0)    return -1;  _st_osfd_limit = (int) rlim.rlim_max;  return 0;}int st_getfdlimit(void){  return _st_osfd_limit;}void st_netfd_free(_st_netfd_t *fd){  if (!fd->inuse)    return;  fd->inuse = 0;  if (fd->aux_data)    _st_netfd_free_aux_data(fd);  if (fd->private_data && fd->destructor)    (*(fd->destructor))(fd->private_data);  fd->private_data = NULL;  fd->destructor = NULL;  fd->next = _st_netfd_freelist;  _st_netfd_freelist = fd;}static _st_netfd_t *_st_netfd_new(int osfd, int nonblock, int is_socket){  _st_netfd_t *fd;  int flags = 1;  if ((*_st_eventsys->fd_new)(osfd) < 0)    return NULL;  if (_st_netfd_freelist) {    fd = _st_netfd_freelist;    _st_netfd_freelist = _st_netfd_freelist->next;  } else {    fd = calloc(1, sizeof(_st_netfd_t));    if (!fd)      return NULL;  }  fd->osfd = osfd;  fd->inuse = 1;  fd->next = NULL;  if (nonblock) {    /* Use just one system call */    if (is_socket && ioctl(osfd, FIONBIO, &flags) != -1)      return fd;    /* Do it the Posix way */    if ((flags = fcntl(osfd, F_GETFL, 0)) < 0 ||	fcntl(osfd, F_SETFL, flags | O_NONBLOCK) < 0) {      st_netfd_free(fd);      return NULL;    }  }  return fd;}_st_netfd_t *st_netfd_open(int osfd){  return _st_netfd_new(osfd, 1, 0);}_st_netfd_t *st_netfd_open_socket(int osfd){  return _st_netfd_new(osfd, 1, 1);}int st_netfd_close(_st_netfd_t *fd){  if ((*_st_eventsys->fd_close)(fd->osfd) < 0)    return -1;  st_netfd_free(fd);  return close(fd->osfd);}int st_netfd_fileno(_st_netfd_t *fd){  return (fd->osfd);}void st_netfd_setspecific(_st_netfd_t *fd, void *value,			  _st_destructor_t destructor){  if (value != fd->private_data) {    /* Free up previously set non-NULL data value */    if (fd->private_data && fd->destructor)      (*(fd->destructor))(fd->private_data);  }  fd->private_data = value;  fd->destructor = destructor;}void *st_netfd_getspecific(_st_netfd_t *fd){  return (fd->private_data);}/* * Wait for I/O on a single descriptor. */int st_netfd_poll(_st_netfd_t *fd, int how, st_utime_t timeout){  struct pollfd pd;  int n;  pd.fd = fd->osfd;  pd.events = (short) how;  pd.revents = 0;  if ((n = st_poll(&pd, 1, timeout)) < 0)    return -1;  if (n == 0) {    /* Timed out */    errno = ETIME;    return -1;  }  if (pd.revents & POLLNVAL) {    errno = EBADF;    return -1;  }  return 0;}#ifdef MD_ALWAYS_UNSERIALIZED_ACCEPT/* No-op */int st_netfd_serialize_accept(_st_netfd_t *fd){  fd->aux_data = NULL;  return 0;}/* No-op */static void _st_netfd_free_aux_data(_st_netfd_t *fd){  fd->aux_data = NULL;}_st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen,		       st_utime_t timeout){  int osfd, err;  _st_netfd_t *newfd;  while ((osfd = accept(fd->osfd, addr, (socklen_t *)addrlen)) < 0) {    if (errno == EINTR)      continue;    if (!_IO_NOT_READY_ERROR)      return NULL;    /* Wait until the socket becomes readable */    if (st_netfd_poll(fd, POLLIN, timeout) < 0)      return NULL;  }  /* On some platforms the new socket created by accept() inherits */  /* the nonblocking attribute of the listening socket */#if defined (MD_ACCEPT_NB_INHERITED)  newfd = _st_netfd_new(osfd, 0, 1);#elif defined (MD_ACCEPT_NB_NOT_INHERITED)  newfd = _st_netfd_new(osfd, 1, 1);#else#error Unknown OS#endif  if (!newfd) {    err = errno;    close(osfd);    errno = err;  }  return newfd;}#else /* MD_ALWAYS_UNSERIALIZED_ACCEPT *//* * On some platforms accept() calls from different processes * on the same listen socket must be serialized. * The following code serializes accept()'s without process blocking. * A pipe is used as an inter-process semaphore. */int st_netfd_serialize_accept(_st_netfd_t *fd){  _st_netfd_t **p;  int osfd[2], err;  if (fd->aux_data) {    errno = EINVAL;    return -1;  }  if ((p = (_st_netfd_t **)calloc(2, sizeof(_st_netfd_t *))) == NULL)    return -1;  if (pipe(osfd) < 0) {    free(p);    return -1;  }  if ((p[0] = st_netfd_open(osfd[0])) != NULL &&      (p[1] = st_netfd_open(osfd[1])) != NULL &&      write(osfd[1], " ", 1) == 1) {    fd->aux_data = p;    return 0;  }  /* Error */  err = errno;  if (p[0])    st_netfd_free(p[0]);  if (p[1])    st_netfd_free(p[1]);  close(osfd[0]);  close(osfd[1]);  free(p);  errno = err;  return -1;}static void _st_netfd_free_aux_data(_st_netfd_t *fd){  _st_netfd_t **p = (_st_netfd_t **) fd->aux_data;  st_netfd_close(p[0]);  st_netfd_close(p[1]);  free(p);  fd->aux_data = NULL;}_st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen,		       st_utime_t timeout){  int osfd, err;  _st_netfd_t *newfd;  _st_netfd_t **p = (_st_netfd_t **) fd->aux_data;  ssize_t n;  char c;  for ( ; ; ) {    if (p == NULL) {      osfd = accept(fd->osfd, addr, (socklen_t *)addrlen);    } else {      /* Get the lock */      n = st_read(p[0], &c, 1, timeout);      if (n < 0)	return NULL;      ST_ASSERT(n == 1);      /* Got the lock */      osfd = accept(fd->osfd, addr, (socklen_t *)addrlen);      /* Unlock */      err = errno;      n = st_write(p[1], &c, 1, timeout);      ST_ASSERT(n == 1);      errno = err;    }    if (osfd >= 0)      break;    if (errno == EINTR)      continue;    if (!_IO_NOT_READY_ERROR)      return NULL;    /* Wait until the socket becomes readable */    if (st_netfd_poll(fd, POLLIN, timeout) < 0)      return NULL;  }  /* On some platforms the new socket created by accept() inherits */  /* the nonblocking attribute of the listening socket */#if defined (MD_ACCEPT_NB_INHERITED)  newfd = _st_netfd_new(osfd, 0, 1);#elif defined (MD_ACCEPT_NB_NOT_INHERITED)  newfd = _st_netfd_new(osfd, 1, 1);#else#error Unknown OS#endif  if (!newfd) {    err = errno;    close(osfd);    errno = err;  }  return newfd;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -