mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-31 17:09:09 +00:00 
			
		
		
		
	 d7ce700605
			
		
	
	
		d7ce700605
		
	
	
	
	
		
			
			Add Posix functions for porting compatibility. Fix compliance issues with ISO/IEC 9899:199409 New Functions: setenv(), fparseln(), GetFileNameFromPath(), rename(), realpath(), setprogname(), getprogname(), strlcat(), strlcpy(), strsep(), setitimer(), getitimer(), timegm(), getopt(), basename(), mkstemp(), ffs(), vsnprintf(), snprintf(), getpass(), usleep(), select(), writev(), strcasecmp(), getcwd(), chdir(), tcgetpgrp(), getpgrp(), gettimeofday(), bcopy(), git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12061 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			304 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			304 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|     Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
 | |
|     This program and the accompanying materials are licensed and made available
 | |
|     under the terms and conditions of the BSD License that accompanies this
 | |
|     distribution.  The full text of the license may be found at
 | |
|     http://opensource.org/licenses/bsd-license.
 | |
| 
 | |
|     THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|     WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
|  * Copyright (c) 1990, 1993
 | |
|  *  The Regents of the University of California.  All rights reserved.
 | |
|  *
 | |
|  * This code is derived from software contributed to Berkeley by
 | |
|  * Chris Torek.
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions
 | |
|  * are met:
 | |
|  * 1. Redistributions of source code must retain the above copyright
 | |
|  *    notice, this list of conditions and the following disclaimer.
 | |
|  * 2. Redistributions in binary form must reproduce the above copyright
 | |
|  *    notice, this list of conditions and the following disclaimer in the
 | |
|  *    documentation and/or other materials provided with the distribution.
 | |
|  * 3. Neither the name of the University nor the names of its contributors
 | |
|  *    may be used to endorse or promote products derived from this software
 | |
|  *    without specific prior written permission.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 | |
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | |
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | |
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 | |
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | |
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | |
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | |
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | |
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | |
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | |
|  * SUCH DAMAGE.
 | |
| 
 | |
|     NetBSD: fseeko.c,v 1.5 2005/03/04 16:04:58 dsl Exp
 | |
|  */
 | |
| //#include <Uefi.h>               // REMOVE, For DEBUG only
 | |
| //#include <Library/UefiLib.h>    // REMOVE, For DEBUG only
 | |
| 
 | |
| #include  <LibConfig.h>
 | |
| #include <sys/EfiCdefs.h>
 | |
| 
 | |
| #include "namespace.h"
 | |
| #include <sys/types.h>
 | |
| #include <sys/stat.h>
 | |
| 
 | |
| #include <assert.h>
 | |
| #include <errno.h>
 | |
| #include <fcntl.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include "reentrant.h"
 | |
| #include "local.h"
 | |
| 
 | |
| #ifdef __weak_alias
 | |
| __weak_alias(fseeko, _fseeko)
 | |
| #endif
 | |
| 
 | |
| #define POS_ERR (-(fpos_t)1)
 | |
| 
 | |
| /*
 | |
|  * Seek the given file to the given offset.
 | |
|  * `Whence' must be one of the three SEEK_* macros.
 | |
|  */
 | |
| int
 | |
| fseeko(FILE *fp, off_t offset, int whence)
 | |
| {
 | |
|   fpos_t (*seekfn)(void *, fpos_t, int);
 | |
|   fpos_t target, curoff;
 | |
|   size_t n;
 | |
|   struct stat st;
 | |
|   int havepos;
 | |
| 
 | |
|   _DIAGASSERT(fp != NULL);
 | |
|   if(fp == NULL) {
 | |
|     errno = EINVAL;
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
| #ifdef __GNUC__
 | |
|   /* This outrageous construct just to shut up a GCC warning. */
 | |
|   (void) &curoff;
 | |
| #endif
 | |
| 
 | |
|   /* make sure stdio is set up */
 | |
|   if (!__sdidinit)
 | |
|     __sinit();
 | |
| 
 | |
| //Print(L"%a( %d, %Ld, %d)\n", __func__, fp->_file, offset, whence);
 | |
|   FLOCKFILE(fp);
 | |
| 
 | |
|   /*
 | |
|    * Have to be able to seek.
 | |
|    */
 | |
|   if ((seekfn = fp->_seek) == NULL) {
 | |
|     errno = ESPIPE;     /* historic practice */
 | |
|     FUNLOCKFILE(fp);
 | |
| //Print(L"%a: %d\n", __func__, __LINE__);
 | |
|     return (-1);
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Change any SEEK_CUR to SEEK_SET, and check `whence' argument.
 | |
|    * After this, whence is either SEEK_SET or SEEK_END.
 | |
|    */
 | |
|   switch (whence) {
 | |
| 
 | |
|   case SEEK_CUR:
 | |
|     /*
 | |
|      * In order to seek relative to the current stream offset,
 | |
|      * we have to first find the current stream offset a la
 | |
|      * ftell (see ftell for details).
 | |
|      */
 | |
|     __sflush(fp); /* may adjust seek offset on append stream */
 | |
|     if (fp->_flags & __SOFF)
 | |
|       curoff = fp->_offset;
 | |
|     else {
 | |
|       curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR);
 | |
|       if (curoff == POS_ERR) {
 | |
|         FUNLOCKFILE(fp);
 | |
| //Print(L"%a: %d\n", __func__, __LINE__);
 | |
|         return (-1);
 | |
|       }
 | |
|     }
 | |
|     if (fp->_flags & __SRD) {
 | |
|       curoff -= fp->_r;
 | |
|       if (HASUB(fp))
 | |
|         curoff -= fp->_ur;
 | |
|     } else if (fp->_flags & __SWR && fp->_p != NULL)
 | |
|       curoff += fp->_p - fp->_bf._base;
 | |
| 
 | |
|     offset += curoff;
 | |
|     whence = SEEK_SET;
 | |
|     havepos = 1;
 | |
|     break;
 | |
| 
 | |
|   case SEEK_SET:
 | |
|   case SEEK_END:
 | |
|     curoff = 0;   /* XXX just to keep gcc quiet */
 | |
|     havepos = 0;
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     errno = EINVAL;
 | |
|     FUNLOCKFILE(fp);
 | |
| //Print(L"%a: %d\n", __func__, __LINE__);
 | |
|     return (-1);
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Can only optimise if:
 | |
|    *  reading (and not reading-and-writing);
 | |
|    *  not unbuffered; and
 | |
|    *  this is a `regular' Unix file (and hence seekfn==__sseek).
 | |
|    * We must check __NBF first, because it is possible to have __NBF
 | |
|    * and __SOPT both set.
 | |
|    */
 | |
|   if (fp->_bf._base == NULL)
 | |
|     __smakebuf(fp);
 | |
|   if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT))
 | |
|     goto dumb;
 | |
|   if ((fp->_flags & __SOPT) == 0) {
 | |
|     if (seekfn != __sseek ||
 | |
|         fp->_file < 0 || fstat(fp->_file, &st) ||
 | |
|         !S_ISREG(st.st_mode)) {
 | |
|       fp->_flags |= __SNPT;
 | |
|       goto dumb;
 | |
|     }
 | |
|     fp->_blksize = st.st_blksize;
 | |
|     fp->_flags |= __SOPT;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * We are reading; we can try to optimise.
 | |
|    * Figure out where we are going and where we are now.
 | |
|    */
 | |
|   if (whence == SEEK_SET)
 | |
|     target = offset;
 | |
|   else {
 | |
|     if (fstat(fp->_file, &st))
 | |
|     {
 | |
| //Print(L"%a: %d\n", __func__, __LINE__);
 | |
|       goto dumb;
 | |
|     }
 | |
|     target = st.st_size + offset;
 | |
|   }
 | |
| 
 | |
|   if (!havepos) {
 | |
|     if (fp->_flags & __SOFF)
 | |
|       curoff = fp->_offset;
 | |
|     else {
 | |
|       curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR);
 | |
|       if (curoff == POS_ERR)
 | |
|       {
 | |
| //Print(L"%a: %d\n", __func__, __LINE__);
 | |
|         goto dumb;
 | |
|       }
 | |
|     }
 | |
|     curoff -= fp->_r;
 | |
|     if (HASUB(fp))
 | |
|       curoff -= fp->_ur;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Compute the number of bytes in the input buffer (pretending
 | |
|    * that any ungetc() input has been discarded).  Adjust current
 | |
|    * offset backwards by this count so that it represents the
 | |
|    * file offset for the first byte in the current input buffer.
 | |
|    */
 | |
|   if (HASUB(fp)) {
 | |
|     curoff += fp->_r; /* kill off ungetc */
 | |
|     n = fp->_up - fp->_bf._base;
 | |
|     curoff -= n;
 | |
|     n += fp->_ur;
 | |
|   } else {
 | |
|     n = fp->_p - fp->_bf._base;
 | |
|     curoff -= n;
 | |
|     n += fp->_r;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * If the target offset is within the current buffer,
 | |
|    * simply adjust the pointers, clear EOF, undo ungetc(),
 | |
|    * and return.  (If the buffer was modified, we have to
 | |
|    * skip this; see fgetln.c.)
 | |
|    */
 | |
|   if ((fp->_flags & __SMOD) == 0 &&
 | |
|       target >= curoff && target < (fpos_t)(curoff + n)) {
 | |
|     int o = (int)(target - curoff);
 | |
| 
 | |
|     fp->_p = fp->_bf._base + o;
 | |
|     fp->_r = (int)(n - o);
 | |
|     if (HASUB(fp))
 | |
|       FREEUB(fp);
 | |
|     WCIO_FREE(fp);    /* Should this really be unconditional??? */
 | |
|     fp->_flags &= ~__SEOF;
 | |
|     FUNLOCKFILE(fp);
 | |
|     return (0);
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * The place we want to get to is not within the current buffer,
 | |
|    * but we can still be kind to the kernel copyout mechanism.
 | |
|    * By aligning the file offset to a block boundary, we can let
 | |
|    * the kernel use the VM hardware to map pages instead of
 | |
|    * copying bytes laboriously.  Using a block boundary also
 | |
|    * ensures that we only read one block, rather than two.
 | |
|    */
 | |
|   curoff = target & ~(fp->_blksize - 1);
 | |
|   if ((*seekfn)(fp->_cookie, curoff, SEEK_SET) == POS_ERR)
 | |
|   {
 | |
| //Print(L"%a: %d\n", __func__, __LINE__);
 | |
|     goto dumb;
 | |
|   }
 | |
|   fp->_r = 0;
 | |
|   fp->_p = fp->_bf._base;
 | |
|   if (HASUB(fp))
 | |
|     FREEUB(fp);
 | |
|   WCIO_FREE(fp);    /* Should this really be unconditional??? */
 | |
|   fp->_flags &= ~__SEOF;
 | |
|   n = (int)(target - curoff);
 | |
|   if (n) {
 | |
|     if (__srefill(fp) || fp->_r < (int)n)
 | |
|     {
 | |
| //Print(L"%a: %d\n", __func__, __LINE__);
 | |
|       goto dumb;
 | |
|     }
 | |
|     fp->_p += n;
 | |
|     fp->_r -= (int)n;
 | |
|   }
 | |
|   FUNLOCKFILE(fp);
 | |
|   return (0);
 | |
| 
 | |
|   /*
 | |
|    * We get here if we cannot optimise the seek ... just
 | |
|    * do it.  Allow the seek function to change fp->_bf._base.
 | |
|    */
 | |
| dumb:
 | |
| //Print(L"%a: %d\n", __func__, __LINE__);
 | |
|   if (__sflush(fp) ||
 | |
|       (*seekfn)(fp->_cookie, (fpos_t)offset, whence) == POS_ERR) {
 | |
|     FUNLOCKFILE(fp);
 | |
| //Print(L"%a: %d\n", __func__, __LINE__);
 | |
|     return (-1);
 | |
|   }
 | |
|   /* success: clear EOF indicator and discard ungetc() data */
 | |
|   if (HASUB(fp))
 | |
|     FREEUB(fp);
 | |
|   WCIO_FREE(fp);    /* Should this really be unconditional??? */
 | |
|   fp->_p = fp->_bf._base;
 | |
|   fp->_r = 0;
 | |
|   fp->_w = 0;
 | |
|   fp->_flags &= ~__SEOF;
 | |
|   FUNLOCKFILE(fp);
 | |
| //Print(L"%a: %d\n", __func__, __LINE__);
 | |
|   return (0);
 | |
| }
 |