4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-01-15 19:09:58 +08:00
newlib-cygwin/winsup/cygwin/fhandler_mem.cc
Yaakov Selkowitz 1f36328e7f Throughout, (mainly in fhandler*) fix remaining gcc 4.7 mismatch
warnings between regparm definitions and declarations.
* smallprint.cc (__small_vswprintf): Conditionalize declaration and
setting of l_opt for only x86_64.
* spawn.cc (child_info_spawn::worker): Remove unused 'pid' variable.
* thread.cc (verifyable_object_isvalid): Temporarily define as
non-inline with gcc 4.7+, regardless of target.
2013-05-01 01:20:37 +00:00

259 lines
5.5 KiB
C++

/* fhandler_mem.cc. See fhandler.h for a description of the fhandler classes.
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011,
2012, 2013 Red Hat, Inc.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
#include <unistd.h>
#include "cygerrno.h"
#include "path.h"
#include "fhandler.h"
#include "ntdll.h"
/**********************************************************************/
/* fhandler_dev_mem */
fhandler_dev_mem::fhandler_dev_mem ()
: fhandler_base ()
{
}
fhandler_dev_mem::~fhandler_dev_mem ()
{
}
int
fhandler_dev_mem::open (int flags, mode_t)
{
NTSTATUS status;
if (!wincap.has_physical_mem_access ())
{
set_errno (EACCES);
debug_printf ("%s is accessible under XP only", dev ().name);
return 0;
}
if (dev () == FH_MEM) /* /dev/mem */
{
SYSTEM_BASIC_INFORMATION sbi;
status = NtQuerySystemInformation (SystemBasicInformation, (PVOID) &sbi,
sizeof sbi, NULL);
if (NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
debug_printf("NtQuerySystemInformation: status %p", status);
mem_size = 0;
}
else
mem_size = (SIZE_T) sbi.PhysicalPageSize
* (SIZE_T) sbi.NumberOfPhysicalPages;
debug_printf ("MemSize: %ld MB", mem_size >> 20);
}
else if (dev () == FH_KMEM) /* /dev/kmem - Not yet supported */
{
mem_size = 0;
debug_printf ("KMemSize: %ld MB", mem_size >> 20);
}
else if (dev () == FH_PORT) /* /dev/port == First 64K of /dev/mem */
{
mem_size = 65536;
debug_printf ("PortSize: 64 KB");
}
else
{
mem_size = 0;
debug_printf ("Illegal minor number");
}
/* Check for illegal flags. */
if (flags & (O_APPEND | O_TRUNC | O_EXCL))
{
set_errno (EINVAL);
return 0;
}
OBJECT_ATTRIBUTES attr;
InitializeObjectAttributes (&attr, &ro_u_pmem,
OBJ_CASE_INSENSITIVE
| (flags & O_CLOEXEC ? 0 : OBJ_INHERIT),
NULL, NULL);
ACCESS_MASK section_access;
if ((flags & O_ACCMODE) == O_RDONLY)
{
set_access (GENERIC_READ);
section_access = SECTION_MAP_READ;
}
else if ((flags & O_ACCMODE) == O_WRONLY)
{
set_access (GENERIC_WRITE);
section_access = SECTION_MAP_READ | SECTION_MAP_WRITE;
}
else
{
set_access (GENERIC_READ | GENERIC_WRITE);
section_access = SECTION_MAP_READ | SECTION_MAP_WRITE;
}
HANDLE mem;
status = NtOpenSection (&mem, section_access, &attr);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
set_io_handle (NULL);
return 0;
}
set_io_handle (mem);
set_open_status ();
return 1;
}
ssize_t __stdcall
fhandler_dev_mem::write (const void *ptr, size_t ulen)
{
if (!ulen || pos >= (off_t) mem_size)
return 0;
if (!(get_access () & GENERIC_WRITE))
{
set_errno (EINVAL);
return -1;
}
if (pos + ulen > mem_size)
ulen = (off_t) mem_size - pos;
PHYSICAL_ADDRESS phys;
NTSTATUS status;
void *viewmem = NULL;
SIZE_T len = ulen + wincap.page_size () - 1;
phys.QuadPart = (ULONGLONG) pos;
status = NtMapViewOfSection (get_handle (), INVALID_HANDLE_VALUE, &viewmem,
0L, len, &phys, &len, ViewShare, 0,
PAGE_READONLY);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
return -1;
}
memcpy ((char *) viewmem + (pos - phys.QuadPart), ptr, ulen);
status = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, viewmem);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
return -1;
}
pos += ulen;
return ulen;
}
void __reg3
fhandler_dev_mem::read (void *ptr, size_t& ulen)
{
if (!ulen || pos >= (off_t) mem_size)
{
ulen = 0;
return;
}
if (!(get_access () & GENERIC_READ))
{
set_errno (EINVAL);
ulen = (size_t) -1;
return;
}
if (pos + ulen > mem_size)
ulen = (off_t) mem_size - pos;
PHYSICAL_ADDRESS phys;
NTSTATUS status;
void *viewmem = NULL;
SIZE_T len = ulen + wincap.page_size () - 1;
phys.QuadPart = (ULONGLONG) pos;
status = NtMapViewOfSection (get_handle (), INVALID_HANDLE_VALUE, &viewmem,
0L, len, &phys, &len, ViewShare, 0,
PAGE_READONLY);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
ulen = (size_t) -1;
return;
}
memcpy (ptr, (char *) viewmem + (pos - phys.QuadPart), ulen);
status = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, viewmem);
if (!NT_SUCCESS (status))
{
__seterrno_from_nt_status (status);
ulen = (size_t) -1;
return;
}
pos += ulen;
}
off_t
fhandler_dev_mem::lseek (off_t offset, int whence)
{
switch (whence)
{
case SEEK_SET:
pos = offset;
break;
case SEEK_CUR:
pos += offset;
break;
case SEEK_END:
pos = (off_t) mem_size;
pos += offset;
break;
default:
set_errno (EINVAL);
return ILLEGAL_SEEK;
}
if (pos > (off_t) mem_size)
{
set_errno (EINVAL);
return ILLEGAL_SEEK;
}
return pos;
}
int __reg2
fhandler_dev_mem::fstat (struct stat *buf)
{
fhandler_base::fstat (buf);
buf->st_blksize = wincap.page_size ();
if (is_auto_device ())
{
buf->st_mode = S_IFCHR;
if (wincap.has_physical_mem_access ())
buf->st_mode |= S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH;
}
return 0;
}