summaryrefslogtreecommitdiff
path: root/usr.bin/cvs/req.c
diff options
context:
space:
mode:
authorJoris Vink <joris@cvs.openbsd.org>2005-06-17 15:09:56 +0000
committerJoris Vink <joris@cvs.openbsd.org>2005-06-17 15:09:56 +0000
commit488e4ef1d130d7aa53c165deb4126e342e5c42e3 (patch)
treef6daed9c57b906b1d017ae9c66640e4fe4daa95f /usr.bin/cvs/req.c
parentb5060d65ffb649e508235afa8b2f91a9497b8829 (diff)
correctly build a temporary copy of the client its repository
localy, so the server can execute the local commands on it and pipe the output to the client. with this diff in, our server is now working, please note that we currently don't have support for all commands yet, but you can expect this soon. ok xsa@
Diffstat (limited to 'usr.bin/cvs/req.c')
-rw-r--r--usr.bin/cvs/req.c196
1 files changed, 156 insertions, 40 deletions
diff --git a/usr.bin/cvs/req.c b/usr.bin/cvs/req.c
index 7ba28b6d41a..bbcf4878f3a 100644
--- a/usr.bin/cvs/req.c
+++ b/usr.bin/cvs/req.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: req.c,v 1.21 2005/06/10 21:14:47 joris Exp $ */
+/* $OpenBSD: req.c,v 1.22 2005/06/17 15:09:55 joris Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -30,6 +30,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -41,6 +42,7 @@
#include "proto.h"
+extern char *cvs_rootstr;
extern int verbosity;
extern int cvs_compress;
extern char *cvs_rsh;
@@ -119,7 +121,7 @@ struct cvs_reqhdlr {
{ cvs_req_command },
{ NULL },
{ cvs_req_command },
- { NULL },
+ { cvs_req_command },
{ NULL }, /* 50 */
{ NULL },
{ NULL },
@@ -147,16 +149,16 @@ struct cvs_reqhdlr {
/*
* 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_currentdir;
-static char *cvs_req_repopath;
-static char cvs_req_tmppath[MAXPATHLEN];
-
extern char cvs_server_tmpdir[MAXPATHLEN];
-static char *cvs_req_args[CVS_PROTO_MAXARG];
-static int cvs_req_nargs = 0;
-
+static CVSENTRIES *cvs_req_entf;
/*
* cvs_req_handle()
@@ -218,6 +220,8 @@ cvs_req_root(int reqid, char *line)
return (-1);
}
+ cvs_rootstr = cvs_req_rootpath;
+
return (0);
}
@@ -264,8 +268,12 @@ cvs_req_validresp(int reqid, char *line)
static int
cvs_req_directory(int reqid, char *line)
{
- int l;
+ int pwd;
+ size_t dirlen;
char rdir[MAXPATHLEN];
+ char *repo, *s, *p;
+
+ pwd = (!strcmp(line, "."));
if (cvs_getln(NULL, rdir, sizeof(rdir)) < 0)
return (-1);
@@ -279,27 +287,96 @@ cvs_req_directory(int reqid, char *line)
return (-1);
}
- /* now obtain the path relative to the Root directory */
- cvs_req_repopath = cvs_req_currentdir + strlen(cvs_req_rootpath) + 1;
+ dirlen = strlen(cvs_req_currentdir);
+
+ /*
+ * Lets make sure we always start at the correct
+ * directory.
+ */
+ if (chdir(cvs_server_tmpdir) == -1) {
+ cvs_log(LP_ERRNO, "failed to change to top directory");
+ return (-1);
+ }
+
+ /*
+ * Set repository path.
+ */
+ 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);
+ }
- /* create tmp path */
- l = snprintf(cvs_req_tmppath, sizeof(cvs_req_tmppath), "%s/%s",
- cvs_server_tmpdir, cvs_req_repopath);
- if (l == -1 || l >= (int)sizeof(cvs_req_tmppath)) {
- errno = ENAMETOOLONG;
- cvs_log(LP_ERRNO, "%s", cvs_req_tmppath);
+ if ((repo = strdup(s)) == NULL) {
+ cvs_log(LP_ERR, "failed to save repository path");
return (-1);
}
- if ((mkdir(cvs_req_tmppath, 0755) == -1) && (errno != EEXIST)) {
- cvs_log(LP_ERRNO, "failed to create temporary directory '%s'",
- cvs_req_tmppath);
+ /*
+ * 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);
}
- /* create the CVS/ administrative files */
- /* XXX - TODO */
+ /*
+ * 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);
}
@@ -307,12 +384,20 @@ static int
cvs_req_entry(int reqid, char *line)
{
struct cvs_ent *ent;
- CVSFILE *cf;
+ /* parse received entry */
if ((ent = cvs_ent_parse(line)) == NULL)
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);
}
@@ -327,37 +412,52 @@ cvs_req_entry(int reqid, char *line)
static int
cvs_req_filestate(int reqid, char *line)
{
- int l;
+ int ret;
mode_t fmode;
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);
if (fdata == NULL)
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 */
- if (cvs_buf_write(fdata, fpath, fmode) < 0) {
- cvs_log(LP_ERR, "failed to create file %s", fpath);
+ if (cvs_buf_write(fdata, line, fmode) < 0) {
+ cvs_log(LP_ERR, "failed to create file %s", line);
cvs_buf_free(fdata);
return (-1);
}
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);
}
/*
@@ -551,7 +651,23 @@ cvs_req_command(int reqid, char *line)
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);
+
if (ret == 0)
ret = cvs_sendresp(CVS_RESP_OK, NULL);