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

📄 open.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: open.c 25049 2006-12-03 21:06:03Z fireball $
 *
 * COPYRIGHT:   See COPYING in the top level directory
 * PROJECT:     ReactOS system libraries
 * FILE:        lib/msvcrt/io/open.c
 * PURPOSE:     Opens a file and translates handles to fileno
 * PROGRAMER:   Ariadne
 * UPDATE HISTORY:
 *              28/12/98: Created
 */
/*
 * Some stuff taken from active perl: perl\win32.c (ioinfo stuff)
 *
 * (c) 1995 Microsoft Corporation. All rights reserved.
 *       Developed by hip communications inc., http://info.hip.com/info/
 * Portions (c) 1993 Intergraph Corporation. All rights reserved.
 *
 *    You may distribute under the terms of either the GNU General Public
 *    License or the Artistic License, as specified in the README file.
 */
/*
 * Some functions taken from/based on wine\dlls\msvcrt\file.c:
 *  split_oflags
 *  _open_osfhandle
 *  many more...
 *
 * Copyright 1996,1998 Marcus Meissner
 * Copyright 1996 Jukka Iivonen
 * Copyright 1997,2000 Uwe Bonnes
 * Copyright 2000 Jon Griffiths
 * Copyright 2004 Eric Pouech
 * Copyright 2004 Juan Lang
 */

// rember to interlock the allocation of fileno when making this thread safe

// possibly store extra information at the handle

#include <precomp.h>

#if !defined(NDEBUG) && defined(DBG)
#include <stdarg.h>
#endif

#include <sys/stat.h>
#include <string.h>
#include <share.h>

#define NDEBUG
#include <internal/debug.h>



FDINFO first_bucket[FDINFO_ENTRIES_PER_BUCKET];
FDINFO* __pioinfo[FDINFO_BUCKETS] = {first_bucket};


/* This critical section protects the tables MSVCRT_fdesc and MSVCRT_fstreams,
 * and their related indexes, MSVCRT_fdstart, MSVCRT_fdend,
 * and MSVCRT_stream_idx, from race conditions.
 * It doesn't protect against race conditions manipulating the underlying files
 * or flags; doing so would probably be better accomplished with per-file
 * protection, rather than locking the whole table for every change.
 */
static CRITICAL_SECTION g_file_cs;
#define LOCK_FILES()    do { EnterCriticalSection(&g_file_cs); } while (0)
#define UNLOCK_FILES()  do { LeaveCriticalSection(&g_file_cs); } while (0)

/////////////////////////////////////////

static int g_fdstart = 3; /* first unallocated fd */
static int g_fdend = 3; /* highest allocated fd */

/*
 * INTERNAL
 */
 /*
static __inline FD_INFO* fdinfo(int fd)
{
   FD_INFO* bucket = __pioinfo[fd >> FDINFO_ENTRIES_PER_BUCKET_SHIFT];
   if (!bucket){
      bucket = alloc_init_bucket(fd);
   }
   return bucket + (fd & (FDINFO_ENTRIES_PER_BUCKET - 1));
}
*/


/*
 * INTERNAL
 */
__inline BOOL is_valid_fd(int fd)
{
   BOOL b = (fd >= 0 && fd < g_fdend && (fdinfo(fd)->fdflags & FOPEN));

   if (!b){
      if (fd >= 0 && fd < g_fdend)
      {
         DPRINT1("not valid fd %i, g_fdend %i, fdinfo %x, bucket %x, fdflags %x\n",
                 fd,g_fdend,fdinfo(fd),fdinfo_bucket(fd),fdinfo(fd)->fdflags);
      }
      else
      {
         DPRINT1("not valid fd %i, g_fdend %i\n",fd,g_fdend);
      }

   }

   return b;
}

/*
 * INTERNAL
 */
char split_oflags(int oflags)
{
    char         fdflags = 0;

    if (oflags & _O_APPEND)              fdflags |= FAPPEND;

    if (oflags & _O_BINARY)              ;
    else if (oflags & _O_TEXT)           fdflags |= FTEXT;
    else if (_fmode& _O_BINARY)  ;
    else                                        fdflags |= FTEXT; /* default to TEXT*/

    if (oflags & _O_NOINHERIT)           fdflags |= FNOINHERIT;

    if (oflags & ~(_O_BINARY|_O_TEXT|_O_APPEND|_O_TRUNC|
                   _O_EXCL|_O_CREAT|_O_RDWR|_O_WRONLY|
                   _O_TEMPORARY|_O_NOINHERIT))
        DPRINT1(":unsupported oflags 0x%04x\n",oflags);

    return fdflags;
}



/*
 * INTERNAL
 */
char __is_text_file(FILE* p)
{
   if ( p == NULL || fdinfo_bucket((p)->_file) == NULL )
     return FALSE;
   return (!((p)->_flag&_IOSTRG) && (fdinfo((p)->_file)->fdflags & FTEXT));
}

/*
 * @implemented
 */
int _open(const char* _path, int _oflag,...)
{
#if !defined(NDEBUG) && defined(DBG)
   va_list arg;
   int pmode;
#endif
   HANDLE hFile;
   DWORD dwDesiredAccess = 0;
   DWORD dwShareMode = 0;
   DWORD dwCreationDistribution = 0;
   DWORD dwFlagsAndAttributes = 0;
   SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};

#if !defined(NDEBUG) && defined(DBG)
   va_start(arg, _oflag);
   pmode = va_arg(arg, int);
#endif


   TRACE("_open('%s', %x, (%x))\n", _path, _oflag);


   if ((_oflag & S_IREAD ) == S_IREAD)
     dwShareMode = FILE_SHARE_READ;
   else if ((_oflag & S_IWRITE) == S_IWRITE) {
      dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
   }
   /*
    *
    * _O_BINARY   Opens file in binary (untranslated) mode. (See fopen for a description of binary mode.)
    * _O_TEXT   Opens file in text (translated) mode. (For more information, see Text and Binary Mode File I/O and fopen.)
    *
    * _O_APPEND   Moves file pointer to end of file before every write operation.
    */
#ifdef _OLD_BUILD_
   if ((_oflag & _O_RDWR) == _O_RDWR)
     dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ;
   else if ((_oflag & O_RDONLY) == O_RDONLY)
     dwDesiredAccess |= GENERIC_READ;
   else if ((_oflag & _O_WRONLY) == _O_WRONLY)
     dwDesiredAccess |= GENERIC_WRITE ;
#else
   if ((_oflag & _O_WRONLY) == _O_WRONLY )
     dwDesiredAccess |= GENERIC_WRITE ;
   else if ((_oflag & _O_RDWR) == _O_RDWR )
     dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ;
   else //if ((_oflag & O_RDONLY) == O_RDONLY)
     dwDesiredAccess |= GENERIC_READ;
#endif

   if (( _oflag & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL))
     dwCreationDistribution |= CREATE_NEW;

   else if ((_oflag &  O_TRUNC ) == O_TRUNC) {
      if ((_oflag &  O_CREAT ) ==  O_CREAT)
    dwCreationDistribution |= CREATE_ALWAYS;
      else if ((_oflag & O_RDONLY ) != O_RDONLY)
    dwCreationDistribution |= TRUNCATE_EXISTING;
   }
   else if ((_oflag & _O_APPEND) == _O_APPEND)
     dwCreationDistribution |= OPEN_EXISTING;
   else if ((_oflag &  _O_CREAT) == _O_CREAT)
     dwCreationDistribution |= OPEN_ALWAYS;
   else
     dwCreationDistribution |= OPEN_EXISTING;

   if ((_oflag &  _O_RANDOM) == _O_RANDOM )
     dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
   if ((_oflag &  _O_SEQUENTIAL) == _O_SEQUENTIAL)
     dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
   if ((_oflag &  _O_TEMPORARY) == _O_TEMPORARY) {
     dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
     DPRINT("FILE_FLAG_DELETE_ON_CLOSE\n");
   }
   if ((_oflag &  _O_SHORT_LIVED) == _O_SHORT_LIVED) {
     dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
     DPRINT("FILE_FLAG_DELETE_ON_CLOSE\n");
   }
   if (_oflag & _O_NOINHERIT)
     sa.bInheritHandle = FALSE;

   if (dwCreationDistribution == OPEN_EXISTING &&
       (dwDesiredAccess & (GENERIC_WRITE|GENERIC_READ)) == GENERIC_READ) {
      /* Allow always shared read for a file which is opened for read only */
      dwShareMode |= FILE_SHARE_READ;
   }

   hFile = CreateFileA(_path,
               dwDesiredAccess,
               dwShareMode,
               &sa,
               dwCreationDistribution,
               dwFlagsAndAttributes,
               NULL);
	if (hFile == (HANDLE)-1) {
		_dosmaperr(GetLastError());
      return( -1);
	}
   DPRINT("OK\n");
   if (!(_oflag & (_O_TEXT|_O_BINARY))) {
       _oflag |= _fmode;
   }
   return(alloc_fd(hFile, split_oflags(_oflag)));
}



/*
 * INTERNAL
 */
static void init_bucket(FDINFO* entry)
{
   int i;

   for(i=0;
       i < FDINFO_ENTRIES_PER_BUCKET;
       i++, entry++)
   {
      entry->hFile = INVALID_HANDLE_VALUE;
      entry->fdflags = 0;
      entry->pipechar = LF;
      entry->lockinitflag = 0;
   }
}

/*
 * INTERNAL
 */
static BOOL alloc_init_bucket(int fd)
{
   fdinfo_bucket(fd) = malloc(FDINFO_ENTRIES_PER_BUCKET * sizeof(FDINFO));
   if (!fdinfo_bucket(fd)) return FALSE;

   init_bucket(fdinfo_bucket(fd));

   return TRUE;
}




/*
 * INTERNAL
 *  Allocate an fd slot from a Win32 HANDLE, starting from fd
 *  caller must hold the files lock
 */
static int alloc_fd_from(HANDLE hand, char flag, int fd)
{

   if (fd >= FDINFO_ENTRIES)
   {
      DPRINT1("files exhausted!\n");
      return -1;
   }

   if (!fdinfo_bucket(fd))
   {
      if (!alloc_init_bucket(fd)){
         //errno = ENOMEM
         return -1;
      }
   }

   fdinfo(fd)->hFile = hand;
   fdinfo(fd)->fdflags = FOPEN | (flag & (FNOINHERIT | FAPPEND | FTEXT));
   fdinfo(fd)->pipechar = LF;
   fdinfo(fd)->lockinitflag = 0;
   //fdinfo(fd)->lock

   /* locate next free slot */
   if (fd == g_fdstart && fd == g_fdend)
   {
      g_fdstart = g_fdend + 1;
   }
   else
   {
#if 0  /* alternate (untested) impl. maybe a tiny bit faster? -Gunnar */
      int i, bidx;

      for (bidx = fdinfo_bucket_idx(g_fdstart); bidx < FDINFO_BUCKETS && __pioinfo[bidx]; bidx++)
      {
         for (i = fdinfo_bucket_entry_idx(g_fdstart);
              g_fdstart < g_fdend && fdinfo(g_fdstart)->fdflags & FOPEN && i < FDINFO_BUCKET_ENTRIES;
              i++)
         {
            g_fdstart++;
         }
      }
#else

      while (g_fdstart < g_fdend &&
             fdinfo_bucket(g_fdstart) &&
             (fdinfo(g_fdstart)->fdflags & FOPEN))
      {
         g_fdstart++;
      }
#endif
   }

  /* update last fd in use */
   if (fd >= g_fdend)
      g_fdend = fd + 1;

   /* alloc more fdinfo buckets by demand.
    * FIXME: should we dealloc buckets when they become unused also? */
   if (!fdinfo_bucket(g_fdstart) && g_fdstart < FDINFO_ENTRIES)
   {
      alloc_init_bucket(g_fdstart);
   }

   DPRINT("fdstart is %d, fdend is %d\n", g_fdstart, g_fdend);

   switch (fd)
   {
      case 0: SetStdHandle(STD_INPUT_HANDLE,  hand); break;

⌨️ 快捷键说明

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