/* zipfile.save(callback) */ Handle<Value> ZipFile::Save(const Arguments& args) { ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This()); if (zf->Busy()) return ThrowException(Exception::Error(String::New("Zipfile already in use.."))); Local<Value> cb = args[0]; if (!cb->IsFunction()) return ThrowException(Exception::Error( String::New("Second argument should be a callback function."))); save_closure_t *save = new save_closure_t; save->done = false; save->zf = zf; save->error = NULL; save->save_cb = Persistent<Function>::New(Handle<Function>::Cast(cb)); pthread_mutex_init(&save->mutex, NULL); saving_closures.insert(save); zf->saving = true; zf->Ref(); ev_ref(EV_DEFAULT_UC); pthread_create(&save->thread, NULL, Save_Thread, save); return Undefined(); }
Handle<Value> ZipFile::readFile(const Arguments& args) { HandleScope scope; if (args.Length() < 2) return ThrowException(Exception::TypeError( String::New("requires two arguments, the name of a file and a callback"))); // first arg must be name if (!args[0]->IsString()) return ThrowException(Exception::TypeError( String::New("first argument must be a file name inside the zip"))); // last arg must be function callback if (!args[args.Length()-1]->IsFunction()) return ThrowException(Exception::TypeError( String::New("last argument must be a callback function"))); std::string name = TOSTR(args[0]); ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This()); closure_t *closure = new closure_t(); closure->request.data = closure; // libzip is not threadsafe so we cannot use the zf->archive_ // instead we open a new zip archive for each thread struct zip *za; int err; char errstr[1024]; if ((za = zip_open(zf->file_name_.c_str() , 0, &err)) == NULL) { zip_error_to_str(errstr, sizeof(errstr), err, errno); std::stringstream s; s << "cannot open file: " << zf->file_name_ << " error: " << errstr << "\n"; zip_close(za); return ThrowException(Exception::Error( String::New(s.str().c_str()))); } closure->zf = zf; closure->za = za; closure->error = false; closure->name = name; closure->cb = Persistent<Function>::New(Handle<Function>::Cast(args[args.Length()-1])); uv_queue_work(uv_default_loop(), &closure->request, Work_ReadFile, Work_AfterReadFile); uv_ref(uv_default_loop()); zf->Ref(); return Undefined(); }
/* zipfile.read(buffer, pos, len, cb) -> cb(bytesRead, error) */ Handle<Value> ZipFile::Read(const Arguments& args) { ZipFile* zf = ObjectWrap::Unwrap<ZipFile>(args.This()); if (!Buffer::HasInstance(args[0])) { return ThrowException(Exception::Error( String::New("First argument needs to be a buffer"))); } Local<Object> buffer_obj = args[0]->ToObject(); char *buffer_data = Buffer::Data(buffer_obj); size_t buffer_length = Buffer::Length(buffer_obj); zip_uint64_t off = args[1]->Int32Value(); if (off >= buffer_length) { return ThrowException(Exception::Error( String::New("Offset is out of bounds"))); } zip_uint64_t len = args[2]->Int32Value(); if (off + len > buffer_length) { return ThrowException(Exception::Error( String::New("Length is extends beyond buffer"))); } Local<Value> cb = args[3]; if (!cb->IsFunction()) return ThrowException(Exception::Error( String::New("Fourth argument should be a callback function."))); read_closure_t *closure = new read_closure_t(); closure->zf = zf; closure->read = 0; closure->data = buffer_data+off; closure->len = len; closure->cb = Persistent<Function>::New(Handle<Function>::Cast(args[3])); eio_custom(EIO_Read, EIO_PRI_DEFAULT, EIO_AfterRead, closure); zf->Ref(); ev_ref(EV_DEFAULT_UC); return Undefined(); }