netstr.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /*
  2. * Part of Very Secure FTPd
  3. * Licence: GPL v2
  4. * Author: Chris Evans
  5. * netstr.c
  6. *
  7. * The netstr interface extends the standard string interface, adding
  8. * functions which can cope safely with building strings from the network,
  9. * and send them out too.
  10. */
  11. #include "netstr.h"
  12. #include "str.h"
  13. #include "sysstr.h"
  14. #include "utility.h"
  15. #include "sysutil.h"
  16. int
  17. str_netfd_alloc(struct vsf_session* p_sess,
  18. struct mystr* p_str,
  19. char term,
  20. char* p_readbuf,
  21. unsigned int maxlen,
  22. str_netfd_read_t p_peekfunc,
  23. str_netfd_read_t p_readfunc)
  24. {
  25. int retval;
  26. unsigned int bytes_read;
  27. unsigned int i;
  28. char* p_readpos = p_readbuf;
  29. unsigned int left = maxlen;
  30. str_empty(p_str);
  31. while (1)
  32. {
  33. if (p_readpos + left != p_readbuf + maxlen)
  34. {
  35. bug("poor buffer accounting in str_netfd_alloc");
  36. }
  37. /* Did we hit the max? */
  38. if (left == 0)
  39. {
  40. return -1;
  41. }
  42. retval = (*p_peekfunc)(p_sess, p_readpos, left);
  43. if (vsf_sysutil_retval_is_error(retval))
  44. {
  45. die("vsf_sysutil_recv_peek");
  46. }
  47. else if (retval == 0)
  48. {
  49. return 0;
  50. }
  51. bytes_read = (unsigned int) retval;
  52. /* Search for the terminator */
  53. for (i=0; i < bytes_read; i++)
  54. {
  55. if (p_readpos[i] == term)
  56. {
  57. /* Got it! */
  58. i++;
  59. retval = (*p_readfunc)(p_sess, p_readpos, i);
  60. if (vsf_sysutil_retval_is_error(retval) ||
  61. (unsigned int) retval != i)
  62. {
  63. die("vsf_sysutil_read_loop");
  64. }
  65. if (p_readpos[i - 1] != term)
  66. {
  67. die("missing terminator in str_netfd_alloc");
  68. }
  69. str_alloc_alt_term(p_str, p_readbuf, term);
  70. return (int) i;
  71. }
  72. }
  73. /* Not found in this read chunk, so consume the data and re-loop */
  74. if (bytes_read > left)
  75. {
  76. bug("bytes_read > left in str_netfd_alloc");
  77. }
  78. left -= bytes_read;
  79. retval = (*p_readfunc)(p_sess, p_readpos, bytes_read);
  80. if (vsf_sysutil_retval_is_error(retval) ||
  81. (unsigned int) retval != bytes_read)
  82. {
  83. die("vsf_sysutil_read_loop");
  84. }
  85. p_readpos += bytes_read;
  86. } /* END: while(1) */
  87. }
  88. int
  89. str_netfd_write(const struct mystr* p_str, int fd)
  90. {
  91. int ret = 0;
  92. int retval;
  93. unsigned int str_len = str_getlen(p_str);
  94. if (str_len == 0)
  95. {
  96. bug("zero str_len in str_netfd_write");
  97. }
  98. retval = str_write_loop(p_str, fd);
  99. if (vsf_sysutil_retval_is_error(retval) || (unsigned int) retval != str_len)
  100. {
  101. ret = -1;
  102. }
  103. return ret;
  104. }
  105. int
  106. str_netfd_read(struct mystr* p_str, int fd, unsigned int len)
  107. {
  108. int retval;
  109. str_reserve(p_str, len);
  110. str_trunc(p_str, len);
  111. retval = str_read_loop(p_str, fd);
  112. if (vsf_sysutil_retval_is_error(retval) || (unsigned int) retval != len)
  113. {
  114. return -1;
  115. }
  116. return retval;
  117. }