From 6726ad6012217b4c1deb337f7a3bdcb6adda8f0b Mon Sep 17 00:00:00 2001 From: Joris Vink Date: Wed, 18 May 2005 20:24:20 +0000 Subject: build a local copy of the client's source tree when acting as a server. more server stuff coming soon! ok jfb@, xsa@ --- usr.bin/cvs/cvs.h | 3 ++- usr.bin/cvs/req.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++- usr.bin/cvs/server.c | 32 +++++++++++++++++++++++++++-- usr.bin/cvs/util.c | 52 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 140 insertions(+), 5 deletions(-) (limited to 'usr.bin') diff --git a/usr.bin/cvs/cvs.h b/usr.bin/cvs/cvs.h index 46928520c31..12b6c140969 100644 --- a/usr.bin/cvs/cvs.h +++ b/usr.bin/cvs/cvs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cvs.h,v 1.54 2005/05/02 15:00:18 xsa Exp $ */ +/* $OpenBSD: cvs.h,v 1.55 2005/05/18 20:24:19 joris Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau * All rights reserved. @@ -406,6 +406,7 @@ int cvs_mkadmin (CVSFILE *, mode_t); int cvs_cksum (const char *, char *, size_t); int cvs_exec (int, char **, int []); int cvs_getargv (const char *, char **, int); +int cvs_remove_dir (const char *); char** cvs_makeargv (const char *, int *); void cvs_freeargv (char **, int); diff --git a/usr.bin/cvs/req.c b/usr.bin/cvs/req.c index b281b6d9112..367382a9440 100644 --- a/usr.bin/cvs/req.c +++ b/usr.bin/cvs/req.c @@ -1,4 +1,4 @@ -/* $OpenBSD: req.c,v 1.13 2005/04/18 21:33:34 jfb Exp $ */ +/* $OpenBSD: req.c,v 1.14 2005/05/18 20:24:19 joris Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau * All rights reserved. @@ -150,7 +150,11 @@ struct cvs_reqhdlr { */ 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; @@ -261,11 +265,42 @@ cvs_req_validresp(int reqid, char *line) static int cvs_req_directory(int reqid, char *line) { + int l; char rdir[MAXPATHLEN]; if (cvs_getln(NULL, rdir, sizeof(rdir)) < 0) return (-1); + if (cvs_req_currentdir != NULL) + free(cvs_req_currentdir); + + cvs_req_currentdir = strdup(rdir); + if (cvs_req_currentdir == NULL) { + cvs_log(LP_ERROR, "failed to duplicate directory"); + return (-1); + } + + /* now obtain the path relative to the Root directory */ + 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", + 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); + return (-1); + } + + if ((mkdir(cvs_req_tmppath, 0755) == -1) && (errno != EEXIST)) { + cvs_log(LP_ERRNO, "failed to create temporary directory '%s'", + cvs_req_tmppath); + return (-1); + } + + /* create the CVS/ administrative files */ + /* XXX - TODO */ + return (0); } @@ -290,13 +325,34 @@ cvs_req_entry(int reqid, char *line) static int cvs_req_filestate(int reqid, char *line) { + int l; mode_t fmode; BUF *fdata; + char fpath[MAXPATHLEN]; if (reqid == 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_ERROR, "failed to create file %s", fpath); + cvs_buf_free(fdata); + return (-1); + } + + cvs_buf_free(fdata); } return (0); diff --git a/usr.bin/cvs/server.c b/usr.bin/cvs/server.c index 9f0442b428a..34443c4e221 100644 --- a/usr.bin/cvs/server.c +++ b/usr.bin/cvs/server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server.c,v 1.13 2005/04/12 14:58:40 joris Exp $ */ +/* $OpenBSD: server.c,v 1.14 2005/05/18 20:24:19 joris Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau * All rights reserved. @@ -25,6 +25,7 @@ */ #include +#include #include #include @@ -47,6 +48,8 @@ u_int cvs_case = 0; struct cvs_cmd_info cmd_server = { NULL, NULL, NULL, NULL, NULL, 0, 0, 0 }; +char cvs_server_tmpdir[MAXPATHLEN]; + /* * cvs_server() * @@ -61,6 +64,7 @@ struct cvs_cmd_info cmd_server = { int cvs_server(int argc, char **argv) { + int l, ret; size_t len; char reqbuf[512]; @@ -72,6 +76,27 @@ cvs_server(int argc, char **argv) (void)setvbuf(stdin, NULL, _IOLBF, 0); (void)setvbuf(stdout, NULL, _IOLBF, 0); + /* create the temporary directory */ + l = snprintf(cvs_server_tmpdir, sizeof(cvs_server_tmpdir), + "%scvs-serv%d", _PATH_TMP, getpid()); + if (l == -1 || l >= (int)sizeof(cvs_server_tmpdir)) { + errno = ENAMETOOLONG; + cvs_log(LP_ERRNO, "%s", cvs_server_tmpdir); + return (CVS_EX_DATA); + } + + if (mkdir(cvs_server_tmpdir, 0700) == -1) { + cvs_log(LP_ERRNO, "failed to create temporary directory '%s'", + cvs_server_tmpdir); + return (CVS_EX_DATA); + } + + if (chdir(cvs_server_tmpdir) == -1) { + cvs_log(LP_ERRNO, "failed to change to temporary directory '%s'" + , cvs_server_tmpdir); + return (CVS_EX_DATA); + } + for (;;) { if (fgets(reqbuf, sizeof(reqbuf), stdin) == NULL) { if (feof(stdin)) @@ -94,5 +119,8 @@ cvs_server(int argc, char **argv) } - return (0); + /* cleanup the temporary tree */ + ret = cvs_remove_dir(cvs_server_tmpdir); + + return (ret); } diff --git a/usr.bin/cvs/util.c b/usr.bin/cvs/util.c index 60416880f96..4e6d9f6b821 100644 --- a/usr.bin/cvs/util.c +++ b/usr.bin/cvs/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.23 2005/04/18 21:02:50 jfb Exp $ */ +/* $OpenBSD: util.c,v 1.24 2005/05/18 20:24:19 joris Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau * All rights reserved. @@ -604,3 +604,53 @@ cvs_exec(int argc, char **argv, int fds[3]) return (ret); } + +/* + * remove a directory tree from disk. + */ +int +cvs_remove_dir(const char *path) +{ + int l, ret; + DIR *dirp; + struct dirent *ent; + char fpath[MAXPATHLEN]; + + if ((dirp = opendir(path)) == NULL) { + cvs_log(LP_ERRNO, "failed to open '%s'", path); + return (CVS_EX_FILE); + } + + while ((ent = readdir(dirp)) != NULL) { + if (!strcmp(ent->d_name, ".") || + !strcmp(ent->d_name, "..")) + continue; + + l = snprintf(fpath, sizeof(fpath), "%s/%s", path, ent->d_name); + if (l == -1 || l >= (int)sizeof(fpath)) { + errno = ENAMETOOLONG; + cvs_log(LP_ERRNO, "%s", fpath); + closedir(dirp); + return (CVS_EX_FILE); + } + + if (ent->d_type == DT_DIR) { + if ((ret = cvs_remove_dir(fpath)) != CVS_EX_OK) { + closedir(dirp); + return (ret); + } + } else { + if ((unlink(fpath) == -1) && (errno != ENOENT)) + cvs_log(LP_ERRNO, "failed to remove '%s'", + fpath); + } + } + + closedir(dirp); + + if ((rmdir(path) == -1) && (errno != ENOENT)) + cvs_log(LP_ERRNO, "failed to remove '%s'", path); + + return (CVS_EX_OK); +} + -- cgit v1.2.3