/*
* Unix SMB/CIFS implementation.
* fusermount smb2 client
* Copyright (C) Volker Lendecke 2016
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define FUSE_USE_VERSION 26
#define _FILE_OFFSET_BITS 64
#include "fuse/fuse_lowlevel.h"
#include "source3/include/includes.h"
#include "client.h"
#include "trans2.h"
#include "libsmb/proto.h"
#include "libsmb/clirap.h"
#include "libsmb/cli_smb2_fnum.h"
#include "lib/util/tevent_ntstatus.h"
#include "libcli/smb/smbXcli_base.h"
#include "libcli/security/security.h"
#include "clifuse.h"
#include "lib/util/idtree.h"
struct mount_state {
struct tevent_context *ev;
struct cli_state *cli;
bool done;
struct tevent_fd *fde;
struct tevent_signal *signal_ev;
struct fuse_chan *ch;
struct fuse_session *se;
size_t bufsize;
char *buf;
struct idr_context *ino_ctx;
TALLOC_CTX *ino_parent;
};
struct inode_state {
struct idr_context *ino_ctx;
fuse_ino_t ino;
char path[];
};
static int inode_state_destructor(struct inode_state *s);
static struct inode_state *inode_state_init(TALLOC_CTX *mem_ctx,
struct idr_context *ino_ctx,
const char *path)
{
struct inode_state *state;
size_t pathlen;
int ino;
pathlen = strlen(path);
state = talloc_size(
mem_ctx, offsetof(struct inode_state, path) + pathlen + 1);
if (state == NULL) {
return NULL;
}
talloc_set_name_const(state, "struct inode_state");
ino = idr_get_new_above(ino_ctx, state, 1, INT32_MAX);
if (ino == -1) {
TALLOC_FREE(state);
return NULL;
}
state->ino = ino;
state->ino_ctx = ino_ctx;
memcpy(state->path, path, pathlen + 1);
DBG_DEBUG("Creating ino %d for path %s\n", ino, path);
talloc_set_destructor(state, inode_state_destructor);
return state;
}
static struct inode_state *inode_state_new(struct mount_state *mstate,
const char *path)
{
return inode_state_init(mstate->ino_parent, mstate->ino_ctx, path);
}
static int inode_state_destructor(struct inode_state *s)
{
DBG_DEBUG("destroying inode %ju\n", (uintmax_t)s->ino);
idr_remove(s->ino_ctx, s->ino);
return 0;
}
struct ll_create_state {
struct mount_state *mstate;
fuse_req_t freq;
struct fuse_file_info fi;
char *path;
};
static void cli_ll_create_done(struct tevent_req *req);
static void cli_ll_create(fuse_req_t freq, fuse_ino_t parent, const char *name,
mode_t mode, struct fuse_file_info *fi)
{
struct mount_state *mstate = talloc_get_type_abort(
fuse_req_userdata(freq), struct mount_state);
struct ll_create_state *state;
struct inode_state *istate;
struct tevent_req *req;
DBG_DEBUG("parent=%ju, name=%s, mode=%x\n", (uintmax_t)parent,
name, (unsigned)mode);
istate = idr_find(mstate->ino_ctx, parent);
if (istate == NULL) {
fuse_reply_err(freq, ENOENT);
return;
}
state = talloc(mstate, struct ll_create_state);
if (state == NULL) {
fuse_reply_err(freq, ENOMEM);
return;
}
state->mstate = mstate;
state->freq = freq;
state->fi = *fi;
state->path = talloc_asprintf(state, "%s%s%s", istate->path,
strlen(istate->path) ? "\\": "",
name);
if (state->path == NULL) {
TALLOC_FREE(state);
fuse_reply_err(freq, ENOMEM);
return;
}
req = cli_smb2_create_fnum_send(
state,
mstate->ev,
mstate->cli, state->path,
(struct cli_smb2_create_flags){0},
SMB2_IMPERSONATION_IMPERSONATION,
FILE_GENERIC_READ|FILE_GENERIC_WRITE,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_CREATE,
FILE_NON_DIRECTORY_FILE,
NULL);
if (req == NULL) {
TALLOC_FREE(state);
fuse_reply_err(freq, ENOMEM);
return;
}
tevent_req_set_callba
|