Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Feb 2009 22:20:38 GMT
From:      Stacey Son <sson@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 157612 for review
Message-ID:  <200902122220.n1CMKcaK029439@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=157612

Change 157612 by sson@sson_amd64 on 2009/02/12 22:19:43

	Rewrite auditd_expire_trails() to use a TAILQ instead of an array
	since the assumption that you can stat a directory and look at the
	nlinks of the file count doesn't hold for all file systems.
	
	Also, if the time stamp encoded in the trail file name is valid
	use it instead of the mtime of the file.

Affected files ...

.. //depot/projects/trustedbsd/openbsm/libauditd/auditd_lib.c#6 edit

Differences ...

==== //depot/projects/trustedbsd/openbsm/libauditd/auditd_lib.c#6 (text+ko) ====

@@ -26,7 +26,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- * $P4: //depot/projects/trustedbsd/openbsm/libauditd/auditd_lib.c#5 $
+ * $P4: //depot/projects/trustedbsd/openbsm/libauditd/auditd_lib.c#6 $
  */
 
 #include <sys/param.h>
@@ -93,9 +93,11 @@
 static TAILQ_HEAD(, dir_ent)	dir_q;
 
 struct audit_trail {
-	time_t			 at_mtime;
+	time_t			 at_time;
 	char			*at_path;
 	off_t			 at_size;
+
+	TAILQ_ENTRY(audit_trail) at_trls;
 };
 
 static int auditd_minval = -1;
@@ -309,19 +311,73 @@
 }
 
 /*
- * Comparison function for audit trail sorting.  Compare modification times
- * of trail files.
+ * Convert a trailname into a timestamp (seconds).  Return 0 if the conversion
+ * was successful.
  */
 static int
-trails_cmp(const void *t1, const void *t2)
+trailname_to_tstamp(char *fn, time_t *tstamp)
 {
-	struct audit_trail *a = (struct audit_trail *)t1;
-	struct audit_trail *b = (struct audit_trail *)t2;
+	struct tm tm;
+	char ts[TIMESTAMP_LEN];
+	char *p;
+
+	*tstamp = 0;
+
+	/*
+	 * Get the ending time stamp.
+	 */
+	if ((p = strchr(fn, '.')) == NULL)
+		return (1);
+	strlcpy(ts, ++p, TIMESTAMP_LEN);
+	if (strlen(ts) != POSTFIX_LEN)
+		return (1);
+
+	bzero(&tm, sizeof(tm));
+
+	/* seconds (0-60) */
+	p = ts + POSTFIX_LEN - 2;
+	printf("sec = [%s]\n", p);
+	tm.tm_sec = atol(p);
+	if (tm.tm_sec < 0 || tm.tm_sec > 60)
+		return (1);
+
+	/* minutes (0-59) */ 
+	*p = '\0'; p -= 2;
+	printf("min = [%s]\n", p);
+	tm.tm_min = atol(p);
+	if (tm.tm_min < 0 || tm.tm_min > 59)
+		return (1);
+
+	/* hours (0 - 23) */
+	*p = '\0'; p -= 2;
+	printf("hr = [%s]\n", p);
+	tm.tm_hour = atol(p);
+	if (tm.tm_hour < 0 || tm.tm_hour > 23)
+		return (1);
+
+	/* day of month (1-31) */
+	*p = '\0'; p -= 2;
+	printf("dom = [%s]\n", p);
+	tm.tm_mday = atol(p);
+	if (tm.tm_mday < 1 || tm.tm_mday > 31)
+		return (1);
+
+	/* month (0 - 11) */
+	*p = '\0'; p -= 2;
+	printf("mon = [%s]\n", p);
+	tm.tm_mon = atol(p) - 1;
+	if (tm.tm_mon < 0 || tm.tm_mon > 11)
+		return (1);
 
-	if (a->at_mtime < b->at_mtime)
-		return (-1);
-	if (a->at_mtime > b->at_mtime)
+	/* year (year - 1900) */
+	*p = '\0'; p -= 4;
+	printf("yr = [%s]\n", p);
+	tm.tm_year = atol(p) - 1900;
+	if (tm.tm_year < 0)
 		return (1);
+
+	*tstamp = timegm(&tm);
+
 	return (0);
 }
 
@@ -335,12 +391,14 @@
 int
 auditd_expire_trails(int (*warn_expired)(char *))
 {
-	int andflg, i, n = 0, num_trails = 0, ret = ADE_NOERR;
+	int andflg, ret = ADE_NOERR;
 	size_t expire_size, total_size = 0L;
 	time_t expire_age, oldest_time, current_time = time(NULL);
 	struct dir_ent *traildir;
-	struct audit_trail *trail;
+	struct audit_trail *at;
 	char *afnp, *pn;
+	TAILQ_HEAD(au_trls_head, audit_trail) head =
+	    TAILQ_HEAD_INITIALIZER(head);
 	struct stat stbuf;
 	char activefn[MAXPATHLEN];
 
@@ -361,23 +419,9 @@
 	if ((afnp = strrchr(activefn, '/')) != NULL) 
 		afnp++;
 
-	/*
-	 * Count up the number of audit trail files we have in all the audit
-	 * trail directories.
-	 */
-	num_trails = 0;
-	TAILQ_FOREACH(traildir, &dir_q, dirs) {
-		if (stat(traildir->dirname, &stbuf) == 0)
-			num_trails += (stbuf.st_nlink - 2);
-	}
-
-	trail = (struct audit_trail *)malloc(sizeof(struct audit_trail) *
-	    num_trails);
-	if (NULL == trail)
-		return (ADE_NOMEM);
 
 	/*
-	 * Build an array of the trail files.
+	 * Build tail queue of the trail files.
 	 */
 	TAILQ_FOREACH(traildir, &dir_q, dirs) {
 		DIR *dirp;
@@ -385,51 +429,64 @@
 
 		dirp = opendir(traildir->dirname);
 		while ((dp = readdir(dirp)) != NULL) {
+			time_t tstamp = 0;
+			struct audit_trail *new;
 
 			/*
-			 * Filter non-trail files.
+			 * Quickly filter non-trail files.
 			 */
-			if (dp->d_type != DT_REG || 
-			    dp->d_namlen != (FILENAME_LEN - 1) ||
+			if (dp->d_namlen != (FILENAME_LEN - 1) ||
+#ifdef DT_REG
+			    dp->d_type != DT_REG || 
+#endif
 			    dp->d_name[POSTFIX_LEN] != '.')
 				continue;
 
-
-			if (n > num_trails) {
-				/*
-				 * This shouldn't happen but, if it does, we 
-				 * break out of the loop and expire what trail
-				 * files we have.  Also, return there was an
-				 * error.
-				 */
-				ret = ADE_EXPIRE;
-				break;
-			}
-
 			if (asprintf(&pn, "%s/%s", traildir->dirname,
 				dp->d_name) < 0) {
 				ret = ADE_NOMEM;
 				break;
 			}
 
-			if (stat(pn, &stbuf) < 0) {
+			if (stat(pn, &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) {
+				free(pn);
+				continue;
+			}
+
+			total_size += stbuf.st_size;
+
+			/*
+			 * If this is the 'current' audit trail then
+			 * don't add it to the tail queue.
+			 */
+			if (NULL != afnp &&
+			    strncmp(dp->d_name, afnp, FILENAME_LEN) == 0) {
 				free(pn);
 				continue;
 			}
 
 			/*
-			 * If the mtime is older than Jan 1, 2000 then update
-			 * the mtime of the trail file to the current time.
-			 * This is so we don't prematurely remove a trail file
-			 * that was created while the system clock reset to the
-			 * "beginning of time" but later the system clock is set
-			 * to the correct current time.
+			 * Get the ending time stamp encoded in the trail
+			 * name.  If we can't read it or if it is older
+			 * than Jan 1, 2000 then use the mtime.
+			 */
+			if (trailname_to_tstamp(dp->d_name, &tstamp) != 0 ||
+			    tstamp < JAN_01_2000)
+				tstamp = stbuf.st_mtime;
+
+			/*
+			 * If the time stamp is older than Jan 1, 2000 then
+			 * update the mtime of the trail file to the current
+			 * time. This is so we don't prematurely remove a trail
+			 * file that was created while the system clock reset
+			 * to the * "beginning of time" but later the system
+			 * clock is set to the correct current time.
 			 */
 			if (current_time >= JAN_01_2000 &&
-			    stbuf.st_mtime < JAN_01_2000) {
+			    tstamp < JAN_01_2000) {
 				struct timeval tv[2];
 
-				stbuf.st_mtime = current_time;
+				tstamp = stbuf.st_mtime = current_time;
 				TIMESPEC_TO_TIMEVAL(&tv[0], 
 				    &stbuf.st_atimespec);
 				TIMESPEC_TO_TIMEVAL(&tv[1], 
@@ -437,54 +494,74 @@
 				utimes(pn, tv);
 			}
 
-			total_size += stbuf.st_size;
-			if (NULL != afnp &&
-			    strncmp(dp->d_name, afnp, FILENAME_LEN) == 0) {
+			/*
+			 * Allocate and populate the new entry.
+			 */
+			new = malloc(sizeof(*new));
+			if (NULL == new) {
 				free(pn);
+				ret = ADE_NOMEM;
+				break;
+			}
+			new->at_time = tstamp;
+			new->at_size = stbuf.st_size;
+			new->at_path = pn;
+
+			/*
+			 * Check to see if we have a new head.  Otherwise,
+			 * walk the tailq from the tail first and do a simple
+			 * insertion sort.
+			 */
+			if (TAILQ_EMPTY(&head) ||
+			    (new->at_time <= TAILQ_FIRST(&head)->at_time)) {
+				TAILQ_INSERT_HEAD(&head, new, at_trls);
 				continue;
 			}
 
-			trail[n].at_mtime = stbuf.st_mtime;
-			trail[n].at_size = stbuf.st_size;
-			trail[n].at_path = pn;
-			n++;
+			TAILQ_FOREACH_REVERSE(at, &head, au_trls_head, at_trls)
+				if (new->at_time >= at->at_time) {
+					TAILQ_INSERT_AFTER(&head, at, new,
+					    at_trls);
+					break;
+				}
+
 		}
 	}
 
-	/*
-	 * Sort the array of trail files by the modification date.
-	 */
-	qsort(trail, n, sizeof(struct audit_trail), trails_cmp);
-
 	oldest_time = current_time - expire_age;
 
 	/* 
 	 * Expire trail files, oldest (mtime) first, if the given
 	 * conditions are met.
 	 */
-	for (i = 0; i < n; i++) {
+	at = TAILQ_FIRST(&head);
+	while (NULL != at) {
+		struct audit_trail *at_next = TAILQ_NEXT(at, at_trls);
+
 		if (andflg) {
 			if ((expire_size && total_size > expire_size) &&
-			    (expire_age && trail[i].at_mtime < oldest_time)) {
+			    (expire_age && at->at_time < oldest_time)) {
 				if (warn_expired)
-				    (*warn_expired)(trail[i].at_path);
-				if (unlink(trail[i].at_path) < 0)
+				    (*warn_expired)(at->at_path);
+				if (unlink(at->at_path) < 0)
 					ret = ADE_EXPIRE;
-				total_size -= trail[i].at_size;
+				total_size -= at->at_size;
 			}
 		} else {
 			if ((expire_size && total_size > expire_size) ||
-			    (expire_age && trail[i].at_mtime < oldest_time)) {
+			    (expire_age && at->at_time < oldest_time)) {
 				if (warn_expired)
-				    (*warn_expired)(trail[i].at_path);
-				if (unlink(trail[i].at_path) < 0)
+				    (*warn_expired)(at->at_path);
+				if (unlink(at->at_path) < 0)
 					ret = ADE_EXPIRE;
-				total_size -= trail[i].at_size;
+				total_size -= at->at_size;
 			}
 		}
-		free(trail[i].at_path);
+
+		free(at->at_path);
+		free(at);
+		at = at_next;
 	}
-	free(trail);
 
 	return (ret);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902122220.n1CMKcaK029439>