* Copy the group file from one descriptor to another, replacing, deleting * or adding a single record on the way. */
| 164 | * or adding a single record on the way. |
| 165 | */ |
| 166 | int |
| 167 | gr_copy(int ffd, int tfd, const struct group *gr, struct group *old_gr) |
| 168 | { |
| 169 | char *buf, *end, *line, *p, *q, *r, *tmp; |
| 170 | struct group *fgr; |
| 171 | const struct group *sgr; |
| 172 | size_t len, size; |
| 173 | int eof, readlen; |
| 174 | char t; |
| 175 | |
| 176 | if (old_gr == NULL && gr == NULL) |
| 177 | return(-1); |
| 178 | |
| 179 | sgr = old_gr; |
| 180 | /* deleting a group */ |
| 181 | if (gr == NULL) { |
| 182 | line = NULL; |
| 183 | } else { |
| 184 | if ((line = gr_make(gr)) == NULL) |
| 185 | return (-1); |
| 186 | } |
| 187 | |
| 188 | /* adding a group */ |
| 189 | if (sgr == NULL) |
| 190 | sgr = gr; |
| 191 | |
| 192 | /* initialize the buffer */ |
| 193 | if ((buf = malloc(size = 1024)) == NULL) |
| 194 | goto err; |
| 195 | |
| 196 | eof = 0; |
| 197 | len = 0; |
| 198 | p = q = end = buf; |
| 199 | for (;;) { |
| 200 | /* find the end of the current line */ |
| 201 | for (p = q; q < end && *q != '\0'; ++q) |
| 202 | if (*q == '\n') |
| 203 | break; |
| 204 | |
| 205 | /* if we don't have a complete line, fill up the buffer */ |
| 206 | if (q >= end) { |
| 207 | if (eof) |
| 208 | break; |
| 209 | while ((size_t)(q - p) >= size) { |
| 210 | if ((tmp = reallocarray(buf, 2, size)) == NULL) { |
| 211 | warnx("group line too long"); |
| 212 | goto err; |
| 213 | } |
| 214 | p = tmp + (p - buf); |
| 215 | q = tmp + (q - buf); |
| 216 | end = tmp + (end - buf); |
| 217 | buf = tmp; |
| 218 | size = size * 2; |
| 219 | } |
| 220 | if (p < end) { |
| 221 | q = memmove(buf, p, end -p); |
| 222 | end -= p - buf; |
| 223 | } else { |