static VALUE rb_smbdir_initialize(VALUE self, VALUE smb_obj, VALUE url_obj) { RB_SMBFILE_DATA_FROM_OBJ(self, data); RB_SMB_DATA_FROM_OBJ(smb_obj, smb_data); smbc_opendir_fn fn; const char *url = StringValueCStr(url_obj); fn = smbc_getFunctionOpendir(smb_data->smbcctx); data->smbcfile = (*fn)(smb_data->smbcctx, url); if (data->smbcfile == NULL) { rb_sys_fail_str(url_obj); } /* FIXME: Take encoding from argument */ /* FIXME: Read unix charset (?) from smb.conf for default encoding */ data->enc = rb_enc_find("UTF-8"); data->smb_obj = smb_obj; data->smb_data = smb_data; data->smbcctx = smb_data->smbcctx; data->url = ruby_strdup(url); RB_SMB_DEBUG("smbcctx=%p smbcfile=%p\n", data->smbcctx, data->smbcfile); if (rb_block_given_p()) { return rb_ensure(rb_yield, self, rb_smbdir_close, self); } return self; }
static VALUE rb_smbfile_seek(int argc, VALUE *argv, VALUE self) { RB_SMBFILE_DATA_FROM_OBJ(self, data); RB_SMBFILE_DATA_CLOSED(data); VALUE whence_num; rb_scan_args(argc, argv, "11", NULL, &whence_num); off_t offset = NUM2OFFT(argv[0]); int whence = NIL_P(whence_num) ? SEEK_SET : NUM2INT(whence_num); switch (whence) { case SEEK_SET: data->pos = offset; break; case SEEK_CUR: if (offset < 0 && offset < -data->pos) { errno = EINVAL; rb_sys_fail(data->url); } data->pos += offset; break; case SEEK_END: /* FIXME */ rb_raise(rb_eNotImpError, "SEEK_END"); break; default: errno = EINVAL; rb_sys_fail(data->url); break; } rb_smbfile_seek_by_data(data); return self; }
static VALUE rb_smbdir_read(VALUE self) { RB_SMBFILE_DATA_FROM_OBJ(self, data); RB_SMBFILE_DATA_CLOSED(data); smbc_readdir_fn fn; struct smbc_dirent *smbcdent; fn = smbc_getFunctionReaddir(data->smbcctx); errno = 0; smbcdent = (*fn)(data->smbcctx, data->smbcfile); if (smbcdent == NULL) { if (errno) { rb_sys_fail(data->url); } return Qnil; } VALUE args[4]; args[0] = rb_external_str_new_with_enc(smbcdent->name, strlen(smbcdent->name), data->enc); args[1] = INT2NUM(smbcdent->smbc_type); args[2] = rb_str_new2(data->url); rb_str_cat2(args[2], "/"); /* FIXME: Unless if the last char is not "/" */ rb_str_cat2(args[2], smbcdent->name); /* FIXME: Must be URL encoding */ args[3] = rb_str_new(smbcdent->comment, smbcdent->commentlen); VALUE entry_obj = rb_class_new_instance(4, args, rb_cSMBDirEntry); return entry_obj; }
static VALUE rb_smbfile_pos(VALUE self) { RB_SMBFILE_DATA_FROM_OBJ(self, data); RB_SMBFILE_DATA_CLOSED(data); return SIZET2NUM(data->pos); }
static VALUE rb_smbdir_close(VALUE self) { RB_SMBFILE_DATA_FROM_OBJ(self, data); RB_SMBFILE_DATA_CLOSED(data); RB_SMB_DEBUG("data=%p smbcctx=%p smbcfile=%p\n", data, data->smbcctx, data->smbcfile); rb_smbdir_close_and_deref_by_data(data); return self; }
static VALUE rb_smbfile_read(int argc, VALUE *argv, VALUE self) { RB_SMBFILE_DATA_FROM_OBJ(self, data); RB_SMBFILE_DATA_CLOSED(data); ssize_t req_read_size; VALUE str = rb_str_new2(""); rb_smbfile_readable_p_by_data(data); if (argc == 0) { req_read_size = -1; } else { req_read_size = NUM2SSIZET(argv[0]); if (req_read_size == 0) { return str; /* Return empty string */ } if (req_read_size < 0) { rb_raise(rb_eArgError, "Negative length given: %zd", req_read_size); } } while (req_read_size) { ssize_t buffer_read_size = data->buffer_used_size - data->buffer_pos; if (buffer_read_size == 0) { /* No remained data in buffer */ rb_smbfile_read_by_data(data); if (data->eof) { /* No remained data in file */ return (req_read_size > 0 && RSTRING_LEN(str) == 0) ? Qnil : str; } buffer_read_size = data->buffer_used_size - data->buffer_pos; } if (req_read_size > 0 && buffer_read_size > req_read_size) { buffer_read_size = req_read_size; } rb_str_cat(str, data->buffer + data->buffer_pos, buffer_read_size); data->pos += buffer_read_size; data->buffer_pos += buffer_read_size; if (req_read_size > 0) { req_read_size -= buffer_read_size; } } return str; }
static VALUE rb_smbdir_seek(VALUE self, VALUE offset_num) { RB_SMBFILE_DATA_FROM_OBJ(self, data); RB_SMBFILE_DATA_CLOSED(data); smbc_lseekdir_fn fn; off_t offset = (off_t)NUM2LONG(offset_num); fn = smbc_getFunctionLseekdir(data->smbcctx); errno = 0; if ((*fn)(data->smbcctx, data->smbcfile, offset) == -1) { rb_sys_fail(data->url); } return self; }
static VALUE rb_smbdir_tell(VALUE self) { RB_SMBFILE_DATA_FROM_OBJ(self, data); RB_SMBFILE_DATA_CLOSED(data); smbc_telldir_fn fn; off_t offset; fn = smbc_getFunctionTelldir(data->smbcctx); errno = 0; offset = (*fn)(data->smbcctx, data->smbcfile); if (offset == (off_t)-1) { if (errno != 0) { rb_sys_fail(data->url); } } return LONG2NUM(offset); }
static VALUE rb_smbfile_eof_p(VALUE self) { RB_SMBFILE_DATA_FROM_OBJ(self, data); RB_SMBFILE_DATA_CLOSED(data); if (data->buffer_used_size - data->buffer_pos > 0) { /* Remained data exist in buffer */ return Qfalse; } /* Try to read from file to buffer */ rb_smbfile_read_by_data(data); if (data->buffer_used_size - data->buffer_pos > 0) { /* Remained data exist in buffer */ return Qfalse; } return Qtrue; }
static VALUE rb_smbdir_xattr_get(VALUE self, VALUE name_obj) { RB_SMBFILE_DATA_FROM_OBJ(self, data); return rb_smb_xattr_get(data->smb_obj, rb_str_new2(data->url), name_obj); }
static VALUE rb_smbdir_closed_p(VALUE self) { RB_SMBFILE_DATA_FROM_OBJ(self, data); return rb_smbdir_closed_p_by_data(data); }
static VALUE rb_smbdir_url(VALUE self) { RB_SMBFILE_DATA_FROM_OBJ(self, data); return rb_str_new2(data->url); }
static VALUE rb_smbdir_smb(VALUE self) { RB_SMBFILE_DATA_FROM_OBJ(self, data); return data->smb_obj; }
static void rb_smbfile_read_by_data(RB_SMBFILE_DATA *data) { smbc_read_fn fn; ssize_t read_size; char *buffer = data->buffer + data->buffer_used_size; size_t buffer_size = data->buffer_size - data->buffer_used_size; if (buffer_size == 0) { /* Buffer is full */ if (data->buffer_pos < data->buffer_used_size) { /* But remained data exists */ return; } /* Rewind */ data->buffer_used_size = 0; data->buffer_pos = 0; buffer = data->buffer; buffer_size = data->buffer_size; } fn = smbc_getFunctionRead(data->smbcctx); try: read_size = (*fn)(data->smbcctx, data->smbcfile, buffer, buffer_size); if (read_size < 0) { if (errno != EBADF) { rb_sys_fail("Bad SMBCFILE"); } else { rb_smbfile_reopen_by_data(data); goto try; } } data->buffer_used_size += read_size; data->eof = (read_size == 0); } static VALUE rb_smbfile_close(VALUE self); static VALUE rb_smbfile_initialize(int argc, VALUE *argv, VALUE self) { RB_SMBFILE_DATA_FROM_OBJ(self, data); VALUE smb_obj, url_obj, mode_obj; rb_scan_args(argc, argv, "21", &smb_obj, &url_obj, &mode_obj); RB_SMB_DATA_FROM_OBJ(smb_obj, smb_data); if (NIL_P(mode_obj)) { data->fmode = FMODE_READABLE; // FIXME data->fmode = FMODE_READABLE | DEFAULT_TEXTMODE; data->oflags = O_RDONLY; } else if (FIXNUM_P(mode_obj)) { rb_raise(rb_eArgError, "FIXME"); data->fmode = 0; data->oflags = NUM2INT(mode_obj); } else { const char *mode_str = StringValueCStr(mode_obj); data->fmode = rb_io_modestr_fmode(mode_str); data->oflags = rb_io_modestr_oflags(mode_str); } data->smb_obj = smb_obj; data->smb_data = smb_data; data->smbcctx = smb_data->smbcctx; data->url = ruby_strdup(RSTRING_PTR(url_obj)); data->buffer = ruby_xmalloc(RB_SMBFILE_BUFFER_SIZE); data->buffer_size = RB_SMBFILE_BUFFER_SIZE; rb_smbfile_open_by_data(data); if (rb_block_given_p()) { return rb_ensure(rb_yield, self, rb_smbfile_close, self); } return self; }