1N/A * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers. 1N/A * All rights reserved. 1N/A * Copyright (c) 1990, 1993 1N/A * The Regents of the University of California. All rights reserved. 1N/A * This code is derived from software contributed to Berkeley by 1N/A * By using this file, you agree to the terms and conditions set 1N/A * forth in the LICENSE file which can be found at the top level of 1N/A * the sendmail distribution. 1N/A#
pragma ident "%Z%%M% %I% %E% SMI" 1N/A** SEEKALRM -- handler when timeout activated for sm_io_seek() 1N/A** Returns flow of control to where setjmp(SeekTimeOut) was set. 1N/A** returns flow of control to setjmp(SeekTimeOut). 1N/A** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 1N/A** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 1N/A** SM_IO_SEEK -- position the file pointer 1N/A** fp -- the file pointer to be seek'd 1N/A** timeout -- time to complete seek (milliseconds) 1N/A** offset -- seek offset based on 'whence' 1N/A** whence -- indicates where seek is relative from. 1N/A** One of SM_IO_SEEK_{CUR,SET,END}. 1N/A** Failure: returns -1 (minus 1) and sets errno 1N/A** Success: returns 0 (zero) 1N/A /* make sure stdio is set up */ 1N/A /* Have to be able to seek. */ 1N/A ** Filling the buffer will take time and we are wanted to 1N/A ** return immediately. So... 1N/A ** Change any SM_IO_SEEK_CUR to SM_IO_SEEK_SET, and check `whence' 1N/A ** argument. After this, whence is either SM_IO_SEEK_SET or 1N/A ** In order to seek relative to the current stream offset, 1N/A ** we have to first find the current stream offset a la 1N/A ** ftell (see ftell for details). 1N/A /* may adjust seek offset on append stream */ 1N/A ** Can only optimise if: 1N/A ** reading (and not reading-and-writing); 1N/A ** not unbuffered; and 1N/A ** this is a `regular' Unix file (and hence seekfn==sm_stdseek). 1N/A ** We must check SMNBF first, because it is possible to have SMNBF 1N/A ** and SMSOPT both set. 1N/A ** We are reading; we can try to optimise. 1N/A ** Figure out where we are going and where we are now. 1N/A ** Compute the number of bytes in the input buffer (pretending 1N/A ** that any ungetc() input has been discarded). Adjust current 1N/A ** offset backwards by this count so that it represents the 1N/A ** file offset for the first byte in the current input buffer. 1N/A ** If the target offset is within the current buffer, 1N/A ** simply adjust the pointers, clear SMFEOF, undo ungetc(), 1N/A ** and return. (If the buffer was modified, we have to 1N/A ** The place we want to get to is not within the current buffer, 1N/A ** but we can still be kind to the kernel copyout mechanism. 1N/A ** By aligning the file offset to a block boundary, we can let 1N/A ** the kernel use the VM hardware to map pages instead of 1N/A ** copying bytes laboriously. Using a block boundary also 1N/A ** ensures that we only read one block, rather than two. 1N/A /* Note: SM_TIME_FOREVER since fn timeout already set */ 1N/A /* We're back. So undo our timeout and handler */ 1N/A ** We get here if we cannot optimise the seek ... just 1N/A ** do it. Allow the seek function to change fp->f_bf.smb_base. 1N/A /* Note: SM_TIME_FOREVER since fn timeout already set */ 1N/A /* success: clear SMFEOF indicator and discard ungetc() data */