/// Calls the given fcntl. Use FCNTLID macro to pass in both \p name and \p request. int fstream::fcntl (const char* rname, int request, long argument) { int rv = ::fcntl (m_fd, request, argument); if (rv < 0) set_and_throw (failbit, rname); return (rv); }
/// Memory-maps the file and returns a link to it. memlink fstream::mmap (off_t n, off_t offset) { void* result = ::mmap (NULL, n, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, offset); if (result == MAP_FAILED) set_and_throw (failbit, "mmap"); return (memlink (result, n)); }
/// Moves the current file position to \p n. off_t fstream::seek (off_t n, seekdir whence) { off_t p = lseek (m_fd, n, whence); if (p < 0) set_and_throw (failbit, "seek"); return (p); }
/// Attaches to the given \p nfd. void fstream::attach (int nfd, const char* filename) { assert (filename && "Don't do that"); m_Filename = filename; clear (goodbit); if (nfd < 0) set_and_throw (badbit, "open"); close(); m_fd = nfd; }
/// Reads at most \p n bytes into \p p, stopping when it feels like it. off_t fstream::readsome (void* p, off_t n) { ssize_t brn; do { brn = ::read (m_fd, p, n); } while ((brn < 0) & (errno == EINTR)); if (brn > 0) return (brn); else if ((brn < 0) & (errno != EAGAIN)) set_and_throw (failbit, "read"); else if (!brn && ios_base::set_and_throw (eofbit | failbit)) throw stream_bounds_exception ("read", name(), pos(), n, 0); return (0); }
/// Closes the file and throws on error. void fstream::close (void) { if (m_fd < 0) return; // already closed while (::close(m_fd)) { if (errno != EINTR) { set_and_throw (badbit | failbit, "close"); break; } } detach(); }
/// Reads at most \p n bytes into \p p, stopping when it feels like it. off_t fstream::readsome (void* p, off_t n) { ssize_t brn; do { brn = ::read (m_fd, p, n); } while (brn < 0 && errno == EINTR); if (brn > 0) return (brn); if (brn < 0 && errno != EAGAIN) set_and_throw (failbit, "read"); if (!brn && ios_base::set_and_throw (eofbit | failbit)) #if PLATFORM_ANDROID printf("stream_bounds_exception\n"); #else /* !PLATFORM_ANDROID */ throw stream_bounds_exception ("read", name(), pos(), n, 0); #endif return (0); }
/// Writes \p n bytes from \p p. off_t fstream::write (const void* p, off_t n) { off_t btw (n); while (btw) { const off_t bw (n - btw); ssize_t bwn = ::write (m_fd, advance(p,bw), btw); if (bwn > 0) btw -= bwn; else if (!bwn) { if (ios_base::set_and_throw (eofbit | failbit)) throw stream_bounds_exception ("write", name(), pos() - bw, n, bw); break; } else if (errno != EINTR) { if (errno != EAGAIN) set_and_throw (failbit, "write"); break; } } return (n - btw); }
/// Checks that \p n bytes are available in the stream, or else throws. void ios_base::overrun (const char* op, const char* type, uint32_t n, uint32_t pos, uint32_t rem) { if (set_and_throw (rem ? failbit : (failbit | eofbit))) throw exception("stream_bounds_exception"); // throw stream_bounds_exception (op, type, pos, n, rem); }
/// Synchronizes a memory-mapped area. void fstream::msync (memlink& l) { if (::msync (l.data(), l.size(), MS_ASYNC | MS_INVALIDATE)) set_and_throw (failbit, "msync"); }
/// Unmaps a memory-mapped area. void fstream::munmap (memlink& l) { if (::munmap (l.data(), l.size())) set_and_throw (failbit, "munmap"); l.unlink(); }
/// Synchronizes the file's data and status with the disk. void fstream::sync (void) { if (fsync (m_fd)) set_and_throw (badbit | failbit, "sync"); }
/// Closes the file and throws on error. void fstream::close (void) { if (m_fd >= 0 && ::close(m_fd)) set_and_throw (badbit | failbit, "close"); detach(); }