qdevice-heuristics-io.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * Copyright (c) 2015-2017 Red Hat, Inc.
  3. *
  4. * All rights reserved.
  5. *
  6. * Author: Jan Friesse (jfriesse@redhat.com)
  7. *
  8. * This software licensed under BSD license, the text of which follows:
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * - Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. * - Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. * - Neither the name of the Red Hat, Inc. nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  23. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  26. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  32. * THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include <limits.h>
  35. #include <errno.h>
  36. #include <signal.h>
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <unistd.h>
  40. #include "qdevice-heuristics-io.h"
  41. #define QDEVICE_HEURISTICS_IO_BUFFER_SIZE 256
  42. ssize_t
  43. qdevice_heuristics_io_blocking_write(int fd, const void *buf, size_t count)
  44. {
  45. ssize_t bytes_written;
  46. ssize_t tmp_bytes_written;
  47. bytes_written = 0;
  48. do {
  49. tmp_bytes_written = write(fd, (const char *)buf + bytes_written,
  50. (count - bytes_written > SSIZE_MAX) ? SSIZE_MAX : count - bytes_written);
  51. if (tmp_bytes_written == -1) {
  52. if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
  53. return (-1);
  54. }
  55. } else {
  56. bytes_written += tmp_bytes_written;
  57. }
  58. } while ((size_t)bytes_written != count);
  59. return (bytes_written);
  60. }
  61. /*
  62. * 1 Full line readed (at least one \n found)
  63. * 0 Partial read (no error)
  64. * -1 End of connection
  65. * -2 Buffer too long
  66. * -3 Unhandled error
  67. */
  68. int
  69. qdevice_heuristics_io_read(int fd, struct dynar *dest)
  70. {
  71. char buf[QDEVICE_HEURISTICS_IO_BUFFER_SIZE];
  72. ssize_t readed;
  73. int res;
  74. size_t zi;
  75. res = 0;
  76. readed = read(fd, buf, sizeof(buf));
  77. if (readed > 0) {
  78. if (dynar_cat(dest, buf, readed) == -1) {
  79. res = -2;
  80. goto exit_err;
  81. }
  82. for (zi = 0; zi < (size_t)readed; zi++) {
  83. if (buf[zi] == '\n') {
  84. res = 1;
  85. }
  86. }
  87. }
  88. if (readed == 0) {
  89. res = -1;
  90. }
  91. if (readed < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
  92. res = -3;
  93. }
  94. exit_err:
  95. return (res);
  96. }
  97. /*
  98. * 1 All data succesfully sent
  99. * 0 Partial send (no error)
  100. * -1 send returned 0,
  101. * -2 Unhandled error
  102. */
  103. int
  104. qdevice_heuristics_io_write(int fd, const struct dynar *msg, size_t *already_sent_bytes)
  105. {
  106. ssize_t sent;
  107. size_t to_send;
  108. int res;
  109. res = 0;
  110. to_send = dynar_size(msg) - *already_sent_bytes;
  111. if (to_send > QDEVICE_HEURISTICS_IO_BUFFER_SIZE) {
  112. to_send = QDEVICE_HEURISTICS_IO_BUFFER_SIZE;
  113. }
  114. sent = write(fd, dynar_data(msg) + *already_sent_bytes,
  115. to_send);
  116. if (sent > 0) {
  117. *already_sent_bytes += sent;
  118. if (*already_sent_bytes == dynar_size(msg)) {
  119. return (1);
  120. }
  121. }
  122. if (sent == 0) {
  123. res = -1;
  124. }
  125. if (sent < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
  126. res = -2;
  127. }
  128. return (res);
  129. }