__stdio_write.c 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. #include "stdio_impl.h"
  2. #include <pthread.h>
  3. static void cleanup(void *p)
  4. {
  5. FILE *f = p;
  6. if (!f->lockcount) __unlockfile(f);
  7. }
  8. size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
  9. {
  10. struct iovec iovs[2] = {
  11. { .iov_base = f->wbase, .iov_len = f->wpos-f->wbase },
  12. { .iov_base = (void *)buf, .iov_len = len }
  13. };
  14. struct iovec *iov = iovs;
  15. size_t rem = iov[0].iov_len + iov[1].iov_len;
  16. int iovcnt = 2;
  17. ssize_t cnt;
  18. for (;;) {
  19. if (libc.main_thread) {
  20. pthread_cleanup_push(cleanup, f);
  21. cnt = syscall_cp(SYS_writev, f->fd, iov, iovcnt);
  22. pthread_cleanup_pop(0);
  23. } else {
  24. cnt = syscall(SYS_writev, f->fd, iov, iovcnt);
  25. }
  26. if (cnt == rem) {
  27. f->wend = f->buf + f->buf_size;
  28. f->wpos = f->wbase = f->buf;
  29. return len;
  30. }
  31. if (cnt < 0) {
  32. f->wpos = f->wbase = f->wend = 0;
  33. f->flags |= F_ERR;
  34. return iovcnt == 2 ? 0 : len-iov[0].iov_len;
  35. }
  36. rem -= cnt;
  37. if (cnt > iov[0].iov_len) {
  38. f->wpos = f->wbase = f->buf;
  39. cnt -= iov[0].iov_len;
  40. iov++; iovcnt--;
  41. } else if (iovcnt == 2) {
  42. f->wbase += cnt;
  43. }
  44. iov[0].iov_base = (char *)iov[0].iov_base + cnt;
  45. iov[0].iov_len -= cnt;
  46. }
  47. }