packaging: Remove ExclusiveArch in spec
[platform/upstream/nbd.git] / cliserv.c
1 #include <config.h>
2 #include <fcntl.h>
3 #include <stdio.h>
4 #include <syslog.h>
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/socket.h>
8
9 #include <cliserv.h>
10 #include <nbd-debug.h>
11
12 const u64 cliserv_magic = 0x00420281861253LL;
13 const u64 opts_magic = 0x49484156454F5054LL;
14 const u64 rep_magic = 0x3e889045565a9LL;
15
16 /**
17  * Set a socket to blocking or non-blocking
18  *
19  * @param fd The socket's FD
20  * @param nb nonzero to set to non-blocking, else 0 to set to blocking
21  * @return 0 - OK, -1 failed
22  */
23 int set_nonblocking(int fd, int nb) {
24         int sf = fcntl (fd, F_GETFL, 0);
25         if (sf == -1)
26                 return -1;
27         return fcntl (fd, F_SETFL, nb ? (sf | O_NONBLOCK) : (sf & ~O_NONBLOCK));
28 }
29
30
31 void setmysockopt(int sock) {
32         int size = 1;
33 #if 0
34         if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &size, sizeof(int)) < 0)
35                  INFO("(no sockopt/1: %m)");
36 #endif
37 #ifdef  IPPROTO_TCP
38         size = 1;
39         if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &size, sizeof(int)) < 0)
40                  INFO("(no sockopt/2: %m)");
41 #endif
42 #if 0
43         size = 1024;
44         if (setsockopt(sock, IPPROTO_TCP, TCP_MAXSEG, &size, sizeof(int)) < 0)
45                  INFO("(no sockopt/3: %m)");
46 #endif
47 }
48
49 void err_nonfatal(const char *s) {
50         char s1[150], *s2;
51
52         strncpy(s1, s, sizeof(s1));
53         if ((s2 = strstr(s, "%m"))) {
54                 strncpy(s1 + (s2 - s), strerror(errno), sizeof(s1) - (s2 - s));
55                 s2 += 2;
56                 strncpy(s1 + strlen(s1), s2, sizeof(s1) - strlen(s1));
57         }
58 #ifndef sun
59         /* Solaris doesn't have %h in syslog */
60         else if ((s2 = strstr(s, "%h"))) {
61                 strncpy(s1 + (s2 - s), hstrerror(h_errno), sizeof(s1) - (s2 - s));
62                 s2 += 2;
63                 strncpy(s1 + strlen(s1), s2, sizeof(s1) - strlen(s1));
64         }
65 #endif
66
67         s1[sizeof(s1)-1] = '\0';
68 #ifdef ISSERVER
69         syslog(LOG_ERR, "%s", s1);
70         syslog(LOG_ERR, "Exiting.");
71 #endif
72         fprintf(stderr, "Error: %s\n", s1);
73 }
74
75 void err(const char *s) {
76         err_nonfatal(s);
77         fprintf(stderr, "Exiting.\n");
78         exit(EXIT_FAILURE);
79 }
80
81 void logging(const char* name) {
82 #ifdef ISSERVER
83         openlog(name, LOG_PID, LOG_DAEMON);
84 #endif
85         setvbuf(stdout, NULL, _IONBF, 0);
86         setvbuf(stderr, NULL, _IONBF, 0);
87 }
88
89 #ifndef ntohll
90 #ifdef WORDS_BIGENDIAN
91 uint64_t ntohll(uint64_t a) {
92         return a;
93 }
94 #else
95 uint64_t ntohll(uint64_t a) {
96         u32 lo = a & 0xffffffff;
97         u32 hi = a >> 32U;
98         lo = ntohl(lo);
99         hi = ntohl(hi);
100         return ((uint64_t) lo) << 32U | hi;
101 }
102 #endif
103 #endif
104
105 /**
106  * Read data from a file descriptor into a buffer
107  *
108  * @param f a file descriptor
109  * @param buf a buffer
110  * @param len the number of bytes to be read
111  * @return 0 on completion, or -1 on failure
112  **/
113 int readit(int f, void *buf, size_t len) {
114         ssize_t res;
115         while (len > 0) {
116                 DEBUG("*");
117                 res = read(f, buf, len);
118                 if (res > 0) {
119                         len -= res;
120                         buf += res;
121                 } else if (res < 0) {
122                         if(errno != EAGAIN) {
123                                 err_nonfatal("Read failed: %m");
124                                 return -1;
125                         }
126                 } else {
127                         errno = ECONNRESET;
128                         return -1;
129                 }
130         }
131         return 0;
132 }
133
134 /**
135  * Write data from a buffer into a filedescriptor
136  *
137  * @param f a file descriptor
138  * @param buf a buffer containing data
139  * @param len the number of bytes to be written
140  * @return 0 on success, or -1 if the socket was closed
141  **/
142 int writeit(int f, void *buf, size_t len) {
143         ssize_t res;
144         while (len > 0) {
145                 DEBUG("+");
146                 if ((res = write(f, buf, len)) <= 0) {
147                         switch(errno) {
148                                 case EAGAIN:
149                                         break;
150                                 default:
151                                         err_nonfatal("Send failed: %m");
152                                         return -1;
153                         }
154                 }
155                 len -= res;
156                 buf += res;
157         }
158         return 0;
159 }