GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/cvs/remote.c Lines: 8 140 5.7 %
Date: 2017-11-07 Branches: 5 104 4.8 %

Line Branch Exec Source
1
/*	$OpenBSD: remote.c,v 1.32 2017/08/28 19:33:20 otto Exp $	*/
2
/*
3
 * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include <sys/param.h>	/* MAXBSIZE */
19
#include <sys/stat.h>
20
21
#include <errno.h>
22
#include <fcntl.h>
23
#include <stdlib.h>
24
#include <string.h>
25
#include <unistd.h>
26
27
#include "atomicio.h"
28
#include "cvs.h"
29
#include "remote.h"
30
31
#define MINIMUM(a, b)	(((a) < (b)) ? (a) : (b))
32
33
struct cvs_resp *
34
cvs_remote_get_response_info(const char *response)
35
{
36
	int i;
37
38
	for (i = 0; cvs_responses[i].supported != -1; i++) {
39
		if (!strcmp(cvs_responses[i].name, response))
40
			return (&(cvs_responses[i]));
41
	}
42
43
	return (NULL);
44
}
45
46
struct cvs_req *
47
cvs_remote_get_request_info(const char *request)
48
{
49
	int i;
50
51
	for (i = 0; cvs_requests[i].supported != -1; i++) {
52
		if (!strcmp(cvs_requests[i].name, request))
53
			return (&(cvs_requests[i]));
54
	}
55
56
	return (NULL);
57
}
58
59
void
60
cvs_remote_output(char *data)
61
{
62
	FILE *out;
63
	size_t len;
64
	char nl = '\n';
65
66
	if (cvs_server_active)
67
		out = stdout;
68
	else
69
		out = current_cvsroot->cr_srvin;
70
71
	fputs(data, out);
72
	fputs("\n", out);
73
74
	if (cvs_server_active == 0 && cvs_client_inlog_fd != -1) {
75
		len = strlen(data);
76
		if (atomicio(vwrite, cvs_client_inlog_fd, data, len) != len ||
77
		    atomicio(vwrite, cvs_client_inlog_fd, &nl, 1) != 1)
78
			fatal("failed to write to log file");
79
	}
80
}
81
82
char *
83
cvs_remote_input(void)
84
{
85
	FILE *in;
86
	size_t len;
87
	char nl = '\n';
88
	char *data, *ldata;
89
90
	if (cvs_server_active)
91
		in = stdin;
92
	else
93
		in = current_cvsroot->cr_srvout;
94
95
	data = fgetln(in, &len);
96
	if (data == NULL) {
97
		if (sig_received != 0)
98
			fatal("received signal %d", sig_received);
99
100
		if (cvs_server_active) {
101
			cvs_cleanup();
102
			exit(0);
103
		}
104
105
		fatal("the connection has been closed by the server");
106
	}
107
108
	if (data[len - 1] == '\n') {
109
		data[len - 1] = '\0';
110
		ldata = xstrdup(data);
111
	} else {
112
		ldata = xmalloc(len + 1);
113
		memcpy(ldata, data, len);
114
		ldata[len] = '\0';
115
	}
116
117
	if (cvs_server_active == 0 && cvs_client_outlog_fd != -1) {
118
		len = strlen(data);
119
		if (atomicio(vwrite, cvs_client_outlog_fd, data, len) != len ||
120
		    atomicio(vwrite, cvs_client_outlog_fd, &nl, 1) != 1)
121
			fatal("failed to write to log file");
122
	}
123
124
	return (ldata);
125
}
126
127
void
128
cvs_remote_receive_file(int fd, size_t len)
129
{
130
	FILE *in;
131
	char data[MAXBSIZE];
132
	size_t nread, nleft, toread;
133
134
	if (cvs_server_active)
135
		in = stdin;
136
	else
137
		in = current_cvsroot->cr_srvout;
138
139
	nleft = len;
140
141
	while (nleft > 0) {
142
		toread = MINIMUM(nleft, MAXBSIZE);
143
144
		nread = fread(data, sizeof(char), toread, in);
145
		if (nread == 0)
146
			fatal("error receiving file");
147
148
		if (atomicio(vwrite, fd, data, nread) != nread)
149
			fatal("failed to write %zu bytes", nread);
150
151
		if (cvs_server_active == 0 && cvs_client_outlog_fd != -1 &&
152
		    atomicio(vwrite, cvs_client_outlog_fd, data, nread)
153
		    != nread)
154
			fatal("failed to write to log file");
155
156
		nleft -= nread;
157
	}
158
}
159
160
void
161
cvs_remote_send_file(const char *path, int _fd)
162
{
163
	int fd;
164
	FILE *out, *in;
165
	size_t ret, rw;
166
	off_t total;
167
	struct stat st;
168
	char buf[18], data[MAXBSIZE];
169
170
	if (cvs_server_active)
171
		out = stdout;
172
	else
173
		out = current_cvsroot->cr_srvin;
174
175
	fd = dup(_fd);
176
	if (fd == -1)
177
		fatal("cvs_remote_send_file: dup: %s", strerror(errno));
178
179
	if (lseek(fd, 0, SEEK_SET) < 0)
180
		fatal("cvs_remote_send_file: %s: lseek: %s", path,
181
		    strerror(errno));
182
183
	if (fstat(fd, &st) == -1)
184
		fatal("cvs_remote_send_file: %s: fstat: %s", path,
185
		    strerror(errno));
186
187
	cvs_modetostr(st.st_mode, buf, sizeof(buf));
188
	cvs_remote_output(buf);
189
190
	(void)xsnprintf(buf, sizeof(buf), "%lld", st.st_size);
191
	cvs_remote_output(buf);
192
193
	if ((in = fdopen(fd, "r")) == NULL)
194
		fatal("cvs_remote_send_file: fdopen %s", strerror(errno));
195
196
	total = 0;
197
	while ((ret = fread(data, sizeof(char), MAXBSIZE, in)) != 0) {
198
		rw = fwrite(data, sizeof(char), ret, out);
199
		if (rw != ret)
200
			fatal("failed to write %zu bytes", ret);
201
202
		if (cvs_server_active == 0 && cvs_client_inlog_fd != -1 &&
203
		    atomicio(vwrite, cvs_client_inlog_fd, data, ret) != ret)
204
			fatal("failed to write to log file");
205
206
		total += ret;
207
	}
208
209
	if (total != st.st_size)
210
		fatal("length mismatch, %lld vs %lld", total, st.st_size);
211
212
	(void)fclose(in);
213
}
214
215
void
216
cvs_remote_send_file_buf(char *file, BUF *bp, mode_t mode)
217
{
218
	char buf[18];
219
	u_char *data;
220
	size_t len, ret;
221
222
	if (cvs_server_active != 1)
223
		fatal("cvs_remote_send_file_buf is server only");
224
225
	len = buf_len(bp);
226
	data = buf_release(bp);
227
228
	cvs_modetostr(mode, buf, sizeof(buf));
229
	cvs_remote_output(buf);
230
231
	(void)xsnprintf(buf, sizeof(buf), "%ld", len);
232
	cvs_remote_output(buf);
233
234
	ret = fwrite(data, sizeof(char), len, stdout);
235
	if (ret != len)
236
		cvs_log(LP_ERR, "warning: sent %s truncated", file);
237
238
	if (cvs_server_active == 0 && cvs_client_inlog_fd != -1 &&
239
	    atomicio(vwrite, cvs_client_inlog_fd, data, len) != len)
240
		fatal("failed to write to log file");
241
242
	free(data);
243
}
244
245
void
246
cvs_remote_classify_file(struct cvs_file *cf)
247
{
248
	struct stat st;
249
	CVSENTRIES *entlist;
250
251
	entlist = cvs_ent_open(cf->file_wd);
252
	cf->file_ent = cvs_ent_get(entlist, cf->file_name);
253
254
	if (cf->file_ent != NULL && cf->file_ent->ce_status != CVS_ENT_REG) {
255
		if (cf->file_ent->ce_status == CVS_ENT_ADDED) {
256
			if (cf->fd != -1)
257
				cf->file_status = FILE_ADDED;
258
			else
259
				cf->file_status = FILE_UNKNOWN;
260
		} else {
261
			cf->file_status = FILE_REMOVED;
262
		}
263
264
		return;
265
	}
266
267
	if (cf->file_ent != NULL) {
268
		if (cf->file_ent->ce_type == CVS_ENT_DIR)
269
			cf->file_type = CVS_DIR;
270
		else
271
			cf->file_type = CVS_FILE;
272
	}
273
274
	if (cf->fd != -1)
275
		cf->file_flags |= FILE_ON_DISK;
276
277
	if ((cf->file_flags & FILE_ON_DISK) && cf->file_ent != NULL) {
278
		if (fstat(cf->fd, &st) == -1)
279
			fatal("cvs_remote_classify_file(%s): %s", cf->file_path,
280
			    strerror(errno));
281
282
		if (st.st_mtime != cf->file_ent->ce_mtime ||
283
		    cf->file_ent->ce_conflict != NULL)
284
			cf->file_status = FILE_MODIFIED;
285
		else
286
			cf->file_status = FILE_UPTODATE;
287
	} else if (!(cf->file_flags & FILE_ON_DISK)) {
288
		cf->file_status = FILE_UNKNOWN;
289
	}
290
291
	if (cvs_cmdop == CVS_OP_IMPORT && cf->file_type == CVS_FILE)
292
		cf->file_status = FILE_MODIFIED;
293
}
294
295
296
void
297
cvs_validate_directory(const char *path)
298
{
299
	char *dir, *sp, *dp;
300
301
446
	dir = xstrdup(path);
302
303
4136
	for (sp = dir; sp != NULL; sp = dp) {
304
1845
		dp = strchr(sp, '/');
305
1845
		if (dp != NULL)
306
1622
			*(dp++) = '\0';
307
308
1845
		if (!strcmp(sp, ".."))
309
			fatal("path validation failed!");
310
	}
311
312
223
	free(dir);
313
223
}