diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2000-10-04 17:08:46 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2000-10-04 17:08:46 +0000 |
commit | f4f898aca065b74b476af4c11423695fefd1de3c (patch) | |
tree | 2a408076bee9adb54477c6b1a09a9e6b2e46c859 /winsup/cygwin/fhandler_mem.cc | |
parent | 52b5a9715669a0cc9aa105ac5dcc486188a515c1 (diff) | |
download | cygnal-f4f898aca065b74b476af4c11423695fefd1de3c.tar.gz cygnal-f4f898aca065b74b476af4c11423695fefd1de3c.tar.bz2 cygnal-f4f898aca065b74b476af4c11423695fefd1de3c.zip |
* fhandler.h (fhandler_dev_mem): Add method `init'. Add members
`mem_size' and `init_phase'.
* fhandler_mem.cc (init): New function to figure out the size of
the physical memory.
(open): Add checking for illegal flags. Change usage of access mode.
(write): Add intended functionality.
(read): Add parameter checking. Eliminate page size constant. Use
getpagesize() instead. Don't touch errno and don't create debug output
while init() is running.
(lseek): Add bounds checking. Fix SEEK_END.
(fstat): Eliminate page size constant. Use getpagesize() instead.
(dup): Add intended functionality.
Diffstat (limited to 'winsup/cygwin/fhandler_mem.cc')
-rw-r--r-- | winsup/cygwin/fhandler_mem.cc | 140 |
1 files changed, 124 insertions, 16 deletions
diff --git a/winsup/cygwin/fhandler_mem.cc b/winsup/cygwin/fhandler_mem.cc index 50370d876..10213e656 100644 --- a/winsup/cygwin/fhandler_mem.cc +++ b/winsup/cygwin/fhandler_mem.cc @@ -36,7 +36,7 @@ ULONG NTAPI RtlNtStatusToDosError(NTSTATUS); fhandler_dev_mem::fhandler_dev_mem (const char *name, int) : fhandler_base (FH_MEM, name), - pos(0UL) + init_phase(false) { } @@ -44,6 +44,30 @@ fhandler_dev_mem::~fhandler_dev_mem (void) { } +void +fhandler_dev_mem::init () +{ + long page_size = getpagesize (); + char buf[1]; + + init_phase = true; + mem_size = pos = 1 << 30; + for (off_t afct = 1 << 29; afct >= page_size; afct >>= 1) + { + if (read (buf, 1) > 0) + pos += afct; + else + { + if (pos < mem_size) + mem_size = pos; + pos -= afct; + } + } + pos = 0; + debug_printf ("MemSize: %d MB", mem_size >>= 20); + init_phase = false; +} + int fhandler_dev_mem::open (const char *, int flags, mode_t) { @@ -54,21 +78,38 @@ fhandler_dev_mem::open (const char *, int flags, mode_t) return 0; } + /* Check for illegal flags. */ + if (flags & (O_APPEND | O_TRUNC | O_EXCL)) + { + set_errno (EINVAL); + return 0; + } + UNICODE_STRING memstr; RtlInitUnicodeString (&memstr, L"\\device\\physicalmemory"); OBJECT_ATTRIBUTES attr; InitializeObjectAttributes(&attr, &memstr, OBJ_CASE_INSENSITIVE, NULL, NULL); + ACCESS_MASK section_access; if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY) - set_access (SECTION_MAP_READ); + { + set_access (GENERIC_READ); + section_access = SECTION_MAP_READ; + } else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY) - set_access (SECTION_MAP_WRITE); + { + set_access (GENERIC_WRITE); + section_access = SECTION_MAP_READ | SECTION_MAP_WRITE; + } else - set_access (SECTION_MAP_READ | SECTION_MAP_WRITE); + { + set_access (GENERIC_READ | GENERIC_WRITE); + section_access = SECTION_MAP_READ | SECTION_MAP_WRITE; + } HANDLE mem; - NTSTATUS ret = NtOpenSection (&mem, get_access (), &attr); + NTSTATUS ret = NtOpenSection (&mem, section_access, &attr); if (!NT_SUCCESS(ret)) { __seterrno_from_win_error (RtlNtStatusToDosError (ret)); @@ -77,26 +118,78 @@ fhandler_dev_mem::open (const char *, int flags, mode_t) } set_io_handle (mem); + init (); return 1; } int -fhandler_dev_mem::write (const void *ptr, size_t len) +fhandler_dev_mem::write (const void *ptr, size_t ulen) { - set_errno (ENOSYS); - return -1; + if (!ulen || pos >= mem_size) + return 0; + + if (!(get_access () & GENERIC_WRITE)) + { + set_errno (EINVAL); + return -1; + } + + if (pos + ulen > mem_size) + ulen = mem_size - pos; + + PHYSICAL_ADDRESS phys; + NTSTATUS ret; + void *viewmem = NULL; + DWORD len = ulen + getpagesize () - 1; + + phys.QuadPart = (ULONGLONG) pos; + if ((ret = NtMapViewOfSection (get_handle (), + INVALID_HANDLE_VALUE, + &viewmem, + 0L, + len, + &phys, + &len, + ViewShare, + 0, + PAGE_READONLY)) != STATUS_SUCCESS) + { + __seterrno_from_win_error (RtlNtStatusToDosError (ret)); + return -1; + } + + memcpy ((char *) viewmem + (pos - phys.QuadPart), ptr, ulen); + + if (!NT_SUCCESS(ret = NtUnmapViewOfSection (INVALID_HANDLE_VALUE, viewmem))) + { + __seterrno_from_win_error (RtlNtStatusToDosError (ret)); + return -1; + } + + pos += ulen; + + return ulen; } int fhandler_dev_mem::read (void *ptr, size_t ulen) { - if (!ulen) + if (!ulen || pos >= mem_size) return 0; + if (!(get_access () & GENERIC_READ)) + { + set_errno (EINVAL); + return -1; + } + + if (pos + ulen > mem_size) + ulen = mem_size - pos; + PHYSICAL_ADDRESS phys; NTSTATUS ret; void *viewmem = NULL; - DWORD len = ulen + 4095; + DWORD len = ulen + getpagesize () - 1; phys.QuadPart = (ULONGLONG) pos; if ((ret = NtMapViewOfSection (get_handle (), @@ -110,7 +203,8 @@ fhandler_dev_mem::read (void *ptr, size_t ulen) 0, PAGE_READONLY)) != STATUS_SUCCESS) { - __seterrno_from_win_error (RtlNtStatusToDosError (ret)); + if (!init_phase) /* Don't want to flood debug output with init crap. */ + __seterrno_from_win_error (RtlNtStatusToDosError (ret)); return -1; } @@ -147,8 +241,8 @@ fhandler_dev_mem::lseek (off_t offset, int whence) break; case SEEK_END: - pos = 0; - pos -= offset; + pos = mem_size; + pos += offset; break; default: @@ -156,6 +250,12 @@ fhandler_dev_mem::lseek (off_t offset, int whence) return (off_t) -1; } + if (pos > mem_size) + { + set_errno (EINVAL); + return (off_t) -1; + } + return pos; } @@ -175,7 +275,7 @@ fhandler_dev_mem::fstat (struct stat *buf) S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; buf->st_nlink = 1; - buf->st_blksize = 4096; + buf->st_blksize = getpagesize (); buf->st_dev = buf->st_rdev = get_device () << 8; return 0; @@ -184,8 +284,16 @@ fhandler_dev_mem::fstat (struct stat *buf) int fhandler_dev_mem::dup (fhandler_base *child) { - set_errno (ENOSYS); - return -1; + int ret = fhandler_base::dup (child); + + if (! ret) + { + fhandler_dev_mem *fhc = (fhandler_dev_mem *) child; + + fhc->mem_size = mem_size; + fhc->pos = pos; + } + return ret; } void |