/* Set a byte in the file at the offset designated by slotNum. */ static int setFileProperty(Ejs *ejs, EjsFile *fp, int slotNum, EjsObj *value) { MprOff offset; int c; if (!(fp->mode & EJS_FILE_OPEN)) { ejsThrowIOError(ejs, "File is not open"); return 0; } if (!(fp->mode & EJS_FILE_WRITE)) { ejsThrowIOError(ejs, "File is not opened for writing"); return 0; } c = ejsIs(ejs, value, Number) ? ejsGetInt(ejs, value) : ejsGetInt(ejs, ejsToNumber(ejs, value)); offset = mprSeekFile(fp->file, SEEK_CUR, 0); if (slotNum < 0) { // could have an mprGetPosition(file) API slotNum = (int) offset; } #if ME_CC_MMU && FUTURE fp->mapped[slotNum] = c; #else if (offset != slotNum && mprSeekFile(fp->file, SEEK_SET, slotNum) != slotNum) { ejsThrowIOError(ejs, "Cannot seek to file offset"); return 0; } if (mprPutFileChar(fp->file, c) < 0) { ejsThrowIOError(ejs, "Cannot write file"); return 0; } #endif return slotNum; }
/* Write another block of data */ static ssize writeHttpData(Ejs *ejs, EjsHttp *hp) { EjsByteArray *ba; HttpConn *conn; ssize count, nbytes; conn = hp->conn; ba = hp->data; nbytes = 0; if (ba && (count = ejsGetByteArrayAvailableData(ba)) > 0) { if (conn->tx->finalizedOutput) { ejsThrowIOError(ejs, "Cannot write to socket"); return 0; } // MOB - or should this be non-blocking nbytes = httpWriteBlock(conn->writeq, (cchar*) &ba->value[ba->readPosition], count, HTTP_BLOCK); if (nbytes < 0) { ejsThrowIOError(ejs, "Cannot write to socket"); return 0; } ba->readPosition += nbytes; } httpServiceQueues(conn); return nbytes; }
static EjsObj *loadXml(Ejs *ejs, EjsXML *xml, int argc, EjsObj **argv) { MprFile *file; MprXml *xp; cchar *filename; assert(argc == 1 && ejsIs(ejs, argv[0], String)); filename = ejsToMulti(ejs, argv[0]); file = mprOpenFile(filename, O_RDONLY, 0664); if (file == 0) { ejsThrowIOError(ejs, "Cannot open: %s", filename); return 0; } // TODO - convert to open/close xp = ejsCreateXmlParser(ejs, xml, filename); if (xp == 0) { ejsThrowMemoryError(ejs); mprCloseFile(file); return 0; } mprXmlSetInputStream(xp, readFileData, (void*) file); if (mprXmlParse(xp) < 0 && !ejsHasException(ejs)) { ejsThrowIOError(ejs, "Cannot parse XML file: %s\nDetails %s", filename, mprXmlGetErrorMsg(xp)); } mprCloseFile(file); return 0; }
/* Set the current working directory function chdir(value: String|Path): void */ static EjsObj *app_chdir(Ejs *ejs, EjsObj *unused, int argc, EjsObj **argv) { cchar *path; assert(argc == 1); if (ejsIs(ejs, argv[0], Path)) { path = ((EjsPath*) argv[0])->value; } else if (ejsIs(ejs, argv[0], String)) { path = ejsToMulti(ejs, argv[0]); } else { ejsThrowIOError(ejs, "Bad path"); return NULL; } #if WINDOWS { MprFileSystem *fs; fs = mprLookupFileSystem(path); if (!mprPathExists(path, X_OK) && *path == '/') { path = sjoin(fs->cygwin, path, NULL); } } #endif if (chdir((char*) path) < 0) { ejsThrowIOError(ejs, "Cannot change the current directory"); } return 0; }
/* Constructor function File(path: Object, options: Object = null) */ static EjsFile *fileConstructor(Ejs *ejs, EjsFile *fp, int argc, EjsObj **argv) { EjsObj *pp, *options; cchar *path; if (argc < 1 || argc > 2) { ejsThrowArgError(ejs, "Bad args"); return 0; } pp = argv[0]; if (ejsIs(ejs, pp, Path)) { path = ((EjsPath*) pp)->value; } else if (ejsIs(ejs, pp, String)) { path = ejsToMulti(ejs, pp); } else { ejsThrowIOError(ejs, "Bad path"); return 0; } fp->path = mprNormalizePath(path); if (argc == 2) { options = (argc >= 2) ? argv[1] : 0; openFile(ejs, fp, 1, &options); } return fp; }
/* Read the required number of bytes into the response content buffer. Count < 0 means transfer the entire content. Returns the number of bytes read. Returns null on EOF. */ static ssize readHttpData(Ejs *ejs, EjsHttp *hp, ssize count) { MprBuf *buf; HttpConn *conn; ssize len, space, nbytes; conn = hp->conn; buf = hp->responseContent; mprResetBufIfEmpty(buf); while (count < 0 || mprGetBufLength(buf) < count) { len = (count < 0) ? BIT_MAX_BUFFER : (count - mprGetBufLength(buf)); space = mprGetBufSpace(buf); if (space < len) { mprGrowBuf(buf, len - space); } if ((nbytes = httpRead(conn, mprGetBufEnd(buf), len)) < 0) { ejsThrowIOError(ejs, "Cannot read required data"); return MPR_ERR_CANT_READ; } mprAdjustBufEnd(buf, nbytes); if (hp->conn->async || (nbytes == 0 && conn->state > HTTP_STATE_CONTENT)) { break; } } if (count < 0) { return mprGetBufLength(buf); } return min(count, mprGetBufLength(buf)); }
/* * Return an array of table names in the database. * function get tables(): Array */ static EjsVar *tables(Ejs *ejs, EjsDb *db, int argc, EjsVar **argv) { EjsArray *ap; char **data, *error; int rc, rowCount, i; ejsSetDbMemoryContext(db->tls, db->arena); ap = ejsCreateArray(ejs, 0); rc = sqlite3_get_table(db->sdb, "SELECT name FROM sqlite_master " "WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%'" "UNION ALL " "SELECT name FROM sqlite_temp_master " "WHERE type IN ('table','view') " "ORDER BY 1", &data, &rowCount, 0, &error); if (error) { ejsThrowIOError(ejs, "%s", error); sqlite3_free(error); } if (rc == SQLITE_OK){ for (i = 1; i <= rowCount; i++) { ejsSetProperty(ejs, (EjsVar*) ap, i - 1, (EjsVar*) ejsCreateString(ejs, data[i])); } } sqlite3_free_table(data); return (EjsVar*) ap; }
/* Function to iterate and return the next element value. NOTE: this is not a method of Array. Rather, it is a callback function for Iterator */ static EjsObj *nextValue(Ejs *ejs, EjsIterator *ip, int argc, EjsObj **argv) { EjsFile *fp; fp = (EjsFile*) ip->target; if (!ejsIs(ejs, fp, File)) { ejsThrowReferenceError(ejs, "Wrong type"); return 0; } if (ip->index < fp->info.size) { #if !ME_CC_MMU || 1 if (mprSeekFile(fp->file, SEEK_CUR, 0) != ip->index) { if (mprSeekFile(fp->file, SEEK_SET, ip->index) != ip->index) { ejsThrowIOError(ejs, "Cannot seek to %d", ip->index); return 0; } } ip->index++; return (EjsObj*) ejsCreateNumber(ejs, mprGetFileChar(fp->file)); #else return (EjsObj*) ejsCreateNumber(ejs, fp->mapped[ip->index++]); #endif } #if ME_CC_MMU && FUTURE unmapFile(fp); fp->mapped = 0; #endif ejsThrowStopIteration(ejs); return 0; }
/* Constructor function open(options: Object = null): File NOTE: options can be an options hash or as mode string */ static EjsObj *openFile(Ejs *ejs, EjsFile *fp, int argc, EjsObj **argv) { EjsObj *options; cchar *mode; int perms, omode; if (argc < 0 || argc > 1) { ejsThrowArgError(ejs, "Bad args"); return 0; } options = argv[0]; if (argc == 0 || !ejsIsDefined(ejs, options)) { omode = O_RDONLY | O_BINARY; perms = EJS_FILE_PERMS; fp->mode = EJS_FILE_READ; mode = "r"; } else { if (ejsIs(ejs, options, String)) { mode = ejsToMulti(ejs, options); perms = EJS_FILE_PERMS; } else { perms = ejsGetNumOption(ejs, options, "permissions", EJS_FILE_PERMS, 1); mode = getStrOption(ejs, options, "mode", "r", 1); if (ejs->exception) { return 0; } } omode = mapMode(mode); if (!(omode & O_WRONLY)) { fp->mode |= EJS_FILE_READ; } if (omode & (O_WRONLY | O_RDWR)) { fp->mode |= EJS_FILE_WRITE; } } fp->modeString = sclone(mode); fp->perms = perms; if (fp->file) { mprCloseFile(fp->file); } fp->file = mprOpenFile(fp->path, omode, perms); if (fp->file == 0) { ejsThrowIOError(ejs, "Cannot open %s", fp->path); return 0; } if (options) { ejsSetPathAttributes(ejs, fp->path, options); } #if ME_CC_MMU && FUTURE mprGetPathInfo(&fp->info); fp->mapped = mapFile(fp, fp->info.size, MPR_MAP_READ | MPR_MAP_WRITE); #endif fp->mode |= EJS_FILE_OPEN; return (EjsObj*) fp; }
/* function truncate(size: Number): Void */ PUBLIC EjsObj *truncateFile(Ejs *ejs, EjsFile *fp, int argc, EjsObj **argv) { int size; size = ejsGetInt(ejs, argv[0]); if (mprTruncateFile(fp->path, size) < 0) { ejsThrowIOError(ejs, "Cant truncate %s", fp->path); } return 0; }
/* * DB Constructor and also used for constructor for sub classes. * * function DB(connectionString: String) */ static EjsVar *dbConstructor(Ejs *ejs, EjsDb *db, int argc, EjsVar **argv) { sqlite3 *sdb; EjsDb **dbp; char *path; path = ejsGetString(argv[0]); /* * Create a memory context for use by sqlite. This is a virtual paged memory region. * TODO - this is not ideal for long running applications. */ db->arena = mprAllocArena(ejs, "sqlite", EJS_MAX_DB_MEM, 0, 0); if (db->arena == 0) { return 0; } /* * Create a destructor object so we can cleanup and close the database. Must create after the arena so it will be * invoked before the arena is freed. */ if ((dbp = mprAllocObject(ejs, 1, (MprDestructor) dbDestructor)) == 0) { ejsThrowMemoryError(ejs); return 0; } *dbp = db; db->tls = mprCreateThreadLocal(db->arena); if (db->tls == 0) { return 0; } ejsSetDbMemoryContext(db->tls, db->arena); sdb = 0; if (sqlite3_open(path, &sdb /* TODO remove , SQLITE_OPEN_READWRITE, 0 */) != SQLITE_OK) { ejsThrowIOError(ejs, "Can't open database %s", path); return 0; } db->sdb = sdb; sqlite3_busy_timeout(sdb, 15000); /* * Query or change the count-changes flag. Normally, when the count-changes flag is not set, INSERT, UPDATE and * DELETE statements return no data. When count-changes is set, each of these commands returns a single row of * data consisting of one integer value - the number of rows inserted, modified or deleted by the command. The * returned change count does not include any insertions, modifications or deletions performed by triggers. */ // sqlite3_exec(sdb, "PRAGMA count_changes = OFF", NULL, NULL, NULL); ejsSetProperty(ejs, (EjsVar*) db, ES_ejs_db_Database__connection, (EjsVar*) ejsCreateString(ejs, path)); ejsSetProperty(ejs, (EjsVar*) db, ES_ejs_db_Database__name, (EjsVar*) ejsCreateString(ejs, mprGetBaseName(path))); return 0; }
/* * Worker thread main procedure */ static void workerMain(EjsWorker *worker, MprWorker *mprWorker) { Ejs *ejs, *inside; EjsWorker *insideWorker; MprDispatcher *dispatcher; Message *msg; mprAssert(!worker->inside); insideWorker = worker->pair; mprAssert(insideWorker->state == EJS_WORKER_BEGIN); ejs = worker->ejs; inside = insideWorker->ejs; insideWorker->state = EJS_WORKER_STARTED; /* * Run the script or file */ if (worker->scriptFile) { loadFile(insideWorker, worker->scriptFile); } else if (worker->scriptLiteral) { if (ejs->service->loadScriptLiteral == 0) { ejsThrowIOError(ejs, "worker: Compiling is not enabled"); return; } (ejs->service->loadScriptLiteral)(inside, worker->scriptLiteral); } /* * Check for exceptions */ if (inside->exception) { handleError(ejs, worker, inside->exception); } if ((msg = mprAllocObjZeroed(ejs, Message)) == 0) { ejsThrowMemoryError(ejs); return; } /* * Post "onclose" finalization message */ msg->worker = worker; msg->callback = "onclose"; msg->callbackSlot = ES_ejs_sys_Worker_onclose; insideWorker->state = EJS_WORKER_CLOSED; worker->state = EJS_WORKER_CLOSED; insideWorker->obj.var.permanent = 0; dispatcher = worker->ejs->dispatcher; mprCreateEvent(dispatcher, (MprEventProc) doMessage, 0, MPR_NORMAL_PRIORITY, msg, 0); mprSignalCond(dispatcher->cond); }
/* * Set the current working directory * * function chdir(value: String|Path): void */ static EjsVar *changeCurrentDir(Ejs *ejs, EjsVar *unused, int argc, EjsVar **argv) { char *path; mprAssert(argc == 1); if (ejsIsPath(argv[0])) { path = ((EjsPath*) argv[0])->path; } else if (ejsIsString(argv[0])) { path = ejsGetString(argv[0]); } else { ejsThrowIOError(ejs, "Bad path"); return NULL; } if (chdir(path) < 0) { ejsThrowIOError(ejs, "Can't change the current directory"); } return 0; }
/* Write data to the file function write(data: Object): Number */ PUBLIC EjsObj *writeFile(Ejs *ejs, EjsFile *fp, int argc, EjsObj **argv) { EjsArray *args; EjsByteArray *ap; EjsObj *vp; EjsString *str; cchar *buf; ssize len, written; int i; assert(argc == 1 && ejsIs(ejs, argv[0], Array)); args = (EjsArray*) argv[0]; if (!(fp->mode & EJS_FILE_WRITE)) { ejsThrowStateError(ejs, "File not opened for writing"); return 0; } written = 0; for (i = 0; i < args->length; i++) { vp = ejsGetProperty(ejs, (EjsObj*) args, i); assert(vp); switch (TYPE(vp)->sid) { case S_ByteArray: ap = (EjsByteArray*) vp; // TODO UNICODE ENCODING buf = (cchar*) &ap->value[ap->readPosition]; len = ap->writePosition - ap->readPosition; break; case S_String: // UNICODE #if UNICODE && FUTURE buf = awtom(((EjsString*) vp)->value, &len); #else buf = ((EjsString*) vp)->value; len = ((EjsString*) vp)->length; #endif break; default: str = ejsToString(ejs, vp); buf = awtom(((EjsString*) str)->value, &len); break; } if (mprWriteFile(fp->file, buf, len) != len) { ejsThrowIOError(ejs, "Cannot write to %s", fp->path); return 0; } written += len; /* Use GC to free buf as it may not be allocated */ } return (EjsObj*) ejsCreateNumber(ejs, (MprNumber) written); }
/* Worker thread main procedure. Worker is the inside worker. */ static int workerMain(EjsWorker *insideWorker, MprEvent *event) { Ejs *outside, *inside; EjsWorker *outsideWorker; MprDispatcher *dispatcher; Message *msg; assert(insideWorker->inside); outsideWorker = insideWorker->pair; assert(!outsideWorker->inside); assert(insideWorker->state == EJS_WORKER_BEGIN); outside = outsideWorker->ejs; inside = insideWorker->ejs; insideWorker->state = EJS_WORKER_STARTED; /* Run the script or file */ if (outsideWorker->scriptFile) { loadFile(insideWorker, outsideWorker->scriptFile); } else if (outsideWorker->scriptLiteral) { if (outside->service->loadScriptLiteral == 0) { ejsThrowIOError(outside, "worker: Compiling is not enabled"); return 0; } (outside->service->loadScriptLiteral)(inside, outsideWorker->scriptLiteral, NULL); } /* Check for exceptions */ if (inside->exception) { handleError(outside, outsideWorker, inside->exception, 0); inside->exception = 0; } ejsBlockGC(inside); if ((msg = createMessage()) == 0) { ejsThrowMemoryError(outside); return 0; } /* Post "onclose" finalization message */ msg->worker = outsideWorker; msg->callback = "onclose"; msg->callbackSlot = ES_Worker_onclose; insideWorker->state = EJS_WORKER_CLOSED; outsideWorker->state = EJS_WORKER_CLOSED; dispatcher = outside->dispatcher; mprCreateEvent(dispatcher, "doMessage", 0, (MprEventProc) doMessage, msg, 0); return 0; }
/* Index into a file and extract a byte. This is random access reading. */ static EjsNumber *getFileProperty(Ejs *ejs, EjsFile *fp, int slotNum) { MprOff offset; int c; if (!(fp->mode & EJS_FILE_OPEN)) { ejsThrowIOError(ejs, "File is not open"); return 0; } #if KEEP if (fp->mode & EJS_FILE_READ) { if (slotNum >= fp->info.size) { ejsThrowOutOfBoundsError(ejs, "Bad file index"); return 0; } } if (slotNum < 0) { ejsThrowOutOfBoundsError(ejs, "Bad file index"); return 0; } #endif #if ME_CC_MMU && FUTURE // must check against mapped size here. c = fp->mapped[slotNum]; #else offset = mprSeekFile(fp->file, SEEK_CUR, 0); if (offset != slotNum) { if (mprSeekFile(fp->file, SEEK_SET, slotNum) != slotNum) { ejsThrowIOError(ejs, "Cannot seek to file offset"); return 0; } } c = mprPeekFileChar(fp->file); if (c < 0) { ejsThrowIOError(ejs, "Cannot read file"); return 0; } #endif return ejsCreateNumber(ejs, c); }
/* uncompressBytes(data: ByteArray): ByteArray */ static EjsObj *zlib_uncompressBytes(Ejs *ejs, EjsObj *unused, int argc, EjsObj **argv) { EjsByteArray *in, *out; z_stream zs; uchar outbuf[ZBUFSIZE]; ssize nbytes, size; int rc; in = (EjsByteArray*) argv[0]; if ((out = ejsCreateByteArray(ejs, in->size)) == 0) { return 0; } if ((size = (int) ejsGetByteArrayAvailableData(in)) == 0) { return (EjsObj*) out; } zs.zalloc = Z_NULL; zs.zfree = Z_NULL; zs.opaque = Z_NULL; zs.avail_in = 0; rc = inflateInit(&zs); zs.next_in = &in->value[in->readPosition]; zs.avail_in = (int) size; do { if (zs.avail_in == 0) { break; } do { zs.avail_out = ZBUFSIZE; zs.next_out = (uchar*) outbuf; if ((rc = inflate(&zs, Z_NO_FLUSH)) == Z_NEED_DICT) { inflateEnd(&zs); return 0; } else if (rc == Z_DATA_ERROR || rc == Z_MEM_ERROR) { inflateEnd(&zs); return 0; } else { nbytes = ZBUFSIZE - zs.avail_out; } if (ejsCopyToByteArray(ejs, out, -1, (char*) outbuf, nbytes) != nbytes) { ejsThrowIOError(ejs, "Cannot copy to byte array"); inflateEnd(&zs); return 0; } out->writePosition += nbytes; } while (zs.avail_out == 0); assure(zs.avail_in == 0); } while (rc != Z_STREAM_END); deflateEnd(&zs); return (EjsObj*) out; }
/* uncompressString(data: String): String */ static EjsString *zlib_uncompressString(Ejs *ejs, EjsObj *unused, int argc, EjsObj **argv) { EjsString *in; MprBuf *out; z_stream zs; uchar outbuf[ZBUFSIZE]; ssize nbytes, size; int rc; in = (EjsString*) argv[0]; if ((out = mprCreateBuf(ZBUFSIZE, -1)) == 0) { return 0; } if ((size = in->length) == 0) { return ESV(empty); } zs.zalloc = Z_NULL; zs.zfree = Z_NULL; zs.opaque = Z_NULL; zs.avail_in = 0; rc = inflateInit(&zs); zs.next_in = (uchar*) in->value; zs.avail_in = (int) size; do { if (zs.avail_in == 0) { break; } do { zs.avail_out = ZBUFSIZE; zs.next_out = outbuf; if ((rc = inflate(&zs, Z_NO_FLUSH)) == Z_NEED_DICT) { inflateEnd(&zs); return 0; } else if (rc == Z_DATA_ERROR || rc == Z_MEM_ERROR) { inflateEnd(&zs); return 0; } else { nbytes = ZBUFSIZE - zs.avail_out; } if (mprPutBlockToBuf(out, (char*) outbuf, nbytes) != nbytes) { ejsThrowIOError(ejs, "Cannot copy to byte array"); inflateEnd(&zs); return 0; } } while (zs.avail_out == 0); assure(zs.avail_in == 0); } while (rc != Z_STREAM_END); deflateEnd(&zs); return ejsCreateStringFromBytes(ejs, mprGetBufStart(out), mprGetBufLength(out)); }
/* function sendBlock(content, options): Number */ static EjsNumber *ws_sendBlock(Ejs *ejs, EjsWebSocket *ws, int argc, EjsObj **argv) { EjsByteArray *ba; EjsAny *content, *vp; ssize nbytes; cchar *str; int last, mode, type, flags; assert(argc == 2); if (ws->conn->state < HTTP_STATE_PARSED && !waitForHttpState(ws, HTTP_STATE_PARSED, -1, 1)) { return ESV(null); } content = argv[0]; last = ejsGetPropertyByName(ejs, argv[1], EN("last")) != ESV(false); if ((vp = ejsGetPropertyByName(ejs, argv[1], EN("mode"))) != 0) { mode = (int) ejsGetNumber(ejs, vp); if (mode != HTTP_BUFFER && mode != HTTP_BLOCK && mode != HTTP_NON_BLOCK) { ejsThrowArgError(ejs, "Bad message mode"); return 0; } } else { mode = HTTP_BUFFER; } if ((vp = ejsGetPropertyByName(ejs, argv[1], EN("type"))) != 0) { type = (int) ejsGetNumber(ejs, vp); if (type != WS_MSG_CONT && type != WS_MSG_TEXT && type != WS_MSG_BINARY) { ejsThrowArgError(ejs, "Bad message type"); return 0; } } else { type = WS_MSG_TEXT; } flags = mode; if (!last) { flags |= HTTP_MORE; } if (ejsIs(ejs, content, ByteArray)) { ba = (EjsByteArray*) content; nbytes = ejsGetByteArrayAvailableData(ba); nbytes = httpSendBlock(ws->conn, type, (cchar*) &ba->value[ba->readPosition], nbytes, flags); } else { str = ejsToMulti(ejs, content); nbytes = httpSendBlock(ws->conn, type, str, slen(str), flags); } if (nbytes < 0) { ejsThrowIOError(ejs, "Cannot send block"); return 0; } return ejsCreateNumber(ejs, (MprNumber) nbytes); }
static EjsObj *saveXml(Ejs *ejs, EjsXML *xml, int argc, EjsObj **argv) { MprBuf *buf; MprFile *file; char *filename; ssize bytes, len; if (argc != 1 || !ejsIs(ejs, argv[0], String)) { ejsThrowArgError(ejs, "Bad args. Usage: save(filename);"); return 0; } filename = awtom(((EjsString*) argv[0])->value, NULL); /* Create a buffer to hold the output. All in memory. */ buf = mprCreateBuf(ME_MAX_BUFFER, -1); mprPutStringToBuf(buf, "<?xml version=\"1.0\"?>\n"); if (ejsXMLToBuf(ejs, buf, xml, 0) < 0) { return 0; } file = mprOpenFile(filename, O_CREAT | O_TRUNC | O_WRONLY | O_TEXT, 0664); if (file == 0) { ejsThrowIOError(ejs, "Cannot open: %s, %d", filename, mprGetOsError(ejs)); return 0; } len = mprGetBufLength(buf); bytes = mprWriteFile(file, buf->start, len); if (bytes != len) { ejsThrowIOError(ejs, "Cannot write to: %s", filename); mprCloseFile(file); return 0; } mprWriteFile(file, "\n", 1); mprCloseFile(file); return 0; }
/* uncompress(src: Path, dest: Path = null) */ static EjsObj *zlib_uncompress(Ejs *ejs, EjsObj *unused, int argc, EjsObj **argv) { MprFile *out; gzFile in; cchar *src, *dest; uchar inbuf[MPR_BUFSIZE]; ssize nbytes; src = ((EjsPath*) argv[0])->value; dest = (argc >= 2) ? ejsToMulti(ejs, argv[1]) : 0; if (!dest) { dest = sjoin(src, ".gz", NULL); } if ((in = gzopen(src, "rb")) == 0) { ejsThrowIOError(ejs, "Cannot open from %s", src); return 0; } if ((out = mprOpenFile(dest, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644)) == 0) { ejsThrowIOError(ejs, "Cannot open destination %s", dest); return 0; } while (1) { if ((nbytes = gzread(in, inbuf, sizeof(inbuf))) < 0) { ejsThrowIOError(ejs, "Cannot read from %s", src); return 0; } else if (nbytes == 0) { break; } if (mprWriteFile(out, inbuf, (int) nbytes) != nbytes) { ejsThrowIOError(ejs, "Cannot write to %s", dest); return 0; } } mprCloseFile(out); gzclose(in); return 0; }
/* DB Constructor and also used for constructor for sub classes. function Debugger(connectionString: String) */ static EjsVar *debuggerConstructor(Ejs *ejs, EjsDebugger *db, int argc, EjsVar **argv) { debugger3 *sdb; cchar *path; path = ejsGetString(ejs, argv[0]); db->ejs = ejs; /* * Create a memory context for use by debugger. This is a virtual paged memory region. * TODO OPT - Could do better for running applications. */ #if MAP_ALLOC db->arena = mprAllocArena(ejs, "debugger", EJS_MAX_SQLITE_MEM, !USE_TLS, 0); if (db->arena == 0) { return 0; } SET_CTX(db->arena); #else db->arena = mprAllocHeap(ejs, "debugger", EJS_MAX_SQLITE_MEM, 1, 0); if (db->arena == 0) { return 0; } SET_CTX(db->arena); #endif #if UNUSED EjsDebugger **dbp; /* * Create a destructor object so we can cleanup and close the database. Must create after the arena so it will be * invoked before the arena is freed. */ if ((dbp = mprAllocWithDestructor(ejs, sizeof(void*), (MprDestructor) sqldbDestructor)) == 0) { ejsThrowMemoryError(ejs); return 0; } *dbp = db; #endif sdb = 0; if (debugger3_open(path, &sdb) != SQLITE_OK) { ejsThrowIOError(ejs, "Cannot open database %s", path); return 0; } db->sdb = sdb; debugger3_busy_timeout(sdb, ME_MAX_SQLITE_DURATION); debugger3_soft_heap_limit(ME_MAX_SQLITE_MEM); return 0; }
/* Read data bytes from a file function readBytes(count: Number = -1): ByteArray */ static EjsObj *readFileBytes(Ejs *ejs, EjsFile *fp, int argc, EjsObj **argv) { EjsByteArray *result; MprPath info; ssize count, totalRead; if (argc == 0) { count = -1; } else if (argc != 1) { count = 0; ejsThrowArgError(ejs, "Bad args"); return 0; } else { assert(argc == 1 && ejsIs(ejs, argv[0], Number)); count = ejsGetInt(ejs, argv[0]); } if (fp->file == 0) { ejsThrowStateError(ejs, "File not open"); return 0; } if (!(fp->mode & EJS_FILE_READ)) { ejsThrowStateError(ejs, "File not opened for reading"); return 0; } if (count < 0) { // TODO OPT could this be cached in fp->info if (mprGetPathInfo(fp->path, &info) == 0) { count = (int) info.size; count -= (int) mprGetFilePosition(fp->file); } else { count = ME_MAX_BUFFER; } assert(count >= 0); } result = ejsCreateByteArray(ejs, count); if (result == 0) { ejsThrowMemoryError(ejs); return 0; } totalRead = readData(ejs, fp, result, 0, count); if (totalRead < 0) { ejsThrowIOError(ejs, "Cannot read from file: %s", fp->path); return 0; } else if (totalRead == 0) { return ESV(null); } ejsSetByteArrayPositions(ejs, result, 0, totalRead); return (EjsObj*) result; }
static int lookupFileProperty(Ejs *ejs, EjsFile *fp, EjsName qname) { int index; if (qname.name == 0 || !isdigit((uchar) qname.name->value[0])) { return EJS_ERR; } if (!(fp->mode & EJS_FILE_OPEN)) { ejsThrowIOError(ejs, "File is not open"); return 0; } index = ejsAtoi(ejs, qname.name, 10); if (index < mprGetFileSize(fp->file)) { return index; } return EJS_ERR; }
/* Read data as a string function readString(count: Number = -1): String */ static EjsString *readFileString(Ejs *ejs, EjsFile *fp, int argc, EjsObj **argv) { EjsString *result; MprPath info; ssize totalRead; int count; if (argc == 0) { count = -1; } else if (argc != 1) { count = 0; ejsThrowArgError(ejs, "Bad args"); return 0; } else { assert(argc == 1 && ejsIs(ejs, argv[0], Number)); count = ejsGetInt(ejs, argv[0]); } if (fp->file == 0) { ejsThrowStateError(ejs, "File not open"); return 0; } if (!(fp->mode & EJS_FILE_READ)) { ejsThrowStateError(ejs, "File not opened for reading"); return 0; } if (count < 0) { // TODO OPT could this be cached in fp->info if (mprGetPathInfo(fp->path, &info) == 0) { count = (int) info.size; count -= (int) mprGetFilePosition(fp->file); } else { count = ME_MAX_BUFFER; } assert(count >= 0); } if ((result = ejsCreateBareString(ejs, count)) == NULL) { ejsThrowMemoryError(ejs); return 0; } totalRead = mprReadFile(fp->file, result->value, count); if (totalRead != count) { ejsThrowIOError(ejs, "Cannot read from file: %s", fp->path); return 0; } return ejsInternString(result); }
/* Seek to a new location in the file and set the File marker to a new read/write position. function set position(value: Number): void */ static EjsObj *setFilePosition(Ejs *ejs, EjsFile *fp, int argc, EjsObj **argv) { MprOff pos; assert(argc == 1 && ejsIs(ejs, argv[0], Number)); pos = ejsGetInt(ejs, argv[0]); if (fp->file == 0) { ejsThrowStateError(ejs, "File not opened"); return 0; } pos = ejsGetInt(ejs, argv[0]); if (mprSeekFile(fp->file, SEEK_SET, pos) != pos) { ejsThrowIOError(ejs, "Cannot seek to %Ld", pos); } return 0; }
static EjsObj *startWebSocketRequest(Ejs *ejs, EjsWebSocket *ws) { HttpConn *conn; conn = ws->conn; if (ws->certFile) { if (!ws->ssl) { ws->ssl = mprCreateSsl(0); } mprSetSslCertFile(ws->ssl, ws->certFile); } if (httpConnect(conn, "GET", ws->uri, ws->ssl) < 0) { ejsThrowIOError(ejs, "Cannot issue request for \"%s\"", ws->uri); return 0; } httpEnableConnEvents(ws->conn); return 0; }
/* compressString(data: String): String */ static EjsString *zlib_compressString(Ejs *ejs, EjsObj *unused, int argc, EjsObj **argv) { EjsString *in; MprBuf *out; z_stream zs; uchar outbuf[ZBUFSIZE]; ssize size, nbytes; int level, flush; in = (EjsString*) argv[0]; if ((size = in->length) == 0) { return ESV(empty); } if ((out = mprCreateBuf(in->length, 0)) == 0) { return 0; } zs.zalloc = Z_NULL; zs.zfree = Z_NULL; zs.opaque = Z_NULL; level = Z_DEFAULT_COMPRESSION; deflateInit(&zs, level); zs.next_in = (uchar*) in->value; zs.avail_in = (int) size; do { flush = (zs.avail_in == 0) ? Z_FINISH : Z_NO_FLUSH; do { zs.avail_out = ZBUFSIZE; zs.next_out = outbuf; deflate(&zs, flush); nbytes = ZBUFSIZE - zs.avail_out; if (mprPutBlockToBuf(out, (char*) outbuf, nbytes) != nbytes) { ejsThrowIOError(ejs, "Cannot copy to output buffer"); deflateEnd(&zs); return 0; } } while (zs.avail_out == 0); assure(zs.avail_in == 0); } while (flush != Z_FINISH); deflateEnd(&zs); return ejsCreateStringFromBytes(ejs, mprGetBufStart(out), mprGetBufLength(out)); }
/* Read the specified count of bytes into the byte array. Grow the array if required and growable */ static ssize readData(Ejs *ejs, EjsFile *fp, EjsByteArray *ap, ssize offset, ssize count) { ssize room, bytes; if (count <= 0) { return 0; } room = ap->size - offset; if (room < count) { if (ap->resizable) { ejsGrowByteArray(ejs, ap, ap->size + (count - room)); } else { count = min(room, count); } } bytes = mprReadFile(fp->file, &ap->value[offset], count); if (bytes < 0) { ejsThrowIOError(ejs, "Error reading from %s", fp->path); } return bytes; }
/* Load a file into the worker. This can be a script file or a module. This runs on the inside interpreter */ static void loadFile(EjsWorker *worker, cchar *path) { Ejs *ejs; cchar *cp; assert(worker->inside); assert(worker->pair && worker->pair->ejs); ejs = worker->ejs; if ((cp = strrchr(path, '.')) != NULL && strcmp(cp, EJS_MODULE_EXT) != 0) { if (ejs->service->loadScriptFile == 0) { ejsThrowIOError(ejs, "load: Compiling is not enabled for %s", path); return; } (ejs->service->loadScriptFile)(ejs, path, NULL); } else { /* Error reporting via thrown exceptions */ ejsLoadModule(ejs, ejsCreateStringFromAsc(ejs, path), -1, -1, EJS_LOADER_RELOAD); } }