📄 jsfile.c
字号:
js_FileSeek(JSContext *cx, JSFile *file, int32 len, int32 mode){ int32 count, i; jsint remainder; unsigned char utfbuf[3]; jschar tmp; switch (mode) { case ASCII: count = PR_Seek(file->handle, len, PR_SEEK_CUR); break; case UTF8: remainder = 0; for (count = 0;count<len;count++) { i = js_BufferedRead(file, utfbuf+remainder, 3-remainder); if (i<=0) { return 0; } i = utf8_to_ucs2_char(utfbuf, (int16)i, &tmp ); if (i<0) { return 0; } else { if (i==1) { utfbuf[0] = utfbuf[1]; utfbuf[1] = utfbuf[2]; remainder = 2; } else if (i==2) { utfbuf[0] = utfbuf[2]; remainder = 1; } else if (i==3) remainder = 0; } } while (remainder>0) { file->byteBuffer[file->nbBytesInBuf] = utfbuf[0]; file->nbBytesInBuf++; utfbuf[0] = utfbuf[1]; utfbuf[1] = utfbuf[2]; remainder--; } break; case UCS2: count = PR_Seek(file->handle, len*2, PR_SEEK_CUR)/2; break; } if(count==-1){ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, JSFILEMSG_OP_FAILED, "seek", file->path); } return count;}static int32js_FileWrite(JSContext *cx, JSFile *file, jschar *buf, int32 len, int32 mode){ unsigned char *aux; int32 count, i, j; unsigned char *utfbuf; switch (mode) { case ASCII: aux = (unsigned char*)JS_malloc(cx, len); if (!aux) return 0; 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); 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; i = 0; for (count = 0;count<len;count++) { j = one_ucs2_to_utf8_char(utfbuf+i, utfbuf+len*3, buf[count]); if (j==-1) { JS_free(cx, utfbuf); return 0; } i+=j; } j = (!file->isNative)? PR_Write(file->handle, utfbuf, i): fwrite(utfbuf, 1, i, file->nativehandle); if (j<i) { JS_free(cx, utfbuf); return 0; } 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) { return 0; } break; } if(count==-1){ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, JSFILEMSG_OP_FAILED, "write", file->path); } return count;}/* ----------------------------- Property checkers -------------------------- */static JSBooljs_exists(JSContext *cx, JSFile *file){ if(!file->isNative){ return (PR_Access(file->path, PR_ACCESS_EXISTS)==PR_SUCCESS); }else{ /* doesn't make sense for a pipe of stdstream */ return JS_FALSE; }}static JSBooljs_canRead(JSContext *cx, JSFile *file){ if(!file->isNative){ if(file->isOpen&&!(file->mode&PR_RDONLY)) return JS_FALSE; return (PR_Access(file->path, PR_ACCESS_READ_OK)==PR_SUCCESS); }else{ if(file->isPipe){ /* pipe open for reading */ return file->path[0]==PIPE_SYMBOL; }else{ return !strcmp(file->path, STDINPUT_NAME); } }}static JSBooljs_canWrite(JSContext *cx, JSFile *file){ if(!file->isNative){ if(file->isOpen&&!(file->mode&PR_WRONLY)) return JS_FALSE; return (PR_Access(file->path, PR_ACCESS_WRITE_OK)==PR_SUCCESS); }else{ if(file->isPipe){ /* pipe open for writing */ return file->path[strlen(file->path)-1]==PIPE_SYMBOL; }else{ return !strcmp(file->path, STDOUTPUT_NAME) || !strcmp(file->path, STDERROR_NAME); } }}static JSBooljs_isFile(JSContext *cx, JSFile *file){ if(!file->isNative){ PRFileInfo info; if ((file->isOpen)? PR_GetOpenFileInfo(file->handle, &info): PR_GetFileInfo(file->path, &info)!=PR_SUCCESS){ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path); return JS_FALSE; }else return (info.type==PR_FILE_FILE); }else{ /* doesn't make sense for a pipe of stdstream */ return JS_FALSE; }}static JSBooljs_isDirectory(JSContext *cx, JSFile *file){ if(!file->isNative){ PRFileInfo info; /* hack needed to get get_property to work */ if(!js_exists(cx, file)) return JS_FALSE; if ((file->isOpen)? PR_GetOpenFileInfo(file->handle, &info): PR_GetFileInfo(file->path, &info)!=PR_SUCCESS){ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path); return JS_FALSE; }else return (info.type==PR_FILE_DIRECTORY); }else{ /* doesn't make sense for a pipe of stdstream */ return JS_FALSE; }}static jsvaljs_size(JSContext *cx, JSFile *file){ PRFileInfo info; JSFILE_CHECK_NATIVE("size"); if ((file->isOpen)? PR_GetOpenFileInfo(file->handle, &info): PR_GetFileInfo(file->path, &info)!=PR_SUCCESS){ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, JSFILEMSG_CANNOT_ACCESS_FILE_STATUS, file->path); goto out; }else return INT_TO_JSVAL(info.size);out: return JSVAL_VOID;}/* Return the parent object */static jsvaljs_parent(JSContext *cx, JSFile *file){ char *str; /* since we only care about pipes and native files, return NULL */ if(file->isNative) return JSVAL_VOID; 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; }else{ return OBJECT_TO_JSVAL(js_NewFileObject(cx, str)); JS_free(cx, str); }}static jsvaljs_name(JSContext *cx, JSFile *file){ return file->isPipe? JSVAL_VOID: STRING_TO_JSVAL(JS_NewStringCopyZ(cx, js_fileBaseName(cx, file->path)));}/* ------------------------------ File object methods ---------------------------- */static JSBoolfile_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL); JSString *strmode, *strtype; char *ctype, *mode; int32 mask, type; int len; SECURITY_CHECK(cx, NULL, "open", file); /* A native file that is already open */ if(file->isOpen && file->isNative){ JS_ReportWarning(cx, "Native file %s is already open, proceeding", file->path); goto good; } /* 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; } if(js_isDirectory(cx, file)){ JS_ReportWarning(cx, "%s seems to be a directory, there is no point in " "trying to open it, proceeding", file->path); goto good; } /* Path must be defined at this point */ len = strlen(file->path); /* Mode */ if (argc>=1){ strmode = JS_ValueToString(cx, argv[0]); if (!strmode){ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, JSFILEMSG_FIRST_ARGUMENT_OPEN_NOT_STRING_ERROR, argv[0]); goto out; } mode = JS_strdup(cx, JS_GetStringBytes(strmode)); }else{ if(file->path[0]==PIPE_SYMBOL){ /* pipe default mode */ mode = JS_strdup(cx, "read"); }else if(file->path[len-1]==PIPE_SYMBOL){ /* pipe default mode */ mode = JS_strdup(cx, "write"); }else{ /* non-destructive, permissive defaults. */ mode = JS_strdup(cx, "readWrite,append,create"); } } /* 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; 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")); /* 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]); goto out; } ctype = JS_GetStringBytes(strtype); if(!strcmp(ctype, utfstring)) type = UTF8; else if (!strcmp(ctype, unicodestring)) type = UCS2; else{ if(strcmp(ctype, asciistring)){ JS_ReportWarning(cx, "File type %s is not supported, using " "'text' instead, proceeding", ctype); } type = ASCII; } }else{ type = ASCII; } /* Save the relevant fields */ file->type = type; file->mode = mask; file->nativehandle = NULL; file->hasRandomAccess = (type!=UTF8); /* 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){ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, JSFILEMSG_BIDIRECTIONAL_PIPE_NOT_SUPPORTED); goto out; }else{ char pipemode[3]; SECURITY_CHECK(cx, NULL, "pipe_open", file); if(file->path[0] == PIPE_SYMBOL){ if(mask & (PR_WRONLY | PR_APPEND | PR_CREATE_FILE | PR_TRUNCATE)){ JS_ReportErrorNumber(cx, JSFile_GetErrorMessage, NULL, JSFILEMSG_OPEN_MODE_NOT_SUPPORTED_WITH_PIPES, mode, file->path); goto out; } /* open(SPOOLER, "| cat -v | lpr -h 2>/dev/null") -- pipe for writing */ pipemode[0] = 'r'; 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){ char *command = JS_malloc(cx, len); strncpy(command, file->path, len-1); command[len-1] = '\0'; /* open(STATUS, "netstat -an 2>&1 |") */ pipemode[0] = 'w'; pipemode[1] = file->type==UTF8?'b':'t'; pipemode[2] = '\0'; file->nativehandle = POPEN(command, pipemode); JS_free(cx, command); } /* set the flags */ file->isNative = JS_TRUE; file->isPipe = JS_TRUE; file->hasRandomAccess = JS_FALSE; } }else{ /* TODO: what about the permissions?? Java ignores the problem... */ file->handle = PR_Open(file->path, mask, 0644); } js_ResetBuffers(file); JS_free(cx, mode); mode = NULL; /* Set the open flag and return result */ if (file->handle==NULL && file->nativehandle==NULL){ file->isOpen = JS_FALSE; 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; return JS_FALSE;}static JSBoolfile_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSFile *file = JS_GetInstancePrivate(cx, obj, &file_class, NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -