diff options
author | Jean-Francois Brousseau <jfb@cvs.openbsd.org> | 2004-07-14 03:33:10 +0000 |
---|---|---|
committer | Jean-Francois Brousseau <jfb@cvs.openbsd.org> | 2004-07-14 03:33:10 +0000 |
commit | 937d3eaef1b8e444fed8680b7bd02eb7a889ef16 (patch) | |
tree | dc792d414ce45572514a329c5984a8854d5976cc /usr.bin | |
parent | 7758ae017f914a3a4224747f433df34d118a94fb (diff) |
cvsignore support and simpler API for file access
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/cvs/cvs.c | 4 | ||||
-rw-r--r-- | usr.bin/cvs/cvs.h | 10 | ||||
-rw-r--r-- | usr.bin/cvs/cvs/Makefile | 4 | ||||
-rw-r--r-- | usr.bin/cvs/file.c | 278 |
4 files changed, 292 insertions, 4 deletions
diff --git a/usr.bin/cvs/cvs.c b/usr.bin/cvs/cvs.c index 8ec94769df0..2ae53090b5a 100644 --- a/usr.bin/cvs/cvs.c +++ b/usr.bin/cvs/cvs.c @@ -1,5 +1,5 @@ #define DEBUG -/* $OpenBSD: cvs.c,v 1.1 2004/07/13 22:02:40 jfb Exp $ */ +/* $OpenBSD: cvs.c,v 1.2 2004/07/14 03:33:09 jfb Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -372,6 +372,8 @@ main(int argc, char **argv) /* setup signal handlers */ signal(SIGCHLD, sigchld_hdlr); + cvs_file_init(); + if (readrc) cvs_readrc(); diff --git a/usr.bin/cvs/cvs.h b/usr.bin/cvs/cvs.h index 0a5b5120619..dff9c9f95ce 100644 --- a/usr.bin/cvs/cvs.h +++ b/usr.bin/cvs/cvs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cvs.h,v 1.1 2004/07/13 22:02:40 jfb Exp $ */ +/* $OpenBSD: cvs.h,v 1.2 2004/07/14 03:33:09 jfb Exp $ */ /* * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> * All rights reserved. @@ -318,6 +318,7 @@ const char* cvs_req_getbyid (int); int cvs_req_getbyname (const char *); char* cvs_req_getvalid (void); + int cvs_resp_handle (char *); const char* cvs_resp_getbyid (int); int cvs_resp_getbyname (const char *); @@ -345,6 +346,13 @@ void cvsroot_free (struct cvsroot *); struct cvsroot* cvsroot_get (const char *); +int cvs_file_init (void); +int cvs_file_ignore (const char *); +int cvs_file_isignored (const char *); +char** cvs_file_getv (const char *, int *); +void cvs_file_free (char **, int); + + /* Entries API */ CVSENTRIES* cvs_ent_open (const char *); struct cvs_ent* cvs_ent_get (CVSENTRIES *, const char *); diff --git a/usr.bin/cvs/cvs/Makefile b/usr.bin/cvs/cvs/Makefile index 1b01c901887..b5d1f36f348 100644 --- a/usr.bin/cvs/cvs/Makefile +++ b/usr.bin/cvs/cvs/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.1 2004/07/13 22:02:40 jfb Exp $ +# $Id: Makefile,v 1.2 2004/07/14 03:33:09 jfb Exp $ .PATH: ${.CURDIR}/.. @@ -9,7 +9,7 @@ BINGRP=_cvsd BINMODE=2555 MAN=cvs.1 cvsrc.5 -SRCS= cvs.c add.c buf.c client.c commit.c diff.c entries.c getlog.c \ +SRCS= cvs.c add.c buf.c client.c commit.c diff.c entries.c file.c getlog.c \ history.c hist.c init.c lock.c log.c proto.c rcs.c rcsnum.c root.c \ server.c sock.c update.c util.c version.c diff --git a/usr.bin/cvs/file.c b/usr.bin/cvs/file.c new file mode 100644 index 00000000000..0e01d971d12 --- /dev/null +++ b/usr.bin/cvs/file.c @@ -0,0 +1,278 @@ +/* $OpenBSD: file.c,v 1.1 2004/07/14 03:33:09 jfb Exp $ */ +/* + * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/stat.h> + +#include <pwd.h> +#include <errno.h> +#include <stdio.h> +#include <fcntl.h> +#include <dirent.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fnmatch.h> + +#include "cvs.h" +#include "log.h" + + +#define CVS_IGN_STATIC 0x01 /* pattern is static, no need to glob */ + + + +#define CVS_CHAR_ISMETA(c) ((c == '*') || (c == '?') || (c == '[')) + + + +/* ignore pattern */ +struct cvs_ignpat { + char ip_pat[MAXNAMLEN]; + int ip_flags; + TAILQ_ENTRY (cvs_ignpat) ip_list; +}; + + +/* + * Standard patterns to ignore. + */ + +static const char *cvs_ign_std[] = { + ".", + "..", + "*.o", + "*.so", + "*.bak", + "*.orig", + "*.rej", + "*.exe", + "*.depend", + "CVS", + "core", +#ifdef OLD_SMELLY_CRUFT + "RCSLOG", + "tags", + "TAGS", + "RCS", + "SCCS", + "#*", + ".#*", + ",*", +#endif +}; + + +TAILQ_HEAD(, cvs_ignpat) cvs_ign_pats; + + +/* + * cvs_file_init() + * + */ + +int +cvs_file_init(void) +{ + int i; + size_t len; + char path[MAXPATHLEN], buf[MAXNAMLEN]; + FILE *ifp; + struct passwd *pwd; + + TAILQ_INIT(&cvs_ign_pats); + + /* standard patterns to ignore */ + for (i = 0; i < sizeof(cvs_ign_std)/sizeof(char *); i++) + cvs_file_ignore(cvs_ign_std[i]); + + /* read the cvsignore file in the user's home directory, if any */ + pwd = getpwuid(getuid()); + if (pwd != NULL) { + snprintf(path, sizeof(path), "%s/.cvsignore", pwd->pw_dir); + ifp = fopen(path, "r"); + if (ifp == NULL) { + if (errno != ENOENT) + cvs_log(LP_ERRNO, "failed to open `%s'", path); + } + else { + while (fgets(buf, sizeof(buf), ifp) != NULL) { + len = strlen(buf); + if (len == 0) + continue; + if (buf[len - 1] != '\n') { + cvs_log(LP_ERR, "line too long in `%s'", + path); + } + buf[--len] = '\0'; + cvs_file_ignore(buf); + } + (void)fclose(ifp); + } + } + + return (0); +} + + +/* + * cvs_file_ignore() + * + * Add the pattern <pat> to the list of patterns for files to ignore. + * Returns 0 on success, or -1 on failure. + */ + +int +cvs_file_ignore(const char *pat) +{ + char *cp; + struct cvs_ignpat *ip; + + ip = (struct cvs_ignpat *)malloc(sizeof(*ip)); + if (ip == NULL) { + cvs_log(LP_ERR, "failed to allocate space for ignore pattern"); + return (-1); + } + + strlcpy(ip->ip_pat, pat, sizeof(ip->ip_pat)); + + /* check if we will need globbing for that pattern */ + ip->ip_flags = CVS_IGN_STATIC; + for (cp = ip->ip_pat; *cp != '\0'; cp++) { + if (CVS_CHAR_ISMETA(*cp)) { + ip->ip_flags &= ~CVS_IGN_STATIC; + break; + } + } + + TAILQ_INSERT_TAIL(&cvs_ign_pats, ip, ip_list); + + return (0); +} + + +/* + * cvs_file_isignored() + * + * Returns 1 if the filename <file> is matched by one of the ignore + * patterns, or 0 otherwise. + */ + +int +cvs_file_isignored(const char *file) +{ + struct cvs_ignpat *ip; + + TAILQ_FOREACH(ip, &cvs_ign_pats, ip_list) { + if (ip->ip_flags & CVS_IGN_STATIC) { + if (strcmp(file, ip->ip_pat) == 0) + return (1); + } + else if (fnmatch(ip->ip_pat, file, FNM_PERIOD) == 0) + return (1); + } + + return (0); +} + + +/* + * cvs_file_getv() + * + * Get a vector of all the files found in the directory <dir> and not + * matching any of the ignore patterns. The number of files found is + * returned in <nfiles>. + * Returns a pointer to a dynamically-allocated string vector on success, + * or NULL on failure. + */ + +char** +cvs_file_getv(const char *dir, int *nfiles) +{ + int nf, ret, fd; + long base; + void *dp, *ep, *tmp; + char fbuf[1024], **fvec; + struct dirent *ent; + + *nfiles = 0; + fvec = NULL; + + fd = open(dir, O_RDONLY); + if (fd == -1) { + cvs_log(LP_ERRNO, "failed to open `%s'", dir); + return (NULL); + } + ret = getdirentries(fd, fbuf, sizeof(fbuf), &base); + if (ret == -1) { + cvs_log(LP_ERRNO, "failed to get directory entries"); + (void)close(fd); + return (NULL); + } + + dp = fbuf; + ep = fbuf + (size_t)ret; + while (dp < ep) { + ent = (struct dirent *)dp; + dp += ent->d_reclen; + + if (cvs_file_isignored(ent->d_name)) + continue; + + tmp = realloc(fvec, (*nfiles + 1) * sizeof(char *)); + if (tmp == NULL) { + cvs_log(LP_ERRNO, "failed to reallocate file vector"); + (void)close(fd); + free(fvec); + return (NULL); + } + fvec[++(*nfiles)] = strdup(ent->d_name); + + *nfiles++; + } + + (void)close(fd); + + return (fvec); +} + + +/* + * cvs_file_freev() + * + * Free a file vector obtained with cvs_file_getv(). + */ + +void +cvs_file_freev(char **fvec, int nfiles) +{ + int i; + + for (i = 0; i < nfiles; i++) + free(fvec[i]); + free(fvec); +} |