version 1.13, 2004/07/30 01:49:24 |
version 1.14, 2004/07/30 17:37:58 |
|
|
#include "buf.h" |
#include "buf.h" |
#include "cvs.h" |
#include "cvs.h" |
#include "log.h" |
#include "log.h" |
|
#include "file.h" |
#include "proto.h" |
#include "proto.h" |
|
|
|
|
|
|
static int cvs_resp_removed (struct cvsroot *, int, char *); |
static int cvs_resp_removed (struct cvsroot *, int, char *); |
static int cvs_resp_mode (struct cvsroot *, int, char *); |
static int cvs_resp_mode (struct cvsroot *, int, char *); |
static int cvs_resp_modxpand (struct cvsroot *, int, char *); |
static int cvs_resp_modxpand (struct cvsroot *, int, char *); |
|
static int cvs_resp_rcsdiff (struct cvsroot *, int, char *); |
|
|
static int cvs_initlog (void); |
static int cvs_initlog (void); |
|
|
|
|
{ CVS_RESP_MODXPAND, "Module-expansion", cvs_resp_modxpand }, |
{ CVS_RESP_MODXPAND, "Module-expansion", cvs_resp_modxpand }, |
{ CVS_RESP_SETSTICKY, "Set-sticky", cvs_resp_sticky }, |
{ CVS_RESP_SETSTICKY, "Set-sticky", cvs_resp_sticky }, |
{ CVS_RESP_CLRSTICKY, "Clear-sticky", cvs_resp_sticky }, |
{ CVS_RESP_CLRSTICKY, "Clear-sticky", cvs_resp_sticky }, |
|
{ CVS_RESP_RCSDIFF, "Rcs-diff", cvs_resp_rcsdiff }, |
}; |
}; |
|
|
|
|
|
|
/* mask of requets supported by server */ |
/* mask of requets supported by server */ |
static u_char cvs_server_validreq[CVS_REQ_MAX + 1]; |
static u_char cvs_server_validreq[CVS_REQ_MAX + 1]; |
|
|
/* |
|
* Local and remote directory used by the `Directory' request. |
|
*/ |
|
char cvs_ldir[MAXPATHLEN]; |
|
char cvs_rdir[MAXPATHLEN]; |
|
|
|
char *cvs_fcksum = NULL; |
char *cvs_fcksum = NULL; |
|
|
mode_t cvs_lastmode = 0; |
mode_t cvs_lastmode = 0; |
|
|
if (cf == NULL) |
if (cf == NULL) |
return (-1); |
return (-1); |
cf->cf_ddat->cd_repo = strdup(line); |
cf->cf_ddat->cd_repo = strdup(line); |
cf->cf_ddat->cd_root = cvs_root; |
cf->cf_ddat->cd_root = root; |
|
root->cr_ref++; |
cvs_mkadmin(cf, 0755); |
cvs_mkadmin(cf, 0755); |
|
|
cf->cf_ddat->cd_root = NULL; |
|
cvs_file_free(cf); |
cvs_file_free(cf); |
} |
} |
} |
} |
|
|
cvs_resp_updated(struct cvsroot *root, int type, char *line) |
cvs_resp_updated(struct cvsroot *root, int type, char *line) |
{ |
{ |
size_t len; |
size_t len; |
|
mode_t fmode; |
char tbuf[32], path[MAXPATHLEN], cksum_buf[CVS_CKSUM_LEN]; |
char tbuf[32], path[MAXPATHLEN], cksum_buf[CVS_CKSUM_LEN]; |
|
BUF *fbuf; |
CVSENTRIES *ef; |
CVSENTRIES *ef; |
struct cvs_ent *ep; |
struct cvs_ent *ep; |
|
|
|
|
if (ep == NULL) |
if (ep == NULL) |
return (-1); |
return (-1); |
|
|
|
snprintf(path, sizeof(path), "%s%s", line, ep->ce_name); |
|
|
/* set the timestamp as the last one received from Mod-time */ |
/* set the timestamp as the last one received from Mod-time */ |
ep->ce_timestamp = ctime_r(&cvs_modtime, tbuf); |
ep->ce_timestamp = ctime_r(&cvs_modtime, tbuf); |
len = strlen(tbuf); |
len = strlen(tbuf); |
|
|
else if (type == CVS_RESP_UPDATED) { |
else if (type == CVS_RESP_UPDATED) { |
} |
} |
|
|
snprintf(path, sizeof(path), "%s%s", line, ep->ce_name); |
fbuf = cvs_recvfile(root, &fmode); |
if (cvs_recvfile(root, path) < 0) { |
if (fbuf == NULL) |
return (-1); |
return (-1); |
} |
|
|
|
|
cvs_buf_write(fbuf, path, fmode); |
|
|
/* now see if there is a checksum */ |
/* now see if there is a checksum */ |
if (cvs_fcksum != NULL) { |
if (cvs_fcksum != NULL) { |
if (cvs_cksum(line, cksum_buf, sizeof(cksum_buf)) < 0) { |
if (cvs_cksum(path, cksum_buf, sizeof(cksum_buf)) < 0) { |
} |
} |
|
|
if (strcmp(cksum_buf, cvs_fcksum) != 0) { |
if (strcmp(cksum_buf, cvs_fcksum) != 0) { |
|
|
return (0); |
return (0); |
} |
} |
|
|
|
/* |
|
* cvs_resp_rcsdiff() |
|
* |
|
* Handler for the `Rcs-diff' response. |
|
*/ |
|
|
|
static int |
|
cvs_resp_rcsdiff(struct cvsroot *root, int type, char *line) |
|
{ |
|
char file[MAXPATHLEN], buf[MAXPATHLEN], cksum_buf[CVS_CKSUM_LEN]; |
|
char *fname, *orig, *patch; |
|
mode_t fmode; |
|
BUF *res, *fcont, *patchbuf; |
|
CVSENTRIES *entf; |
|
struct cvs_ent *ent; |
|
|
|
/* get remote path and build local path of file to be patched */ |
|
cvs_getln(root, buf, sizeof(buf)); |
|
fname = strrchr(buf, '/'); |
|
if (fname == NULL) |
|
fname = buf; |
|
snprintf(file, sizeof(file), "%s%s", line, fname); |
|
printf("FILE TO PATCH: %s\n", file); |
|
|
|
/* get updated entry fields */ |
|
cvs_getln(root, buf, sizeof(buf)); |
|
ent = cvs_ent_parse(buf); |
|
if (ent == NULL) { |
|
return (-1); |
|
} |
|
|
|
patchbuf = cvs_recvfile(root, &fmode); |
|
fcont = cvs_buf_load(file, BUF_AUTOEXT); |
|
if (fcont == NULL) |
|
return (-1); |
|
|
|
cvs_buf_putc(patchbuf, '\0'); |
|
cvs_buf_putc(fcont, '\0'); |
|
orig = cvs_buf_release(fcont); |
|
patch = cvs_buf_release(patchbuf); |
|
|
|
res = rcs_patch(orig, patch); |
|
if (res == NULL) |
|
return (-1); |
|
|
|
cvs_buf_write(res, file, fmode); |
|
|
|
/* now see if there is a checksum */ |
|
if (cvs_fcksum != NULL) { |
|
if (cvs_cksum(file, cksum_buf, sizeof(cksum_buf)) < 0) { |
|
} |
|
|
|
if (strcmp(cksum_buf, cvs_fcksum) != 0) { |
|
cvs_log(LP_ERR, "checksum error on received file"); |
|
(void)unlink(file); |
|
} |
|
|
|
free(cvs_fcksum); |
|
cvs_fcksum = NULL; |
|
} |
|
|
|
/* update revision in entries */ |
|
entf = cvs_ent_open(line, O_WRONLY); |
|
if (entf == NULL) |
|
return (-1); |
|
|
|
cvs_ent_close(entf); |
|
|
|
return (0); |
|
} |
|
|
|
|
/* |
/* |
* cvs_sendfile() |
* cvs_sendfile() |
* |
* |
|
|
* information. |
* information. |
*/ |
*/ |
|
|
int |
BUF* |
cvs_recvfile(struct cvsroot *root, const char *path) |
cvs_recvfile(struct cvsroot *root, mode_t *mode) |
{ |
{ |
int fd; |
|
mode_t mode; |
|
size_t len; |
size_t len; |
ssize_t ret; |
ssize_t ret; |
off_t fsz, cnt; |
off_t fsz, cnt; |
char buf[4096], *ep; |
char buf[4096], *ep; |
|
BUF *fbuf; |
|
|
|
fbuf = cvs_buf_alloc(sizeof(buf), BUF_AUTOEXT); |
|
if (fbuf == NULL) |
|
return (NULL); |
|
|
if ((cvs_getln(root, buf, sizeof(buf)) < 0) || |
if ((cvs_getln(root, buf, sizeof(buf)) < 0) || |
(cvs_strtomode(buf, &mode) < 0)) { |
(cvs_strtomode(buf, mode) < 0)) { |
return (-1); |
return (NULL); |
} |
} |
|
|
cvs_getln(root, buf, sizeof(buf)); |
cvs_getln(root, buf, sizeof(buf)); |
|
|
fsz = (off_t)strtol(buf, &ep, 10); |
fsz = (off_t)strtol(buf, &ep, 10); |
if (*ep != '\0') { |
if (*ep != '\0') { |
cvs_log(LP_ERR, "parse error in file size transmission"); |
cvs_log(LP_ERR, "parse error in file size transmission"); |
return (-1); |
return (NULL); |
} |
} |
|
|
fd = open(path, O_WRONLY|O_CREAT, mode); |
|
if (fd == -1) { |
|
cvs_log(LP_ERRNO, "failed to open `%s'", path); |
|
return (-1); |
|
} |
|
|
|
cnt = 0; |
cnt = 0; |
do { |
do { |
len = MIN(sizeof(buf), (size_t)(fsz - cnt)); |
len = MIN(sizeof(buf), (size_t)(fsz - cnt)); |
|
|
break; |
break; |
ret = cvs_recvraw(root, buf, len); |
ret = cvs_recvraw(root, buf, len); |
if (ret == -1) { |
if (ret == -1) { |
(void)close(fd); |
cvs_buf_free(fbuf); |
(void)unlink(path); |
return (NULL); |
return (-1); |
|
} |
} |
|
|
if (write(fd, buf, (size_t)ret) == -1) { |
if (cvs_buf_append(fbuf, buf, (size_t)ret) == -1) { |
cvs_log(LP_ERRNO, |
cvs_log(LP_ERR, |
"failed to write contents to file `%s'", path); |
"failed to append received file data"); |
(void)close(fd); |
cvs_buf_free(fbuf); |
(void)unlink(path); |
return (NULL); |
return (-1); |
|
} |
} |
|
|
cnt += (off_t)ret; |
cnt += (off_t)ret; |
} while (cnt < fsz); |
} while (cnt < fsz); |
|
|
(void)close(fd); |
return (fbuf); |
|
|
return (0); |
|
} |
} |
|
|
|
|