diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c
index ada3b2ded35b407dc6b006870540af20904f6438..be8f0c90f1cf61c25e0a328437ce822580964f98 100644
--- a/src/sbbs3/userdat.c
+++ b/src/sbbs3/userdat.c
@@ -2217,66 +2217,73 @@ int getuserrec(scfg_t* cfg, int usernumber,int start, int length, char *str)
 }
 
 /****************************************************************************/
-/* Places into user.dat at the offset for usernumber+start for length bytes */
-/* Called from various locations											*/
+/* Write a string (str) into user.dat at the offset for usernumber + start	*/
+/* 'length' may be auto-determined (from 'start') by passing 0 for length	*/
+/* If 'str' is longer than 'length', only 'length' characters are written	*/
 /****************************************************************************/
-int putuserrec(scfg_t* cfg, int usernumber,int start, uint length, const char *str)
+int putuserrec(scfg_t* cfg, int usernumber, int start, int length, const char *str)
 {
-	char	str2[256];
+	const char*	p;
+	char	buf[256];
+	char	path[MAX_PATH + 1];
 	int		file;
-	uint	c,i;
+	uint	i;
 
-	if(!VALID_CFG(cfg) || usernumber<1 || str==NULL)
-		return(-1);
+	if(!VALID_CFG(cfg) || usernumber < 1 || str == NULL)
+		return -1;
 
-	if(length > sizeof(str2) - 1)
-		return -10;
+	if(length == 0) {	/* auto-length */
+		length = user_rec_len(start);
+		if(length < 1)
+			return -2;
+	}
+	size_t slen = strlen(str);
+	if(slen >= (size_t)length)
+		p = str;
+	else {
+		if(length > sizeof(buf))
+			return -10;
+		memset(buf, ETX, length);
+		memcpy(buf, str, slen);
+		p = buf;
+	}
 
-	SAFEPRINTF(str2,"%suser/user.dat",cfg->data_dir);
-	if((file=nopen(str2,O_RDWR|O_DENYNONE))==-1)
-		return(errno);
+	SAFEPRINTF(path, "%suser/user.dat", cfg->data_dir);
+	if((file = nopen(path, O_RDWR|O_DENYNONE))==-1)
+		return errno;
 
-	if(filelength(file)<((long)usernumber-1)*U_LEN) {
+	off_t offset = (usernumber - 1) * U_LEN;
+	if(filelength(file) < offset) {
 		close(file);
-		return(-4);
-	}
-
-	if(length==0) {	/* auto-length */
-		length=user_rec_len(start);
-		if((long)length < 0) {
-			close(file);
-			return -2;
-		}
+		return -4;
 	}
 
-	SAFECOPY(str2,str);
-	if(strlen(str2)<length) {
-		for(c=strlen(str2);c<length;c++)
-			str2[c]=ETX;
-		str2[c]=0;
+	offset += start;
+	if(lseek(file, offset, SEEK_SET) != offset) {
+		close(file);
+		return -5;
 	}
-	lseek(file,(long)((long)((long)((long)usernumber-1)*U_LEN)+start),SEEK_SET);
 
 	i=0;
-	while(i<LOOP_NODEDAB
-		&& lock(file,(long)((long)(usernumber-1)*U_LEN)+start,length)==-1) {
+	while(i < LOOP_NODEDAB
+		&& lock(file, offset, length) == -1) {
 		if(i)
 			mswait(100);
 		i++;
 	}
 
-	if(i>=LOOP_NODEDAB) {
+	if(i >= LOOP_NODEDAB) {
 		close(file);
-		return(-3);
+		return -3;
 	}
 
-	int wr = write(file, str2, length);
-	unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
+	int wr = write(file, p, length);
+	unlock(file, offset, length);
 	close(file);
 	if(wr != length)
-		return -4;
-	dirtyuserdat(cfg,usernumber);
-	return(0);
+		return -6;
+	dirtyuserdat(cfg, usernumber);
+	return 0;
 }
 
 /****************************************************************************/
diff --git a/src/sbbs3/userdat.h b/src/sbbs3/userdat.h
index 2f47bfadbd4e32d46aeb31dbeec371e5a21073cc..9dc1d7915f344a0e30370550440c64759a69213e 100644
--- a/src/sbbs3/userdat.h
+++ b/src/sbbs3/userdat.h
@@ -81,7 +81,7 @@ DLLEXPORT uint	userdatdupe(scfg_t*, uint usernumber, uint offset, uint datlen, c
 DLLEXPORT BOOL	chk_ar(scfg_t*, uchar* str, user_t*, client_t*); /* checks access requirements */
 
 DLLEXPORT int	getuserrec(scfg_t*, int usernumber, int start, int length, char *str);
-DLLEXPORT int	putuserrec(scfg_t*, int usernumber, int start, uint length, const char *str);
+DLLEXPORT int	putuserrec(scfg_t*, int usernumber, int start, int length, const char *str);
 DLLEXPORT ulong	adjustuserrec(scfg_t*, int usernumber, int start, int length, long adj);
 DLLEXPORT BOOL	logoutuserdat(scfg_t*, user_t*, time_t now, time_t logontime);
 DLLEXPORT void	resetdailyuserdat(scfg_t*, user_t*, BOOL write);