Beispiel #1
0
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);
}
Beispiel #3
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;
}
Beispiel #4
0
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);
    }
}
Beispiel #6
0
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;
}