summaryrefslogtreecommitdiff
path: root/src/libstddjb/mininetstring_write.c
blob: 09833e279fed5339fd1c9652491996289554c8c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/* ISC license. */

#include <stdint.h>
#include <errno.h>
#include <skalibs/uint16.h>
#include <skalibs/allreadwrite.h>
#include <skalibs/mininetstring.h>

int mininetstring_write (int fd, char const *s, uint16_t len, uint32_t *w)
{
  if (!*w)
  {
    char pack[2] ;
    uint16_pack_big(pack, len) ;
    switch (fd_write(fd, pack, 2))
    {
      case -1 : return -1 ;
      case 0 : return (errno = EAGAIN, -1) ;
      case 1 : *w = (1U << 31) ; break ;
      case 2 : *w = len ; break ;
      default : return (errno = EDOM, -1) ;
    }
  }
  if (*w & (1U << 31))
  {
    unsigned char c = len & 0xFFU ;
    switch (fd_write(fd, (char const *)&c, 1))
    {
      case -1 : return -1 ;
      case 0 : return (errno = EAGAIN, -1) ;
      case 1 : *w = len ; break ;
      default : return (errno = EDOM, -1) ;
    }
  }
  *w -= allwrite(fd, s + len - *w, *w) ;
  return *w ? -1 : 1 ;
}