summaryrefslogtreecommitdiff
path: root/usr.bin/cvs/file.c
diff options
context:
space:
mode:
authorJean-Francois Brousseau <jfb@cvs.openbsd.org>2005-01-03 22:53:07 +0000
committerJean-Francois Brousseau <jfb@cvs.openbsd.org>2005-01-03 22:53:07 +0000
commitfb7d022f94f7f3472324e1f25d612c1d0907006d (patch)
treec34f8fdef6bcaaa1b0f4f5cc77cfa67c647fc6e1 /usr.bin/cvs/file.c
parent1b777c790d75642378b0eb0c2a6521f26761fa76 (diff)
when releasing a file structure, free the reference to its name so
we don't leak memory spotted by Joris Vink, more complete diff from me
Diffstat (limited to 'usr.bin/cvs/file.c')
-rw-r--r--usr.bin/cvs/file.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/usr.bin/cvs/file.c b/usr.bin/cvs/file.c
index 4aca44e51e2..aaa38e743c2 100644
--- a/usr.bin/cvs/file.c
+++ b/usr.bin/cvs/file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.c,v 1.46 2004/12/28 20:00:14 jfb Exp $ */
+/* $OpenBSD: file.c,v 1.47 2005/01/03 22:53:06 jfb Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -121,6 +121,7 @@ static int cvs_file_cmp (const void *, const void *);
static int cvs_file_cmpname (const char *, const char *);
static u_int8_t cvs_file_hashname (const char *);
static struct cvs_fname* cvs_file_getname (const char *);
+static void cvs_file_freename (struct cvs_fname *);
static CVSFILE* cvs_file_alloc (const char *, u_int);
static CVSFILE* cvs_file_lget (const char *, int, CVSFILE *);
@@ -688,6 +689,8 @@ cvs_file_free(CVSFILE *cf)
{
if (cf->cf_ddat != NULL)
cvs_file_freedir(cf->cf_ddat);
+ if (cf->cf_name != NULL)
+ cvs_file_freename(cf->cf_name);
free(cf);
}
@@ -1008,3 +1011,31 @@ cvs_file_getname(const char *name)
return (fnp);
}
+
+
+/*
+ * cvs_file_freename()
+ *
+ * Free the reference to a file name previously obtained with
+ * cvs_file_getname().
+ */
+static void
+cvs_file_freename(struct cvs_fname *fn)
+{
+ u_int8_t h;
+
+ if (fn->cf_ref == 0) {
+ cvs_log(LP_WARN, "refcount for `%s' is already 0", fn->cf_name);
+ return;
+ }
+
+ fn->cf_ref--;
+ if (fn->cf_ref == 0) {
+ /* no more references, free the file */
+ h = cvs_file_hashname(fn->cf_name);
+
+ SLIST_REMOVE(&(cvs_fnht[h]), fn, cvs_fname, cf_list);
+ free(fn->cf_name);
+ free(fn);
+ }
+}