summaryrefslogtreecommitdiff
path: root/usr.bin/cvs/file.c
diff options
context:
space:
mode:
authorJoris Vink <joris@cvs.openbsd.org>2005-06-14 15:27:32 +0000
committerJoris Vink <joris@cvs.openbsd.org>2005-06-14 15:27:32 +0000
commit9c7eda0365b7c23520fbc684ef785dffd90ab524 (patch)
treef92e78c7d21e45825946721553c2ebe18f7b6f4f /usr.bin/cvs/file.c
parent15ca9651efc74c158bdbd509b206196cde48c2e3 (diff)
finish pruning support, this has been sitting
in my tree since c2k5 ok xsa@
Diffstat (limited to 'usr.bin/cvs/file.c')
-rw-r--r--usr.bin/cvs/file.c67
1 files changed, 65 insertions, 2 deletions
diff --git a/usr.bin/cvs/file.c b/usr.bin/cvs/file.c
index 44d831ae5bb..d12d6eddef0 100644
--- a/usr.bin/cvs/file.c
+++ b/usr.bin/cvs/file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.c,v 1.87 2005/06/09 01:45:45 joris Exp $ */
+/* $OpenBSD: file.c,v 1.88 2005/06/14 15:27:31 joris Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -116,7 +116,6 @@ static CVSFILE* cvs_file_alloc (const char *, u_int);
static CVSFILE* cvs_file_lget (const char *, int, CVSFILE *, struct cvs_ent *);
-
/*
* cvs_file_init()
*
@@ -1153,3 +1152,67 @@ cvs_file_cmpname(const char *name1, const char *name2)
return (cvs_nocase == 0) ? (strcmp(name1, name2)) :
(strcasecmp(name1, name2));
}
+
+/*
+ * remove a directory if it does not contain
+ * any files other than the CVS/ administrative files.
+ */
+int
+cvs_file_prune(char *path)
+{
+ DIR *dirp;
+ int l, pwd, empty;
+ struct dirent *dp;
+ char fpath[MAXPATHLEN];
+ CVSENTRIES *entf;
+
+ pwd = (!strcmp(path, "."));
+
+ if ((dirp = opendir(path)) == NULL) {
+ cvs_log(LP_ERRNO, "failed to open `%s'", fpath);
+ return (-1);
+ }
+
+ empty = 0;
+ entf = cvs_ent_open(path, O_RDWR);
+
+ while ((dp = readdir(dirp)) != NULL) {
+ if (!strcmp(dp->d_name, ".") ||
+ !strcmp(dp->d_name, "..") ||
+ !strcmp(dp->d_name, CVS_PATH_CVSDIR))
+ continue;
+
+ empty++;
+ if (dp->d_type == DT_DIR) {
+ l = snprintf(fpath, sizeof(fpath), "%s%s%s",
+ (pwd) ? "" : path, (pwd) ? "" : "/", dp->d_name);
+ if (l == -1 || l >= (int)sizeof(fpath)) {
+ errno = ENAMETOOLONG;
+ cvs_log(LP_ERRNO, "%s", fpath);
+ continue;
+ }
+
+ if (cvs_file_prune(fpath)) {
+ empty--;
+ if (entf)
+ cvs_ent_remove(entf, fpath);
+ } else {
+ empty++;
+ }
+ }
+ }
+
+ closedir(dirp);
+ if (entf)
+ cvs_ent_close(entf);
+
+ empty = (empty == 0);
+ if (empty) {
+ if (cvs_remove_dir(path) < 0) {
+ cvs_log(LP_ERR, "failed to prune `%s'", path);
+ empty = 0;
+ }
+ }
+
+ return (empty);
+}