-
Notifications
You must be signed in to change notification settings - Fork 14
/
helper.c
158 lines (139 loc) · 4.16 KB
/
helper.c
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// this file implents helper function needed by the client and server code
#include<stdlib.h>
#include<stdio.h>
#include"helper.h"
#include <unistd.h>
#include <errno.h>
#include <string.h>
// THESE FUNCTIONS ARE TAKEN FROM CS:APP and its license is applied accordingly
/****************************************
* The Rio package - Robust I/O functions
****************************************/
/*
* rio_readn - Robustly read n bytes (unbuffered)
*/
ssize_t rio_readn(int fd, void *usrbuf, size_t n) {
size_t nleft = n;
ssize_t nread;
char *bufp = usrbuf;
while (nleft > 0) {
if ((nread = read(fd, bufp, nleft)) < 0) {
if (errno != EINTR) {
return -1; /* errno set by read() */
}
/* Interrupted by sig handler return, call read() again */
nread = 0;
} else if (nread == 0) {
break; /* EOF */
}
nleft -= (size_t)nread;
bufp += nread;
}
return (ssize_t)(n - nleft); /* Return >= 0 */
}
/*
* rio_writen - Robustly write n bytes (unbuffered)
*/
ssize_t rio_writen(int fd, const void *usrbuf, size_t n) {
size_t nleft = n;
ssize_t nwritten;
const char *bufp = usrbuf;
while (nleft > 0) {
if ((nwritten = write(fd, bufp, nleft)) <= 0) {
if (errno != EINTR) {
return -1; /* errno set by write() */
}
/* Interrupted by sig handler return, call write() again */
nwritten = 0;
}
nleft -= (size_t)nwritten;
bufp += nwritten;
}
return (ssize_t)n;
}
/*
* rio_read - This is a wrapper for the Unix read() function that
* transfers min(n, rio_cnt) bytes from an internal buffer to a user
* buffer, where n is the number of bytes requested by the user and
* rio_cnt is the number of unread bytes in the internal buffer. On
* entry, rio_read() refills the internal buffer via a call to
* read() if the internal buffer is empty.
*/
static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n) {
size_t cnt;
while (rp->rio_cnt <= 0) { /* Refill if buf is empty */
rp->rio_cnt = read(rp->rio_fd, rp->rio_buf, sizeof(rp->rio_buf));
if (rp->rio_cnt < 0) {
if (errno != EINTR) {
return -1; /* errno set by read() */
}
/* Interrupted by sig handler return, nothing to do */
} else if (rp->rio_cnt == 0) {
return 0; /* EOF */
} else {
rp->rio_bufptr = rp->rio_buf; /* Reset buffer ptr */
}
}
/* Copy min(n, rp->rio_cnt) bytes from internal buf to user buf */
cnt = n;
if ((size_t)rp->rio_cnt < n) {
cnt = (size_t)rp->rio_cnt;
}
memcpy(usrbuf, rp->rio_bufptr, cnt);
rp->rio_bufptr += cnt;
rp->rio_cnt -= cnt;
return (ssize_t)cnt;
}
/*
* rio_readinitb - Associate a descriptor with a read buffer and reset buffer
*/
void rio_readinitb(rio_t *rp, int fd) {
rp->rio_fd = fd;
rp->rio_cnt = 0;
rp->rio_bufptr = rp->rio_buf;
}
/*
* rio_readnb - Robustly read n bytes (buffered)
*/
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n) {
size_t nleft = n;
ssize_t nread;
char *bufp = usrbuf;
while (nleft > 0) {
if ((nread = rio_read(rp, bufp, nleft)) < 0) {
return -1; /* errno set by read() */
} else if (nread == 0) {
break; /* EOF */
}
nleft -= (size_t)nread;
bufp += nread;
}
return (ssize_t)(n - nleft); /* return >= 0 */
}
/*
* rio_readlineb - Robustly read a text line (buffered)
*/
ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen) {
size_t n;
ssize_t rc;
char c, *bufp = usrbuf;
for (n = 1; n < maxlen; n++) {
if ((rc = rio_read(rp, &c, 1)) == 1) {
*bufp++ = c;
if (c == '\n') {
n++;
break;
}
} else if (rc == 0) {
if (n == 1) {
return 0; /* EOF, no data read */
} else {
break; /* EOF, some data was read */
}
} else {
return -1; /* Error */
}
}
*bufp = 0;
return (ssize_t)(n - 1);
}