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; }
int SmbFs::fs_opendir(const char *path, struct fuse_file_info *fi) { QMutexLocker locker(&_mutex); SMBCFILE *dir = (smbc_getFunctionOpendir(_ctx))(_ctx, qPrintable(getPath(path))); if(dir == NULL) return(-errno); fi->fh = (unsigned long)dir; return(0); }
int smbc_opendir(const char *durl) { SMBCFILE * file; int fd; file = smbc_getFunctionOpendir(statcont)(statcont, durl); if (!file) return -1; fd = add_fd(file); if (fd == -1) smbc_getFunctionClosedir(statcont)(statcont, file); return fd; }
SMBCFILE * SMBC_open_ctx(SMBCCTX *context, const char *fname, int flags, mode_t mode) { char *server = NULL; char *share = NULL; char *user = NULL; char *password = NULL; char *workgroup = NULL; char *path = NULL; char *targetpath = NULL; struct cli_state *targetcli = NULL; SMBCSRV *srv = NULL; SMBCFILE *file = NULL; uint16_t fd; uint16_t port = 0; NTSTATUS status = NT_STATUS_OBJECT_PATH_INVALID; TALLOC_CTX *frame = talloc_stackframe(); if (!context || !context->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); return NULL; } if (!fname) { errno = EINVAL; TALLOC_FREE(frame); return NULL; } if (SMBC_parse_path(frame, context, fname, &workgroup, &server, &port, &share, &path, &user, &password, NULL)) { errno = EINVAL; TALLOC_FREE(frame); return NULL; } if (!user || user[0] == (char)0) { user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); return NULL; } } srv = SMBC_server(frame, context, True, server, port, share, &workgroup, &user, &password); if (!srv) { if (errno == EPERM) errno = EACCES; TALLOC_FREE(frame); return NULL; /* SMBC_server sets errno */ } /* Hmmm, the test for a directory is suspect here ... FIXME */ if (strlen(path) > 0 && path[strlen(path) - 1] == '\\') { status = NT_STATUS_OBJECT_PATH_INVALID; } else { file = SMB_MALLOC_P(SMBCFILE); if (!file) { errno = ENOMEM; TALLOC_FREE(frame); return NULL; } ZERO_STRUCTP(file); /*d_printf(">>>open: resolving %s\n", path);*/ status = cli_resolve_path( frame, "", context->internal->auth_info, srv->cli, path, &targetcli, &targetpath); if (!NT_STATUS_IS_OK(status)) { d_printf("Could not resolve %s\n", path); errno = ENOENT; SAFE_FREE(file); TALLOC_FREE(frame); return NULL; } /*d_printf(">>>open: resolved %s as %s\n", path, targetpath);*/ status = cli_open(targetcli, targetpath, flags, context->internal->share_mode, &fd); if (!NT_STATUS_IS_OK(status)) { /* Handle the error ... */ SAFE_FREE(file); errno = SMBC_errno(context, targetcli); TALLOC_FREE(frame); return NULL; } /* Fill in file struct */ file->cli_fd = fd; file->fname = SMB_STRDUP(fname); file->srv = srv; file->offset = 0; file->file = True; /* * targetcli is either equal to srv->cli or * is a subsidiary DFS connection. Either way * file->cli_fd belongs to it so we must cache * it for read/write/close, not re-resolve each time. * Re-resolving is both slow and incorrect. */ file->targetcli = targetcli; DLIST_ADD(context->internal->files, file); /* * If the file was opened in O_APPEND mode, all write * operations should be appended to the file. To do that, * though, using this protocol, would require a getattrE() * call for each and every write, to determine where the end * of the file is. (There does not appear to be an append flag * in the protocol.) Rather than add all of that overhead of * retrieving the current end-of-file offset prior to each * write operation, we'll assume that most append operations * will continuously write, so we'll just set the offset to * the end of the file now and hope that's adequate. * * Note to self: If this proves inadequate, and O_APPEND * should, in some cases, be forced for each write, add a * field in the context options structure, for * "strict_append_mode" which would select between the current * behavior (if FALSE) or issuing a getattrE() prior to each * write and forcing the write to the end of the file (if * TRUE). Adding that capability will likely require adding * an "append" flag into the _SMBCFILE structure to track * whether a file was opened in O_APPEND mode. -- djl */ if (flags & O_APPEND) { if (SMBC_lseek_ctx(context, file, 0, SEEK_END) < 0) { (void) SMBC_close_ctx(context, file); errno = ENXIO; TALLOC_FREE(frame); return NULL; } } TALLOC_FREE(frame); return file; } /* Check if opendir needed ... */ if (!NT_STATUS_IS_OK(status)) { int eno = 0; eno = SMBC_errno(context, srv->cli); file = smbc_getFunctionOpendir(context)(context, fname); if (!file) errno = eno; TALLOC_FREE(frame); return file; } errno = EINVAL; /* FIXME, correct errno ? */ TALLOC_FREE(frame); return NULL; }
static void list_dir (SMBCCTX *smb_context, const gchar *dirname, const gchar *path, GCancellable *cancellable, SMBData *data) { struct smbc_dirent *dirent; smbc_closedir_fn smbclient_closedir; smbc_readdir_fn smbclient_readdir; smbc_opendir_fn smbclient_opendir; PpPrintDevice *device; const gchar *host_name; SMBCFILE *dir; if (!g_cancellable_is_cancelled (cancellable)) { smbclient_closedir = smbc_getFunctionClosedir (smb_context); smbclient_readdir = smbc_getFunctionReaddir (smb_context); smbclient_opendir = smbc_getFunctionOpendir (smb_context); dir = smbclient_opendir (smb_context, dirname); if (!dir && errno == EACCES) { if (g_str_has_prefix (dirname, "smb://")) host_name = dirname + 6; else host_name = dirname; if (data->auth_if_needed) { data->cancelled = FALSE; smbc_setFunctionAuthDataWithContext (smb_context, auth_fn); dir = smbclient_opendir (smb_context, dirname); smbc_setFunctionAuthDataWithContext (smb_context, anonymous_auth_fn); if (data->cancelled) { device = g_object_new (PP_TYPE_PRINT_DEVICE, "host-name", host_name, "is-authenticated-server", TRUE, NULL); data->devices->devices = g_list_append (data->devices->devices, device); if (dir) smbclient_closedir (smb_context, dir); return; } } else { device = g_object_new (PP_TYPE_PRINT_DEVICE, "host-name", host_name, "is-authenticated-server", TRUE, NULL); data->devices->devices = g_list_append (data->devices->devices, device); } } while (dir && (dirent = smbclient_readdir (smb_context, dir))) { gchar *device_name; gchar *device_uri; gchar *subdirname = NULL; gchar *subpath = NULL; gchar *uri; if (dirent->smbc_type == SMBC_WORKGROUP) { subdirname = g_strdup_printf ("%s%s", dirname, dirent->name); subpath = g_strdup_printf ("%s%s", path, dirent->name); } if (dirent->smbc_type == SMBC_SERVER) { subdirname = g_strdup_printf ("smb://%s", dirent->name); subpath = g_strdup_printf ("%s//%s", path, dirent->name); } if (dirent->smbc_type == SMBC_PRINTER_SHARE) { uri = g_strdup_printf ("%s/%s", dirname, dirent->name); device_uri = g_uri_escape_string (uri, G_URI_RESERVED_CHARS_GENERIC_DELIMITERS G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS, FALSE); device_name = g_strdup (dirent->name); device_name = g_strcanon (device_name, ALLOWED_CHARACTERS, '-'); device = g_object_new (PP_TYPE_PRINT_DEVICE, "device-uri", device_uri, "is-network-device", TRUE, "device-info", dirent->comment, "device-name", device_name, "acquisition-method", data->hostname_set ? ACQUISITION_METHOD_SAMBA_HOST : ACQUISITION_METHOD_SAMBA, "device-location", path, "host-name", dirname, NULL); g_free (device_name); g_free (device_uri); g_free (uri); data->devices->devices = g_list_append (data->devices->devices, device); } if (subdirname) { list_dir (smb_context, subdirname, subpath, cancellable, data); g_free (subdirname); g_free (subpath); } } if (dir) smbclient_closedir (smb_context, dir); } }
static smbresultlist* browse(SMBCCTX *ctx, char *path, int maxdepth, int depth) { SMBCFILE *fd; struct smbc_dirent *dirent; char fullpath[2560] = ""; char acl[1024] = ""; int aclret; char mode[128] = ""; int moderet; smbresultlist *thisresults = NULL; smbresultlist *subresults = NULL; //Try and get a directory listing of the object we just opened. //This could be a workgroup, server, share, or directory and //we'll get the full listing. If it doesn't work, return our error. //Errors will happen a lot in normal usage due to access denied. if ((fd = smbc_getFunctionOpendir(ctx)(ctx, path)) == NULL) { smbresult *tmp = createSMBResultEmpty(); parse_smburl(path, &tmp->host, &tmp->share, &tmp->object); tmp->statuscode = errno; smbresultlist_push(&thisresults, tmp); return thisresults; } //Get the current entity of the directory item we're working on. while ((dirent = smbc_getFunctionReaddir(ctx)(ctx, fd)) != NULL) { smbresult *thisresult = createSMBResultEmpty(); //Check to see if what we're working on is blank, or one of the //special directory characters. If so, skip them. if(strcmp(dirent->name, "") == 0) continue; if(strcmp(dirent->name, ".") == 0) continue; if(strcmp(dirent->name, "..") == 0) continue; //Create the full path for this object by concating it with the //parent path. sprintf(fullpath, "%s/%s", path, dirent->name); //Parse out the various parts of the path for pretty output. parse_smburl(fullpath, &thisresult->host, &thisresult->share, &thisresult->object); //Set the type so we have it thisresult->type = dirent->smbc_type; //Get the "dos_attr.mode" extended attribute which is the file permissions. moderet = smbc_getFunctionGetxattr(ctx)(ctx, fullpath, "system.dos_attr.mode", &mode, sizeof(mode)); if(moderet == -1 && errno == 13) { thisresult->mode = -1; } else { //The ACL is returned as a string pointer, but we need to convert it to a long so we can //do binary comparison on the settings eventually. thisresult->mode = strtol(acl, NULL, 16); } //Get the ACL ACEs for the NTFS permissions. The + is so we lookup SIDs to names aclret = smbc_getFunctionGetxattr(ctx)(ctx, fullpath, "system.nt_sec_desc.acl.*+", acl, sizeof(acl)); if(aclret < 0) { char permerrbuf[100]; sprintf(permerrbuf, "Unable to pull permissions (%d): %s", errno, strerror(errno)); thisresult->acl = strdup(permerrbuf); thisresult->statuscode = errno; } else { thisresult->acl = strdup(acl); } smbresultlist_push(&thisresults, thisresult); //If we have a directory or share we want to recurse to our max depth if(depth < maxdepth) { switch (thisresult->type) { case SMBC_FILE_SHARE: case SMBC_DIR: subresults = browse(ctx, fullpath, maxdepth, depth++); smbresultlist_merge(&thisresults, &subresults); } } } //Try to close the directory that we had opened. If it failed, it'll return > 0. if(smbc_getFunctionClosedir(ctx)(ctx, fd) > 0) { smbresult *tmp = createSMBResultEmpty(); parse_smburl(path, &tmp->host, &tmp->share, &tmp->object); tmp->statuscode = errno; smbresultlist_push(&thisresults, tmp); } //Finally, we're done, lets return to the user. return thisresults; }