зеркало из https://github.com/mozilla/gecko-dev.git
bug 132949: fix some of the more egregious bugs in jsfile.c, this also cleans up some of the style nits, but is nowhere a complete patch. Use jsfile.c at your own risk! rs=shaver
This commit is contained in:
Родитель
4b96a2d85d
Коммит
11127076c8
|
@ -1205,7 +1205,7 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj)
|
|||
js_InitXMLClasses(cx, obj) &&
|
||||
#endif
|
||||
#if JS_HAS_FILE_OBJECT
|
||||
js_InitFileClass(cx, obj, JS_TRUE) &&
|
||||
js_InitFileClass(cx, obj) &&
|
||||
#endif
|
||||
js_InitDateClass(cx, obj);
|
||||
}
|
||||
|
@ -1245,6 +1245,9 @@ static struct {
|
|||
{js_InitXMLClass, ATOM_OFFSET(XML)},
|
||||
{js_InitNamespaceClass, ATOM_OFFSET(Namespace)},
|
||||
{js_InitQNameClass, ATOM_OFFSET(QName)},
|
||||
#endif
|
||||
#if JS_HAS_FILE_OBJECT
|
||||
{js_InitFileClass, ATOM_OFFSET(File)},
|
||||
#endif
|
||||
{NULL, 0}
|
||||
};
|
||||
|
|
|
@ -102,6 +102,7 @@ const char js_RegExp_str[] = "RegExp";
|
|||
const char js_Script_str[] = "Script";
|
||||
const char js_String_str[] = "String";
|
||||
const char js_XML_str[] = "XML";
|
||||
const char js_File_str[] = "File";
|
||||
const char js_anonymous_str[] = "anonymous";
|
||||
const char js_arguments_str[] = "arguments";
|
||||
const char js_arity_str[] = "arity";
|
||||
|
@ -319,6 +320,7 @@ js_InitPinnedAtoms(JSContext *cx, JSAtomState *state)
|
|||
FROB(ScriptAtom, js_Script_str);
|
||||
FROB(StringAtom, js_String_str);
|
||||
FROB(XMLAtom, js_XML_str);
|
||||
FROB(FileAtom, js_File_str);
|
||||
FROB(anonymousAtom, js_anonymous_str);
|
||||
FROB(argumentsAtom, js_arguments_str);
|
||||
FROB(arityAtom, js_arity_str);
|
||||
|
|
|
@ -180,6 +180,7 @@ struct JSAtomState {
|
|||
JSAtom *ScriptAtom;
|
||||
JSAtom *StringAtom;
|
||||
JSAtom *XMLAtom;
|
||||
JSAtom *FileAtom;
|
||||
JSAtom *anonymousAtom;
|
||||
JSAtom *argumentsAtom;
|
||||
JSAtom *arityAtom;
|
||||
|
@ -286,6 +287,7 @@ extern const char js_RegExp_str[];
|
|||
extern const char js_Script_str[];
|
||||
extern const char js_String_str[];
|
||||
extern const char js_XML_str[];
|
||||
extern const char js_File_str[];
|
||||
extern const char js_anonymous_str[];
|
||||
extern const char js_arguments_str[];
|
||||
extern const char js_arity_str[];
|
||||
|
|
476
js/src/jsfile.c
476
js/src/jsfile.c
|
@ -1,4 +1,5 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=80:
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
@ -220,7 +221,6 @@ JSFile_GetErrorMessage(void *userRef, const char *locale,
|
|||
typedef struct JSFile {
|
||||
char *path; /* the path to the file. */
|
||||
JSBool isOpen;
|
||||
JSString *linebuffer; /* temp buffer used by readln. */
|
||||
int32 mode; /* mode used to open the file: read, write, append, create, etc.. */
|
||||
int32 type; /* Asciiz, utf, unicode */
|
||||
char byteBuffer[3]; /* bytes read in advance by js_FileRead ( UTF8 encoding ) */
|
||||
|
@ -328,59 +328,69 @@ js_fileBaseName(JSContext *cx, const char *pathname)
|
|||
}
|
||||
|
||||
/*
|
||||
Returns everytynig but the last component from a path name.
|
||||
Returned string must be freed. Returned string must be freed.
|
||||
* Returns everything but the last component from a path name.
|
||||
* Returned string must be freed.
|
||||
*/
|
||||
static char *
|
||||
js_fileDirectoryName(JSContext *cx, const char *pathname)
|
||||
{
|
||||
jsint index;
|
||||
char *result;
|
||||
const char *cp, *end;
|
||||
size_t pathsize;
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_OS2)
|
||||
char drive = '\0';
|
||||
const char *oldpathname = pathname;
|
||||
end = pathname + strlen(pathname);
|
||||
cp = end - 1;
|
||||
|
||||
/* First, get rid of the drive selector */
|
||||
if ((strlen(pathname)>=2)&&(pathname[1]==':')) {
|
||||
drive = pathname[0];
|
||||
pathname = &pathname[2];
|
||||
}
|
||||
#endif
|
||||
index = strlen(pathname)-1;
|
||||
while ((index>0)&&((pathname[index]==FILESEPARATOR)||
|
||||
(pathname[index]==FILESEPARATOR2))) index--;
|
||||
while ((index>0)&&(pathname[index]!=FILESEPARATOR)&&
|
||||
(pathname[index]!=FILESEPARATOR2)) index--;
|
||||
|
||||
if (index>=0){
|
||||
result = (char*)JS_malloc(cx, index+4);
|
||||
if (!result) return NULL;
|
||||
#if defined(XP_WIN) || defined(XP_OS2)
|
||||
if (drive!='\0') {
|
||||
result[0] = toupper(drive);
|
||||
result[1] = ':';
|
||||
strncpy(&result[2], pathname, index);
|
||||
result[index+3] = '\0';
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
strncpy(result, pathname, index);
|
||||
result[index] = '\0';
|
||||
/* If this is already a directory, chop off the trailing /s. */
|
||||
while (cp >= pathname) {
|
||||
if (*cp != FILESEPARATOR && *cp != FILESEPARATOR2) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* add terminating separator */
|
||||
index = strlen(result)-1;
|
||||
result[index] = FILESEPARATOR;
|
||||
result[index+1] = '\0';
|
||||
} else{
|
||||
#if defined(XP_WIN) || defined(XP_OS2)
|
||||
result = JS_strdup(cx, oldpathname); /* may include drive selector */
|
||||
#else
|
||||
result = JS_strdup(cx, pathname);
|
||||
#endif
|
||||
--cp;
|
||||
}
|
||||
|
||||
if (cp < pathname && end != pathname) {
|
||||
/* There were just /s, return the root. */
|
||||
result = JS_malloc(cx, 1 + 1); /* The separator + trailing NUL. */
|
||||
result[0] = FILESEPARATOR;
|
||||
result[1] = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Now chop off the last portion. */
|
||||
while (cp >= pathname) {
|
||||
if (*cp == FILESEPARATOR || *cp == FILESEPARATOR2) {
|
||||
break;
|
||||
}
|
||||
|
||||
--cp;
|
||||
}
|
||||
|
||||
/* Check if this is a leaf. */
|
||||
if (cp < pathname) {
|
||||
/* It is, return "pathname/". */
|
||||
pathsize = end - pathname + 1;
|
||||
result = JS_malloc(cx, pathsize + 1);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
strcpy(result, pathname);
|
||||
result[pathsize - 1] = FILESEPARATOR;
|
||||
result[pathsize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Return everything up to and including the seperator. */
|
||||
pathsize = cp - pathname + 1;
|
||||
result = JS_malloc(cx, pathsize + 1);
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
strncpy(result, pathname, pathsize);
|
||||
result[pathsize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -571,22 +581,23 @@ js_canonicalPath(JSContext *cx, char *oldpath)
|
|||
#define LINE_SEPARATOR 0x2028
|
||||
#define PARAGRAPH_SEPARATOR 0x2029
|
||||
static int16 one_ucs2_to_utf8_char(unsigned char *tobufp,
|
||||
unsigned char *tobufendp, uint16 onechar)
|
||||
unsigned char *tobufendp,
|
||||
uint16 onechar)
|
||||
{
|
||||
|
||||
int16 numUTF8bytes = 0;
|
||||
|
||||
if((onechar == LINE_SEPARATOR)||(onechar == PARAGRAPH_SEPARATOR))
|
||||
{
|
||||
if (onechar == LINE_SEPARATOR || onechar == PARAGRAPH_SEPARATOR) {
|
||||
strcpy((char*)tobufp, "\n");
|
||||
return strlen((char*)tobufp);;
|
||||
return strlen((char*)tobufp);
|
||||
}
|
||||
|
||||
if (onechar < 0x80) { numUTF8bytes = 1;
|
||||
} else if (onechar < 0x800) { numUTF8bytes = 2;
|
||||
} else if (onechar <= MAX_UCS2) { numUTF8bytes = 3;
|
||||
} else { numUTF8bytes = 2;
|
||||
onechar = DEFAULT_CHAR;
|
||||
if (onechar < 0x80) {
|
||||
numUTF8bytes = 1;
|
||||
} else if (onechar < 0x800) {
|
||||
numUTF8bytes = 2;
|
||||
} else {
|
||||
/* 0x800 >= onechar <= MAX_UCS2 */
|
||||
numUTF8bytes = 3;
|
||||
}
|
||||
|
||||
tobufp += numUTF8bytes;
|
||||
|
@ -596,9 +607,7 @@ static int16 one_ucs2_to_utf8_char(unsigned char *tobufp,
|
|||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
switch(numUTF8bytes) {
|
||||
|
||||
case 3: *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
|
||||
*--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
|
||||
*--tobufp = onechar | THREE_OCTET_BASE;
|
||||
|
@ -607,10 +616,12 @@ static int16 one_ucs2_to_utf8_char(unsigned char *tobufp,
|
|||
case 2: *--tobufp = (onechar | BYTE_MARK) & BYTE_MASK; onechar >>=6;
|
||||
*--tobufp = onechar | TWO_OCTET_BASE;
|
||||
break;
|
||||
case 1: *--tobufp = (unsigned char)onechar; break;
|
||||
|
||||
case 1: *--tobufp = (unsigned char)onechar;
|
||||
break;
|
||||
}
|
||||
|
||||
return(numUTF8bytes);
|
||||
return numUTF8bytes;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -725,17 +736,17 @@ js_ResetBuffers(JSFile * file)
|
|||
{
|
||||
file->charBufferUsed = JS_FALSE;
|
||||
file->nbBytesInBuf = 0;
|
||||
file->linebuffer = NULL; /* TODO: check for mem. leak? */
|
||||
}
|
||||
|
||||
/* Reset file attributes */
|
||||
static void
|
||||
js_ResetAttributes(JSFile * file){
|
||||
js_ResetAttributes(JSFile * file)
|
||||
{
|
||||
file->mode = file->type = 0;
|
||||
file->isOpen = JS_FALSE;
|
||||
file->handle = NULL;
|
||||
file->nativehandle = NULL;
|
||||
file->hasRandomAccess = JS_TRUE; /* innocent until proven guilty */
|
||||
file->hasRandomAccess = JS_TRUE; /* Innocent until proven guilty. */
|
||||
file->hasAutoflush = JS_FALSE;
|
||||
file->isNative = JS_FALSE;
|
||||
file->isPipe = JS_FALSE;
|
||||
|
@ -777,9 +788,9 @@ js_BufferedRead(JSFile * f, char *buf, int32 len)
|
|||
}
|
||||
|
||||
if (len>0) {
|
||||
count+= (!f->isNative)?
|
||||
PR_Read(f->handle, buf, len):
|
||||
fread(buf, 1, len, f->nativehandle);
|
||||
count += (!f->isNative)
|
||||
? PR_Read(f->handle, buf, len)
|
||||
: fread(buf, 1, len, f->nativehandle);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -802,19 +813,21 @@ js_FileRead(JSContext *cx, JSFile * file, jschar*buf, int32 len, int32 mode)
|
|||
switch (mode) {
|
||||
case ASCII:
|
||||
aux = (unsigned char*)JS_malloc(cx, len);
|
||||
if (!aux) {
|
||||
if (!aux)
|
||||
return 0;
|
||||
}
|
||||
|
||||
count = js_BufferedRead(file, aux, len);
|
||||
if (count == -1) {
|
||||
JS_free(cx, aux);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0;i<len;i++) {
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
buf[i] = (jschar)aux[i];
|
||||
}
|
||||
|
||||
JS_free(cx, aux);
|
||||
break;
|
||||
|
||||
case UTF8:
|
||||
remainder = 0;
|
||||
for (count = 0;count<len;count++) {
|
||||
|
@ -830,15 +843,14 @@ js_FileRead(JSContext *cx, JSFile * file, jschar*buf, int32 len, int32 mode)
|
|||
utfbuf[0] = utfbuf[1];
|
||||
utfbuf[1] = utfbuf[2];
|
||||
remainder = 2;
|
||||
} else
|
||||
if (i==2) {
|
||||
} else if (i==2) {
|
||||
utfbuf[0] = utfbuf[2];
|
||||
remainder = 1;
|
||||
} else
|
||||
if (i==3)
|
||||
} else if (i==3) {
|
||||
remainder = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (remainder>0) {
|
||||
file->byteBuffer[file->nbBytesInBuf] = utfbuf[0];
|
||||
file->nbBytesInBuf++;
|
||||
|
@ -847,12 +859,17 @@ js_FileRead(JSContext *cx, JSFile * file, jschar*buf, int32 len, int32 mode)
|
|||
remainder--;
|
||||
}
|
||||
break;
|
||||
|
||||
case UCS2:
|
||||
count = js_BufferedRead(file, (char*)buf, len*2) >> 1;
|
||||
if (count==-1) {
|
||||
if (count == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Not reached. */
|
||||
JS_ASSERT(0);
|
||||
}
|
||||
|
||||
if(count == -1) {
|
||||
|
@ -875,6 +892,7 @@ js_FileSeek(JSContext *cx, JSFile *file, int32 len, int32 mode)
|
|||
case ASCII:
|
||||
count = PR_Seek(file->handle, len, PR_SEEK_CUR);
|
||||
break;
|
||||
|
||||
case UTF8:
|
||||
remainder = 0;
|
||||
for (count = 0;count<len;count++) {
|
||||
|
@ -886,20 +904,18 @@ js_FileSeek(JSContext *cx, JSFile *file, int32 len, int32 mode)
|
|||
if (i<0) {
|
||||
return 0;
|
||||
} else {
|
||||
|
||||
if (i==1) {
|
||||
utfbuf[0] = utfbuf[1];
|
||||
utfbuf[1] = utfbuf[2];
|
||||
remainder = 2;
|
||||
} else
|
||||
if (i==2) {
|
||||
} else if (i==2) {
|
||||
utfbuf[0] = utfbuf[2];
|
||||
remainder = 1;
|
||||
} else
|
||||
if (i==3)
|
||||
} else if (i==3) {
|
||||
remainder = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (remainder>0) {
|
||||
file->byteBuffer[file->nbBytesInBuf] = utfbuf[0];
|
||||
file->nbBytesInBuf++;
|
||||
|
@ -908,9 +924,14 @@ js_FileSeek(JSContext *cx, JSFile *file, int32 len, int32 mode)
|
|||
remainder--;
|
||||
}
|
||||
break;
|
||||
|
||||
case UCS2:
|
||||
count = PR_Seek(file->handle, len*2, PR_SEEK_CUR)/2;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Not reached. */
|
||||
JS_ASSERT(0);
|
||||
}
|
||||
|
||||
if(count == -1) {
|
||||
|
@ -931,22 +952,24 @@ js_FileWrite(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode)
|
|||
switch (mode) {
|
||||
case ASCII:
|
||||
aux = (unsigned char*)JS_malloc(cx, len);
|
||||
if (!aux) return 0;
|
||||
if (!aux)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i<len; i++) {
|
||||
for (i = 0; i<len; i++)
|
||||
aux[i] = buf[i] % 256;
|
||||
}
|
||||
|
||||
count = (!file->isNative)?
|
||||
PR_Write(file->handle, aux, len):
|
||||
fwrite(aux, 1, len, file->nativehandle);
|
||||
count = (!file->isNative)
|
||||
? PR_Write(file->handle, aux, len)
|
||||
: fwrite(aux, 1, len, file->nativehandle);
|
||||
|
||||
if (count==-1) {
|
||||
JS_free(cx, aux);
|
||||
return 0;
|
||||
}
|
||||
|
||||
JS_free(cx, aux);
|
||||
break;
|
||||
|
||||
case UTF8:
|
||||
utfbuf = (unsigned char*)JS_malloc(cx, len*3);
|
||||
if (!utfbuf) return 0;
|
||||
|
@ -959,9 +982,9 @@ js_FileWrite(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode)
|
|||
}
|
||||
i+=j;
|
||||
}
|
||||
j = (!file->isNative)?
|
||||
PR_Write(file->handle, utfbuf, i):
|
||||
fwrite(utfbuf, 1, i, file->nativehandle);
|
||||
j = (!file->isNative)
|
||||
? PR_Write(file->handle, utfbuf, i)
|
||||
: fwrite(utfbuf, 1, i, file->nativehandle);
|
||||
|
||||
if (j<i) {
|
||||
JS_free(cx, utfbuf);
|
||||
|
@ -969,20 +992,26 @@ js_FileWrite(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode)
|
|||
}
|
||||
JS_free(cx, utfbuf);
|
||||
break;
|
||||
case UCS2:
|
||||
count = (!file->isNative)?
|
||||
PR_Write(file->handle, buf, len*2)>>1:
|
||||
fwrite(buf, 1, len*2, file->nativehandle)>>1;
|
||||
|
||||
if (count==-1) {
|
||||
case UCS2:
|
||||
count = (!file->isNative)
|
||||
? PR_Write(file->handle, buf, len*2) >> 1
|
||||
: fwrite(buf, 1, len*2, file->nativehandle) >> 1;
|
||||
|
||||
if (count == -1)
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Not reached. */
|
||||
JS_ASSERT(0);
|
||||
}
|
||||
|
||||
if(count == -1) {
|
||||
JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
|
||||
JSFILEMSG_OP_FAILED, "write", file->path);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -1093,25 +1122,36 @@ out:
|
|||
return JSVAL_VOID;
|
||||
}
|
||||
|
||||
/* Return the parent object */
|
||||
static jsval
|
||||
js_parent(JSContext *cx, JSFile *file)
|
||||
/*
|
||||
* Return the parent object
|
||||
*/
|
||||
static JSBool
|
||||
js_parent(JSContext *cx, JSFile *file, jsval *resultp)
|
||||
{
|
||||
char *str;
|
||||
|
||||
/* since we only care about pipes and native files, return NULL */
|
||||
if(file->isNative) return JSVAL_VOID;
|
||||
/* Since we only care about pipes and native files, return NULL. */
|
||||
if (file->isNative) {
|
||||
*resultp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
str = js_fileDirectoryName(cx, file->path);
|
||||
/* root.parent = null ??? */
|
||||
if(!strcmp(file->path, str) ||
|
||||
(!strncmp(str, file->path, strlen(str)-1)&&
|
||||
file->path[strlen(file->path)]-1)==FILESEPARATOR){
|
||||
return JSVAL_NULL;
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
|
||||
/* If the directory is equal to the original path, we're at the root. */
|
||||
if (!strcmp(file->path, str)) {
|
||||
*resultp = JSVAL_NULL;
|
||||
} else {
|
||||
return OBJECT_TO_JSVAL(js_NewFileObject(cx, str));
|
||||
JS_free(cx, str);
|
||||
JSObject *obj = js_NewFileObject(cx, str);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
*resultp = OBJECT_TO_JSVAL(obj);
|
||||
}
|
||||
|
||||
JS_free(cx, str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static jsval
|
||||
|
@ -1131,6 +1171,8 @@ file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
int32 mask, type;
|
||||
int len;
|
||||
|
||||
mode = NULL;
|
||||
|
||||
SECURITY_CHECK(cx, NULL, "open", file);
|
||||
|
||||
/* A native file that is already open */
|
||||
|
@ -1142,10 +1184,10 @@ file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
|
||||
/* Close before proceeding */
|
||||
if (file->isOpen) {
|
||||
JS_ReportWarning(cx,
|
||||
"File %s is already open, we will close it and reopen, proceeding",
|
||||
file->path);
|
||||
if(!file_close(cx, obj, 0, NULL, rval)) goto out;
|
||||
JS_ReportWarning(cx, "File %s is already open, we will close it and "
|
||||
"reopen, proceeding", file->path);
|
||||
if(!file_close(cx, obj, 0, NULL, rval))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (js_isDirectory(cx, file)) {
|
||||
|
@ -1162,7 +1204,8 @@ file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
strmode = JS_ValueToString(cx, argv[0]);
|
||||
if (!strmode) {
|
||||
JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
|
||||
JSFILEMSG_FIRST_ARGUMENT_OPEN_NOT_STRING_ERROR, argv[0]);
|
||||
JSFILEMSG_FIRST_ARGUMENT_OPEN_NOT_STRING_ERROR,
|
||||
argv[0]);
|
||||
goto out;
|
||||
}
|
||||
mode = JS_strdup(cx, JS_GetStringBytes(strmode));
|
||||
|
@ -1170,8 +1213,7 @@ file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
if(file->path[0]==PIPE_SYMBOL) {
|
||||
/* pipe default mode */
|
||||
mode = JS_strdup(cx, "read");
|
||||
}else
|
||||
if(file->path[len-1]==PIPE_SYMBOL){
|
||||
} else if(file->path[len-1]==PIPE_SYMBOL) {
|
||||
/* pipe default mode */
|
||||
mode = JS_strdup(cx, "write");
|
||||
} else {
|
||||
|
@ -1182,35 +1224,37 @@ file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
|
||||
/* Process the mode */
|
||||
mask = 0;
|
||||
/* TODO: this is pretty ugly, BTW, we walk thru the string too many times */
|
||||
mask|=(js_FileHasOption(cx, mode, "read"))? PR_RDONLY : 0;
|
||||
mask|=(js_FileHasOption(cx, mode, "write"))? PR_WRONLY : 0;
|
||||
mask|=(js_FileHasOption(cx, mode, "readWrite"))? PR_RDWR : 0;
|
||||
mask|=(js_FileHasOption(cx, mode, "append"))? PR_APPEND : 0;
|
||||
mask|=(js_FileHasOption(cx, mode, "create"))? PR_CREATE_FILE : 0;
|
||||
mask|=(js_FileHasOption(cx, mode, "replace"))? PR_TRUNCATE : 0;
|
||||
/* TODO: this is pretty ugly, we walk thru the string too many times */
|
||||
mask |= js_FileHasOption(cx, mode, "read") ? PR_RDONLY : 0;
|
||||
mask |= js_FileHasOption(cx, mode, "write") ? PR_WRONLY : 0;
|
||||
mask |= js_FileHasOption(cx, mode, "readWrite")? PR_RDWR : 0;
|
||||
mask |= js_FileHasOption(cx, mode, "append") ? PR_APPEND : 0;
|
||||
mask |= js_FileHasOption(cx, mode, "create") ? PR_CREATE_FILE : 0;
|
||||
mask |= js_FileHasOption(cx, mode, "replace") ? PR_TRUNCATE : 0;
|
||||
|
||||
if((mask&PR_RDWR)) mask|=(PR_RDONLY|PR_WRONLY);
|
||||
if((mask&PR_RDONLY)&&(mask&PR_WRONLY)) mask|=PR_RDWR;
|
||||
if (mask & PR_RDWR)
|
||||
mask |= (PR_RDONLY | PR_WRONLY);
|
||||
if ((mask & PR_RDONLY) && (mask & PR_WRONLY))
|
||||
mask |= PR_RDWR;
|
||||
|
||||
file->hasAutoflush|=(js_FileHasOption(cx, mode, "autoflush"));
|
||||
file->hasAutoflush |= js_FileHasOption(cx, mode, "autoflush");
|
||||
|
||||
/* Type */
|
||||
if (argc > 1) {
|
||||
strtype = JS_ValueToString(cx, argv[1]);
|
||||
if (!strtype) {
|
||||
JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
|
||||
JSFILEMSG_SECOND_ARGUMENT_OPEN_NOT_STRING_ERROR, argv[1]);
|
||||
JSFILEMSG_SECOND_ARGUMENT_OPEN_NOT_STRING_ERROR,
|
||||
argv[1]);
|
||||
goto out;
|
||||
}
|
||||
ctype = JS_GetStringBytes(strtype);
|
||||
|
||||
if(!strcmp(ctype, utfstring))
|
||||
if(!strcmp(ctype, utfstring)) {
|
||||
type = UTF8;
|
||||
else
|
||||
if (!strcmp(ctype, unicodestring))
|
||||
} else if (!strcmp(ctype, unicodestring)) {
|
||||
type = UCS2;
|
||||
else{
|
||||
} else {
|
||||
if (strcmp(ctype, asciistring)) {
|
||||
JS_ReportWarning(cx, "File type %s is not supported, using "
|
||||
"'text' instead, proceeding", ctype);
|
||||
|
@ -1228,8 +1272,8 @@ file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
file->hasRandomAccess = (type != UTF8);
|
||||
|
||||
/*
|
||||
Deal with pipes here. We can't use NSPR for pipes,
|
||||
so we have to use POPEN.
|
||||
* Deal with pipes here. We can't use NSPR for pipes, so we have to use
|
||||
* POPEN.
|
||||
*/
|
||||
if (file->path[0]==PIPE_SYMBOL || file->path[len-1]==PIPE_SYMBOL) {
|
||||
if (file->path[0] == PIPE_SYMBOL && file->path[len-1] == PIPE_SYMBOL) {
|
||||
|
@ -1252,8 +1296,7 @@ file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
pipemode[1] = file->type==UTF8 ? 'b' : 't';
|
||||
pipemode[2] = '\0';
|
||||
file->nativehandle = POPEN(&file->path[1], pipemode);
|
||||
}else
|
||||
if(file->path[len-1] == PIPE_SYMBOL){
|
||||
} else if(file->path[len-1] == PIPE_SYMBOL) {
|
||||
char *command = JS_malloc(cx, len);
|
||||
|
||||
strncpy(command, file->path, len-1);
|
||||
|
@ -1286,15 +1329,16 @@ file_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
|
||||
JSFILEMSG_OP_FAILED, "open", file->path);
|
||||
goto out;
|
||||
}else
|
||||
goto good;
|
||||
}
|
||||
|
||||
good:
|
||||
file->isOpen = JS_TRUE;
|
||||
*rval = JSVAL_TRUE;
|
||||
return JS_TRUE;
|
||||
|
||||
out:
|
||||
if(mode) JS_free(cx, mode);
|
||||
*rval = JSVAL_VOID;
|
||||
if(mode)
|
||||
JS_free(cx, mode);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1334,8 +1378,8 @@ file_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
js_ResetAttributes(file);
|
||||
*rval = JSVAL_TRUE;
|
||||
return JS_TRUE;
|
||||
|
||||
out:
|
||||
*rval = JSVAL_FALSE;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1650,71 +1694,83 @@ file_readln(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
{
|
||||
JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
||||
JSString *str;
|
||||
jschar *buf;
|
||||
int32 offset;
|
||||
jschar *buf = NULL, *tmp;
|
||||
int32 offset, read;
|
||||
intN room;
|
||||
jschar data, data2;
|
||||
JSBool endofline;
|
||||
|
||||
SECURITY_CHECK(cx, NULL, "readln", file);
|
||||
JSFILE_CHECK_READ;
|
||||
|
||||
if (!file->linebuffer) {
|
||||
buf = JS_malloc(cx, MAX_LINE_LENGTH*(sizeof data));
|
||||
if (!buf) goto out;
|
||||
file->linebuffer = JS_NewUCString(cx, buf, MAX_LINE_LENGTH);
|
||||
}
|
||||
room = JS_GetStringLength(file->linebuffer);
|
||||
buf = JS_malloc(cx, MAX_LINE_LENGTH * sizeof data);
|
||||
if (!buf)
|
||||
return JS_FALSE;
|
||||
|
||||
room = MAX_LINE_LENGTH - 1;
|
||||
offset = 0;
|
||||
|
||||
/* XXX TEST ME!! TODO: yes, please do */
|
||||
for (;;) {
|
||||
if (!js_FileRead(cx, file, &data, 1, file->type)) {
|
||||
endofline = JS_FALSE;
|
||||
goto loop;
|
||||
}
|
||||
read = js_FileRead(cx, file, &data, 1, file->type);
|
||||
if (read < 0)
|
||||
goto out;
|
||||
if (read == 0)
|
||||
goto eof;
|
||||
|
||||
switch (data) {
|
||||
case '\n' :
|
||||
endofline = JS_TRUE;
|
||||
goto loop;
|
||||
case '\r':
|
||||
if (!js_FileRead(cx, file, &data2, 1, file->type)) {
|
||||
endofline = JS_TRUE;
|
||||
goto loop;
|
||||
}
|
||||
if (data2!='\n') { /* We read one char too far. Buffer it. */
|
||||
read = js_FileRead(cx, file, &data2, 1, file->type);
|
||||
if (read < 0)
|
||||
goto out;
|
||||
|
||||
if (read == 1 && data2 != '\n') {
|
||||
/* We read one char too far. Buffer it. */
|
||||
file->charBuffer = data2;
|
||||
file->charBufferUsed = JS_TRUE;
|
||||
}
|
||||
endofline = JS_TRUE;
|
||||
goto loop;
|
||||
|
||||
/* Fall through. */
|
||||
case '\n':
|
||||
goto done;
|
||||
|
||||
default:
|
||||
if (--room < 0) {
|
||||
buf = JS_malloc(cx, (offset+MAX_LINE_LENGTH)*sizeof data);
|
||||
if (!buf) return JS_FALSE;
|
||||
tmp = JS_realloc(cx, buf,
|
||||
(offset + MAX_LINE_LENGTH) * sizeof data);
|
||||
if (!tmp)
|
||||
goto out;
|
||||
|
||||
room = MAX_LINE_LENGTH - 1;
|
||||
memcpy(buf, JS_GetStringChars(file->linebuffer),
|
||||
JS_GetStringLength(file->linebuffer));
|
||||
/* what follows may not be the cleanest way. */
|
||||
file->linebuffer->chars = buf;
|
||||
file->linebuffer->length = offset+MAX_LINE_LENGTH;
|
||||
buf = tmp;
|
||||
}
|
||||
file->linebuffer->chars[offset++] = data;
|
||||
|
||||
buf[offset++] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
loop:
|
||||
file->linebuffer->chars[offset] = 0;
|
||||
if ((endofline==JS_TRUE)) {
|
||||
str = JS_NewUCStringCopyN(cx, JS_GetStringChars(file->linebuffer),
|
||||
offset);
|
||||
|
||||
eof:
|
||||
if (offset == 0) {
|
||||
*rval = JSVAL_FALSE;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
done:
|
||||
buf[offset] = 0;
|
||||
tmp = JS_realloc(cx, buf, (offset + 1) * sizeof data);
|
||||
if (!tmp)
|
||||
goto out;
|
||||
|
||||
str = JS_NewUCString(cx, tmp, offset);
|
||||
if (!str)
|
||||
goto out;
|
||||
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
return JS_TRUE;
|
||||
}else{
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
*rval = JSVAL_NULL;
|
||||
if (buf)
|
||||
JS_free(cx, buf);
|
||||
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1989,7 +2045,8 @@ file_init(JSContext *cx, JSObject *obj, char *bytes)
|
|||
JSFile *file;
|
||||
|
||||
file = JS_malloc(cx, sizeof *file);
|
||||
if (!file) return NULL;
|
||||
if (!file)
|
||||
return NULL;
|
||||
memset(file, 0 , sizeof *file);
|
||||
|
||||
js_ResetAttributes(file);
|
||||
|
@ -2001,7 +2058,8 @@ file_init(JSContext *cx, JSObject *obj, char *bytes)
|
|||
JSFILEMSG_CANNOT_SET_PRIVATE_FILE, file->path);
|
||||
JS_free(cx, file);
|
||||
return NULL;
|
||||
}else
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
|
@ -2065,23 +2123,32 @@ file_constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
JSString *str;
|
||||
JSFile *file;
|
||||
|
||||
str = (argc==0)?JS_InternString(cx, ""):JS_ValueToString(cx, argv[0]);
|
||||
if (!(cx->fp->flags & JSFRAME_CONSTRUCTING)) {
|
||||
/* Replace obj with a new File object. */
|
||||
obj = JS_NewObject(cx, &file_class, NULL, NULL);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
str = (argc == 0)
|
||||
? JS_InternString(cx, "")
|
||||
: JS_ValueToString(cx, argv[0]);
|
||||
|
||||
if (!str) {
|
||||
JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL,
|
||||
JSFILEMSG_FIRST_ARGUMENT_CONSTRUCTOR_NOT_STRING_ERROR, argv[0]);
|
||||
goto out;
|
||||
JSFILEMSG_FIRST_ARGUMENT_CONSTRUCTOR_NOT_STRING_ERROR,
|
||||
argv[0]);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
file = file_init(cx, obj, JS_GetStringBytes(str));
|
||||
if (!file) goto out;
|
||||
if (!file)
|
||||
return JS_FALSE;
|
||||
|
||||
SECURITY_CHECK(cx, NULL, "constructor", file);
|
||||
|
||||
*rval = OBJECT_TO_JSVAL(obj);
|
||||
return JS_TRUE;
|
||||
out:
|
||||
*rval = JSVAL_VOID;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* -------------------- File methods and properties ------------------------- */
|
||||
|
@ -2173,7 +2240,8 @@ file_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
switch (tiny) {
|
||||
case FILE_PARENT:
|
||||
SECURITY_CHECK(cx, NULL, "parent", file);
|
||||
*vp = js_parent(cx, file);
|
||||
if (!js_parent(cx, file, vp))
|
||||
return JS_FALSE;
|
||||
break;
|
||||
case FILE_PATH:
|
||||
*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, file->path));
|
||||
|
@ -2428,7 +2496,6 @@ file_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
}
|
||||
return JS_TRUE;
|
||||
out:
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -2484,7 +2551,6 @@ file_setProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
|
||||
return JS_TRUE;
|
||||
out:
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
|
@ -2494,28 +2560,32 @@ out:
|
|||
static JSBool
|
||||
file_currentDirSetter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
JSObject *rhsObject;
|
||||
char *path;
|
||||
JSFile *file = JS_GetInstancePrivate(cx, rhsObject, &file_class, NULL);
|
||||
JSFile *file;
|
||||
|
||||
file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
|
||||
|
||||
/* Look at the rhs and extract a file object from it */
|
||||
if (JSVAL_IS_OBJECT(*vp)) {
|
||||
if (JS_InstanceOf(cx, rhsObject, &file_class, NULL)){
|
||||
if (JS_InstanceOf(cx, obj, &file_class, NULL)) {
|
||||
/* Braindamaged rhs -- just return the old value */
|
||||
if (file && (!js_exists(cx, file) || !js_isDirectory(cx, file))) {
|
||||
JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, vp);
|
||||
goto out;
|
||||
return JS_FALSE;
|
||||
} else {
|
||||
rhsObject = JSVAL_TO_OBJECT(*vp);
|
||||
chdir(file->path);
|
||||
return JS_TRUE;
|
||||
}
|
||||
}else
|
||||
goto out;
|
||||
} else {
|
||||
return JS_FALSE;
|
||||
}
|
||||
} else {
|
||||
JSObject *rhsObject;
|
||||
char *path;
|
||||
|
||||
path = JS_GetStringBytes(JS_ValueToString(cx, *vp));
|
||||
rhsObject = js_NewFileObject(cx, path);
|
||||
if (!rhsObject) goto out;
|
||||
if (!rhsObject)
|
||||
return JS_FALSE;
|
||||
|
||||
if (!file || !js_exists(cx, file) || !js_isDirectory(cx, file)){
|
||||
JS_GetProperty(cx, obj, CURRENTDIR_PROPERTY, vp);
|
||||
|
@ -2524,10 +2594,8 @@ file_currentDirSetter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
chdir(path);
|
||||
}
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
out:
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* Declare class */
|
||||
|
@ -2539,7 +2607,7 @@ static JSClass file_class = {
|
|||
|
||||
/* -------------------- Functions exposed to the outside -------------------- */
|
||||
JS_PUBLIC_API(JSObject*)
|
||||
js_InitFileClass(JSContext *cx, JSObject* obj, JSBool initStandardStreams)
|
||||
js_InitFileClass(JSContext *cx, JSObject* obj)
|
||||
{
|
||||
JSObject *file, *ctor, *afile;
|
||||
jsval vp;
|
||||
|
@ -2569,8 +2637,6 @@ js_InitFileClass(JSContext *cx, JSObject* obj, JSBool initStandardStreams)
|
|||
JS_PropertyStub, file_currentDirSetter,
|
||||
JSPROP_ENUMERATE | JSPROP_READONLY );
|
||||
|
||||
if(initStandardStreams){
|
||||
/* Code to create stdin, stdout, and stderr. Insert in the appropriate place. */
|
||||
/* Define input */
|
||||
vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stdin,
|
||||
STDINPUT_NAME, PR_RDONLY, JS_TRUE, JS_FALSE));
|
||||
|
@ -2585,7 +2651,7 @@ js_InitFileClass(JSContext *cx, JSObject* obj, JSBool initStandardStreams)
|
|||
vp = OBJECT_TO_JSVAL(js_NewFileObjectFromFILE(cx, stderr,
|
||||
STDERROR_NAME, PR_WRONLY, JS_TRUE, JS_FALSE));
|
||||
JS_SetProperty(cx, ctor, "error", &vp);
|
||||
}
|
||||
|
||||
separator[0] = FILESEPARATOR;
|
||||
separator[1] = '\0';
|
||||
vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, separator));
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
#if JS_HAS_FILE_OBJECT
|
||||
extern JS_PUBLIC_API(JSObject*)
|
||||
js_InitFileClass(JSContext *cx, JSObject* obj, JSBool initStandardStreams);
|
||||
js_InitFileClass(JSContext *cx, JSObject* obj);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject*)
|
||||
js_NewFileObject(JSContext *cx, char *bytes);
|
||||
|
|
|
@ -55,6 +55,7 @@ MSG_DEF(JSFILEMSG_CANNOT_FLUSH_CLOSE_FILE_ERROR, 10, 1, JSEXN_N
|
|||
MSG_DEF(JSFILEMSG_CANNOT_OPEN_WRITING_ERROR, 11, 1, JSEXN_NONE, "Cannot open file {0} for writing")
|
||||
MSG_DEF(JSFILEMSG_WRITEALL_EXPECTS_ONE_ARG_ERROR, 12, 0, JSEXN_NONE, "writeAll expects one argument")
|
||||
MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_WRITEALL_NOT_ARRAY_ERROR, 13, 0, JSEXN_NONE, "writeAll expects an array as an argument")
|
||||
MSG_DEF(JSFILEMSG_UNUSED0, 14, 0, JSEXN_NONE, "Unused error message slot")
|
||||
MSG_DEF(JSFILEMSG_CANNOT_OPEN_FILE_ERROR, 15, 1, JSEXN_NONE, "Cannot open file {0}")
|
||||
MSG_DEF(JSFILEMSG_FIRST_ARGUMENT_CONSTRUCTOR_NOT_STRING_ERROR, 16, 1, JSEXN_NONE, "The argument to the File constructor {0} must be a string")
|
||||
MSG_DEF(JSFILEMSG_BIDIRECTIONAL_PIPE_NOT_SUPPORTED, 17, 0, JSEXN_NONE, "Bidirectional pipes are not supported")
|
||||
|
|
Загрузка…
Ссылка в новой задаче