Skip to content
Snippets Groups Projects
js_file.c 87.8 KiB
Newer Older
					if (val < 0)
						*o.sb = (int8_t)val;
						*o.b = (uint8_t)val;
					if (val < 0)
						*o.sw = (int16_t)val;
						*o.w = (uint16_t)val;
					if (p->network_byte_order)
					if (val < 0)
						*o.sl = (int32_t)val;
						*o.l = (uint32_t)val;
					if (p->network_byte_order)
						*o.sq = (int64_t)val;
					else
						*o.q = (uint64_t)val;
					if (p->network_byte_order)
						*o.q = BE_INT64(*o.q);
					else
						*o.q = LE_INT64(*o.q);
	rc = JS_SUSPENDREQUEST(cx);
	wr = fwrite(buffer, size, count, p->fp);
	if (wr == count)
		JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
js_writeall(JSContext *cx, uintN argc, jsval *arglist)
	JSObject * obj = JS_THIS_OBJECT(cx, arglist);
	jsval *    argv = JS_ARGV(cx, arglist);
	jsuint     i;
	jsuint     limit;
	JSObject*  array;
	jsval      elemval;
	private_t* p;
	JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
	if ((p = (private_t*)js_GetClassPrivate(cx, obj, &js_file_class)) == NULL) {
	if (JSVAL_IS_NULL(argv[0]) || !JSVAL_IS_OBJECT(argv[0]))
	array = JSVAL_TO_OBJECT(argv[0]);
	if (array == NULL || !JS_IsArrayObject(cx, array))
	if (!JS_GetArrayLength(cx, array, &limit))
	JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
	for (i = 0; i < limit; i++) {
		jsval rval;
deuce's avatar
deuce committed

		if (!JS_GetElement(cx, array, i, &elemval))
		js_writeln_internal(cx, obj, &elemval, &rval);
		JS_SET_RVAL(cx, arglist, rval);
		if (rval != JSVAL_TRUE)
js_lock(JSContext *cx, uintN argc, jsval *arglist)
	JSObject * obj = JS_THIS_OBJECT(cx, arglist);
	jsval *    argv = JS_ARGV(cx, arglist);
	off_t      offset = 0;
	off_t      len = 0;
	private_t* p;
	jsrefcount rc;
	jsdouble   val;
	JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
	if ((p = (private_t*)js_GetClassPrivate(cx, obj, &js_file_class)) == NULL) {
	if (argc) {
		if (!JS_ValueToNumber(cx, argv[0], &val))
		offset = (off_t)val;
	if (argc > 1) {
		if (!JS_ValueToNumber(cx, argv[1], &val))
	rc = JS_SUSPENDREQUEST(cx);
	if (len == 0)
		len = filelength(fileno(p->fp)) - offset;
	if (lock(fileno(p->fp), offset, len) == 0)
		JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
js_unlock(JSContext *cx, uintN argc, jsval *arglist)
	JSObject * obj = JS_THIS_OBJECT(cx, arglist);
	jsval *    argv = JS_ARGV(cx, arglist);
	off_t      offset = 0;
	off_t      len = 0;
	private_t* p;
	jsrefcount rc;
	jsdouble   val;
	JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
	if ((p = (private_t*)js_GetClassPrivate(cx, obj, &js_file_class)) == NULL) {
	if (argc) {
		if (!JS_ValueToNumber(cx, argv[0], &val))
		offset = (off_t)val;
	if (argc > 1) {
		if (!JS_ValueToNumber(cx, argv[1], &val))
	rc = JS_SUSPENDREQUEST(cx);
	if (len == 0)
		len = filelength(fileno(p->fp)) - offset;
	if (unlock(fileno(p->fp), offset, len) == 0)
		JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
static JSBool
js_delete(JSContext *cx, uintN argc, jsval *arglist)
	JSObject * obj = JS_THIS_OBJECT(cx, arglist);
	private_t* p;
	jsrefcount rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((p = (private_t*)js_GetClassPrivate(cx, obj, &js_file_class)) == NULL) {
	if (p->fp != NULL) {   /* close it if it's open */
		fclose(p->fp);
	rc = JS_SUSPENDREQUEST(cx);
	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(remove(p->name) == 0));
js_flush(JSContext *cx, uintN argc, jsval *arglist)
	JSObject * obj = JS_THIS_OBJECT(cx, arglist);
	private_t* p;
	jsrefcount rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((p = (private_t*)js_GetClassPrivate(cx, obj, &js_file_class)) == NULL) {
	rc = JS_SUSPENDREQUEST(cx);
	if (p->fp == NULL)
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
		JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(fflush(p->fp) == 0));
js_rewind(JSContext *cx, uintN argc, jsval *arglist)
	JSObject * obj = JS_THIS_OBJECT(cx, arglist);
	private_t* p;
	jsrefcount rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((p = (private_t*)js_GetClassPrivate(cx, obj, &js_file_class)) == NULL) {
	rc = JS_SUSPENDREQUEST(cx);
	if (p->fp == NULL)
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
		JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
js_truncate(JSContext *cx, uintN argc, jsval *arglist)
	JSObject * obj = JS_THIS_OBJECT(cx, arglist);
	jsval *    argv = JS_ARGV(cx, arglist);
	private_t* p;
	int32      len = 0;
	jsrefcount rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((p = (private_t*)js_GetClassPrivate(cx, obj, &js_file_class)) == NULL) {
	if (argc && !JSVAL_NULL_OR_VOID(argv[0])) {
		if (!JS_ValueToInt32(cx, argv[0], &len))
	rc = JS_SUSPENDREQUEST(cx);
	JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
	if (p->fp != NULL && chsize(fileno(p->fp), len) == 0) {
		fseek(p->fp, len, SEEK_SET);
		JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
js_clear_error(JSContext *cx, uintN argc, jsval *arglist)
	JSObject * obj = JS_THIS_OBJECT(cx, arglist);
	private_t* p;
	jsrefcount rc;
	JS_SET_RVAL(cx, arglist, JSVAL_VOID);

	if ((p = (private_t*)js_GetClassPrivate(cx, obj, &js_file_class)) == NULL) {
	rc = JS_SUSPENDREQUEST(cx);
	if (p->fp == NULL)
		JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
	else  {
		clearerr(p->fp);
		JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
js_fprintf(JSContext *cx, uintN argc, jsval *arglist)
	JSObject * obj = JS_THIS_OBJECT(cx, arglist);
	jsval *    argv = JS_ARGV(cx, arglist);
	char*      cp;
	private_t* p;
	jsrefcount rc;
	JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
	if ((p = (private_t*)js_GetClassPrivate(cx, obj, &js_file_class)) == NULL) {
	if ((cp = js_sprintf(cx, 0, argc, argv)) == NULL) {
		JS_ReportError(cx, "js_sprintf failed");
	rc = JS_SUSPENDREQUEST(cx);
	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(fwrite(cp, 1, strlen(cp), p->fp)));
/* File Object Properties */
	FILE_PROP_NAME
	, FILE_PROP_MODE
	, FILE_PROP_ETX
	, FILE_PROP_EXISTS
	, FILE_PROP_DATE
	, FILE_PROP_IS_OPEN
	, FILE_PROP_EOF
	, FILE_PROP_ERROR
	, FILE_PROP_DESCRIPTOR
	, FILE_PROP_DEBUG
	, FILE_PROP_POSITION
	, FILE_PROP_LENGTH
	, FILE_PROP_ATTRIBUTES
	, FILE_PROP_YENCODED
	, FILE_PROP_UUENCODED
	, FILE_PROP_B64ENCODED
	, FILE_PROP_ROT13
	, FILE_PROP_NETWORK_ORDER
	, FILE_PROP_CHKSUM
	, FILE_PROP_CRC16
	, FILE_PROP_CRC32
	, FILE_PROP_MD5_HEX
	, FILE_PROP_MD5_B64
	, FILE_PROP_SHA1_HEX
	, FILE_PROP_SHA1_B64
	, FILE_INI_KEY_LEN
	, FILE_INI_KEY_PREFIX
	, FILE_INI_SECTION_SEPARATOR
	, FILE_INI_VALUE_SEPARATOR
	, FILE_INI_BIT_SEPARATOR
	, FILE_INI_LITERAL_SEPARATOR
static JSBool js_file_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
	jsval      idval;
	int        result;
	int32      i = 0;
	uint32     u = 0;
	jsint      tiny;
	private_t* p;
	jsrefcount rc;
	char*      str = NULL;

	if ((p = (private_t*)JS_GetInstancePrivate(cx, obj, &js_file_class, NULL)) == NULL) {
	JS_IdToValue(cx, id, &idval);
	tiny = JSVAL_TO_INT(idval);
	rc = JS_SUSPENDREQUEST(cx);
	dbprintf(FALSE, p, "setting property %d", tiny);
		case FILE_PROP_DEBUG:
			JS_ValueToBoolean(cx, *vp, &(p->debug));
			JS_ValueToBoolean(cx, *vp, &(p->yencoded));
			JS_ValueToBoolean(cx, *vp, &(p->uuencoded));
			JS_ValueToBoolean(cx, *vp, &(p->b64encoded));
			JS_ValueToBoolean(cx, *vp, &(p->rot13));
			JS_ValueToBoolean(cx, *vp, &(p->network_byte_order));
		case FILE_PROP_POSITION:
			if (p->fp != NULL) {
				if (!JS_ValueToECMAUint32(cx, *vp, &u))
				rc = JS_SUSPENDREQUEST(cx);
			if (!JS_ValueToECMAUint32(cx, *vp, &u))
			rc = JS_SUSPENDREQUEST(cx);
		case FILE_PROP_LENGTH:
			if (p->fp != NULL) {
				if (!JS_ValueToECMAUint32(cx, *vp, &u))
				rc = JS_SUSPENDREQUEST(cx);
				result = chsize(fileno(p->fp), u);
					JS_ReportError(cx, "Error %d changing file size", errno);
					return JS_FALSE;
				}
			break;
		case FILE_PROP_ATTRIBUTES:
			if (!JS_ValueToInt32(cx, *vp, &i))
			rc = JS_SUSPENDREQUEST(cx);
			(void)CHMOD(p->name, i);
		case FILE_PROP_ETX:
			if (!JS_ValueToInt32(cx, *vp, &i))
			if (!JS_ValueToInt32(cx, *vp, &i))
			p->ini_style.key_len = i;
			break;
		case FILE_INI_KEY_PREFIX:
			FREE_AND_NULL(p->ini_style.key_prefix);
			if (!JSVAL_NULL_OR_VOID(*vp)) {
				JSVALUE_TO_MSTRING(cx, *vp, str, NULL);
				HANDLE_PENDING(cx, str);
				p->ini_style.key_prefix = str;
			}
			break;
		case FILE_INI_SECTION_SEPARATOR:
			FREE_AND_NULL(p->ini_style.section_separator);
			if (!JSVAL_NULL_OR_VOID(*vp)) {
				JSVALUE_TO_MSTRING(cx, *vp, str, NULL);
				HANDLE_PENDING(cx, str);
				p->ini_style.section_separator = str;
			}
			break;
		case FILE_INI_VALUE_SEPARATOR:
			FREE_AND_NULL(p->ini_style.value_separator);
			if (!JSVAL_NULL_OR_VOID(*vp)) {
				JSVALUE_TO_MSTRING(cx, *vp, str, NULL);
				HANDLE_PENDING(cx, str);
				p->ini_style.value_separator = str;
			}
			break;
		case FILE_INI_BIT_SEPARATOR:
			FREE_AND_NULL(p->ini_style.bit_separator);
			if (!JSVAL_NULL_OR_VOID(*vp)) {
				JSVALUE_TO_MSTRING(cx, *vp, str, NULL);
				HANDLE_PENDING(cx, str);
				p->ini_style.bit_separator = str;
			}
			break;
		case FILE_INI_LITERAL_SEPARATOR:
			FREE_AND_NULL(p->ini_style.literal_separator);
			if (!JSVAL_NULL_OR_VOID(*vp)) {
				JSVALUE_TO_MSTRING(cx, *vp, str, NULL);
				HANDLE_PENDING(cx, str);
				p->ini_style.literal_separator = str;
			}
static JSBool js_file_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
	jsval      idval;
	char       str[128];
	char*      s = NULL;
	size_t     i;
	size_t     rd;
	off_t      offset;
	ulong      sum = 0;
	ushort     c16 = 0;
	uint32     c32 = ~0;
	MD5        md5_ctx;
	SHA1_CTX   sha1_ctx;
	BYTE       block[4096];
	BYTE       digest[SHA1_DIGEST_SIZE];
	jsint      tiny;
	JSString*  js_str = NULL;
	private_t* p;
	jsrefcount rc;
	time_t     tt;
	off_t      lng;
	int        in;

	if ((p = (private_t*)JS_GetPrivate(cx, obj)) == NULL)
	JS_IdToValue(cx, id, &idval);
	tiny = JSVAL_TO_INT(idval);
		case FILE_PROP_NAME:
			break;
		case FILE_PROP_MODE:
			break;
		case FILE_PROP_EXISTS:
			if (p->fp)   /* open? */
deuce's avatar
deuce committed
			else {
				rc = JS_SUSPENDREQUEST(cx);
				*vp = BOOLEAN_TO_JSVAL(fexistcase(p->name));
			break;
		case FILE_PROP_DATE:
			rc = JS_SUSPENDREQUEST(cx);
			tt = fdate(p->name);
			*vp = DOUBLE_TO_JSVAL((double)tt);
			break;
		case FILE_PROP_IS_OPEN:
			*vp = BOOLEAN_TO_JSVAL(p->fp != NULL);
			break;
		case FILE_PROP_EOF:
			if (p->fp) {
				rc = JS_SUSPENDREQUEST(cx);
				*vp = BOOLEAN_TO_JSVAL(feof(p->fp) != 0);
			break;
		case FILE_PROP_ERROR:
			if (p->fp) {
				rc = JS_SUSPENDREQUEST(cx);
				*vp = INT_TO_JSVAL(ferror(p->fp));
			break;
		case FILE_PROP_POSITION:
			if (p->fp) {
				rc = JS_SUSPENDREQUEST(cx);
				lng = ftell(p->fp);
				*vp = DOUBLE_TO_JSVAL((double)lng);
			break;
		case FILE_PROP_LENGTH:
			rc = JS_SUSPENDREQUEST(cx);
			if (p->fp)   /* open? */
deuce's avatar
deuce committed
				lng = filelength(fileno(p->fp));
deuce's avatar
deuce committed
				lng = flength(p->name);
			*vp = DOUBLE_TO_JSVAL((double)lng);
			break;
		case FILE_PROP_ATTRIBUTES:
			rc = JS_SUSPENDREQUEST(cx);
			in = getfmode(p->name);
			*vp = INT_TO_JSVAL(in);
			break;
		case FILE_PROP_DEBUG:
			*vp = BOOLEAN_TO_JSVAL(p->debug);
			break;
		case FILE_PROP_YENCODED:
			*vp = BOOLEAN_TO_JSVAL(p->yencoded);
			break;
		case FILE_PROP_UUENCODED:
			*vp = BOOLEAN_TO_JSVAL(p->uuencoded);
		case FILE_PROP_B64ENCODED:
			*vp = BOOLEAN_TO_JSVAL(p->b64encoded);
			break;
		case FILE_PROP_ROT13:
			*vp = BOOLEAN_TO_JSVAL(p->rot13);
			break;
		case FILE_PROP_NETWORK_ORDER:
			*vp = BOOLEAN_TO_JSVAL(p->network_byte_order);
			break;
		case FILE_PROP_DESCRIPTOR:
				*vp = INT_TO_JSVAL(fileno(p->fp));
			else
				*vp = INT_TO_JSVAL(-1);
		case FILE_PROP_ETX:
			*vp = INT_TO_JSVAL(p->etx);
			break;
		case FILE_PROP_CHKSUM:
		case FILE_PROP_CRC16:
		case FILE_PROP_CRC32:
			*vp = JSVAL_ZERO;
		case FILE_PROP_SHA1_HEX:
		case FILE_PROP_SHA1_B64:
			rc = JS_SUSPENDREQUEST(cx);
			offset = ftell(p->fp);            /* save current file position */
			fseek(p->fp, 0, SEEK_SET);
				case FILE_PROP_MD5_HEX:
				case FILE_PROP_MD5_B64:
					MD5_open(&md5_ctx);
					break;
				case FILE_PROP_SHA1_HEX:
				case FILE_PROP_SHA1_B64:
					SHA1Init(&sha1_ctx);
					break;
			while (!feof(p->fp)) {
				if ((rd = fread(block, 1, sizeof(block), p->fp)) < 1)
						for (i = 0; i < rd; i++)
							sum += block[i];
						for (i = 0; i < rd; i++)
							c16 = ucrc16(block[i], c16);
						for (i = 0; i < rd; i++)
							c32 = ucrc32(block[i], c32);
						break;
					case FILE_PROP_MD5_HEX:
					case FILE_PROP_MD5_B64:
						MD5_digest(&md5_ctx, block, rd);
					case FILE_PROP_SHA1_HEX:
					case FILE_PROP_SHA1_B64:
						SHA1Update(&sha1_ctx, block, rd);
					*vp = DOUBLE_TO_JSVAL((double)sum);
					*vp = UINT_TO_JSVAL(c16);
					*vp = UINT_TO_JSVAL(~c32);
					break;
				case FILE_PROP_MD5_HEX:
				case FILE_PROP_MD5_B64:
					MD5_close(&md5_ctx, digest);
					if (tiny == FILE_PROP_MD5_HEX)
						MD5_hex(str, digest);
						b64_encode(str, sizeof(str) - 1, (char *)digest, sizeof(digest));
					js_str = JS_NewStringCopyZ(cx, str);
					break;
				case FILE_PROP_SHA1_HEX:
				case FILE_PROP_SHA1_B64:
					SHA1Final(&sha1_ctx, digest);
					if (tiny == FILE_PROP_SHA1_HEX)
						SHA1_hex(str, digest);
						b64_encode(str, sizeof(str) - 1, (char *)digest, sizeof(digest));
					js_str = JS_NewStringCopyZ(cx, str);
			rc = JS_SUSPENDREQUEST(cx);
			fseeko(p->fp, offset, SEEK_SET);  /* restore saved file position */
		case FILE_INI_KEY_LEN:
			*vp = INT_TO_JSVAL(p->ini_style.key_len);
			break;
		case FILE_INI_KEY_PREFIX:
			s = p->ini_style.key_prefix;
			break;
		case FILE_INI_SECTION_SEPARATOR:
			s = p->ini_style.section_separator;
			break;
		case FILE_INI_VALUE_SEPARATOR:
			s = p->ini_style.value_separator;
			break;
		case FILE_INI_BIT_SEPARATOR:
			s = p->ini_style.bit_separator;
			break;
		case FILE_INI_LITERAL_SEPARATOR:
			s = p->ini_style.literal_separator;
	if (s != NULL) {
		if ((js_str = JS_NewStringCopyZ(cx, s)) == NULL)
			return JS_FALSE;
		*vp = STRING_TO_JSVAL(js_str);
#define FILE_PROP_FLAGS JSPROP_ENUMERATE | JSPROP_READONLY
static jsSyncPropertySpec js_file_properties[] = {
/*		 name				,tinyid					,flags,				ver	*/
	{   "name", FILE_PROP_NAME, FILE_PROP_FLAGS,   310},
	{   "mode", FILE_PROP_MODE, FILE_PROP_FLAGS,   310},
	{   "exists", FILE_PROP_EXISTS, FILE_PROP_FLAGS,   310},
	{   "is_open", FILE_PROP_IS_OPEN, FILE_PROP_FLAGS,   310},
	{   "eof", FILE_PROP_EOF, FILE_PROP_FLAGS,   310},
	{   "error", FILE_PROP_ERROR, FILE_PROP_FLAGS,   310},
	{   "descriptor", FILE_PROP_DESCRIPTOR, FILE_PROP_FLAGS,   310},
	{   "etx", FILE_PROP_ETX, JSPROP_ENUMERATE,  310},
	{   "debug", FILE_PROP_DEBUG, JSPROP_ENUMERATE,  310},
	{   "position", FILE_PROP_POSITION, JSPROP_ENUMERATE,  310},
	{   "date", FILE_PROP_DATE, JSPROP_ENUMERATE,  311},
	{   "length", FILE_PROP_LENGTH, JSPROP_ENUMERATE,  310},
	{   "attributes", FILE_PROP_ATTRIBUTES, JSPROP_ENUMERATE,  310},
	{   "network_byte_order", FILE_PROP_NETWORK_ORDER, JSPROP_ENUMERATE,  311},
	{   "rot13", FILE_PROP_ROT13, JSPROP_ENUMERATE,  311},
	{   "uue", FILE_PROP_UUENCODED, JSPROP_ENUMERATE,  311},
	{   "yenc", FILE_PROP_YENCODED, JSPROP_ENUMERATE,  311},
	{   "base64", FILE_PROP_B64ENCODED, JSPROP_ENUMERATE,  311},
	{   "crc16", FILE_PROP_CRC16, FILE_PROP_FLAGS,   311},
	{   "crc32", FILE_PROP_CRC32, FILE_PROP_FLAGS,   311},
	{   "chksum", FILE_PROP_CHKSUM, FILE_PROP_FLAGS,   311},
	{   "md5_hex", FILE_PROP_MD5_HEX, FILE_PROP_FLAGS,   311},
	{   "md5_base64", FILE_PROP_MD5_B64, FILE_PROP_FLAGS,   311},
	{   "sha1_hex", FILE_PROP_SHA1_HEX, FILE_PROP_FLAGS,   31900},
	{   "sha1_base64", FILE_PROP_SHA1_B64, FILE_PROP_FLAGS,   31900},
	/* ini style elements */
	{   "ini_key_len", FILE_INI_KEY_LEN, JSPROP_ENUMERATE,  317},
	{   "ini_key_prefix", FILE_INI_KEY_PREFIX, JSPROP_ENUMERATE,  317},
	{   "ini_section_separator", FILE_INI_SECTION_SEPARATOR, JSPROP_ENUMERATE,  317},
	{   "ini_value_separator", FILE_INI_VALUE_SEPARATOR, JSPROP_ENUMERATE,  317},
	{   "ini_bit_separator", FILE_INI_BIT_SEPARATOR, JSPROP_ENUMERATE,  317},
	{   "ini_literal_separator", FILE_INI_LITERAL_SEPARATOR, JSPROP_ENUMERATE,  317},
static const char*      file_prop_desc[] = {
	"Filename specified in constructor - <small>READ ONLY</small>"
	, "Mode string specified in <i>open</i> call - <small>READ ONLY</small>"
	, "<i>true</i> if the file is open or exists (case-insensitive) - <small>READ ONLY</small>"
	, "<i>true</i> if the file has been opened successfully - <small>READ ONLY</small>"
	, "<i>true</i> if the current file position is at the <i>end of file</i> - <small>READ ONLY</small>"
	, "The last occurred error value (use <i>clear_error</i> to clear) - <small>READ ONLY</small>"
	, "The open file descriptor (advanced use only) - <small>READ ONLY</small>"
	, "End-of-text character (advanced use only), if non-zero used by <i>read</i>, <i>readln</i>, and <i>write</i>"
	, "Set to <i>true</i> to enable debug log output"
	, "The current file position (offset in bytes), change value to seek within file"
	, "Last modified date/time (in time_t format)"
	, "The current length of the file (in bytes)"
	, "File type/mode flags (i.e. <tt>struct stat.st_mode</tt> value, compatible with <tt>file_chmod()</tt>)"
	, "Set to <i>true</i> if binary data is to be written and read in Network Byte Order (big end first)"
	, "Set to <i>true</i> to enable automatic ROT13 translation of text"
	, "Set to <i>true</i> to enable automatic Unix-to-Unix encode and decode on <tt>read</tt> and <tt>write</tt> calls"
	, "Set to <i>true</i> to enable automatic yEnc encode and decode on <tt>read</tt> and <tt>write</tt> calls"
	, "Set to <i>true</i> to enable automatic Base64 encode and decode on <tt>read</tt> and <tt>write</tt> calls"
	, "Calculated 16-bit CRC of file contents - <small>READ ONLY</small>"
	, "Calculated 32-bit CRC of file contents - <small>READ ONLY</small>"
	, "Calculated 32-bit checksum of file contents - <small>READ ONLY</small>"
	, "Calculated 128-bit MD5 digest of file contents as hexadecimal string - <small>READ ONLY</small>"
	, "Calculated 128-bit MD5 digest of file contents as base64-encoded string - <small>READ ONLY</small>"
	, "Calculated 160-bit SHA1 digest of file contents as hexadecimal string - <small>READ ONLY</small>"
	, "Calculated 160-bit SHA1 digest of file contents as base64-encoded string - <small>READ ONLY</small>"
	, "Ini style: minimum key length (for left-justified white-space padded keys)"
	, "Ini style: key prefix (e.g. '\\t', null = default prefix)"
	, "Ini style: section separator (e.g. '\\n', null = default separator)"
	, "Ini style: value separator (e.g. ' = ', null = default separator)"
	, "Ini style: bit separator (e.g. ' | ', null = default separator)"
	, "Ini style: literal separator (null = default separator)"
	, NULL
static jsSyncMethodSpec js_file_functions[] = {
	{"open",            js_open,            1,  JSTYPE_BOOLEAN, JSDOCSTR("[<i>string</i> mode=\"w+\"] [,<i>bool</i> shareable=false] [,<i>number</i> buffer_length]")
	 , JSDOCSTR("Open file, <i>shareable</i> defaults to <i>false</i>, <i>buffer_length</i> defaults to 2048 bytes, "
		        "mode (default: <tt>'w+'</tt>) specifies the type of access requested for the file, as follows:<br>"
		        "<tt>r&nbsp</tt> open for reading; if the file does not exist or cannot be found, the open call fails<br>"
		        "<tt>w&nbsp</tt> open an empty file for writing; if the given file exists, its contents are destroyed<br>"
		        "<tt>a&nbsp</tt> open for writing at the end of the file (appending); creates the file first if it doesn't exist<br>"
		        "<tt>r+</tt> open for both reading and writing (the file must exist)<br>"
		        "<tt>w+</tt> open an empty file for both reading and writing; if the given file exists, its contents are destroyed<br>"
		        "<tt>a+</tt> open for reading and appending<br>"
		        "<tt>b&nbsp</tt> open in binary (untranslated) mode; translations involving carriage-return and linefeed characters are suppressed (e.g. <tt>r+b</tt>)<br>"
		        "<tt>x&nbsp</tt> open a <i>non-shareable</i> file (that must not already exist) for <i>exclusive</i> access<br>"
		        "<br><b>Note:</b> When using the <tt>iniSet</tt> methods to modify a <tt>.ini</tt> file, "
		        "the file must be opened for both reading <b>and</b> writing.<br>"
		        "<br><b>Note:</b> To open an existing or create a new file for both reading and writing "
		        "(e.g. updating an <tt>.ini</tt> file) "
		        "use the <i>exists</i> property like so:<br>"
		        "<tt>file.open(file.exists ? 'r+':'w+');</tt><br>"
		        "<br><b>Note:</b> When <i>shareable</i> is <tt>false</tt>, uses the Synchronet <tt>nopen()</tt> function which will lock the file "
		        "and perform automatic retries.  The lock mode is as follows:<br>"
		        "<tt>r&nbsp</tt> DENYWRITE - Allows other scripts to open the file for reading, but not for writing.<br>"
		        "<tt>w&nbsp</tt> DENYALL - Does not allow other scripts to open the file when <i>shareable</i> is set to true<br>"
		        "<tt>a&nbsp</tt> DENYALL - Does not allow other scripts to open the file when <i>shareable</i> is set to true<br>"
		        "<tt>r+</tt> DENYALL - Does not allow other scripts to open the file when <i>shareable</i> is set to true<br>"
		        "<tt>w+</tt> DENYALL - Does not allow other scripts to open the file when <i>shareable</i> is set to true<br>"
		        "<tt>a+</tt> DENYALL - Does not allow other scripts to open the file when <i>shareable</i> is set to true<br>"
		        "<br>When <i>shareable</i> is <tt>true</tt> uses the standard C <tt>fopen()</tt> function, "
		        "and will only attempt to open the file once and will perform no locking.<br>"
		        "The behavior when one script has a file opened with <i>shareable</i> set to a different value than is used "
		        "with a new call is OS specific.  On Windows, the second open will always fail and on *nix, "
		        "the second open will always succeed.<br>"
		        )
	 , 310},
	{"popen",           js_popen,           1,  JSTYPE_BOOLEAN, JSDOCSTR("[<i>string</i> mode=\"r+\"] [,<i>number</i> buffer_length]")
	 , JSDOCSTR("Open pipe to command, <i>buffer_length</i> defaults to 2048 bytes, "
		        "mode (default: <tt>'r+'</tt>) specifies the type of access requested for the file, as follows:<br>"
		        "<tt>r&nbsp</tt> read the programs stdout;<br>"
		        "<tt>w&nbsp</tt> write to the programs stdin<br>"
		        "<tt>r+</tt> open for both reading stdout and writing stdin<br>"
		        "(<b>only functional on UNIX systems</b>)"
		        )
	 , 315},
	{"close",           js_close,           0,  JSTYPE_VOID,    JSDOCSTR("")
	 , JSDOCSTR("Close file")
	 , 310},
	{"remove",          js_delete,          0,  JSTYPE_BOOLEAN, JSDOCSTR("")
	 , JSDOCSTR("Remove the file from the disk")
	 , 310},
	{"clearError",      js_clear_error,     0,  JSTYPE_ALIAS },
	{"clear_error",     js_clear_error,     0,  JSTYPE_BOOLEAN, JSDOCSTR("")
	 , JSDOCSTR("Clears the current error value (AKA clearError)")
	 , 310},
	{"flush",           js_flush,           0,  JSTYPE_BOOLEAN, JSDOCSTR("")
	 , JSDOCSTR("Flush/commit buffers to disk")
	 , 310},
	{"rewind",          js_rewind,          0,  JSTYPE_BOOLEAN, JSDOCSTR("")
	 , JSDOCSTR("Repositions the file pointer (<i>position</i>) to the beginning of a file "
		        "and clears error and end-of-file indicators")
	 , 311},
	{"truncate",        js_truncate,        0,  JSTYPE_BOOLEAN, JSDOCSTR("[length=0]")
	 , JSDOCSTR("Changes the file <i>length</i> (default: 0) and repositions the file pointer "
		        "(<i>position</i>) to the new end-of-file")
	 , 314},
	{"lock",            js_lock,            2,  JSTYPE_BOOLEAN, JSDOCSTR("[offset=0] [,length=<i>file_length</i>-<i>offset</i>]")
	 , JSDOCSTR("Lock file record for exclusive access (file must be opened <i>shareable</i>)")
	 , 310},
	{"unlock",          js_unlock,          2,  JSTYPE_BOOLEAN, JSDOCSTR("[offset=0] [,length=<i>file_length</i>-<i>offset</i>]")
	 , JSDOCSTR("Unlock file record for exclusive access")
	 , 310},
	{"read",            js_read,            0,  JSTYPE_STRING,  JSDOCSTR("[maxlen=<i>file_length</i>-<i>file_position</i>]")
	 , JSDOCSTR("Read a string from file (optionally unix-to-unix or base64 encoding in the process), "
		        "<i>maxlen</i> defaults to the current length of the file minus the current file position")
	 , 310},
	{"readln",          js_readln,          0,  JSTYPE_STRING,  JSDOCSTR("[maxlen=512]")
	 , JSDOCSTR("Read a line-feed terminated string, <i>maxlen</i> defaults to 512 characters. "
		        "Returns <i>null</i> upon end of file.")
	 , 310},
	{"readBin",         js_readbin,         0,  JSTYPE_NUMBER,  JSDOCSTR("[bytes=4 [,count=1]]")
	 , JSDOCSTR("Read one or more binary integers from the file, default number of <i>bytes</i> is 4 (32-bits). "
		        "if count is not equal to 1, an array is returned (even if no integers were read)")
	 , 310},
	{"readAll",         js_readall,         0,  JSTYPE_ARRAY,   JSDOCSTR("[maxlen=512]")
	 , JSDOCSTR("Read all lines into an array of strings, <i>maxlen</i> defaults to 512 characters")
	 , 310},
	{"raw_read",        js_raw_read,        0,  JSTYPE_STRING,  JSDOCSTR("[maxlen=1]")
	 , JSDOCSTR("Read a string from underlying file descriptor. "
		        "Undefined results when mixed with any other read/write methods except raw_write, including indirect ones. "
		        "<i>maxlen</i> defaults to one")
	 , 317},
	{"raw_pollin",      js_raw_pollin,      0,  JSTYPE_BOOLEAN, JSDOCSTR("[timeout]")
	 , JSDOCSTR("Waits up to <i>timeout</i> milliseconds (or forever if timeout is not specified) for data to be available "
		        "via raw_read().")
	 , 317},
	{"write",           js_write,           1,  JSTYPE_BOOLEAN, JSDOCSTR("text [,length=<i>text_length</i>]")
	 , JSDOCSTR("Write a string to the file (optionally unix-to-unix or base64 decoding in the process). "
		        "If the specified <i>length</i> is longer than the <i>text</i>, the remaining length will be written as NUL bytes.")
	 , 310},
	{"writeln",         js_writeln,         0,  JSTYPE_BOOLEAN, JSDOCSTR("[text]")
	 , JSDOCSTR("Write a new-line terminated string (a line of text) to the file")
	 , 310},
	{"writeBin",        js_writebin,        1,  JSTYPE_BOOLEAN, JSDOCSTR("value(s) [,bytes=4]")
	 , JSDOCSTR("Write one or more binary integers to the file, default number of <i>bytes</i> is 4 (32-bits). "
		        "If value is an array, writes the entire array to the file.")
	 , 310},
	{"writeAll",        js_writeall,        0,  JSTYPE_BOOLEAN, JSDOCSTR("array lines")
	 , JSDOCSTR("Write an array of new-line terminated strings (lines of text) to the file")
	 , 310},
	{"raw_write",       js_raw_write,       1,  JSTYPE_BOOLEAN, JSDOCSTR("text")
	 , JSDOCSTR("Write a string to the underlying file descriptor. "
		        "Undefined results when mixed with any other read/write methods except raw_read, including indirect ones.")
	 , 317},
	{"printf",          js_fprintf,         0,  JSTYPE_NUMBER,  JSDOCSTR("format [,args]")
	 , JSDOCSTR("Write a C-style formatted string to the file (ala the standard C <tt>fprintf</tt> function)")
	 , 310},
	{"iniGetSections",  js_iniGetSections,  0,  JSTYPE_ARRAY,   JSDOCSTR("[prefix=<i>none</i>]")
	 , JSDOCSTR("Parse all section names from a <tt>.ini</tt> file (format = '<tt>[section]</tt>') "
		        "and return the section names as an <i>array of strings</i>, "
		        "optionally, only those section names that begin with the specified <i>prefix</i>")
	 , 311},
	{"iniGetKeys",      js_iniGetKeys,      1,  JSTYPE_ARRAY,   JSDOCSTR("[section=<i>root</i>]")
	 , JSDOCSTR("Parse all key names from the specified <i>section</i> in a <tt>.ini</tt> file "
		        "and return the key names as an <i>array of strings</i>. "
		        "if <i>section</i> is undefined, returns key names from the <i>root</i> section")
	 , 311},
	{"iniGetValue",     js_iniGetValue,     3,  JSTYPE_UNDEF,   JSDOCSTR("section, key [,default=<i>none</i>]")
	 , JSDOCSTR("Parse a key from a <tt>.ini</tt> file and return its value (format = '<tt>key = value</tt>'). "
		        "To parse a key from the <i>root</i> section, pass <i>null</i> for <i>section</i>. "
		        "Returns the specified <i>default</i> value if the key or value is missing or invalid.<br>"
		        "Returns a <i>bool</i>, <i>number</i>, <i>string</i>, or an <i>array of strings</i> "
		        "determined by the type of <i>default</i> value specified. "
		        "<br><b>Note:</b> To insure that any/all values are returned as a string (e.g. numeric passwords are <b>not</b> returned as a <i>number</i>), "
		        "pass an empty string ('') for the <i>default</i> value." )
	 , 311},
	{"iniSetValue",     js_iniSetValue,     3,  JSTYPE_BOOLEAN, JSDOCSTR("section, key, [value=<i>none</i>]")
	 , JSDOCSTR("Set the specified <i>key</i> to the specified <i>value</i> in the specified <i>section</i> "
		        "of a <tt>.ini</tt> file. "
		        "to set a key in the <i>root</i> section, pass <i>null</i> for <i>section</i>. ")
	 , 312},
	{"iniGetObject",    js_iniGetObject,    1,  JSTYPE_OBJECT,  JSDOCSTR("[section=<i>root</i>] [,<i>bool</i> lowercase=false] "
		                                                                 "[,<i>bool</i> blanks=false]")
	 , JSDOCSTR("Parse an entire section from a .ini file "
		        "and return all of its keys (optionally lowercased) and values as properties of an object.<br>"