diff --git a/src/sbbs3/js_file.c b/src/sbbs3/js_file.c
index d5cdf5ab2e3226438738cf1828721e2d4b08f554..c7028fc2c90a70437cd33a0576714de8c5c0121d 100644
--- a/src/sbbs3/js_file.c
+++ b/src/sbbs3/js_file.c
@@ -1248,6 +1248,31 @@ js_rewind(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 	return(JS_TRUE);
 }
 
+static JSBool
+js_truncate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+	private_t*	p;
+	int32		len=0;
+
+	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
+		JS_ReportError(cx,getprivate_failure,WHERE);
+		return(JS_FALSE);
+	}
+
+	if(argc) {
+		if(!JS_ValueToInt32(cx,argv[0],&len))
+			return(JS_FALSE);
+	}
+
+	*rval = JSVAL_FALSE;
+	if(p->fp!=NULL && chsize(fileno(p->fp),len)==0) {
+		fseek(p->fp,len,SEEK_SET);
+		*rval = JSVAL_TRUE;
+	}
+
+	return(JS_TRUE);
+}
+
 static JSBool
 js_clear_error(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
@@ -1705,6 +1730,11 @@ static jsSyncMethodSpec js_file_functions[] = {
 		"and clears error and end-of-file indicators")
 	,311
 	},
+	{"truncate",		js_truncate,		0,	JSTYPE_BOOLEAN,	JSDOCSTR("[length]")
+	,JSDOCSTR("changes the file <i>length</i> (default: 0) and repositions the file pointer "
+	"(<i>position</i>) to the new end-of-file")
+	,31301
+	},
 	{"lock",			js_lock,			2,	JSTYPE_BOOLEAN,	JSDOCSTR("[offset, length]")
 	,JSDOCSTR("lock file record for exclusive access (file must be opened <i>shareable</i>)")
 	,310