📄 ptio.c
字号:
char **bp = (char**)&(iov[iov_index].iov_base); iov[iov_index].iov_len -= bytes; /* there's that much left */ *bp += bytes; /* starting there */ break; /* go off and do that */ } bytes -= iov[iov_index].iov_len; /* that element's consumed */ } op->arg2.buffer = &iov[iov_index]; /* new start of array */ op->arg3.amount -= iov_index; /* and array length */ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE; } else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno)) { op->result.code = -1; return PR_TRUE; } else return PR_FALSE;} /* pt_writev_cont */static PRBool pt_sendto_cont(pt_Continuation *op, PRInt16 revents){ PRIntn bytes = sendto( op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags, (struct sockaddr*)op->arg5.addr, PR_NETADDR_SIZE(op->arg5.addr)); op->syserrno = errno; if (bytes >= 0) /* this is progress */ { char *bp = (char*)op->arg2.buffer; bp += bytes; /* adjust the buffer pointer */ op->arg2.buffer = bp; op->result.code += bytes; /* accumulate the number sent */ op->arg3.amount -= bytes; /* and reduce the required count */ return (0 == op->arg3.amount) ? PR_TRUE : PR_FALSE; } else if ((EWOULDBLOCK != op->syserrno) && (EAGAIN != op->syserrno)) { op->result.code = -1; return PR_TRUE; } else return PR_FALSE;} /* pt_sendto_cont */static PRBool pt_recvfrom_cont(pt_Continuation *op, PRInt16 revents){ pt_SockLen addr_len = sizeof(PRNetAddr); op->result.code = recvfrom( op->arg1.osfd, op->arg2.buffer, op->arg3.amount, op->arg4.flags, (struct sockaddr*)op->arg5.addr, &addr_len); op->syserrno = errno; return ((-1 == op->result.code) && (EWOULDBLOCK == op->syserrno || EAGAIN == op->syserrno)) ? PR_FALSE : PR_TRUE;} /* pt_recvfrom_cont */#ifdef AIXstatic PRBool pt_aix_sendfile_cont(pt_Continuation *op, PRInt16 revents){ struct sf_parms *sf_struct = (struct sf_parms *) op->arg2.buffer; ssize_t rv; unsigned long long saved_file_offset; long long saved_file_bytes; saved_file_offset = sf_struct->file_offset; saved_file_bytes = sf_struct->file_bytes; sf_struct->bytes_sent = 0; if ((sf_struct->file_bytes > 0) && (sf_struct->file_size > 0)) PR_ASSERT((sf_struct->file_bytes + sf_struct->file_offset) <= sf_struct->file_size); rv = AIX_SEND_FILE(&op->arg1.osfd, sf_struct, op->arg4.flags); op->syserrno = errno; if (rv != -1) { op->result.code += sf_struct->bytes_sent; /* * A bug in AIX 4.3.2 prevents the 'file_bytes' field from * being updated. So, 'file_bytes' is maintained by NSPR to * avoid conflict when this bug is fixed in AIX, in the future. */ if (saved_file_bytes != -1) saved_file_bytes -= (sf_struct->file_offset - saved_file_offset); sf_struct->file_bytes = saved_file_bytes; } else if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) { op->result.code = -1; } else { return PR_FALSE; } if (rv == 1) { /* more data to send */ return PR_FALSE; } return PR_TRUE;}#endif /* AIX */#ifdef HPUX11static PRBool pt_hpux_sendfile_cont(pt_Continuation *op, PRInt16 revents){ struct iovec *hdtrl = (struct iovec *) op->arg2.buffer; int count; count = sendfile(op->arg1.osfd, op->filedesc, op->arg3.file_spec.offset, op->arg3.file_spec.nbytes, hdtrl, op->arg4.flags); PR_ASSERT(count <= op->nbytes_to_send); op->syserrno = errno; if (count != -1) { op->result.code += count; } else if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) { op->result.code = -1; } else { return PR_FALSE; } if (count != -1 && count < op->nbytes_to_send) { if (count < hdtrl[0].iov_len) { /* header not sent */ hdtrl[0].iov_base = ((char *) hdtrl[0].iov_len) + count; hdtrl[0].iov_len -= count; } else if (count < (hdtrl[0].iov_len + op->arg3.file_spec.nbytes)) { /* header sent, file not sent */ PRUint32 file_nbytes_sent = count - hdtrl[0].iov_len; hdtrl[0].iov_base = NULL; hdtrl[0].iov_len = 0; op->arg3.file_spec.offset += file_nbytes_sent; op->arg3.file_spec.nbytes -= file_nbytes_sent; } else if (count < (hdtrl[0].iov_len + op->arg3.file_spec.nbytes + hdtrl[1].iov_len)) { PRUint32 trailer_nbytes_sent = count - (hdtrl[0].iov_len + op->arg3.file_spec.nbytes); /* header sent, file sent, trailer not sent */ hdtrl[0].iov_base = NULL; hdtrl[0].iov_len = 0; /* * set file offset and len so that no more file data is * sent */ op->arg3.file_spec.offset = op->arg3.file_spec.st_size; op->arg3.file_spec.nbytes = 0; hdtrl[1].iov_base =((char *) hdtrl[1].iov_base)+ trailer_nbytes_sent; hdtrl[1].iov_len -= trailer_nbytes_sent; } op->nbytes_to_send -= count; return PR_FALSE; } return PR_TRUE;}#endif /* HPUX11 */#ifdef SOLARIS static PRBool pt_solaris_sendfile_cont(pt_Continuation *op, PRInt16 revents){ struct sendfilevec *vec = (struct sendfilevec *) op->arg2.buffer; size_t xferred; ssize_t count; count = SOLARIS_SENDFILEV(op->arg1.osfd, vec, op->arg3.amount, &xferred); op->syserrno = errno; PR_ASSERT((count == -1) || (count == xferred)); if (count == -1) { if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN && op->syserrno != EINTR) { op->result.code = -1; return PR_TRUE; } count = xferred; } PR_ASSERT(count <= op->nbytes_to_send); op->result.code += count; if (count < op->nbytes_to_send) { op->nbytes_to_send -= count; while (count >= vec->sfv_len) { count -= vec->sfv_len; vec++; op->arg3.amount--; } PR_ASSERT(op->arg3.amount > 0); vec->sfv_off += count; vec->sfv_len -= count; PR_ASSERT(vec->sfv_len > 0); op->arg2.buffer = vec; return PR_FALSE; } return PR_TRUE;}#endif /* SOLARIS */#ifdef LINUX static PRBool pt_linux_sendfile_cont(pt_Continuation *op, PRInt16 revents){ ssize_t rv; off_t oldoffset; oldoffset = op->offset; rv = sendfile(op->arg1.osfd, op->in_fd, &op->offset, op->count); op->syserrno = errno; if (rv == -1) { if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) { op->result.code = -1; return PR_TRUE; } rv = 0; } PR_ASSERT(rv == op->offset - oldoffset); op->result.code += rv; if (rv < op->count) { op->count -= rv; return PR_FALSE; } return PR_TRUE;}#endif /* LINUX */void _PR_InitIO(void){#if defined(DEBUG) memset(&pt_debug, 0, sizeof(PTDebug)); pt_debug.timeStarted = PR_Now();#endif _pr_flock_lock = PR_NewLock(); PR_ASSERT(NULL != _pr_flock_lock); _pr_flock_cv = PR_NewCondVar(_pr_flock_lock); PR_ASSERT(NULL != _pr_flock_cv); _pr_rename_lock = PR_NewLock(); PR_ASSERT(NULL != _pr_rename_lock); _PR_InitFdCache(); /* do that */ _pr_stdin = pt_SetMethods(0, PR_DESC_FILE, PR_FALSE, PR_TRUE); _pr_stdout = pt_SetMethods(1, PR_DESC_FILE, PR_FALSE, PR_TRUE); _pr_stderr = pt_SetMethods(2, PR_DESC_FILE, PR_FALSE, PR_TRUE); PR_ASSERT(_pr_stdin && _pr_stdout && _pr_stderr);} /* _PR_InitIO */void _PR_CleanupIO(void){ _PR_Putfd(_pr_stdin); _pr_stdin = NULL; _PR_Putfd(_pr_stdout); _pr_stdout = NULL; _PR_Putfd(_pr_stderr); _pr_stderr = NULL; _PR_CleanupFdCache(); if (_pr_flock_cv) { PR_DestroyCondVar(_pr_flock_cv); _pr_flock_cv = NULL; } if (_pr_flock_lock) { PR_DestroyLock(_pr_flock_lock); _pr_flock_lock = NULL; } if (_pr_rename_lock) { PR_DestroyLock(_pr_rename_lock); _pr_rename_lock = NULL; }} /* _PR_CleanupIO */PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD osfd){ PRFileDesc *result = NULL; PR_ASSERT(osfd >= PR_StandardInput && osfd <= PR_StandardError); if (!_pr_initialized) _PR_ImplicitInitialization(); switch (osfd) { case PR_StandardInput: result = _pr_stdin; break; case PR_StandardOutput: result = _pr_stdout; break; case PR_StandardError: result = _pr_stderr; break; default: (void)PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); } return result;} /* PR_GetSpecialFD *//*****************************************************************************//***************************** I/O private methods ***************************//*****************************************************************************/static PRBool pt_TestAbort(void){ PRThread *me = PR_CurrentThread(); if(_PT_THREAD_INTERRUPTED(me)) { PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); me->state &= ~PT_THREAD_ABORTED; return PR_TRUE; } return PR_FALSE;} /* pt_TestAbort */static void pt_MapError(void (*mapper)(PRIntn), PRIntn syserrno){ switch (syserrno) { case EINTR: PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); break; case ETIMEDOUT: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); break; default: mapper(syserrno); }} /* pt_MapError */static PRStatus pt_Close(PRFileDesc *fd){ if ((NULL == fd) || (NULL == fd->secret) || ((_PR_FILEDESC_OPEN != fd->secret->state) && (_PR_FILEDESC_CLOSED != fd->secret->state))) { PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0); return PR_FAILURE; } if (pt_TestAbort()) return PR_FAILURE; if (_PR_FILEDESC_OPEN == fd->secret->state) { if (-1 == close(fd->secret->md.osfd)) {#ifdef OSF1 /* * Bug 86941: On Tru64 UNIX V5.0A and V5.1, the close() * system call, when called to close a TCP socket, may * return -1 with errno set to EINVAL but the system call * does close the socket successfully. An application * may safely ignore the EINVAL error. This bug is fixed * on Tru64 UNIX V5.1A and later. The defect tracking * number is QAR 81431. */ if (PR_DESC_SOCKET_TCP != fd->methods->file_type || EINVAL != errno) { pt_MapError(_PR_MD_MAP_CLOSE_ERROR, errno); return PR_FAILURE; }#else pt_MapError(_PR_MD_MAP_CLOSE_ERROR, errno); return PR_FAILURE;#endif } fd->secret->state = _PR_FILEDESC_CLOSED; } _PR_Putfd(fd); return PR_SUCCESS;} /* pt_Close */static PRInt32 pt_Read(PRFileDesc *fd, void *buf, PRInt32 amount){ PRInt32 syserrno, bytes = -1; if (pt_TestAbort()) return bytes; bytes = read(fd->secret->md.osfd, buf, amount); syserrno = errno; if ((bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN) && (!fd->secret->nonblocking)) { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = buf; op.arg3.amount = amount; op.timeout = PR_INTERVAL_NO_TIMEOUT; op.function = pt_read_cont; op.event = POLLIN | POLLPRI; bytes = pt_Continue(&op); syserrno = op.syserrno; } if (bytes < 0) pt_MapError(_PR_MD_MAP_READ_ERROR, syserrno); return bytes;} /* pt_Read */static PRInt32 pt_Write(PRFileDesc *fd, const void *buf, PRInt32 amount){ PRInt32 syserrno, bytes = -1; PRBool fNeedContinue = PR_FALSE; if (pt_TestAbort()) return bytes; bytes = write(fd->secret->md.osfd, buf, amount); syserrno = errno; if ( (bytes >= 0) && (bytes < amount) && (!fd->secret->nonblocking) ) { buf = (char *) buf + bytes; amount -= bytes; fNeedContinue = PR_TRUE; } if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN) && (!fd->secret->nonblocking) ) { bytes = 0; fNeedContinue = PR_TRUE; } if (fNeedContinue == PR_TRUE) { pt_Continuation op; op.arg1.osfd = fd->secret->md.osfd; op.arg2.buffer = (void*)buf; op.arg3.amount = amount; op.timeout = PR_INTERVAL_NO_TIMEOUT; op.result.code = bytes; /* initialize the number sent */ op.function = pt_write_cont; op.event = POLLOUT | POLLPRI; bytes = pt_Continue(&op); syserrno = op.syserrno; } if (bytes == -1) pt_MapError(_PR_MD_MAP_WRITE_ERROR, syserrno); return bytes;} /* pt_Write */static PRInt32 pt_Writev( PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_len, PRIntervalTime timeout){ PRIntn iov_index; PRBool fNeedContinue = PR_FALSE; PRInt32 syserrno, bytes, rv = -1; struct iovec osiov_local[PR_MAX_IOVECTOR_SIZE], *osiov; int osiov_len; if (pt_TestAbort()) return rv;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -