version 1.21, 2005/06/10 21:14:47 |
version 1.22, 2005/06/17 15:09:55 |
|
|
|
|
#include <errno.h> |
#include <errno.h> |
#include <fcntl.h> |
#include <fcntl.h> |
|
#include <libgen.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
|
#include "proto.h" |
#include "proto.h" |
|
|
|
|
|
extern char *cvs_rootstr; |
extern int verbosity; |
extern int verbosity; |
extern int cvs_compress; |
extern int cvs_compress; |
extern char *cvs_rsh; |
extern char *cvs_rsh; |
|
|
{ cvs_req_command }, |
{ cvs_req_command }, |
{ NULL }, |
{ NULL }, |
{ cvs_req_command }, |
{ cvs_req_command }, |
{ NULL }, |
{ cvs_req_command }, |
{ NULL }, /* 50 */ |
{ NULL }, /* 50 */ |
{ NULL }, |
{ NULL }, |
{ NULL }, |
{ NULL }, |
|
|
/* |
/* |
* Argument array built by `Argument' and `Argumentx' requests. |
* Argument array built by `Argument' and `Argumentx' requests. |
*/ |
*/ |
|
static char *cvs_req_args[CVS_PROTO_MAXARG]; |
|
|
|
/* start at 1, because 0 will be the command name */ |
|
static int cvs_req_nargs = 1; |
|
|
|
static char *cvs_req_modulename; |
static char *cvs_req_rootpath; |
static char *cvs_req_rootpath; |
static char *cvs_req_currentdir; |
static char *cvs_req_currentdir; |
static char *cvs_req_repopath; |
|
static char cvs_req_tmppath[MAXPATHLEN]; |
|
|
|
extern char cvs_server_tmpdir[MAXPATHLEN]; |
extern char cvs_server_tmpdir[MAXPATHLEN]; |
static char *cvs_req_args[CVS_PROTO_MAXARG]; |
static CVSENTRIES *cvs_req_entf; |
static int cvs_req_nargs = 0; |
|
|
|
|
|
/* |
/* |
* cvs_req_handle() |
* cvs_req_handle() |
* |
* |
|
|
return (-1); |
return (-1); |
} |
} |
|
|
|
cvs_rootstr = cvs_req_rootpath; |
|
|
return (0); |
return (0); |
} |
} |
|
|
|
|
static int |
static int |
cvs_req_directory(int reqid, char *line) |
cvs_req_directory(int reqid, char *line) |
{ |
{ |
int l; |
int pwd; |
|
size_t dirlen; |
char rdir[MAXPATHLEN]; |
char rdir[MAXPATHLEN]; |
|
char *repo, *s, *p; |
|
|
|
pwd = (!strcmp(line, ".")); |
|
|
if (cvs_getln(NULL, rdir, sizeof(rdir)) < 0) |
if (cvs_getln(NULL, rdir, sizeof(rdir)) < 0) |
return (-1); |
return (-1); |
|
|
|
|
return (-1); |
return (-1); |
} |
} |
|
|
/* now obtain the path relative to the Root directory */ |
dirlen = strlen(cvs_req_currentdir); |
cvs_req_repopath = cvs_req_currentdir + strlen(cvs_req_rootpath) + 1; |
|
|
|
/* create tmp path */ |
/* |
l = snprintf(cvs_req_tmppath, sizeof(cvs_req_tmppath), "%s/%s", |
* Lets make sure we always start at the correct |
cvs_server_tmpdir, cvs_req_repopath); |
* directory. |
if (l == -1 || l >= (int)sizeof(cvs_req_tmppath)) { |
*/ |
errno = ENAMETOOLONG; |
if (chdir(cvs_server_tmpdir) == -1) { |
cvs_log(LP_ERRNO, "%s", cvs_req_tmppath); |
cvs_log(LP_ERRNO, "failed to change to top directory"); |
return (-1); |
return (-1); |
} |
} |
|
|
if ((mkdir(cvs_req_tmppath, 0755) == -1) && (errno != EEXIST)) { |
/* |
cvs_log(LP_ERRNO, "failed to create temporary directory '%s'", |
* Set repository path. |
cvs_req_tmppath); |
*/ |
|
s = cvs_req_currentdir + strlen(cvs_req_rootpath) + 1; |
|
if (s >= (cvs_req_currentdir + dirlen)) { |
|
cvs_log(LP_ERR, "you're bad, go away"); |
return (-1); |
return (-1); |
} |
} |
|
|
/* create the CVS/ administrative files */ |
if ((repo = strdup(s)) == NULL) { |
/* XXX - TODO */ |
cvs_log(LP_ERR, "failed to save repository path"); |
|
return (-1); |
|
} |
|
|
|
/* |
|
* Skip back "foo/bar" part, so we can feed the repo |
|
* as a startpoint for cvs_create_dir(). |
|
*/ |
|
if (!pwd) { |
|
s = repo + strlen(repo) - strlen(line) - 1; |
|
if (*s != '/') { |
|
cvs_log(LP_ERR, "malformed directory"); |
|
free(repo); |
|
return (-1); |
|
} |
|
|
|
*s = '\0'; |
|
} |
|
|
|
/* |
|
* Obtain the modulename, we only need to do this at |
|
* the very first time we get a Directory request. |
|
*/ |
|
if (cvs_req_modulename == NULL) { |
|
if ((p = strchr(repo, '/')) != NULL) |
|
*p = '\0'; |
|
|
|
if ((cvs_req_modulename = strdup(repo)) == NULL) { |
|
cvs_log(LP_ERR, "failed to save modulename"); |
|
free(repo); |
|
return (-1); |
|
} |
|
|
|
if (p != NULL) |
|
*p = '/'; |
|
|
|
/* |
|
* Now, create the admin files in the top-level |
|
* directory for the temp repo. |
|
*/ |
|
if (cvs_mkadmin(cvs_server_tmpdir, cvs_rootstr, repo) < 0) { |
|
cvs_log(LP_ERR, "failed to create admin files"); |
|
free(repo); |
|
return (-1); |
|
} |
|
} |
|
|
|
/* |
|
* create the directory plus the administrative files. |
|
*/ |
|
if (cvs_create_dir(line, 1, cvs_rootstr, repo) < 0) { |
|
free(repo); |
|
return (-1); |
|
} |
|
|
|
/* |
|
* cvs_create_dir() has already put us in the correct directory |
|
* so now open it's Entry file for incoming files. |
|
*/ |
|
if (cvs_req_entf != NULL) |
|
cvs_ent_close(cvs_req_entf); |
|
cvs_req_entf = cvs_ent_open(".", O_RDWR); |
|
if (cvs_req_entf == NULL) { |
|
cvs_log(LP_ERR, "failed to open Entry file for %s", line); |
|
free(repo); |
|
return (-1); |
|
} |
|
|
|
free(repo); |
return (0); |
return (0); |
} |
} |
|
|
|
|
cvs_req_entry(int reqid, char *line) |
cvs_req_entry(int reqid, char *line) |
{ |
{ |
struct cvs_ent *ent; |
struct cvs_ent *ent; |
CVSFILE *cf; |
|
|
|
|
/* parse received entry */ |
if ((ent = cvs_ent_parse(line)) == NULL) |
if ((ent = cvs_ent_parse(line)) == NULL) |
return (-1); |
return (-1); |
|
|
cf = cvs_file_create(NULL, ent->ce_name, DT_REG, 0644); |
/* add it to the entry file and done */ |
|
if (cvs_ent_add(cvs_req_entf, ent) < 0) { |
|
cvs_log(LP_ERR, "failed to add '%s' to the Entry file", |
|
ent->ce_name); |
|
return (-1); |
|
} |
|
|
|
/* XXX */ |
|
cvs_ent_write(cvs_req_entf); |
|
|
return (0); |
return (0); |
} |
} |
|
|
|
|
static int |
static int |
cvs_req_filestate(int reqid, char *line) |
cvs_req_filestate(int reqid, char *line) |
{ |
{ |
int l; |
int ret; |
mode_t fmode; |
mode_t fmode; |
BUF *fdata; |
BUF *fdata; |
char fpath[MAXPATHLEN]; |
struct cvs_ent *ent; |
|
|
if (reqid == CVS_REQ_MODIFIED) { |
ret = 0; |
|
switch (reqid) { |
|
case CVS_REQ_MODIFIED: |
fdata = cvs_recvfile(NULL, &fmode); |
fdata = cvs_recvfile(NULL, &fmode); |
if (fdata == NULL) |
if (fdata == NULL) |
return (-1); |
return (-1); |
|
|
/* create full temporary path */ |
|
l = snprintf(fpath, sizeof(fpath), "%s/%s", cvs_req_tmppath, |
|
line); |
|
if (l == -1 || l >= (int)sizeof(fpath)) { |
|
errno = ENAMETOOLONG; |
|
cvs_log(LP_ERRNO, "%s", fpath); |
|
cvs_buf_free(fdata); |
|
return (-1); |
|
} |
|
|
|
/* write the file */ |
/* write the file */ |
if (cvs_buf_write(fdata, fpath, fmode) < 0) { |
if (cvs_buf_write(fdata, line, fmode) < 0) { |
cvs_log(LP_ERR, "failed to create file %s", fpath); |
cvs_log(LP_ERR, "failed to create file %s", line); |
cvs_buf_free(fdata); |
cvs_buf_free(fdata); |
return (-1); |
return (-1); |
} |
} |
|
|
cvs_buf_free(fdata); |
cvs_buf_free(fdata); |
|
break; |
|
case CVS_REQ_ISMODIFIED: |
|
break; |
|
case CVS_REQ_UNCHANGED: |
|
ent = cvs_ent_get(cvs_req_entf, line); |
|
if (ent == NULL) { |
|
cvs_log(LP_ERR, |
|
"received Unchanged request for a non-existing file"); |
|
ret = -1; |
|
} else { |
|
ent->ce_status = CVS_ENT_UPTODATE; |
|
} |
|
break; |
|
case CVS_REQ_QUESTIONABLE: |
|
break; |
|
default: |
|
cvs_log(LP_ERR, "wrong request id type"); |
|
ret = -1; |
|
break; |
} |
} |
|
|
return (0); |
/* XXX */ |
|
cvs_req_entf->cef_flags &= ~CVS_ENTF_SYNC; |
|
cvs_ent_write(cvs_req_entf); |
|
|
|
return (ret); |
} |
} |
|
|
/* |
/* |
|
|
return (-1); |
return (-1); |
} |
} |
|
|
|
/* close the Entry file if it's still open */ |
|
if (cvs_req_entf != NULL) |
|
cvs_ent_close(cvs_req_entf); |
|
|
|
/* fill in the command name */ |
|
cvs_req_args[0] = cmdp->cmd_name; |
|
|
|
/* switch to the correct directory */ |
|
if (cmdp->cmd_op != CVS_OP_VERSION) { |
|
if (chdir(cvs_server_tmpdir) == -1) { |
|
cvs_log(LP_ERRNO, "failed to change dir"); |
|
return (-1); |
|
} |
|
} |
|
|
ret = cvs_startcmd(cmdp, cvs_req_nargs, cvs_req_args); |
ret = cvs_startcmd(cmdp, cvs_req_nargs, cvs_req_args); |
|
|
if (ret == 0) |
if (ret == 0) |
ret = cvs_sendresp(CVS_RESP_OK, NULL); |
ret = cvs_sendresp(CVS_RESP_OK, NULL); |
|
|