mph_size_t Mono_Posix_Stdlib_fread (unsigned char *ptr, mph_size_t size, mph_size_t nmemb, void *stream) { mph_return_if_size_t_overflow (size); mph_return_if_size_t_overflow (nmemb); return fread (ptr, (size_t) size, (size_t) nmemb, (FILE*) stream); }
int Mono_Posix_Syscall_munlock (void *start, mph_size_t len) { mph_return_if_size_t_overflow (len); return munlock (start, (size_t) len); }
int Mono_Posix_Syscall_munmap (void *start, mph_size_t length) { mph_return_if_size_t_overflow (length); return munmap (start, (size_t) length); }
int Mono_Posix_Syscall_mincore (void *start, mph_size_t length, unsigned char *vec) { mph_return_if_size_t_overflow (length); return mincore (start, (size_t) length, (void*)vec); }
gint32 Mono_Posix_Syscall_posix_fallocate (gint32 fd, mph_off_t offset, mph_size_t len) { mph_return_if_off_t_overflow (offset); mph_return_if_size_t_overflow (len); return posix_fallocate (fd, (off_t) offset, (size_t) len); }
gint32 Mono_Posix_Syscall_posix_madvise (void *addr, mph_size_t len, gint32 advice) { mph_return_if_size_t_overflow (len); if (Mono_Posix_FromPosixMadviseAdvice (advice, &advice) == -1) return -1; return posix_madvise (addr, (size_t) len, advice); }
int Mono_Posix_Syscall_msync (void *start, mph_size_t len, int flags) { int _flags; mph_return_if_size_t_overflow (len); if (Mono_Posix_FromMsyncFlags (flags, &_flags) == -1) return -1; return msync (start, (size_t) len, _flags); }
int Mono_Posix_Syscall_mprotect (void *start, mph_size_t len, int prot) { int _prot; mph_return_if_size_t_overflow (len); if (Mono_Posix_FromMmapProts (prot, &_prot) == -1) return -1; return mprotect (start, (size_t) len, _prot); }
/* * Translate the GNU semantics to the XPG semantics. * * From reading the (RH9-using) GLibc 2.3.2 sysdeps/generic/_strerror.c, * we can say the following: * - If errnum is a valid error number, a pointer to a constant string is * returned. Thus, the prototype *lies* (it's not really a char*). * `buf' is unchanged (WTF?). * - If errnum is an *invalid* error number, an error message is copied * into `buf' and `buf' is returned. The error message returned is * "Unknown error %i", where %i is the input errnum. * * Meanwhile, XPG always modifies `buf' if there's enough space, and either * returns 0 (success) or -1 (error) with errno = EINVAL (bad errnum) or * ERANGE (`buf' isn't big enough). Also, GLibc 2.3.3 (which has the XPG * version) first checks the validity of errnum first, then does the copy. * * Assuming that the GNU implementation doesn't change much (ha!), we can * check for EINVAL by comparing the strerror_r return to `buf', OR by * comparing the return value to "Uknown error". (This assumes that * strerror_r will always only return the input buffer for errors.) * * Check for ERANGE by comparing the string length returned by strerror_r to * `n'. * * Then pray that this actually works... */ gint32 Mono_Posix_Syscall_strerror_r (int errnum, char *buf, mph_size_t n) { char *r; char ebuf [sizeof(mph_unknown)]; size_t len; size_t blen; mph_return_if_size_t_overflow (n); /* first, check for valid errnum */ #if PLATFORM_ANDROID /* Android NDK defines _GNU_SOURCE but strerror_r follows the XSI semantics * not the GNU one. XSI version returns an integer, as opposed to the GNU one * which returns pointer to the buffer. */ if (strerror_r (errnum, ebuf, sizeof(ebuf)) == -1) { /* XSI strerror_r will return -1 if errno is set, but if we leave the value * alone it breaks Mono.Posix StdioFileStream tests, so we'll ignore the value * and set errno as below */ errno = EINVAL; return -1; } r = ebuf; #else r = strerror_r (errnum, ebuf, sizeof(ebuf)); #endif if (!r) { errno = EINVAL; return -1; } len = strlen (r); if (r == ebuf || strncmp (r, mph_unknown, mph_min (len, sizeof(mph_unknown))) == 0) { errno = EINVAL; return -1; } /* valid errnum (we hope); is buffer big enough? */ blen = (size_t) n; if ((len+1) > blen) { errno = ERANGE; return -1; } strncpy (buf, r, len); buf[len] = '\0'; return 0; }
gint32 Mono_Posix_Stdlib_snprintf (char *s, mph_size_t n, char *format, ...) { va_list ap; gint32 r; mph_return_if_size_t_overflow (n); va_start (ap, format); r = vsnprintf (s, (size_t) n, format, ap); va_end (ap); return r; }
mph_size_t Mono_Posix_Stdlib_fwrite (unsigned char *ptr, mph_size_t size, mph_size_t nmemb, void *stream) { mph_return_if_size_t_overflow (size); mph_return_if_size_t_overflow (nmemb); size_t ret = fwrite (ptr, (size_t) size, (size_t) nmemb, (FILE*) stream); #ifdef HOST_WIN32 // Workaround for a particular weirdness on Windows triggered by the // StdioFileStreamTest.Write() test method. The test writes 15 bytes to a // file, then rewinds the file pointer and reads the same bytes. It then // writes 15 additional bytes to the file. This second write fails on // Windows with 0 returned from fwrite(). Calling fseek() followed by a retry // of fwrite() like we do here fixes the issue. if (ret != nmemb) { fseek (stream, 0, SEEK_CUR); ret = fwrite (ptr + (ret * nmemb), (size_t) size, (size_t) nmemb - ret, (FILE*) stream); } #endif return ret; }
int Mono_Posix_Syscall_remap_file_pages (void *start, mph_size_t size, int prot, mph_ssize_t pgoff, int flags) { int _prot, _flags; mph_return_if_size_t_overflow (size); mph_return_if_ssize_t_overflow (pgoff); if (Mono_Posix_FromMmapProts (prot, &_prot) == -1) return -1; if (Mono_Posix_FromMmapFlags (flags, &_flags) == -1) return -1; return remap_file_pages (start, (size_t) size, _prot, (ssize_t) pgoff, _flags); }
gint32 Mono_Posix_Syscall_strerror_r (int errnum, char *buf, mph_size_t n) { mph_return_if_size_t_overflow (n); return strerror_r (errnum, buf, (size_t) n); }
gint32 Mono_Posix_Stdlib_setvbuf (void* stream, void *buf, int mode, mph_size_t size) { mph_return_if_size_t_overflow (size); return setvbuf (stream, (char *) buf, mode, (size_t) size); }