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

📄 syscalls.cc

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 CC
📖 第 1 页 / 共 4 页
字号:
/* syscalls.cc: syscalls   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.This file is part of Cygwin.This software is a copyrighted work licensed under the terms of theCygwin license.  Please consult the file "CYGWIN_LICENSE" fordetails. */#define _close __FOO_close__#define _lseek __FOO_lseek__#define _open __FOO_open__#define _read __FOO_read__#define _write __FOO_write__#include "winsup.h"#include <sys/stat.h>#include <sys/vfs.h> /* needed for statfs */#include <pwd.h>#include <grp.h>#include <stdlib.h>#include <stdio.h>#include <process.h>#include <utmp.h>#include <sys/uio.h>#include <errno.h>#include <limits.h>#include <winnls.h>#include <wininet.h>#include <lmcons.h> /* for UNLEN */#include <cygwin/version.h>#include <sys/cygwin.h>#include "cygerrno.h"#include "perprocess.h"#include "security.h"#include "fhandler.h"#include "path.h"#include "dtable.h"#include "sigproc.h"#include "pinfo.h"#include <unistd.h>#include "shared_info.h"#include "cygheap.h"#define NEED_VFORK#include <setjmp.h>#include "perthread.h"#undef _close#undef _lseek#undef _open#undef _read#undef _writeSYSTEM_INFO system_info;/* Close all files and process any queued deletions.   Lots of unix style applications will open a tmp file, unlink it,   but never call close.  This function is called by _exit to   ensure we don't leave any such files lying around.  */void __stdcallclose_all_files (void){  SetResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "close_all_files");  fhandler_base *fh;  for (int i = 0; i < (int) cygheap->fdtab.size; i++)    if ((fh = cygheap->fdtab[i]) != NULL)      {	fh->close ();	cygheap->fdtab.release (i);      }  ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK | READ_LOCK, "close_all_files");  cygwin_shared->delqueue.process_queue ();}BOOL __stdcallcheck_pty_fds (void){  int res = FALSE;  SetResourceLock (LOCK_FD_LIST, WRITE_LOCK, "check_pty_fds");  fhandler_base *fh;  for (int i = 0; i < (int) cygheap->fdtab.size; i++)    if ((fh = cygheap->fdtab[i]) != NULL &&	(fh->get_device () == FH_TTYS || fh->get_device () == FH_PTYM))      {	res = TRUE;	break;      }  ReleaseResourceLock (LOCK_FD_LIST, WRITE_LOCK, "check_pty_fds");  return res;}intdup (int fd){  return cygheap->fdtab.dup2 (fd, cygheap_fdnew ());}intdup2 (int oldfd, int newfd){  return cygheap->fdtab.dup2 (oldfd, newfd);}extern "C" intunlink (const char *ourname){  int res = -1;  DWORD devn;  sigframe thisframe (mainthread);  path_conv win32_name (ourname, PC_SYM_NOFOLLOW | PC_FULL);  if (win32_name.error)    {      set_errno (win32_name.error);      goto done;    }  if ((devn = win32_name.get_devn ()) == FH_PROC || devn == FH_REGISTRY      || devn == FH_PROCESS)    {      set_errno (EROFS);      goto done;    }  syscall_printf ("_unlink (%s)", win32_name.get_win32 ());  if (!win32_name.exists ())    {      syscall_printf ("unlinking a nonexistent file");      set_errno (ENOENT);      goto done;    }  else if (win32_name.isdir ())    {      syscall_printf ("unlinking a directory");      set_errno (EPERM);      goto done;    }  /* Windows won't check the directory mode, so we do that ourselves.  */  if (!writable_directory (win32_name))    {      syscall_printf ("non-writable directory");      goto done;    }  /* Check for shortcut as symlink condition. */  if (win32_name.has_attribute (FILE_ATTRIBUTE_READONLY))    {      int len = strlen (win32_name);      if (len > 4 && strcasematch ((char *) win32_name + len - 4, ".lnk"))	SetFileAttributes (win32_name, (DWORD) win32_name & ~FILE_ATTRIBUTE_READONLY);    }  DWORD lasterr;  lasterr = 0;  for (int i = 0; i < 2; i++)    {      if (DeleteFile (win32_name))	{	  syscall_printf ("DeleteFile succeeded");	  goto ok;	}      lasterr = GetLastError ();      if (i || lasterr != ERROR_ACCESS_DENIED || win32_name.issymlink ())	break;		/* Couldn't delete it. */      /* if access denied, chmod to be writable, in case it is not,	 and try again */      (void) chmod (win32_name, 0777);    }  /* Windows 9x seems to report ERROR_ACCESS_DENIED rather than sharing     violation.  So, set lasterr to ERROR_SHARING_VIOLATION in this case     to simplify tests. */  if (wincap.access_denied_on_delete () && lasterr == ERROR_ACCESS_DENIED      && !win32_name.isremote ())    lasterr = ERROR_SHARING_VIOLATION;  /* Tried to delete file by normal DeleteFile and by resetting protection     and then deleting.  That didn't work.     There are two possible reasons for this:  1) The file may be opened and     Windows is not allowing it to be deleted, or 2) We may not have permissions     to delete the file.     So, first assume that it may be 1) and try to remove the file using the     Windows FILE_FLAG_DELETE_ON_CLOSE semantics.  This seems to work only     spottily on Windows 9x/Me but it does seem to work reliably on NT as     long as the file doesn't exist on a remote drive. */  bool delete_on_close_ok;  delete_on_close_ok  = !win32_name.isremote ()			&& wincap.has_delete_on_close ();  /* Attempt to use "delete on close" semantics to handle removing     a file which may be open. */  HANDLE h;  h = CreateFile (win32_name, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih,		  OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);  if (h == INVALID_HANDLE_VALUE)    {      if (GetLastError () == ERROR_FILE_NOT_FOUND)	goto ok;    }  else    {      CloseHandle (h);      syscall_printf ("CreateFile/CloseHandle succeeded");      /* Everything is fine if the file has disappeared or if we know that the	 FILE_FLAG_DELETE_ON_CLOSE will eventually work. */      if (GetFileAttributes (win32_name) == INVALID_FILE_ATTRIBUTES	  || delete_on_close_ok)	goto ok;	/* The file is either gone already or will eventually be			   deleted by the OS. */    }  /* FILE_FLAGS_DELETE_ON_CLOSE was a bust.  If this is a sharing     violation, then queue the file for deletion when the process     exits.  Otherwise, punt. */  if (lasterr != ERROR_SHARING_VIOLATION)    goto err;  syscall_printf ("couldn't delete file, err %d", lasterr);  /* Add file to the "to be deleted" queue. */  cygwin_shared->delqueue.queue_file (win32_name); /* Success condition. */ ok:  res = 0;  goto done; /* Error condition. */ err:  __seterrno ();  res = -1; done:  syscall_printf ("%d = unlink (%s)", res, ourname);  return res;}extern "C" intremove (const char *ourname){  path_conv win32_name (ourname, PC_SYM_NOFOLLOW | PC_FULL);  if (win32_name.error)    {      set_errno (win32_name.error);      syscall_printf ("-1 = remove (%s)", ourname);      return -1;    }  return win32_name.isdir () ? rmdir (ourname) : unlink (ourname);}extern "C" pid_tgetpid (){  return myself->pid;}extern "C" pid_t_getpid_r (struct _reent *){  return getpid ();}/* getppid: POSIX 4.1.1.1 */extern "C" pid_tgetppid (){  return myself->ppid;}/* setsid: POSIX 4.3.2.1 */extern "C" pid_tsetsid (void){  vfork_save *vf = vfork_storage.val ();  /* This is a horrible, horrible kludge */  if (vf && vf->pid < 0)    {      pid_t pid = fork ();      if (pid > 0)	{	  syscall_printf ("longjmping due to vfork");	  vf->restore_pid (pid);	}      /* assuming that fork was successful */    }  if (myself->pgid != myself->pid)    {      if (myself->ctty == TTY_CONSOLE	  && !cygheap->fdtab.has_console_fds ()	  && !check_pty_fds ())	FreeConsole ();      myself->ctty = -1;      myself->sid = getpid ();      myself->pgid = getpid ();      syscall_printf ("sid %d, pgid %d, ctty %d", myself->sid, myself->pgid, myself->ctty);      return myself->sid;    }  set_errno (EPERM);  return -1;}extern "C" pid_tgetsid (pid_t pid){  pid_t res;  if (!pid)    res = myself->sid;  else    {      pinfo p (pid);      if (p)	res = p->sid;      else	{	  set_errno (ESRCH);	  res = -1;	}    }  return res;}extern "C" ssize_tread (int fd, void *ptr, size_t len){  const struct iovec iov =    {      iov_base: ptr,      iov_len: len    };  return readv (fd, &iov, 1);}extern "C" ssize_t _read (int, void *, size_t)  __attribute__ ((alias ("read")));extern "C" ssize_twrite (int fd, const void *ptr, size_t len){  const struct iovec iov =    {      iov_base: (void *) ptr,	// const_cast      iov_len: len    };  return writev (fd, &iov, 1);}extern "C" ssize_t _write (int fd, const void *ptr, size_t len)  __attribute__ ((alias ("write")));extern "C" ssize_treadv (int fd, const struct iovec *const iov, const int iovcnt){  extern int sigcatchers;  const int e = get_errno ();  int res = -1;  const ssize_t tot = check_iovec_for_read (iov, iovcnt);  if (tot <= 0)    {      res = tot;      goto done;    }  while (1)    {      sig_dispatch_pending (0);      sigframe thisframe (mainthread);      cygheap_fdget cfd (fd);      if (cfd < 0)	break;      if ((cfd->get_flags () & O_ACCMODE) == O_WRONLY)	{	  set_errno (EBADF);	  break;	}      DWORD wait = cfd->is_nonblocking () ? 0 : INFINITE;      /* Could block, so let user know we at least got here.  */      syscall_printf ("readv (%d, %p, %d) %sblocking, sigcatchers %d",		      fd, iov, iovcnt, wait ? "" : "non", sigcatchers);      if (wait && (!cfd->is_slow () || cfd->get_r_no_interrupt ()))	debug_printf ("no need to call ready_for_read");      else if (!cfd->ready_for_read (fd, wait))	{	  res = -1;	  goto out;	}      /* FIXME: This is not thread safe.  We need some method to	 ensure that an fd, closed in another thread, aborts I/O	 operations. */      if (!cfd.isopen ())	break;      /* Check to see if this is a background read from a "tty",	 sending a SIGTTIN, if appropriate */      res = cfd->bg_check (SIGTTIN);      if (!cfd.isopen ())	{	  res = -1;	  break;	}      if (res > bg_eof)	{	  myself->process_state |= PID_TTYIN;	  if (!cfd.isopen ())	    {	      res = -1;	      break;	    }	  res = cfd->readv (iov, iovcnt, tot);	  myself->process_state &= ~PID_TTYIN;	}    out:      if (res >= 0 || get_errno () != EINTR || !thisframe.call_signal_handler ())	break;      set_errno (e);    }done:  syscall_printf ("%d = readv (%d, %p, %d), errno %d", res, fd, iov, iovcnt,		  get_errno ());  MALLOC_CHECK;  return res;}extern "C" ssize_twritev (const int fd, const struct iovec *const iov, const int iovcnt){  int res = -1;  sig_dispatch_pending (0);  const ssize_t tot = check_iovec_for_write (iov, iovcnt);  sigframe thisframe (mainthread);  cygheap_fdget cfd (fd);  if (cfd < 0)    goto done;  if (tot <= 0)    {      res = tot;      goto done;    }  if ((cfd->get_flags () & O_ACCMODE) == O_RDONLY)    {      set_errno (EBADF);      goto done;    }  /* Could block, so let user know we at least got here.  */  if (fd == 1 || fd == 2)    paranoid_printf ("writev (%d, %p, %d)", fd, iov, iovcnt);  else    syscall_printf  ("writev (%d, %p, %d)", fd, iov, iovcnt);  res = cfd->bg_check (SIGTTOU);  if (res > bg_eof)    {      myself->process_state |= PID_TTYOU;      res = cfd->writev (iov, iovcnt, tot);      myself->process_state &= ~PID_TTYOU;    }done:  if (fd == 1 || fd == 2)    paranoid_printf ("%d = write (%d, %p, %d), errno %d",		     res, fd, iov, iovcnt, get_errno ());  else    syscall_printf ("%d = write (%d, %p, %d), errno %d",		    res, fd, iov, iovcnt, get_errno ());  MALLOC_CHECK;  return res;}/* _open *//* newlib's fcntl.h defines _open as taking variable args so we must   correspond.  The third arg if it exists is: mode_t mode. */extern "C" intopen (const char *unix_path, int flags, ...){  int res = -1;  va_list ap;  mode_t mode = 0;  sig_dispatch_pending (0);  sigframe thisframe (mainthread);  syscall_printf ("open (%s, %p)", unix_path, flags);  if (!check_null_empty_str_errno (unix_path))    {      /* check for optional mode argument */      va_start (ap, flags);      mode = va_arg (ap, mode_t);      va_end (ap);      fhandler_base *fh;      cygheap_fdnew fd;      if (fd >= 0)	{	  path_conv pc;	  if (!(fh = cygheap->fdtab.build_fhandler_from_name (fd, unix_path,							      NULL, pc)))	    res = -1;		// errno already set	  else if (!fh->open (&pc, flags, (mode & 07777) & ~cygheap->umask))	    {	      fd.release ();	      res = -1;	    }	  else if ((res = fd) <= 2)	    set_std_handle (res);	}    }  syscall_printf ("%d = open (%s, %p)", res, unix_path, flags);  return res;}extern "C" int _open (const char *, int flags, ...)  __attribute__ ((alias ("open")));extern "C" __off64_tlseek64 (int fd, __off64_t pos, int dir){  __off64_t res;  sigframe thisframe (mainthread);  if (dir != SEEK_SET && dir != SEEK_CUR && dir != SEEK_END)    {      set_errno (EINVAL);      res = -1;    }  else    {      cygheap_fdget cfd (fd);      if (cfd >= 0)	res = cfd->lseek (pos, dir);      else	res = -1;    }  syscall_printf ("%d = lseek (%d, %D, %d)", res, fd, pos, dir);  return res;}extern "C" __off32_tlseek (int fd, __off32_t pos, int dir){  return lseek64 (fd, (__off64_t) pos, dir);}extern "C" __off32_t _lseek (int, __off32_t, int)  __attribute__ ((alias ("lseek")));extern "C" intclose (int fd){  int res;  sigframe thisframe (mainthread);  syscall_printf ("close (%d)", fd);  MALLOC_CHECK;  cygheap_fdget cfd (fd, true);  if (cfd < 0)    res = -1;  else    {      res = cfd->close ();      cfd.release ();    }  syscall_printf ("%d = close (%d)", res, fd);  MALLOC_CHECK;  return res;}extern "C" int _close (int) __attribute__ ((alias ("close")));extern "C" intisatty (int fd){  int res;  sigframe thisframe (mainthread);  cygheap_fdget cfd (fd);  if (cfd < 0)    res = 0;  else    res = cfd->is_tty ();  syscall_printf ("%d = isatty (%d)", res, fd);  return res;}/* Under NT, try to make a hard link using backup API.  If that   fails or we are Win 95, just copy the file.   FIXME: We should actually be checking partition type, not OS.   Under NTFS, we should support hard links.  On FAT partitions,   we should just copy the file.*/extern "C" intlink (const char *a, const char *b){  int res = -1;  sigframe thisframe (mainthread);  path_conv real_a (a, PC_SYM_FOLLOW | PC_FULL);  path_conv real_b (b, PC_SYM_NOFOLLOW | PC_FULL);  if (real_a.error)    {      set_errno (real_a.error);      goto done;    }  if (real_b.error)    {      set_errno (real_b.case_clash ? ECASECLASH : real_b.error);      goto done;

⌨️ 快捷键说明

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