diff --git a/src/modules/rlm_detail/rlm_detail.c b/src/modules/rlm_detail/rlm_detail.c
index fba5e9d..5a859f5 100644
--- a/src/modules/rlm_detail/rlm_detail.c
+++ b/src/modules/rlm_detail/rlm_detail.c
@@ -28,9 +28,11 @@ RCSID("$Id$")
 #include	<freeradius-devel/rad_assert.h>
 #include	<freeradius-devel/detail.h>
 
-#include	<sys/stat.h>
 #include	<ctype.h>
 #include	<fcntl.h>
+#include	<sys/stat.h>
+#include	<sys/types.h>
+#include	<unistd.h>
 
 #define 	DIRLEN	8192
 
@@ -170,6 +172,33 @@ static int detail_instantiate(CONF_SECTION *conf, void **instance)
 }
 
 /*
+ * Perform a checked write. If the write fails or is not complete, truncate
+ * the file, eliminating the last bytes_accum + current partial write.
+ */
+int checked_write(off_t *bytes_accum, FILE *fp, const char *format, ...) {
+	char buf[2048];
+	int buf_used, written;
+	va_list args;
+
+	va_start(args, format);
+	buf_used = vsnprintf(buf, sizeof(buf), format, args);
+
+	written = fputs(buf, fp);
+	if (written > 0) {
+		*bytes_accum += written;
+	}
+	if (written != buf_used) {
+		/* Don't worry if the truncate fails, since the detail
+		 * reader ignores partial entries.
+		 */
+		ftruncate(fileno(fp), ftell(fp) - *bytes_accum);
+		fclose(fp);
+		return -written;
+	}
+	return written;
+}
+
+/*
  *	Do detail, compatible with old accounting
  */
 static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
@@ -183,6 +212,7 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
 	struct stat	st;
 	int		locked;
 	int		lock_count;
+	off_t		bytes_accum = 0;
 	struct timeval	tv;
 	VALUE_PAIR	*pair;
 
@@ -205,7 +235,11 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
 	 *	feed it through radius_xlat() to expand the
 	 *	variables.
 	 */
-	radius_xlat(buffer, sizeof(buffer), inst->detailfile, request, NULL);
+	if (radius_xlat(buffer, sizeof(buffer), inst->detailfile, request, NULL) == 0) {
+		radlog_request(L_ERR, 0, request, "rlm_detail: Failed to expand detail file %s",
+		    inst->detailfile);
+	    return RLM_MODULE_FAIL;
+	}
 	RDEBUG2("%s expands to %s", inst->detailfile, buffer);
 
 	/*
@@ -332,9 +366,23 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
 	/*
 	 *	Post a timestamp
 	 */
-	fseek(outfp, 0L, SEEK_END);
-	radius_xlat(timestamp, sizeof(timestamp), inst->header, request, NULL);
-	fprintf(outfp, "%s\n", timestamp);
+	if (fseek(outfp, 0L, SEEK_END) != 0) {
+		radlog_request(L_ERR, 0, request, "rlm_detail: Failed to seek to the end of detail file %s",
+			buffer);
+		fclose(outfp);
+		return RLM_MODULE_FAIL;
+	}
+	if (radius_xlat(timestamp, sizeof(timestamp), inst->header, request, NULL) == 0) {
+		radlog_request(L_ERR, 0, request, "rlm_detail: Unable to expand detail header format %s",
+			inst->header);
+		fclose(outfp);
+		return RLM_MODULE_FAIL;
+	}
+	if (checked_write(&bytes_accum, outfp, "%s\n", timestamp) < 0) {
+		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+			buffer, strerror(errno));
+		return RLM_MODULE_FAIL;
+	}
 
 	/*
 	 *	Write the information to the file.
@@ -346,10 +394,20 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
 		 */
 		if ((packet->code > 0) &&
 		    (packet->code < FR_MAX_PACKET_CODE)) {
-			fprintf(outfp, "\tPacket-Type = %s\n",
-				fr_packet_codes[packet->code]);
+			if (checked_write(&bytes_accum, outfp,
+				"\tPacket-Type = %s\n",
+				fr_packet_codes[packet->code]) == -1) {
+        		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+	        		buffer, strerror(errno));
+				return RLM_MODULE_FAIL;	
+			}
 		} else {
-			fprintf(outfp, "\tPacket-Type = %d\n", packet->code);
+			if (checked_write(&bytes_accum, outfp,
+				"\tPacket-Type = %d\n", packet->code) == -1) {
+        		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+	        		buffer, strerror(errno));
+				return RLM_MODULE_FAIL;
+			}
 		}
 	}
 
@@ -385,12 +443,28 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
 			break;
 		}
 
-		fputs("\t", outfp);
+		if (checked_write(&bytes_accum, outfp, "\t") == -1) {
+       		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+        		buffer, strerror(errno));
+			return RLM_MODULE_FAIL;
+		}
 		vp_print(outfp, &src_vp);
-		fputs("\n", outfp);
-		fputs("\t", outfp);
+		if (checked_write(&bytes_accum, outfp, "\n") == -1) {
+       		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+        		buffer, strerror(errno));
+			return RLM_MODULE_FAIL;
+		}
+		if (checked_write(&bytes_accum, outfp, "\t") == -1) {
+       		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+        		buffer, strerror(errno));
+			return RLM_MODULE_FAIL;
+		}
 		vp_print(outfp, &dst_vp);
-		fputs("\n", outfp);
+		if (checked_write(&bytes_accum, outfp, "\n") == -1) {
+       		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+        		buffer, strerror(errno));
+			return RLM_MODULE_FAIL;
+		}
 
 		src_vp.attribute = PW_PACKET_SRC_PORT;
 		src_vp.type = PW_TYPE_INTEGER;
@@ -399,12 +473,28 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
 		dst_vp.type = PW_TYPE_INTEGER;
 		dst_vp.vp_integer = packet->dst_port;
 
-		fputs("\t", outfp);
+		if (checked_write(&bytes_accum, outfp, "\t") == -1) {
+       		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+        		buffer, strerror(errno));
+			return RLM_MODULE_FAIL;
+		}
 		vp_print(outfp, &src_vp);
-		fputs("\n", outfp);
-		fputs("\t", outfp);
+		if (checked_write(&bytes_accum, outfp, "\n") == -1) {
+       		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+        		buffer, strerror(errno));
+			return RLM_MODULE_FAIL;
+		}
+		if (checked_write(&bytes_accum, outfp, "\t") == -1) {
+       		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+        		buffer, strerror(errno));
+			return RLM_MODULE_FAIL;
+		}
 		vp_print(outfp, &dst_vp);
-		fputs("\n", outfp);
+		if (checked_write(&bytes_accum, outfp, "\n") == -1) {
+       		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+        		buffer, strerror(errno));
+			return RLM_MODULE_FAIL;
+		}
 	}
 
 	/* Write each attribute/value to the log file */
@@ -423,9 +513,17 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
 		/*
 		 *	Print all of the attributes.
 		 */
-		fputs("\t", outfp);
+		if (checked_write(&bytes_accum, outfp, "\t") == -1) {
+       		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+        		buffer, strerror(errno));
+			return RLM_MODULE_FAIL;
+		}
 		vp_print(outfp, pair);
-		fputs("\n", outfp);
+		if (checked_write(&bytes_accum, outfp, "\n") == -1) {
+       		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+        		buffer, strerror(errno));
+			return RLM_MODULE_FAIL;
+		}
 	}
 
 	/*
@@ -438,23 +536,42 @@ static int do_detail(void *instance, REQUEST *request, RADIUS_PACKET *packet,
 			inet_ntop(request->proxy->dst_ipaddr.af,
 				  &request->proxy->dst_ipaddr.ipaddr,
 				  proxy_buffer, sizeof(proxy_buffer));
-			fprintf(outfp, "\tFreeradius-Proxied-To = %s\n",
-					proxy_buffer);
-				RDEBUG("Freeradius-Proxied-To = %s",
-				      proxy_buffer);
+			if (checked_write(&bytes_accum, outfp,
+				"\tFreeradius-Proxied-To = %s\n",
+				proxy_buffer) == -1) {
+           		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+            		buffer, strerror(errno));
+				return RLM_MODULE_FAIL;   
+			}
+			RDEBUG("Freeradius-Proxied-To = %s",
+				proxy_buffer);
 		}
 
-		fprintf(outfp, "\tTimestamp = %ld\n",
-			(unsigned long) request->timestamp);
+		if (checked_write(&bytes_accum, outfp,
+			"\tTimestamp = %ld\n",
+			(unsigned long) request->timestamp) == -1) {
+	 		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+		   		buffer, strerror(errno));
+			return RLM_MODULE_FAIL;
+		}
 
 		/*
 		 *	We no longer permit Accounting-Request packets
 		 *	with an authenticator of zero.
 		 */
-		fputs("\tRequest-Authenticator = Verified\n", outfp);
+		if (checked_write(&bytes_accum, outfp,
+			"\tRequest-Authenticator = Verified\n") == -1) {
+	 		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+		   		buffer, strerror(errno));
+			return RLM_MODULE_FAIL;
+		}
 	}
 
-	fputs("\n", outfp);
+	if (checked_write(&bytes_accum, outfp, "\n") == -1) {
+		radlog_request(L_ERR, 0, request, "rlm_detail: Got short write for detail file %s: %s",
+	   		buffer, strerror(errno));
+		return RLM_MODULE_FAIL;
+	}
 
 	if (inst->locking) {
 		fflush(outfp);
